From f33ae0db297fcfaceb792acad084cf70963f20c0 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Sat, 20 Jun 2009 12:57:22 +0000 Subject: [PATCH] openwrt: initial import of 8.09 packages files patches and config --- openwrt/config | 1315 +++++ openwrt/files/etc/config/dhcp | 23 + openwrt/files/etc/config/dropbear | 3 + openwrt/files/etc/config/firewall | 87 + openwrt/files/etc/config/network | 17 + openwrt/files/etc/config/system | 10 + openwrt/files/etc/config/wireless | 19 + openwrt/files/etc/hosts | 2 + openwrt/files/etc/inittab | 2 + openwrt/files/etc/passwd | 3 + openwrt/packages/expat/Makefile | 58 + .../packages/expat/patches/001-destdir.patch | 45 + .../expat/patches/110-avr32_compile_fix.patch | 21 + openwrt/packages/flukso/Makefile | 44 + openwrt/packages/flukso/src/auth.lua | 73 + openwrt/packages/flukso/src/data.lua | 62 + openwrt/packages/flukso/src/dbg.lua | 50 + openwrt/packages/flukso/src/flukso.init | 17 + openwrt/packages/flukso/src/flukso.lua | 154 + openwrt/packages/flukso/src/heartbeat.lua | 90 + openwrt/packages/flukso/src/load.lua | 14 + openwrt/packages/luaexpat/Makefile | 93 + .../luaexpat/patches/010-compat-5.1.patch | 22 + .../patches/010-luaL_findstring.patch | 18 + openwrt/packages/luasocket/Makefile | 184 + .../luasocket/patches/010-compat-5.1.patch | 14 + openwrt/packages/luaxmlrpc/Makefile | 45 + openwrt/packages/luaxmlrpc/src/http.lua | 44 + openwrt/packages/luaxmlrpc/src/init.lua | 593 ++ openwrt/packages/luaxmlrpc/src/server.lua | 90 + openwrt/packages/luaxyssl/Makefile | 43 + .../luaxyssl/patches/100-compile-fixes.patch | 273 + openwrt/packages/luci/.buildpath | 5 + openwrt/packages/luci/.cproject | 221 + openwrt/packages/luci/.gitignore | 6 + openwrt/packages/luci/.project | 78 + openwrt/packages/luci/INSTALL | 27 + openwrt/packages/luci/LICENSE | 201 + openwrt/packages/luci/Makefile | 84 + openwrt/packages/luci/NOTICE | 8 + openwrt/packages/luci/THANKYOU | 26 + .../applications/freifunk-community/Makefile | 2 + .../htdocs/cgi-bin-nodes.html | 10 + .../htdocs/cgi-bin-status.html | 10 + .../luci/applications/luci-ddns/Makefile | 2 + .../luci-ddns/luasrc/controller/ddns.lua | 32 + .../luci-ddns/luasrc/i18n/ddns.de.lua | 8 + .../luci-ddns/luasrc/i18n/ddns.de.xml | 13 + .../luci-ddns/luasrc/i18n/ddns.en.lua | 8 + .../luci-ddns/luasrc/i18n/ddns.en.xml | 13 + .../luci-ddns/luasrc/i18n/ddns.fr.lua | 8 + .../luci-ddns/luasrc/i18n/ddns.fr.xml | 13 + .../luci-ddns/luasrc/i18n/ddns.pt-br.lua | 8 + .../luci-ddns/luasrc/i18n/ddns.pt-br.xml | 13 + .../luci-ddns/luasrc/model/cbi/ddns/ddns.lua | 74 + .../luasrc/model/cbi/ddns/ddnsmini.lua | 52 + .../root/lib/uci/schema/default/ddns | 147 + .../luci-ffwizard-leipzig/Makefile | 2 + .../luasrc/controller/ffwizard.lua | 21 + .../luasrc/model/cbi/ffwizard.lua | 391 ++ .../luasrc/tools/ffwizard.lua | 149 + .../luci/applications/luci-fw/Makefile | 2 + .../luasrc/controller/luci_fw/luci_fw.lua | 13 + .../luci-fw/luasrc/i18n/luci-fw.de.lua | 56 + .../luci-fw/luasrc/i18n/luci-fw.de.xml | 67 + .../luci-fw/luasrc/i18n/luci-fw.en.lua | 56 + .../luci-fw/luasrc/i18n/luci-fw.en.xml | 66 + .../luci-fw/luasrc/i18n/luci-fw.fr.lua | 56 + .../luci-fw/luasrc/i18n/luci-fw.fr.xml | 66 + .../luci-fw/luasrc/i18n/luci-fw.pt-br.lua | 56 + .../luci-fw/luasrc/i18n/luci-fw.pt-br.xml | 66 + .../luasrc/model/cbi/luci_fw/miniportfw.lua | 45 + .../luasrc/model/cbi/luci_fw/redirect.lua | 50 + .../luasrc/model/cbi/luci_fw/rrule.lua | 69 + .../luasrc/model/cbi/luci_fw/traffic.lua | 82 + .../luasrc/model/cbi/luci_fw/trule.lua | 72 + .../luasrc/model/cbi/luci_fw/zones.lua | 71 + .../root/lib/uci/schema/default/firewall | 255 + .../luci/applications/luci-hd_idle/Makefile | 2 + .../applications/luci-hd_idle/ipkg/postinst | 4 + .../luasrc/controller/hd_idle.lua | 28 + .../luci-hd_idle/luasrc/i18n/hd_idle.de.lua | 7 + .../luci-hd_idle/luasrc/i18n/hd_idle.de.xml | 13 + .../luci-hd_idle/luasrc/i18n/hd_idle.en.lua | 7 + .../luci-hd_idle/luasrc/i18n/hd_idle.en.xml | 13 + .../luasrc/i18n/hd_idle.pt-br.lua | 7 + .../luasrc/i18n/hd_idle.pt-br.xml | 13 + .../luci-hd_idle/luasrc/model/cbi/hd_idle.lua | 41 + .../root/etc/uci-defaults/luci-hd_idle | 7 + .../luci/applications/luci-initmgr/Makefile | 2 + .../luci-initmgr/luasrc/controller/init.lua | 29 + .../luci-initmgr/luasrc/i18n/initmgr.de.lua | 5 + .../luci-initmgr/luasrc/i18n/initmgr.de.xml | 11 + .../luci-initmgr/luasrc/i18n/initmgr.en.lua | 5 + .../luci-initmgr/luasrc/i18n/initmgr.en.xml | 11 + .../luasrc/i18n/initmgr.pt-br.lua | 5 + .../luasrc/i18n/initmgr.pt-br.xml | 11 + .../luasrc/model/cbi/init/init.lua | 58 + .../luci/applications/luci-livestats/Makefile | 2 + .../resources/livestats/ExCanvas.js | 19 + .../resources/livestats/GraphRPC.js | 204 + .../resources/livestats/JsonRpc.js | 220 + .../luci-static/resources/livestats/Legend.js | 228 + .../resources/livestats/MochiKit.js | 4800 +++++++++++++++++ .../resources/livestats/PlotKit.js | 2177 ++++++++ .../luasrc/controller/livestats.lua | 29 + .../luasrc/i18n/livestats.de.lua | 8 + .../luasrc/i18n/livestats.en.lua | 8 + .../luasrc/view/livestats/loadavg.htm | 33 + .../luasrc/view/livestats/traffic.htm | 66 + .../luasrc/view/livestats/wireless.htm | 43 + .../applications/luci-mmc_over_gpio/Makefile | 2 + .../luci-mmc_over_gpio/ipkg/postinst | 4 + .../luasrc/controller/mmc_over_gpio.lua | 28 + .../luasrc/i18n/mmc_over_gpio.de.lua | 3 + .../luasrc/i18n/mmc_over_gpio.de.xml | 9 + .../luasrc/i18n/mmc_over_gpio.en.lua | 3 + .../luasrc/i18n/mmc_over_gpio.en.xml | 9 + .../luasrc/i18n/mmc_over_gpio.pt-br.lua | 3 + .../luasrc/i18n/mmc_over_gpio.pt-br.xml | 9 + .../luasrc/model/cbi/mmc_over_gpio.lua | 41 + .../root/etc/uci-defaults/luci-mmc_over_gpio | 7 + .../luci/applications/luci-ntpc/Makefile | 2 + .../luci-ntpc/luasrc/controller/ntpc.lua | 32 + .../luci-ntpc/luasrc/i18n/ntpc.de.lua | 9 + .../luci-ntpc/luasrc/i18n/ntpc.de.xml | 14 + .../luci-ntpc/luasrc/i18n/ntpc.en.lua | 9 + .../luci-ntpc/luasrc/i18n/ntpc.en.xml | 14 + .../luci-ntpc/luasrc/i18n/ntpc.pt-br.lua | 9 + .../luci-ntpc/luasrc/i18n/ntpc.pt-br.xml | 14 + .../luci-ntpc/luasrc/model/cbi/ntpc/ntpc.lua | 39 + .../luasrc/model/cbi/ntpc/ntpcmini.lua | 34 + .../root/lib/uci/schema/default/ntpclient | 53 + .../luci/applications/luci-olsr/Makefile | 2 + .../luci/applications/luci-olsr/ipkg/postinst | 4 + .../luci-olsr/luasrc/controller/olsr.lua | 225 + .../luci-olsr/luasrc/i18n/olsr.de.lua | 127 + .../luci-olsr/luasrc/i18n/olsr.de.xml | 184 + .../luci-olsr/luasrc/i18n/olsr.en.lua | 127 + .../luci-olsr/luasrc/i18n/olsr.en.xml | 184 + .../luci-olsr/luasrc/model/cbi/olsr/olsrd.lua | 145 + .../luasrc/model/cbi/olsr/olsrdhna.lua | 36 + .../luasrc/model/cbi/olsr/olsrdplugins.lua | 244 + .../luasrc/view/status-olsr/error_olsr.htm | 19 + .../luci-olsr/luasrc/view/status-olsr/hna.htm | 32 + .../luasrc/view/status-olsr/index.htm | 57 + .../luci-olsr/luasrc/view/status-olsr/mid.htm | 32 + .../luasrc/view/status-olsr/routes.htm | 51 + .../luasrc/view/status-olsr/topology.htm | 39 + .../luci-olsr/root/etc/uci-defaults/luci-olsr | 7 + .../luci/applications/luci-p910nd/Makefile | 2 + .../applications/luci-p910nd/ipkg/postinst | 4 + .../luci-p910nd/luasrc/controller/p910nd.lua | 28 + .../luci-p910nd/luasrc/i18n/p910nd.de.lua | 4 + .../luci-p910nd/luasrc/i18n/p910nd.de.xml | 10 + .../luci-p910nd/luasrc/i18n/p910nd.en.lua | 4 + .../luci-p910nd/luasrc/i18n/p910nd.en.xml | 10 + .../luci-p910nd/luasrc/i18n/p910nd.pt-br.lua | 4 + .../luci-p910nd/luasrc/i18n/p910nd.pt-br.xml | 10 + .../luci-p910nd/luasrc/model/cbi/p910nd.lua | 33 + .../root/etc/uci-defaults/luci-p910nd | 7 + .../luci/applications/luci-polipo/Makefile | 2 + .../applications/luci-polipo/ipkg/postinst | 4 + .../luci-polipo/luasrc/controller/polipo.lua | 28 + .../luci-polipo/luasrc/i18n/polipo.en.lua | 43 + .../luci-polipo/luasrc/i18n/polipo.en.xml | 49 + .../luci-polipo/luasrc/model/cbi/polipo.lua | 67 + .../root/etc/uci-defaults/luci-polipo | 7 + .../luci-polipo/root/usr/sbin/polipo_purge | 18 + .../luci/applications/luci-qos/Makefile | 2 + .../luci-qos/luasrc/controller/qos.lua | 29 + .../luci-qos/luasrc/i18n/qos.de.lua | 17 + .../luci-qos/luasrc/i18n/qos.de.xml | 22 + .../luci-qos/luasrc/i18n/qos.en.lua | 18 + .../luci-qos/luasrc/i18n/qos.en.xml | 23 + .../luci-qos/luasrc/i18n/qos.fr.lua | 17 + .../luci-qos/luasrc/i18n/qos.fr.xml | 23 + .../luci-qos/luasrc/i18n/qos.pt-br.lua | 17 + .../luci-qos/luasrc/i18n/qos.pt-br.xml | 22 + .../luci-qos/luasrc/model/cbi/qos/qos.lua | 89 + .../luci-qos/luasrc/model/cbi/qos/qosmini.lua | 82 + .../luci-qos/root/lib/uci/schema/default/qos | 200 + .../luci/applications/luci-samba/Makefile | 2 + .../luci-samba/luasrc/controller/samba.lua | 27 + .../luci-samba/luasrc/i18n/samba.de.lua | 17 + .../luci-samba/luasrc/i18n/samba.de.xml | 24 + .../luci-samba/luasrc/i18n/samba.en.lua | 17 + .../luci-samba/luasrc/i18n/samba.en.xml | 24 + .../luci-samba/luasrc/i18n/samba.pt-br.lua | 17 + .../luci-samba/luasrc/i18n/samba.pt-br.xml | 24 + .../luci-samba/luasrc/model/cbi/samba.lua | 56 + .../root/lib/uci/schema/default/samba | 76 + .../applications/luci-siitwizard/Makefile | 2 + .../luasrc/controller/siitwizard.lua | 21 + .../luasrc/model/cbi/siitwizard.lua | 338 ++ .../luci-siitwizard/root/etc/config/siit | 10 + .../luci/applications/luci-splash/Makefile | 2 + .../luci-splash/htdocs/luci/splash/index.html | 10 + .../applications/luci-splash/ipkg/postinst | 5 + .../luasrc/controller/splash/splash.lua | 29 + .../luasrc/model/cbi/splash/splash.lua | 47 + .../luci-splash/luasrc/view/splash/splash.htm | 47 + .../luasrc/view/splash_splash/index.htm | 16 + .../luasrc/view/splash_splash/splash.htm | 21 + .../luci-splash/root/etc/config/luci_splash | 2 + .../root/etc/cron.minutely/luci_splash | 2 + .../luci-splash/root/etc/init.d/luci_splash | 87 + .../root/lib/uci/schema/default/luci_splash | 14 + .../luci-splash/root/usr/bin/luci-splashd | 38 + .../luci-splash/root/usr/sbin/luci-splash | 190 + .../applications/luci-statistics/Makefile | 2 + .../luci-statistics/ipkg/postinst | 7 + .../luci_statistics/luci_statistics.lua | 198 + .../luasrc/i18n/rrdtool.de.lua | 70 + .../luasrc/i18n/rrdtool.de.xml.hide | 96 + .../luasrc/i18n/rrdtool.en.lua | 69 + .../luasrc/i18n/rrdtool.en.xml.hide | 95 + .../luasrc/i18n/rrdtool.pt-br.lua | 69 + .../luasrc/i18n/rrdtool.pt-br.xml.hide | 95 + .../luasrc/i18n/statistics.de.lua | 212 + .../luasrc/i18n/statistics.de.xml | 259 + .../luasrc/i18n/statistics.en.lua | 212 + .../luasrc/i18n/statistics.en.xml | 258 + .../luasrc/i18n/statistics.pt-br.lua | 212 + .../luasrc/i18n/statistics.pt-br.xml | 258 + .../model/cbi/luci_statistics/collectd.lua | 74 + .../luasrc/model/cbi/luci_statistics/cpu.lua | 25 + .../luasrc/model/cbi/luci_statistics/csv.lua | 36 + .../luasrc/model/cbi/luci_statistics/df.lua | 48 + .../luasrc/model/cbi/luci_statistics/disk.lua | 36 + .../luasrc/model/cbi/luci_statistics/dns.lua | 43 + .../model/cbi/luci_statistics/email.lua | 52 + .../luasrc/model/cbi/luci_statistics/exec.lua | 70 + .../model/cbi/luci_statistics/interface.lua | 42 + .../model/cbi/luci_statistics/iptables.lua | 116 + .../luasrc/model/cbi/luci_statistics/irq.lua | 36 + .../luasrc/model/cbi/luci_statistics/load.lua | 25 + .../model/cbi/luci_statistics/netlink.lua | 90 + .../model/cbi/luci_statistics/network.lua | 79 + .../luasrc/model/cbi/luci_statistics/ping.lua | 36 + .../model/cbi/luci_statistics/processes.lua | 30 + .../model/cbi/luci_statistics/rrdtool.lua | 94 + .../model/cbi/luci_statistics/tcpconns.lua | 40 + .../model/cbi/luci_statistics/unixsock.lua | 44 + .../model/cbi/luci_statistics/wireless.lua | 25 + .../luasrc/statistics/datatree.lua | 181 + .../luasrc/statistics/i18n.lua | 115 + .../luasrc/statistics/rrdtool.lua | 607 +++ .../luasrc/statistics/rrdtool/colors.lua | 73 + .../luasrc/statistics/rrdtool/definitions.lua | 1123 ++++ .../rrdtool/definitions/cpu/cpu.lua | 38 + .../statistics/rrdtool/definitions/df/df.lua | 41 + .../rrdtool/definitions/interface.lua | 107 + .../definitions/iptables/ipt_bytes.lua | 27 + .../definitions/iptables/ipt_packets.lua | 27 + .../rrdtool/definitions/irq/irq.lua | 25 + .../rrdtool/definitions/load/load.lua | 33 + .../rrdtool/definitions/netlink.lua | 193 + .../rrdtool/definitions/ping/ping.lua | 27 + .../rrdtool/definitions/processes.lua | 101 + .../definitions/tcpconns/tcp_connections.lua | 31 + .../rrdtool/definitions/wireless.lua | 71 + .../luasrc/view/admin_statistics/index.htm | 22 + .../view/admin_statistics/networkplugins.htm | 32 + .../view/admin_statistics/outputplugins.htm | 33 + .../view/admin_statistics/systemplugins.htm | 29 + .../luasrc/view/public_statistics/graph.htm | 39 + .../root/etc/config/luci_statistics | 132 + .../root/etc/init.d/luci_statistics | 31 + .../root/etc/uci-defaults/luci-statistics | 7 + .../root/usr/bin/stat-genconfig | 381 ++ .../luci/applications/luci-tinyproxy/Makefile | 2 + .../luasrc/controller/tinyproxy.lua | 25 + .../luasrc/i18n/tinyproxy.de.lua | 32 + .../luasrc/i18n/tinyproxy.de.xml | 38 + .../luasrc/i18n/tinyproxy.en.lua | 32 + .../luasrc/i18n/tinyproxy.en.xml | 38 + .../luasrc/i18n/tinyproxy.fr.lua | 34 + .../luasrc/i18n/tinyproxy.fr.xml | 40 + .../luasrc/i18n/tinyproxy.pt-br.lua | 34 + .../luasrc/i18n/tinyproxy.pt-br.xml | 40 + .../luasrc/model/cbi/tinyproxy.lua | 80 + .../luci/applications/luci-upnp/Makefile | 2 + .../luci-upnp/luasrc/controller/upnp.lua | 30 + .../luci-upnp/luasrc/i18n/upnp.de.lua | 7 + .../luci-upnp/luasrc/i18n/upnp.de.xml | 12 + .../luci-upnp/luasrc/i18n/upnp.en.lua | 7 + .../luci-upnp/luasrc/i18n/upnp.en.xml | 12 + .../luci-upnp/luasrc/i18n/upnp.pt-br.lua | 7 + .../luci-upnp/luasrc/i18n/upnp.pt-br.xml | 12 + .../luci-upnp/luasrc/model/cbi/upnp/upnp.lua | 38 + .../luasrc/model/cbi/upnp/upnpmini.lua | 36 + .../luci-upnp/root/etc/uci-defaults/luci-upnp | 3 + .../root/lib/uci/schema/default/upnpd | 28 + .../luci/applications/luci-ushare/Makefile | 2 + .../applications/luci-ushare/ipkg/postinst | 4 + .../luci-ushare/luasrc/controller/ushare.lua | 28 + .../luci-ushare/luasrc/i18n/ushare.de.lua | 8 + .../luci-ushare/luasrc/i18n/ushare.de.xml | 14 + .../luci-ushare/luasrc/i18n/ushare.en.lua | 8 + .../luci-ushare/luasrc/i18n/ushare.en.xml | 14 + .../luci-ushare/luasrc/i18n/ushare.pt-br.lua | 8 + .../luci-ushare/luasrc/i18n/ushare.pt-br.xml | 14 + .../luci-ushare/luasrc/model/cbi/ushare.lua | 42 + .../root/etc/uci-defaults/luci-ushare | 7 + .../applications/luci-uvc_streamer/Makefile | 2 + .../luci-uvc_streamer/ipkg/postinst | 4 + .../luasrc/controller/uvc_streamer.lua | 28 + .../luasrc/i18n/uvc_streamer.de.lua | 5 + .../luasrc/i18n/uvc_streamer.de.xml | 11 + .../luasrc/i18n/uvc_streamer.en.lua | 5 + .../luasrc/i18n/uvc_streamer.en.xml | 11 + .../luasrc/i18n/uvc_streamer.fr.lua | 5 + .../luasrc/i18n/uvc_streamer.fr.xml | 11 + .../luasrc/i18n/uvc_streamer.pt-br.lua | 5 + .../luasrc/i18n/uvc_streamer.pt-br.xml | 11 + .../luasrc/model/cbi/uvc_streamer.lua | 47 + .../root/etc/uci-defaults/luci-uvc_streamer | 7 + .../root/lib/uci/schema/default/uvc-streamer | 41 + .../luci/applications/myapplication/Makefile | 2 + openwrt/packages/luci/build/cbi2uvl.lua | 135 + openwrt/packages/luci/build/config.mk | 16 + openwrt/packages/luci/build/gccconfig.mk | 22 + openwrt/packages/luci/build/hostenv.sh | 7 + .../packages/luci/build/i18n-lua-xhtml1.xsl | 238 + openwrt/packages/luci/build/i18n-lua2xml.lua | 22 + openwrt/packages/luci/build/i18n-xml2lua.sh | 38 + openwrt/packages/luci/build/makedocs.sh | 2 + openwrt/packages/luci/build/mkversion.sh | 21 + openwrt/packages/luci/build/module.mk | 42 + openwrt/packages/luci/build/uvl2cbi.lua | 88 + openwrt/packages/luci/build/uvl2i18n.lua | 33 + openwrt/packages/luci/build/uvldoc | 24 + openwrt/packages/luci/build/zoneinfo2lua.pl | 138 + openwrt/packages/luci/contrib/axtls/Makefile | 62 + .../luci/contrib/axtls/files/axtls-config | 116 + .../luci/contrib/axtls/files/axtls-config.h | 117 + .../contrib/axtls/patches/001-ld-fix.patch | 12 + .../contrib/axtls/patches/002-httpd-fix.patch | 12 + .../axtls/patches/003-content-type.patch | 37 + .../axtls/patches/004-cgi-nph-mode.patch | 20 + .../packages/luci/contrib/bitlib/.gitignore | 1 + openwrt/packages/luci/contrib/bitlib/Makefile | 36 + openwrt/packages/luci/contrib/lpeg/.gitignore | 1 + openwrt/packages/luci/contrib/lpeg/Makefile | 33 + .../packages/luci/contrib/luacurses/Makefile | 10 + .../luci/contrib/luacurses/doc/curses.pdf | Bin 0 -> 39485 bytes .../luci/contrib/luacurses/doc/curses.ps.gz | Bin 0 -> 36118 bytes .../luci/contrib/luacurses/src/curses.c | 3630 +++++++++++++ .../luci/contrib/luacurses/src/luacurses.c | 137 + .../luci/contrib/luacurses/src/luacurses.h | 38 + .../luci/contrib/luacurses/test/filter.lua | 49 + .../luci/contrib/luacurses/test/getnstr.lua | 12 + .../luci/contrib/luacurses/test/getyx.lua | 13 + .../luci/contrib/luacurses/test/hello.lua | 20 + .../luci/contrib/luacurses/test/mouse.lua | 54 + .../luci/contrib/luacurses/test/pair.lua | 18 + .../luci/contrib/luacurses/test/rain.lua | 89 + openwrt/packages/luci/contrib/luadoc/Makefile | 2 + .../luci/contrib/luadoc/hostfiles/bin/luadoc | 121 + .../luci/contrib/luadoc/lua/luadoc/config.lua | 34 + .../luadoc/lua/luadoc/doclet/debug.lua | 46 + .../luadoc/lua/luadoc/doclet/formatter.lua | 84 + .../contrib/luadoc/lua/luadoc/doclet/html.lua | 275 + .../luadoc/lua/luadoc/doclet/html/constant.lp | 28 + .../luadoc/lua/luadoc/doclet/html/file.lp | 112 + .../luadoc/lua/luadoc/doclet/html/function.lp | 64 + .../luadoc/lua/luadoc/doclet/html/index.lp | 67 + .../luadoc/lua/luadoc/doclet/html/luadoc.css | 286 + .../luadoc/lua/luadoc/doclet/html/menu.lp | 55 + .../luadoc/lua/luadoc/doclet/html/module.lp | 120 + .../luadoc/lua/luadoc/doclet/html/table.lp | 15 + .../contrib/luadoc/lua/luadoc/doclet/raw.lua | 12 + .../luci/contrib/luadoc/lua/luadoc/init.lua | 50 + .../luci/contrib/luadoc/lua/luadoc/lp.lua | 130 + .../luadoc/lua/luadoc/taglet/standard.lua | 565 ++ .../lua/luadoc/taglet/standard/tags.lua | 178 + .../luci/contrib/luadoc/lua/luadoc/util.lua | 201 + .../packages/luci/contrib/luaposix/.gitignore | 3 + .../packages/luci/contrib/luaposix/Makefile | 35 + .../luci/contrib/luasocket/.gitignore | 1 + .../packages/luci/contrib/luasocket/Makefile | 32 + .../packages/luci/contrib/package/Makefile | 2 + .../luci/contrib/package/lpeg/Makefile | 42 + .../luci/contrib/package/luasocket/Makefile | 40 + .../luci/contrib/package/luaxyssl/Makefile | 43 + .../luaxyssl/patches/100-compile-fixes.patch | 273 + .../luci/contrib/package/luci/Makefile | 956 ++++ .../luci/contrib/package/olsrd-luci/Makefile | 210 + .../package/olsrd-luci/files/etc/config/olsrd | 22 + .../olsrd-luci/files/etc/default/olsrd | 8 + .../package/olsrd-luci/files/etc/init.d/olsrd | 575 ++ .../contrib/package/olsrd-luci/ipkg/postinst | 5 + .../olsrd-luci/patches/100-olsrd-hg-r3.patch | 500 ++ .../patches/131-olsrd-tweak-ffetx.patch | 13 + .../patches/137-olsrd-192.168.1.1.patch | 11 + .../patches/139-olsrd-magicarprefresh.patch | 45 + .../patches/140-olsrd-optimize-size.patch | 2139 ++++++++ .../luci/contrib/package/xrelayd/Makefile | 59 + openwrt/packages/luci/contrib/uci/.gitignore | 4 + openwrt/packages/luci/contrib/uci/Makefile | 41 + .../luci/contrib/uci/hostfiles/bin/uci | 2 + .../contrib/uci/hostfiles/bin/uci-defaults | 7 + .../contrib/uci/hostfiles/etc/config/batmand | 10 + .../contrib/uci/hostfiles/etc/config/ddns | 85 + .../contrib/uci/hostfiles/etc/config/dhcp | 23 + .../contrib/uci/hostfiles/etc/config/dropbear | 3 + .../contrib/uci/hostfiles/etc/config/firewall | 80 + .../contrib/uci/hostfiles/etc/config/fstab | 10 + .../contrib/uci/hostfiles/etc/config/httpd | 5 + .../contrib/uci/hostfiles/etc/config/network | 27 + .../uci/hostfiles/etc/config/ntpclient | 22 + .../luci/contrib/uci/hostfiles/etc/config/qos | 89 + .../contrib/uci/hostfiles/etc/config/system | 3 + .../contrib/uci/hostfiles/etc/config/upnpd | 4 + .../contrib/uci/hostfiles/etc/config/wireless | 13 + openwrt/packages/luci/host/bin/luadoc | 121 + openwrt/packages/luci/host/bin/uci | 2 + openwrt/packages/luci/host/bin/uci-defaults | 7 + openwrt/packages/luci/host/etc/boa/boa.conf | 17 + openwrt/packages/luci/host/etc/config/batmand | 10 + openwrt/packages/luci/host/etc/config/ddns | 85 + openwrt/packages/luci/host/etc/config/dhcp | 23 + .../packages/luci/host/etc/config/dropbear | 3 + .../packages/luci/host/etc/config/firewall | 80 + .../packages/luci/host/etc/config/freifunk | 126 + .../luci/host/etc/config/freifunk_augsburg | 2 + .../luci/host/etc/config/freifunk_berlin | 2 + .../luci/host/etc/config/freifunk_hannover | 5 + openwrt/packages/luci/host/etc/config/fstab | 10 + openwrt/packages/luci/host/etc/config/httpd | 5 + openwrt/packages/luci/host/etc/config/luci | 43 + .../packages/luci/host/etc/config/luci_ethers | 1 + .../packages/luci/host/etc/config/luci_hosts | 1 + .../packages/luci/host/etc/config/luci_splash | 2 + .../luci/host/etc/config/luci_statistics | 132 + .../packages/luci/host/etc/config/lucittpd | 6 + openwrt/packages/luci/host/etc/config/network | 27 + .../packages/luci/host/etc/config/ntpclient | 22 + openwrt/packages/luci/host/etc/config/qos | 89 + openwrt/packages/luci/host/etc/config/siit | 10 + openwrt/packages/luci/host/etc/config/system | 3 + .../packages/luci/host/etc/config/ucitrack | 81 + openwrt/packages/luci/host/etc/config/upnpd | 4 + .../packages/luci/host/etc/config/wireless | 13 + .../luci/host/etc/cron.minutely/luci_splash | 2 + .../packages/luci/host/etc/firewall.freifunk | 53 + .../etc/hotplug.d/iface/22-firewall-nat-fix | 61 + openwrt/packages/luci/host/etc/init.d/boa | 57 + .../packages/luci/host/etc/init.d/freifunk | 24 + .../packages/luci/host/etc/init.d/luci_ethers | 37 + .../luci/host/etc/init.d/luci_fixtime | 11 + .../packages/luci/host/etc/init.d/luci_hosts | 36 + .../packages/luci/host/etc/init.d/luci_splash | 87 + .../luci/host/etc/init.d/luci_statistics | 31 + .../packages/luci/host/etc/init.d/lucittpd | 44 + openwrt/packages/luci/host/etc/lpk.conf | 1 + openwrt/packages/luci/host/etc/mime.types | 748 +++ openwrt/packages/luci/host/etc/rc.local | 2 + .../luci/host/lib/uci/schema/default/ddns | 147 + .../luci/host/lib/uci/schema/default/dhcp | 240 + .../luci/host/lib/uci/schema/default/dropbear | 24 + .../luci/host/lib/uci/schema/default/firewall | 255 + .../luci/host/lib/uci/schema/default/fstab | 54 + .../luci/host/lib/uci/schema/default/httpd | 37 + .../host/lib/uci/schema/default/luci_hosts | 21 + .../host/lib/uci/schema/default/luci_splash | 14 + .../luci/host/lib/uci/schema/default/network | 495 ++ .../host/lib/uci/schema/default/ntpclient | 53 + .../luci/host/lib/uci/schema/default/qos | 200 + .../luci/host/lib/uci/schema/default/samba | 76 + .../luci/host/lib/uci/schema/default/system | 103 + .../luci/host/lib/uci/schema/default/upnpd | 28 + .../host/lib/uci/schema/default/uvc-streamer | 41 + .../luci/host/lib/uci/schema/default/wireless | 523 ++ .../luci/host/lib/uci/schema/meta/schema | 403 ++ openwrt/packages/luci/host/luci | 1 + openwrt/packages/luci/host/sbin/luci-flash | 89 + openwrt/packages/luci/host/sbin/luci-reload | 34 + openwrt/packages/luci/host/tmp/.uci/luci | 0 openwrt/packages/luci/host/usr/bin/boa | Bin 0 -> 82281 bytes .../packages/luci/host/usr/bin/boa_indexer | Bin 0 -> 11434 bytes openwrt/packages/luci/host/usr/bin/lpk | 2 + .../packages/luci/host/usr/bin/luci-splashd | 38 + openwrt/packages/luci/host/usr/bin/lucittpd | Bin 0 -> 24930 bytes .../packages/luci/host/usr/bin/stat-genconfig | 381 ++ openwrt/packages/luci/host/usr/bin/uci | Bin 0 -> 16410 bytes openwrt/packages/luci/host/usr/bin/uvl | 241 + openwrt/packages/luci/host/usr/bin/uvlc | 22 + openwrt/packages/luci/host/usr/include/uci.h | 545 ++ .../luci/host/usr/include/uci_config.h | 3 + .../packages/luci/host/usr/include/uci_list.h | 601 +++ .../packages/luci/host/usr/include/ucimap.h | 125 + .../packages/luci/host/usr/lib/boa/luci.lua | 66 + .../packages/luci/host/usr/lib/lua/ltn12.lua | 292 + .../luci/host/usr/lib/lua/luadoc/config.lua | 34 + .../host/usr/lib/lua/luadoc/doclet/debug.lua | 46 + .../usr/lib/lua/luadoc/doclet/formatter.lua | 84 + .../host/usr/lib/lua/luadoc/doclet/html.lua | 275 + .../lib/lua/luadoc/doclet/html/constant.lp | 28 + .../usr/lib/lua/luadoc/doclet/html/file.lp | 112 + .../lib/lua/luadoc/doclet/html/function.lp | 64 + .../usr/lib/lua/luadoc/doclet/html/index.lp | 67 + .../usr/lib/lua/luadoc/doclet/html/luadoc.css | 286 + .../usr/lib/lua/luadoc/doclet/html/menu.lp | 55 + .../usr/lib/lua/luadoc/doclet/html/module.lp | 120 + .../usr/lib/lua/luadoc/doclet/html/table.lp | 15 + .../host/usr/lib/lua/luadoc/doclet/raw.lua | 12 + .../luci/host/usr/lib/lua/luadoc/init.lua | 50 + .../luci/host/usr/lib/lua/luadoc/lp.lua | 130 + .../usr/lib/lua/luadoc/taglet/standard.lua | 565 ++ .../lib/lua/luadoc/taglet/standard/tags.lua | 178 + .../luci/host/usr/lib/lua/luadoc/util.lua | 201 + .../host/usr/lib/lua/luci/cacheloader.lua | 23 + .../luci/host/usr/lib/lua/luci/cbi.lua | 1621 ++++++ .../luci/host/usr/lib/lua/luci/ccache.lua | 86 + .../luci/host/usr/lib/lua/luci/config.lua | 42 + .../lua/luci/controller/admin/filebrowser.lua | 20 + .../lib/lua/luci/controller/admin/index.lua | 67 + .../lib/lua/luci/controller/admin/network.lua | 97 + .../lua/luci/controller/admin/services.lua | 54 + .../lib/lua/luci/controller/admin/status.lua | 33 + .../lib/lua/luci/controller/admin/system.lua | 235 + .../usr/lib/lua/luci/controller/admin/uci.lua | 90 + .../host/usr/lib/lua/luci/controller/ddns.lua | 32 + .../usr/lib/lua/luci/controller/ffwizard.lua | 21 + .../lua/luci/controller/freifunk/freifunk.lua | 192 + .../usr/lib/lua/luci/controller/hd_idle.lua | 28 + .../host/usr/lib/lua/luci/controller/init.lua | 29 + .../usr/lib/lua/luci/controller/livestats.lua | 29 + .../lua/luci/controller/luci_fw/luci_fw.lua | 13 + .../luci_statistics/luci_statistics.lua | 198 + .../lib/lua/luci/controller/mini/index.lua | 53 + .../lib/lua/luci/controller/mini/network.lua | 26 + .../lib/lua/luci/controller/mini/system.lua | 130 + .../lib/lua/luci/controller/mmc_over_gpio.lua | 28 + .../host/usr/lib/lua/luci/controller/ntpc.lua | 32 + .../host/usr/lib/lua/luci/controller/olsr.lua | 225 + .../usr/lib/lua/luci/controller/p910nd.lua | 28 + .../usr/lib/lua/luci/controller/polipo.lua | 28 + .../host/usr/lib/lua/luci/controller/qos.lua | 29 + .../host/usr/lib/lua/luci/controller/rpc.lua | 179 + .../usr/lib/lua/luci/controller/samba.lua | 27 + .../lib/lua/luci/controller/siitwizard.lua | 21 + .../lib/lua/luci/controller/splash/splash.lua | 29 + .../usr/lib/lua/luci/controller/tinyproxy.lua | 25 + .../host/usr/lib/lua/luci/controller/upnp.lua | 30 + .../usr/lib/lua/luci/controller/ushare.lua | 28 + .../lib/lua/luci/controller/uvc_streamer.lua | 28 + .../luci/host/usr/lib/lua/luci/debug.lua | 25 + .../luci/host/usr/lib/lua/luci/dispatcher.lua | 720 +++ .../luci/host/usr/lib/lua/luci/fs.lua | 270 + .../luci/host/usr/lib/lua/luci/http.lua | 293 + .../host/usr/lib/lua/luci/http/protocol.lua | 690 +++ .../lua/luci/http/protocol/conditionals.lua | 154 + .../usr/lib/lua/luci/http/protocol/date.lua | 115 + .../usr/lib/lua/luci/http/protocol/mime.lua | 98 + .../luci/host/usr/lib/lua/luci/httpd.lua | 126 + .../usr/lib/lua/luci/httpd/handler/file.lua | 199 + .../usr/lib/lua/luci/httpd/handler/luci.lua | 96 + .../host/usr/lib/lua/luci/httpd/module.lua | 136 + .../host/usr/lib/lua/luci/httpd/server.lua | 241 + .../luci/host/usr/lib/lua/luci/i18n.lua | 98 + .../usr/lib/lua/luci/i18n/admin-core.de.lua | 346 ++ .../usr/lib/lua/luci/i18n/admin-core.en.lua | 329 ++ .../usr/lib/lua/luci/i18n/admin-core.fr.lua | 327 ++ .../usr/lib/lua/luci/i18n/admin-core.it.lua | 327 ++ .../lib/lua/luci/i18n/admin-core.pt-br.lua | 327 ++ .../usr/lib/lua/luci/i18n/admin-core.ru.lua | 269 + .../host/usr/lib/lua/luci/i18n/cbi.de.lua | 16 + .../host/usr/lib/lua/luci/i18n/cbi.en.lua | 17 + .../host/usr/lib/lua/luci/i18n/cbi.fr.lua | 17 + .../host/usr/lib/lua/luci/i18n/cbi.it.lua | 17 + .../host/usr/lib/lua/luci/i18n/cbi.pt-br.lua | 17 + .../host/usr/lib/lua/luci/i18n/cbi.ru.lua | 10 + .../host/usr/lib/lua/luci/i18n/ddns.de.lua | 8 + .../host/usr/lib/lua/luci/i18n/ddns.en.lua | 8 + .../host/usr/lib/lua/luci/i18n/ddns.fr.lua | 8 + .../host/usr/lib/lua/luci/i18n/ddns.pt-br.lua | 8 + .../host/usr/lib/lua/luci/i18n/default.de.lua | 102 + .../host/usr/lib/lua/luci/i18n/default.en.lua | 102 + .../host/usr/lib/lua/luci/i18n/default.fr.lua | 99 + .../host/usr/lib/lua/luci/i18n/default.it.lua | 102 + .../usr/lib/lua/luci/i18n/default.pt-br.lua | 103 + .../host/usr/lib/lua/luci/i18n/default.ru.lua | 95 + .../usr/lib/lua/luci/i18n/freifunk.de.lua | 21 + .../usr/lib/lua/luci/i18n/freifunk.en.lua | 21 + .../host/usr/lib/lua/luci/i18n/hd_idle.de.lua | 7 + .../host/usr/lib/lua/luci/i18n/hd_idle.en.lua | 7 + .../usr/lib/lua/luci/i18n/hd_idle.pt-br.lua | 7 + .../host/usr/lib/lua/luci/i18n/initmgr.de.lua | 5 + .../host/usr/lib/lua/luci/i18n/initmgr.en.lua | 5 + .../usr/lib/lua/luci/i18n/initmgr.pt-br.lua | 5 + .../usr/lib/lua/luci/i18n/livestats.de.lua | 8 + .../usr/lib/lua/luci/i18n/livestats.en.lua | 8 + .../host/usr/lib/lua/luci/i18n/luci-fw.de.lua | 56 + .../host/usr/lib/lua/luci/i18n/luci-fw.en.lua | 56 + .../host/usr/lib/lua/luci/i18n/luci-fw.fr.lua | 56 + .../usr/lib/lua/luci/i18n/luci-fw.pt-br.lua | 56 + .../lib/lua/luci/i18n/mmc_over_gpio.de.lua | 3 + .../lib/lua/luci/i18n/mmc_over_gpio.en.lua | 3 + .../lib/lua/luci/i18n/mmc_over_gpio.pt-br.lua | 3 + .../host/usr/lib/lua/luci/i18n/ntpc.de.lua | 9 + .../host/usr/lib/lua/luci/i18n/ntpc.en.lua | 9 + .../host/usr/lib/lua/luci/i18n/ntpc.pt-br.lua | 9 + .../host/usr/lib/lua/luci/i18n/olsr.de.lua | 127 + .../host/usr/lib/lua/luci/i18n/olsr.en.lua | 127 + .../host/usr/lib/lua/luci/i18n/p910nd.de.lua | 4 + .../host/usr/lib/lua/luci/i18n/p910nd.en.lua | 4 + .../usr/lib/lua/luci/i18n/p910nd.pt-br.lua | 4 + .../host/usr/lib/lua/luci/i18n/polipo.en.lua | 43 + .../host/usr/lib/lua/luci/i18n/qos.de.lua | 17 + .../host/usr/lib/lua/luci/i18n/qos.en.lua | 18 + .../host/usr/lib/lua/luci/i18n/qos.fr.lua | 17 + .../host/usr/lib/lua/luci/i18n/qos.pt-br.lua | 17 + .../host/usr/lib/lua/luci/i18n/rrdtool.de.lua | 70 + .../usr/lib/lua/luci/i18n/rrdtool.de.xml.hide | 96 + .../host/usr/lib/lua/luci/i18n/rrdtool.en.lua | 69 + .../usr/lib/lua/luci/i18n/rrdtool.en.xml.hide | 95 + .../usr/lib/lua/luci/i18n/rrdtool.pt-br.lua | 69 + .../lib/lua/luci/i18n/rrdtool.pt-br.xml.hide | 95 + .../host/usr/lib/lua/luci/i18n/samba.de.lua | 17 + .../host/usr/lib/lua/luci/i18n/samba.en.lua | 17 + .../usr/lib/lua/luci/i18n/samba.pt-br.lua | 17 + .../usr/lib/lua/luci/i18n/statistics.de.lua | 212 + .../usr/lib/lua/luci/i18n/statistics.en.lua | 212 + .../lib/lua/luci/i18n/statistics.pt-br.lua | 212 + .../host/usr/lib/lua/luci/i18n/sysauth.de.lua | 3 + .../host/usr/lib/lua/luci/i18n/sysauth.en.lua | 3 + .../host/usr/lib/lua/luci/i18n/sysauth.fr.lua | 3 + .../host/usr/lib/lua/luci/i18n/sysauth.it.lua | 3 + .../usr/lib/lua/luci/i18n/sysauth.pt-br.lua | 3 + .../host/usr/lib/lua/luci/i18n/sysauth.ru.lua | 3 + .../usr/lib/lua/luci/i18n/tinyproxy.de.lua | 32 + .../usr/lib/lua/luci/i18n/tinyproxy.en.lua | 32 + .../usr/lib/lua/luci/i18n/tinyproxy.fr.lua | 34 + .../usr/lib/lua/luci/i18n/tinyproxy.pt-br.lua | 34 + .../host/usr/lib/lua/luci/i18n/upnp.de.lua | 7 + .../host/usr/lib/lua/luci/i18n/upnp.en.lua | 7 + .../host/usr/lib/lua/luci/i18n/upnp.pt-br.lua | 7 + .../host/usr/lib/lua/luci/i18n/ushare.de.lua | 8 + .../host/usr/lib/lua/luci/i18n/ushare.en.lua | 8 + .../usr/lib/lua/luci/i18n/ushare.pt-br.lua | 8 + .../usr/lib/lua/luci/i18n/uvc_streamer.de.lua | 5 + .../usr/lib/lua/luci/i18n/uvc_streamer.en.lua | 5 + .../usr/lib/lua/luci/i18n/uvc_streamer.fr.lua | 5 + .../lib/lua/luci/i18n/uvc_streamer.pt-br.lua | 5 + .../host/usr/lib/lua/luci/i18n/uvl.de.lua | 39 + .../host/usr/lib/lua/luci/i18n/uvl.en.lua | 39 + .../host/usr/lib/lua/luci/i18n/uvl.pt-br.lua | 39 + .../host/usr/lib/lua/luci/i18n/wifi.de.lua | 37 + .../host/usr/lib/lua/luci/i18n/wifi.en.lua | 38 + .../host/usr/lib/lua/luci/i18n/wifi.it.lua | 37 + .../host/usr/lib/lua/luci/i18n/wifi.pt-br.lua | 37 + .../luci/host/usr/lib/lua/luci/init.lua | 34 + .../luci/host/usr/lib/lua/luci/ip.lua | 632 +++ .../luci/host/usr/lib/lua/luci/json.lua | 538 ++ .../luci/host/usr/lib/lua/luci/jsonrpc.lua | 94 + .../host/usr/lib/lua/luci/jsonrpcbind/uci.lua | 94 + .../host/usr/lib/lua/luci/jsonrpcbind/uvl.lua | 41 + .../luci/host/usr/lib/lua/luci/lpk.lua | 41 + .../luci/host/usr/lib/lua/luci/lpk/core.lua | 107 + .../usr/lib/lua/luci/lpk/core/download.lua | 1 + .../usr/lib/lua/luci/lpk/core/install.lua | 16 + .../usr/lib/lua/luci/lpk/core/resolve.lua | 0 .../usr/lib/lua/luci/lpk/core/retrieve.lua | 7 + .../host/usr/lib/lua/luci/lpk/core/unpack.lua | 0 .../luci/host/usr/lib/lua/luci/lpk/util.lua | 59 + .../luci/host/usr/lib/lua/luci/ltn12.lua | 391 ++ .../lua/luci/model/cbi/admin_index/luci.lua | 52 + .../model/cbi/admin_network/conntrack.lua | 49 + .../lua/luci/model/cbi/admin_network/dhcp.lua | 72 + .../model/cbi/admin_network/dhcpleases.lua | 61 + .../luci/model/cbi/admin_network/hosts.lua | 33 + .../luci/model/cbi/admin_network/ifaces.lua | 343 ++ .../luci/model/cbi/admin_network/network.lua | 128 + .../luci/model/cbi/admin_network/routes.lua | 120 + .../lua/luci/model/cbi/admin_network/vlan.lua | 22 + .../lua/luci/model/cbi/admin_network/wifi.lua | 373 ++ .../luci/model/cbi/admin_network/wireless.lua | 134 + .../luci/model/cbi/admin_services/crontab.lua | 35 + .../luci/model/cbi/admin_services/dnsmasq.lua | 45 + .../model/cbi/admin_services/dropbear.lua | 27 + .../luci/model/cbi/admin_services/httpd.lua | 31 + .../model/cbi/admin_services/lucittpd.lua | 25 + .../luci/model/cbi/admin_system/buttons.lua | 31 + .../lua/luci/model/cbi/admin_system/fstab.lua | 86 + .../lua/luci/model/cbi/admin_system/ipkg.lua | 35 + .../lua/luci/model/cbi/admin_system/leds.lua | 86 + .../luci/model/cbi/admin_system/passwd.lua | 45 + .../luci/model/cbi/admin_system/processes.lua | 44 + .../luci/model/cbi/admin_system/sshkeys.lua | 35 + .../luci/model/cbi/admin_system/system.lua | 73 + .../usr/lib/lua/luci/model/cbi/ddns/ddns.lua | 74 + .../lib/lua/luci/model/cbi/ddns/ddnsmini.lua | 52 + .../usr/lib/lua/luci/model/cbi/ffwizard.lua | 391 ++ .../lua/luci/model/cbi/freifunk/contact.lua | 34 + .../lua/luci/model/cbi/freifunk/freifunk.lua | 24 + .../luci/model/cbi/freifunk/public_status.lua | 216 + .../usr/lib/lua/luci/model/cbi/hd_idle.lua | 41 + .../usr/lib/lua/luci/model/cbi/init/init.lua | 58 + .../lua/luci/model/cbi/luci_fw/miniportfw.lua | 45 + .../lua/luci/model/cbi/luci_fw/redirect.lua | 50 + .../lib/lua/luci/model/cbi/luci_fw/rrule.lua | 69 + .../lua/luci/model/cbi/luci_fw/traffic.lua | 82 + .../lib/lua/luci/model/cbi/luci_fw/trule.lua | 72 + .../lib/lua/luci/model/cbi/luci_fw/zones.lua | 71 + .../model/cbi/luci_statistics/collectd.lua | 74 + .../luci/model/cbi/luci_statistics/cpu.lua | 25 + .../luci/model/cbi/luci_statistics/csv.lua | 36 + .../lua/luci/model/cbi/luci_statistics/df.lua | 48 + .../luci/model/cbi/luci_statistics/disk.lua | 36 + .../luci/model/cbi/luci_statistics/dns.lua | 43 + .../luci/model/cbi/luci_statistics/email.lua | 52 + .../luci/model/cbi/luci_statistics/exec.lua | 70 + .../model/cbi/luci_statistics/interface.lua | 42 + .../model/cbi/luci_statistics/iptables.lua | 116 + .../luci/model/cbi/luci_statistics/irq.lua | 36 + .../luci/model/cbi/luci_statistics/load.lua | 25 + .../model/cbi/luci_statistics/netlink.lua | 90 + .../model/cbi/luci_statistics/network.lua | 79 + .../luci/model/cbi/luci_statistics/ping.lua | 36 + .../model/cbi/luci_statistics/processes.lua | 30 + .../model/cbi/luci_statistics/rrdtool.lua | 94 + .../model/cbi/luci_statistics/tcpconns.lua | 40 + .../model/cbi/luci_statistics/unixsock.lua | 44 + .../model/cbi/luci_statistics/wireless.lua | 25 + .../usr/lib/lua/luci/model/cbi/mini/dhcp.lua | 105 + .../usr/lib/lua/luci/model/cbi/mini/index.lua | 14 + .../usr/lib/lua/luci/model/cbi/mini/luci.lua | 37 + .../lib/lua/luci/model/cbi/mini/network.lua | 196 + .../lib/lua/luci/model/cbi/mini/passwd.lua | 45 + .../lib/lua/luci/model/cbi/mini/system.lua | 55 + .../usr/lib/lua/luci/model/cbi/mini/wifi.lua | 277 + .../lib/lua/luci/model/cbi/mmc_over_gpio.lua | 41 + .../usr/lib/lua/luci/model/cbi/ntpc/ntpc.lua | 39 + .../lib/lua/luci/model/cbi/ntpc/ntpcmini.lua | 34 + .../usr/lib/lua/luci/model/cbi/olsr/olsrd.lua | 145 + .../lib/lua/luci/model/cbi/olsr/olsrdhna.lua | 36 + .../lua/luci/model/cbi/olsr/olsrdplugins.lua | 244 + .../usr/lib/lua/luci/model/cbi/p910nd.lua | 33 + .../usr/lib/lua/luci/model/cbi/polipo.lua | 67 + .../usr/lib/lua/luci/model/cbi/qos/qos.lua | 89 + .../lib/lua/luci/model/cbi/qos/qosmini.lua | 82 + .../host/usr/lib/lua/luci/model/cbi/samba.lua | 56 + .../usr/lib/lua/luci/model/cbi/siitwizard.lua | 338 ++ .../lib/lua/luci/model/cbi/splash/splash.lua | 47 + .../usr/lib/lua/luci/model/cbi/tinyproxy.lua | 80 + .../usr/lib/lua/luci/model/cbi/upnp/upnp.lua | 38 + .../lib/lua/luci/model/cbi/upnp/upnpmini.lua | 36 + .../usr/lib/lua/luci/model/cbi/ushare.lua | 42 + .../lib/lua/luci/model/cbi/uvc_streamer.lua | 47 + .../luci/host/usr/lib/lua/luci/model/ipkg.lua | 150 + .../luci/host/usr/lib/lua/luci/model/uci.lua | 333 ++ .../luci/host/usr/lib/lua/luci/sauth.lua | 106 + .../luci/host/usr/lib/lua/luci/sgi/cgi.lua | 90 + .../luci/host/usr/lib/lua/luci/sgi/webuci.lua | 74 + .../luci/host/usr/lib/lua/luci/sgi/wsapi.lua | 79 + .../usr/lib/lua/luci/statistics/datatree.lua | 181 + .../host/usr/lib/lua/luci/statistics/i18n.lua | 115 + .../usr/lib/lua/luci/statistics/rrdtool.lua | 607 +++ .../lua/luci/statistics/rrdtool/colors.lua | 73 + .../luci/statistics/rrdtool/definitions.lua | 1123 ++++ .../rrdtool/definitions/cpu/cpu.lua | 38 + .../statistics/rrdtool/definitions/df/df.lua | 41 + .../rrdtool/definitions/interface.lua | 107 + .../definitions/iptables/ipt_bytes.lua | 27 + .../definitions/iptables/ipt_packets.lua | 27 + .../rrdtool/definitions/irq/irq.lua | 25 + .../rrdtool/definitions/load/load.lua | 33 + .../rrdtool/definitions/netlink.lua | 193 + .../rrdtool/definitions/ping/ping.lua | 27 + .../rrdtool/definitions/processes.lua | 101 + .../definitions/tcpconns/tcp_connections.lua | 31 + .../rrdtool/definitions/wireless.lua | 71 + .../luci/host/usr/lib/lua/luci/sys.lua | 782 +++ .../host/usr/lib/lua/luci/sys/iptparser.lua | 244 + .../host/usr/lib/lua/luci/sys/zoneinfo.lua | 572 ++ .../luci/host/usr/lib/lua/luci/template.lua | 239 + .../host/usr/lib/lua/luci/tools/ffwizard.lua | 149 + .../host/usr/lib/lua/luci/tools/webadmin.lua | 173 + .../usr/lib/lua/luci/ttpd/handler/file.lua | 252 + .../usr/lib/lua/luci/ttpd/handler/luci.lua | 92 + .../host/usr/lib/lua/luci/ttpd/module.lua | 121 + .../host/usr/lib/lua/luci/ttpd/server.lua | 444 ++ .../luci/host/usr/lib/lua/luci/util.lua | 787 +++ .../luci/host/usr/lib/lua/luci/uvl.lua | 1209 +++++ .../host/usr/lib/lua/luci/uvl/datatypes.lua | 187 + .../usr/lib/lua/luci/uvl/dependencies.lua | 196 + .../luci/host/usr/lib/lua/luci/uvl/errors.lua | 204 + .../host/usr/lib/lua/luci/uvl/validation.lua | 72 + .../lua/luci/uvldoc/proto/xhtml/footer.xml | 11 + .../lua/luci/uvldoc/proto/xhtml/header.xml | 15 + .../lib/lua/luci/uvldoc/proto/xhtml/index.xml | 12 + .../lib/lua/luci/uvldoc/proto/xhtml/menu.xml | 22 + .../lua/luci/uvldoc/proto/xhtml/scheme.xml | 16 + .../lua/luci/uvldoc/proto/xhtml/section.xml | 198 + .../lua/luci/uvldoc/proto/xhtml/uvldoc.css | 135 + .../host/usr/lib/lua/luci/uvldoc/renderer.lua | 124 + .../luci/host/usr/lib/lua/luci/version.lua | 12 + .../luci/host/usr/lib/lua/luci/view/about.htm | 45 + .../lib/lua/luci/view/admin_index/index.htm | 24 + .../lua/luci/view/admin_services/index.htm | 19 + .../lua/luci/view/admin_statistics/index.htm | 22 + .../view/admin_statistics/networkplugins.htm | 32 + .../view/admin_statistics/outputplugins.htm | 33 + .../view/admin_statistics/systemplugins.htm | 29 + .../lib/lua/luci/view/admin_status/dmesg.htm | 20 + .../lib/lua/luci/view/admin_status/index.htm | 19 + .../lib/lua/luci/view/admin_status/syslog.htm | 20 + .../luci/view/admin_system/applyreboot.htm | 21 + .../lib/lua/luci/view/admin_system/backup.htm | 40 + .../lib/lua/luci/view/admin_system/ipkg.htm | 18 + .../lua/luci/view/admin_system/packages.htm | 98 + .../lib/lua/luci/view/admin_system/reboot.htm | 33 + .../lua/luci/view/admin_system/upgrade.htm | 52 + .../usr/lib/lua/luci/view/admin_uci/apply.htm | 42 + .../lib/lua/luci/view/admin_uci/changes.htm | 45 + .../lib/lua/luci/view/admin_uci/revert.htm | 31 + .../usr/lib/lua/luci/view/cbi/browser.htm | 23 + .../host/usr/lib/lua/luci/view/cbi/button.htm | 21 + .../lua/luci/view/cbi/cell_valuefooter.htm | 34 + .../lua/luci/view/cbi/cell_valueheader.htm | 17 + .../host/usr/lib/lua/luci/view/cbi/dvalue.htm | 22 + .../usr/lib/lua/luci/view/cbi/dynlist.htm | 45 + .../usr/lib/lua/luci/view/cbi/filebrowser.htm | 122 + .../host/usr/lib/lua/luci/view/cbi/footer.htm | 26 + .../lua/luci/view/cbi/full_valuefooter.htm | 45 + .../lua/luci/view/cbi/full_valueheader.htm | 24 + .../host/usr/lib/lua/luci/view/cbi/fvalue.htm | 17 + .../host/usr/lib/lua/luci/view/cbi/header.htm | 22 + .../host/usr/lib/lua/luci/view/cbi/lvalue.htm | 32 + .../host/usr/lib/lua/luci/view/cbi/map.htm | 36 + .../host/usr/lib/lua/luci/view/cbi/mvalue.htm | 35 + .../usr/lib/lua/luci/view/cbi/nsection.htm | 45 + .../usr/lib/lua/luci/view/cbi/nullsection.htm | 23 + .../usr/lib/lua/luci/view/cbi/simpleform.htm | 46 + .../usr/lib/lua/luci/view/cbi/tblsection.htm | 135 + .../usr/lib/lua/luci/view/cbi/tsection.htm | 59 + .../host/usr/lib/lua/luci/view/cbi/tvalue.htm | 19 + .../usr/lib/lua/luci/view/cbi/ucisection.htm | 66 + .../host/usr/lib/lua/luci/view/cbi/upload.htm | 28 + .../host/usr/lib/lua/luci/view/cbi/value.htm | 38 + .../usr/lib/lua/luci/view/cbi/valuefooter.htm | 16 + .../usr/lib/lua/luci/view/cbi/valueheader.htm | 16 + .../host/usr/lib/lua/luci/view/error404.htm | 19 + .../host/usr/lib/lua/luci/view/error500.htm | 19 + .../host/usr/lib/lua/luci/view/footer.htm | 15 + .../lib/lua/luci/view/freifunk/contact.htm | 27 + .../usr/lib/lua/luci/view/freifunk/index.htm | 24 + .../host/usr/lib/lua/luci/view/header.htm | 15 + .../host/usr/lib/lua/luci/view/indexer.htm | 15 + .../lib/lua/luci/view/livestats/loadavg.htm | 33 + .../lib/lua/luci/view/livestats/traffic.htm | 66 + .../lib/lua/luci/view/livestats/wireless.htm | 43 + .../lib/lua/luci/view/mini/applyreboot.htm | 21 + .../usr/lib/lua/luci/view/mini/backup.htm | 40 + .../host/usr/lib/lua/luci/view/mini/index.htm | 21 + .../usr/lib/lua/luci/view/mini/reboot.htm | 33 + .../usr/lib/lua/luci/view/mini/upgrade.htm | 52 + .../lua/luci/view/public_statistics/graph.htm | 39 + .../usr/lib/lua/luci/view/splash/splash.htm | 47 + .../lib/lua/luci/view/splash_splash/index.htm | 16 + .../lua/luci/view/splash_splash/splash.htm | 21 + .../lua/luci/view/status-olsr/error_olsr.htm | 19 + .../usr/lib/lua/luci/view/status-olsr/hna.htm | 32 + .../lib/lua/luci/view/status-olsr/index.htm | 57 + .../usr/lib/lua/luci/view/status-olsr/mid.htm | 32 + .../lib/lua/luci/view/status-olsr/routes.htm | 51 + .../lua/luci/view/status-olsr/topology.htm | 39 + .../host/usr/lib/lua/luci/view/sysauth.htm | 49 + .../luci/view/themes/fledermaus/footer.htm | 22 + .../luci/view/themes/fledermaus/header.htm | 180 + .../luci/view/themes/freifunk-bno/footer.htm | 29 + .../luci/view/themes/freifunk-bno/header.htm | 196 + .../lua/luci/view/themes/freifunk/footer.htm | 29 + .../lua/luci/view/themes/freifunk/header.htm | 196 + .../luci/view/themes/openwrt-light/footer.htm | 21 + .../luci/view/themes/openwrt-light/header.htm | 163 + .../themes/openwrt.org-oxygen/dashboard.htm | 46 + .../view/themes/openwrt.org-oxygen/footer.htm | 21 + .../view/themes/openwrt.org-oxygen/header.htm | 166 + .../themes/openwrt.org-oxygen/indexer.htm | 17 + .../luci/view/themes/openwrt.org/footer.htm | 21 + .../luci/view/themes/openwrt.org/header.htm | 163 + .../lua/luci/view/themes/oxygen/dashboard.htm | 46 + .../lua/luci/view/themes/oxygen/footer.htm | 22 + .../lua/luci/view/themes/oxygen/header.htm | 129 + .../lua/luci/view/themes/oxygen/indexer.htm | 17 + .../packages/luci/host/usr/lib/lua/mime.lua | 87 + .../packages/luci/host/usr/lib/lua/socket.lua | 133 + .../luci/host/usr/lib/lua/socket/ftp.lua | 281 + .../luci/host/usr/lib/lua/socket/http.lua | 350 ++ .../luci/host/usr/lib/lua/socket/smtp.lua | 251 + .../luci/host/usr/lib/lua/socket/tp.lua | 123 + .../luci/host/usr/lib/lua/socket/url.lua | 297 + .../host/usr/lib/lucittpd/plugins/httpd.lua | 34 + .../usr/lib/lucittpd/plugins/luci-webui.lua | 29 + .../luci/host/usr/sbin/ff_olsr_test_gw | 41 + .../packages/luci/host/usr/sbin/luci-splash | 190 + .../packages/luci/host/usr/sbin/polipo_purge | 18 + .../packages/luci/host/www/cgi-bin-nodes.html | 10 + .../luci/host/www/cgi-bin-status.html | 10 + openwrt/packages/luci/host/www/cgi-bin/luci | 5 + openwrt/packages/luci/host/www/index.html | 10 + .../www/luci-static/fledermaus/cascade.css | 626 +++ .../www/luci-static/fledermaus/fledermaus.png | Bin 0 -> 7321 bytes .../host/www/luci-static/fledermaus/logo.png | Bin 0 -> 4002 bytes .../www/luci-static/freifunk-bno/cascade.css | 726 +++ .../freifunk-bno/images/bgoption.png | Bin 0 -> 141 bytes .../freifunk-bno/images/favicon.ico | Bin 0 -> 5310 bytes .../freifunk-bno/images/header-back.gif | Bin 0 -> 127 bytes .../freifunk-bno/images/header-left.gif | Bin 0 -> 293 bytes .../freifunk-bno/images/header-right.gif | Bin 0 -> 365 bytes .../luci-static/freifunk-bno/images/logo.gif | Bin 0 -> 2415 bytes .../freifunk-bno/images/main-back.png | Bin 0 -> 404 bytes .../freifunk-bno/images/schriftzug.gif | Bin 0 -> 3606 bytes .../host/www/luci-static/freifunk/cascade.css | 726 +++ .../luci-static/freifunk/images/bgoption.png | Bin 0 -> 141 bytes .../luci-static/freifunk/images/favicon.ico | Bin 0 -> 4286 bytes .../freifunk/images/header-back.gif | Bin 0 -> 127 bytes .../freifunk/images/header-left.gif | Bin 0 -> 293 bytes .../freifunk/images/header-right.gif | Bin 0 -> 365 bytes .../www/luci-static/freifunk/images/logo.png | Bin 0 -> 6400 bytes .../luci-static/freifunk/images/main-back.png | Bin 0 -> 404 bytes .../freifunk/images/schriftzug.png | Bin 0 -> 4487 bytes .../www/luci-static/openwrt-light/cascade.css | 790 +++ .../www/luci-static/openwrt-light/ie6.css | 77 + .../www/luci-static/openwrt-light/ie7.css | 20 + .../www/luci-static/openwrt.org-oxygen/bg.jpg | Bin 0 -> 40537 bytes .../openwrt.org-oxygen/cascade.css | 803 +++ .../openwrt.org-oxygen/dashboard.css | 99 + .../luci-static/openwrt.org-oxygen/header.png | Bin 0 -> 33244 bytes .../openwrt.org-oxygen/icons/COPYING.oxygen | 48 + .../openwrt.org-oxygen/icons/datetime.png | Bin 0 -> 5250 bytes .../openwrt.org-oxygen/icons/default.png | Bin 0 -> 5022 bytes .../openwrt.org-oxygen/icons/desktop.png | Bin 0 -> 6487 bytes .../openwrt.org-oxygen/icons/flash.png | Bin 0 -> 5065 bytes .../openwrt.org-oxygen/icons/freifunk.png | Bin 0 -> 2404 bytes .../openwrt.org-oxygen/icons/harddisk.png | Bin 0 -> 3317 bytes .../openwrt.org-oxygen/icons/key.png | Bin 0 -> 4129 bytes .../openwrt.org-oxygen/icons/lightbulb.png | Bin 0 -> 5550 bytes .../openwrt.org-oxygen/icons/login.png | Bin 0 -> 2918 bytes .../openwrt.org-oxygen/icons/logout.png | Bin 0 -> 3577 bytes .../openwrt.org-oxygen/icons/network.png | Bin 0 -> 6602 bytes .../openwrt.org-oxygen/icons/overview.png | Bin 0 -> 4553 bytes .../openwrt.org-oxygen/icons/package.png | Bin 0 -> 4996 bytes .../openwrt.org-oxygen/icons/restart.png | Bin 0 -> 4081 bytes .../openwrt.org-oxygen/icons/services.png | Bin 0 -> 4630 bytes .../openwrt.org-oxygen/icons/shell.png | Bin 0 -> 2110 bytes .../openwrt.org-oxygen/icons/stats.png | Bin 0 -> 3102 bytes .../openwrt.org-oxygen/icons/status.png | Bin 0 -> 3192 bytes .../openwrt.org-oxygen/icons/switch.png | Bin 0 -> 3940 bytes .../openwrt.org-oxygen/icons/system.png | Bin 0 -> 6296 bytes .../openwrt.org-oxygen/icons/worker.png | Bin 0 -> 4630 bytes .../luci-static/openwrt.org-oxygen/ie6.css | 77 + .../luci-static/openwrt.org-oxygen/ie7.css | 20 + .../host/www/luci-static/openwrt.org/bg.jpg | Bin 0 -> 40537 bytes .../www/luci-static/openwrt.org/cascade.css | 804 +++ .../www/luci-static/openwrt.org/header.png | Bin 0 -> 33244 bytes .../host/www/luci-static/openwrt.org/ie6.css | 77 + .../host/www/luci-static/openwrt.org/ie7.css | 20 + .../luci/host/www/luci-static/oxygen/bg.png | Bin 0 -> 40400 bytes .../host/www/luci-static/oxygen/cascade.css | 660 +++ .../host/www/luci-static/oxygen/dashboard.css | 108 + .../host/www/luci-static/oxygen/flukso.png | Bin 0 -> 1830 bytes .../host/www/luci-static/oxygen/footer.png | Bin 0 -> 61400 bytes .../host/www/luci-static/oxygen/header.png | Bin 0 -> 33244 bytes .../luci-static/oxygen/icons/COPYING.oxygen | 48 + .../www/luci-static/oxygen/icons/datetime.png | Bin 0 -> 5250 bytes .../www/luci-static/oxygen/icons/default.png | Bin 0 -> 5022 bytes .../www/luci-static/oxygen/icons/desktop.png | Bin 0 -> 6487 bytes .../www/luci-static/oxygen/icons/flash.png | Bin 0 -> 5065 bytes .../www/luci-static/oxygen/icons/freifunk.png | Bin 0 -> 2404 bytes .../www/luci-static/oxygen/icons/harddisk.png | Bin 0 -> 3317 bytes .../host/www/luci-static/oxygen/icons/key.png | Bin 0 -> 4129 bytes .../luci-static/oxygen/icons/lightbulb.png | Bin 0 -> 5550 bytes .../www/luci-static/oxygen/icons/login.png | Bin 0 -> 2918 bytes .../www/luci-static/oxygen/icons/logout.png | Bin 0 -> 3577 bytes .../www/luci-static/oxygen/icons/network.png | Bin 0 -> 6602 bytes .../www/luci-static/oxygen/icons/overview.png | Bin 0 -> 4553 bytes .../www/luci-static/oxygen/icons/package.png | Bin 0 -> 4996 bytes .../www/luci-static/oxygen/icons/restart.png | Bin 0 -> 4081 bytes .../www/luci-static/oxygen/icons/services.png | Bin 0 -> 4630 bytes .../www/luci-static/oxygen/icons/shell.png | Bin 0 -> 2110 bytes .../www/luci-static/oxygen/icons/stats.png | Bin 0 -> 3102 bytes .../www/luci-static/oxygen/icons/status.png | Bin 0 -> 3192 bytes .../www/luci-static/oxygen/icons/switch.png | Bin 0 -> 3940 bytes .../www/luci-static/oxygen/icons/system.png | Bin 0 -> 6296 bytes .../www/luci-static/oxygen/icons/wifi.png | Bin 0 -> 7109 bytes .../www/luci-static/oxygen/icons/wireless.png | Bin 0 -> 8431 bytes .../www/luci-static/oxygen/icons/worker.png | Bin 0 -> 4630 bytes .../www/luci-static/resources/Dropdowns.js | 120 + .../host/www/luci-static/resources/VarType.js | 91 + .../host/www/luci-static/resources/XHTML1.js | 271 + .../host/www/luci-static/resources/cbi.js | 221 + .../www/luci-static/resources/cbi/add.gif | Bin 0 -> 378 bytes .../www/luci-static/resources/cbi/apply.gif | Bin 0 -> 268 bytes .../www/luci-static/resources/cbi/arrow.gif | Bin 0 -> 135 bytes .../luci-static/resources/cbi/download.gif | Bin 0 -> 189 bytes .../www/luci-static/resources/cbi/edit.gif | Bin 0 -> 280 bytes .../luci-static/resources/cbi/fieldadd.gif | Bin 0 -> 379 bytes .../www/luci-static/resources/cbi/find.gif | Bin 0 -> 273 bytes .../www/luci-static/resources/cbi/help.gif | Bin 0 -> 266 bytes .../www/luci-static/resources/cbi/key.gif | Bin 0 -> 230 bytes .../www/luci-static/resources/cbi/link.gif | Bin 0 -> 279 bytes .../www/luci-static/resources/cbi/reload.gif | Bin 0 -> 248 bytes .../www/luci-static/resources/cbi/remove.gif | Bin 0 -> 385 bytes .../www/luci-static/resources/cbi/reset.gif | Bin 0 -> 258 bytes .../www/luci-static/resources/cbi/save.gif | Bin 0 -> 263 bytes .../www/luci-static/resources/cbi/user.gif | Bin 0 -> 246 bytes .../resources/livestats/ExCanvas.js | 19 + .../resources/livestats/GraphRPC.js | 204 + .../resources/livestats/JsonRpc.js | 220 + .../luci-static/resources/livestats/Legend.js | 228 + .../resources/livestats/MochiKit.js | 4800 +++++++++++++++++ .../resources/livestats/PlotKit.js | 2177 ++++++++ .../luci/host/www/luci/splash/index.html | 10 + openwrt/packages/luci/i18n/english/Makefile | 2 + .../packages/luci/i18n/english/ipkg/postinst | 4 + .../english/luasrc/i18n/admin-core.en.lua | 329 ++ .../english/luasrc/i18n/admin-core.en.xml | 334 ++ .../luci/i18n/english/luasrc/i18n/cbi.en.lua | 17 + .../luci/i18n/english/luasrc/i18n/cbi.en.xml | 23 + .../i18n/english/luasrc/i18n/default.en.lua | 102 + .../i18n/english/luasrc/i18n/default.en.xml | 109 + .../i18n/english/luasrc/i18n/sysauth.en.lua | 3 + .../i18n/english/luasrc/i18n/sysauth.en.xml | 9 + .../luci/i18n/english/luasrc/i18n/wifi.en.lua | 38 + .../luci/i18n/english/luasrc/i18n/wifi.en.xml | 44 + .../root/etc/uci-defaults/luci-i18n-english | 6 + openwrt/packages/luci/i18n/french/Makefile | 2 + .../packages/luci/i18n/french/ipkg/postinst | 4 + .../i18n/french/luasrc/i18n/admin-core.fr.lua | 327 ++ .../i18n/french/luasrc/i18n/admin-core.fr.xml | 334 ++ .../luci/i18n/french/luasrc/i18n/cbi.fr.lua | 17 + .../luci/i18n/french/luasrc/i18n/cbi.fr.xml | 23 + .../i18n/french/luasrc/i18n/default.fr.lua | 99 + .../i18n/french/luasrc/i18n/default.fr.xml | 106 + .../i18n/french/luasrc/i18n/sysauth.fr.lua | 3 + .../i18n/french/luasrc/i18n/sysauth.fr.xml | 9 + .../root/etc/uci-defaults/luci-i18n-french | 6 + openwrt/packages/luci/i18n/german/Makefile | 2 + .../packages/luci/i18n/german/ipkg/postinst | 4 + .../i18n/german/luasrc/i18n/admin-core.de.lua | 346 ++ .../i18n/german/luasrc/i18n/admin-core.de.xml | 372 ++ .../luci/i18n/german/luasrc/i18n/cbi.de.lua | 16 + .../luci/i18n/german/luasrc/i18n/cbi.de.xml | 22 + .../i18n/german/luasrc/i18n/default.de.lua | 102 + .../i18n/german/luasrc/i18n/default.de.xml | 131 + .../i18n/german/luasrc/i18n/sysauth.de.lua | 3 + .../i18n/german/luasrc/i18n/sysauth.de.xml | 9 + .../luci/i18n/german/luasrc/i18n/wifi.de.lua | 37 + .../luci/i18n/german/luasrc/i18n/wifi.de.xml | 44 + .../root/etc/uci-defaults/luci-i18n-german | 6 + openwrt/packages/luci/i18n/italian/Makefile | 2 + .../packages/luci/i18n/italian/ipkg/postinst | 4 + .../italian/luasrc/i18n/admin-core.it.lua | 327 ++ .../italian/luasrc/i18n/admin-core.it.xml | 333 ++ .../luci/i18n/italian/luasrc/i18n/cbi.it.lua | 17 + .../luci/i18n/italian/luasrc/i18n/cbi.it.xml | 23 + .../i18n/italian/luasrc/i18n/default.it.lua | 102 + .../i18n/italian/luasrc/i18n/default.it.xml | 109 + .../i18n/italian/luasrc/i18n/sysauth.it.lua | 3 + .../i18n/italian/luasrc/i18n/sysauth.it.xml | 9 + .../luci/i18n/italian/luasrc/i18n/wifi.it.lua | 37 + .../luci/i18n/italian/luasrc/i18n/wifi.it.xml | 44 + .../root/etc/uci-defaults/luci-i18n-italian | 6 + .../luci/i18n/portuguese_brazilian/Makefile | 2 + .../i18n/portuguese_brazilian/ipkg/postinst | 4 + .../luasrc/i18n/admin-core.pt-br.lua | 327 ++ .../luasrc/i18n/admin-core.pt-br.xml | 333 ++ .../luasrc/i18n/cbi.pt-br.lua | 17 + .../luasrc/i18n/cbi.pt-br.xml | 23 + .../luasrc/i18n/default.pt-br.lua | 103 + .../luasrc/i18n/default.pt-br.xml | 110 + .../luasrc/i18n/sysauth.pt-br.lua | 3 + .../luasrc/i18n/sysauth.pt-br.xml | 9 + .../luasrc/i18n/wifi.pt-br.lua | 37 + .../luasrc/i18n/wifi.pt-br.xml | 44 + .../luci-i18n-portuguese_brazilian | 5 + openwrt/packages/luci/i18n/russian/Makefile | 2 + .../packages/luci/i18n/russian/ipkg/postinst | 4 + .../russian/luasrc/i18n/admin-core.ru.lua | 269 + .../russian/luasrc/i18n/admin-core.ru.xml | 276 + .../luci/i18n/russian/luasrc/i18n/cbi.ru.lua | 10 + .../luci/i18n/russian/luasrc/i18n/cbi.ru.xml | 16 + .../i18n/russian/luasrc/i18n/default.ru.lua | 95 + .../i18n/russian/luasrc/i18n/default.ru.xml | 101 + .../i18n/russian/luasrc/i18n/sysauth.ru.lua | 3 + .../i18n/russian/luasrc/i18n/sysauth.ru.xml | 9 + .../root/etc/uci-defaults/luci-i18n-russian | 6 + openwrt/packages/luci/libs/cbi/Makefile | 2 + .../cbi/htdocs/luci-static/resources/cbi.js | 221 + .../htdocs/luci-static/resources/cbi/add.gif | Bin 0 -> 378 bytes .../luci-static/resources/cbi/apply.gif | Bin 0 -> 268 bytes .../luci-static/resources/cbi/arrow.gif | Bin 0 -> 135 bytes .../luci-static/resources/cbi/download.gif | Bin 0 -> 189 bytes .../htdocs/luci-static/resources/cbi/edit.gif | Bin 0 -> 280 bytes .../luci-static/resources/cbi/fieldadd.gif | Bin 0 -> 379 bytes .../htdocs/luci-static/resources/cbi/find.gif | Bin 0 -> 273 bytes .../htdocs/luci-static/resources/cbi/help.gif | Bin 0 -> 266 bytes .../htdocs/luci-static/resources/cbi/key.gif | Bin 0 -> 230 bytes .../htdocs/luci-static/resources/cbi/link.gif | Bin 0 -> 279 bytes .../luci-static/resources/cbi/reload.gif | Bin 0 -> 248 bytes .../luci-static/resources/cbi/remove.gif | Bin 0 -> 385 bytes .../luci-static/resources/cbi/reset.gif | Bin 0 -> 258 bytes .../htdocs/luci-static/resources/cbi/save.gif | Bin 0 -> 263 bytes .../htdocs/luci-static/resources/cbi/user.gif | Bin 0 -> 246 bytes openwrt/packages/luci/libs/cbi/luasrc/cbi.lua | 1621 ++++++ .../luci/libs/cbi/luasrc/view/cbi/browser.htm | 23 + .../luci/libs/cbi/luasrc/view/cbi/button.htm | 21 + .../cbi/luasrc/view/cbi/cell_valuefooter.htm | 34 + .../cbi/luasrc/view/cbi/cell_valueheader.htm | 17 + .../luci/libs/cbi/luasrc/view/cbi/dvalue.htm | 22 + .../luci/libs/cbi/luasrc/view/cbi/dynlist.htm | 45 + .../libs/cbi/luasrc/view/cbi/filebrowser.htm | 122 + .../luci/libs/cbi/luasrc/view/cbi/footer.htm | 26 + .../cbi/luasrc/view/cbi/full_valuefooter.htm | 45 + .../cbi/luasrc/view/cbi/full_valueheader.htm | 24 + .../luci/libs/cbi/luasrc/view/cbi/fvalue.htm | 17 + .../luci/libs/cbi/luasrc/view/cbi/header.htm | 22 + .../luci/libs/cbi/luasrc/view/cbi/lvalue.htm | 32 + .../luci/libs/cbi/luasrc/view/cbi/map.htm | 36 + .../luci/libs/cbi/luasrc/view/cbi/mvalue.htm | 35 + .../libs/cbi/luasrc/view/cbi/nsection.htm | 45 + .../libs/cbi/luasrc/view/cbi/nullsection.htm | 23 + .../libs/cbi/luasrc/view/cbi/simpleform.htm | 46 + .../libs/cbi/luasrc/view/cbi/tblsection.htm | 135 + .../libs/cbi/luasrc/view/cbi/tsection.htm | 59 + .../luci/libs/cbi/luasrc/view/cbi/tvalue.htm | 19 + .../libs/cbi/luasrc/view/cbi/ucisection.htm | 66 + .../luci/libs/cbi/luasrc/view/cbi/upload.htm | 28 + .../luci/libs/cbi/luasrc/view/cbi/value.htm | 38 + .../libs/cbi/luasrc/view/cbi/valuefooter.htm | 16 + .../libs/cbi/luasrc/view/cbi/valueheader.htm | 16 + openwrt/packages/luci/libs/core/Makefile | 2 + .../packages/luci/libs/core/luasrc/ccache.lua | 86 + .../packages/luci/libs/core/luasrc/debug.lua | 25 + openwrt/packages/luci/libs/core/luasrc/fs.lua | 270 + .../packages/luci/libs/core/luasrc/init.lua | 34 + openwrt/packages/luci/libs/core/luasrc/ip.lua | 632 +++ .../packages/luci/libs/core/luasrc/ltn12.lua | 391 ++ .../packages/luci/libs/core/luasrc/util.lua | 787 +++ .../luci/libs/core/luasrc/version.lua | 12 + openwrt/packages/luci/libs/fastindex/Makefile | 13 + .../luci/libs/fastindex/src/fastindex.c | 379 ++ .../packages/luci/libs/fastindex/src/list.h | 601 +++ openwrt/packages/luci/libs/http/Makefile | 2 + .../luci/libs/http/luasrc/http/protocol.lua | 690 +++ .../luasrc/http/protocol/conditionals.lua | 154 + .../libs/http/luasrc/http/protocol/date.lua | 115 + .../libs/http/luasrc/http/protocol/mime.lua | 98 + openwrt/packages/luci/libs/httpd/Makefile | 2 + openwrt/packages/luci/libs/httpd/host/runluci | 48 + .../luci/libs/httpd/hostfiles/www/index.html | 10 + .../packages/luci/libs/httpd/luasrc/httpd.lua | 126 + .../libs/httpd/luasrc/httpd/handler/file.lua | 199 + .../libs/httpd/luasrc/httpd/handler/luci.lua | 96 + .../luci/libs/httpd/luasrc/httpd/module.lua | 136 + .../luci/libs/httpd/luasrc/httpd/server.lua | 241 + openwrt/packages/luci/libs/ipkg/Makefile | 2 + .../luci/libs/ipkg/luasrc/model/ipkg.lua | 150 + openwrt/packages/luci/libs/json/Makefile | 2 + .../packages/luci/libs/json/luasrc/json.lua | 538 ++ openwrt/packages/luci/libs/lpk/Makefile | 2 + openwrt/packages/luci/libs/lpk/luasrc/lpk.lua | 41 + .../luci/libs/lpk/luasrc/lpk/core.lua | 107 + .../libs/lpk/luasrc/lpk/core/download.lua | 1 + .../luci/libs/lpk/luasrc/lpk/core/install.lua | 16 + .../luci/libs/lpk/luasrc/lpk/core/resolve.lua | 0 .../libs/lpk/luasrc/lpk/core/retrieve.lua | 7 + .../luci/libs/lpk/luasrc/lpk/core/unpack.lua | 0 .../luci/libs/lpk/luasrc/lpk/util.lua | 59 + .../packages/luci/libs/lpk/root/etc/lpk.conf | 1 + .../packages/luci/libs/lpk/root/usr/bin/lpk | 2 + openwrt/packages/luci/libs/lucittpd/Makefile | 18 + .../usr/lib/lucittpd/plugins/httpd.lua | 34 + .../packages/luci/libs/lucittpd/ipkg/postinst | 6 + .../lucittpd/luasrc/ttpd/handler/file.lua | 252 + .../luci/libs/lucittpd/luasrc/ttpd/module.lua | 121 + .../luci/libs/lucittpd/luasrc/ttpd/server.lua | 444 ++ .../libs/lucittpd/root/etc/config/lucittpd | 6 + .../libs/lucittpd/root/etc/init.d/lucittpd | 44 + .../root/usr/lib/lucittpd/plugins/httpd.lua | 35 + .../luci/libs/lucittpd/src/.gitignore | 1 + .../packages/luci/libs/lucittpd/src/Makefile | 20 + .../luci/libs/lucittpd/src/include/lib/list.h | 601 +++ .../luci/libs/lucittpd/src/include/lib/log.h | 24 + .../libs/lucittpd/src/include/lib/luaplugin.h | 71 + .../libs/lucittpd/src/include/lib/signal.h | 25 + .../luci/libs/lucittpd/src/include/lib/uci.h | 54 + .../luci/libs/lucittpd/src/include/uci.h | 543 ++ .../libs/lucittpd/src/include/uci_config.h | 3 + .../packages/luci/libs/lucittpd/src/lib/log.c | 45 + .../luci/libs/lucittpd/src/lib/luaplugin.c | 383 ++ .../luci/libs/lucittpd/src/lib/signal.c | 52 + .../packages/luci/libs/lucittpd/src/lib/uci.c | 206 + .../packages/luci/libs/lucittpd/src/main.c | 333 ++ openwrt/packages/luci/libs/sgi-cgi/Makefile | 2 + .../luci/libs/sgi-cgi/htdocs/cgi-bin/luci | 5 + .../luci/libs/sgi-cgi/htdocs/index.html | 10 + .../luci/libs/sgi-cgi/luasrc/sgi/cgi.lua | 90 + openwrt/packages/luci/libs/sgi-luci/Makefile | 2 + .../usr/lib/lucittpd/plugins/luci-webui.lua | 29 + .../sgi-luci/luasrc/ttpd/handler/luci.lua | 92 + .../usr/lib/lucittpd/plugins/luci-webui.lua | 17 + .../packages/luci/libs/sgi-webuci/.gitignore | 2 + .../packages/luci/libs/sgi-webuci/Makefile | 52 + .../sgi-webuci/boa-patches/100-no_tz.patch | 22 + .../boa-patches/110-host_lookup.patch | 22 + .../boa-patches/120-setuid_fix.patch | 13 + .../boa-patches/200-plugin_api.patch | 1109 ++++ .../boa-patches/210-accept_fix.patch | 15 + .../boa-patches/220-ipv6-vs-ipv4.patch | 257 + .../luci/libs/sgi-webuci/host/buildconfig.sh | 20 + .../libs/sgi-webuci/luasrc/sgi/webuci.lua | 74 + .../libs/sgi-webuci/root/etc/boa/boa.conf | 17 + .../luci/libs/sgi-webuci/root/etc/init.d/boa | 57 + .../luci/libs/sgi-webuci/root/etc/mime.types | 748 +++ .../libs/sgi-webuci/root/usr/lib/boa/luci.lua | 66 + .../packages/luci/libs/sgi-webuci/src/cgi.c | 530 ++ .../packages/luci/libs/sgi-webuci/src/luci.c | 236 + openwrt/packages/luci/libs/sgi-wsapi/Makefile | 2 + .../luci/libs/sgi-wsapi/luasrc/sgi/wsapi.lua | 79 + openwrt/packages/luci/libs/sys/Makefile | 2 + openwrt/packages/luci/libs/sys/luasrc/sys.lua | 782 +++ .../luci/libs/sys/luasrc/sys/iptparser.lua | 244 + .../luci/libs/sys/luasrc/sys/zoneinfo.lua | 572 ++ openwrt/packages/luci/libs/uci/Makefile | 2 + .../luci/libs/uci/luasrc/model/uci.lua | 333 ++ .../luci/libs/uci/root/etc/config/ucitrack | 55 + .../luci/libs/uci/root/sbin/luci-reload | 34 + openwrt/packages/luci/libs/uvl/Makefile | 2 + .../luci/libs/uvl/luasrc/i18n/uvl.de.lua | 39 + .../luci/libs/uvl/luasrc/i18n/uvl.de.xml | 45 + .../luci/libs/uvl/luasrc/i18n/uvl.en.lua | 39 + .../luci/libs/uvl/luasrc/i18n/uvl.en.xml | 45 + .../luci/libs/uvl/luasrc/i18n/uvl.pt-br.lua | 39 + .../luci/libs/uvl/luasrc/i18n/uvl.pt-br.xml | 45 + openwrt/packages/luci/libs/uvl/luasrc/uvl.lua | 1209 +++++ .../luci/libs/uvl/luasrc/uvl/datatypes.lua | 187 + .../luci/libs/uvl/luasrc/uvl/dependencies.lua | 196 + .../luci/libs/uvl/luasrc/uvl/errors.lua | 204 + .../luci/libs/uvl/luasrc/uvl/validation.lua | 72 + .../libs/uvl/root/lib/uci/schema/meta/schema | 403 ++ .../packages/luci/libs/uvl/root/usr/bin/uvl | 241 + .../packages/luci/libs/uvl/root/usr/bin/uvlc | 22 + openwrt/packages/luci/libs/uvldoc/Makefile | 2 + .../luasrc/uvldoc/proto/xhtml/footer.xml | 11 + .../luasrc/uvldoc/proto/xhtml/header.xml | 15 + .../luasrc/uvldoc/proto/xhtml/index.xml | 12 + .../uvldoc/luasrc/uvldoc/proto/xhtml/menu.xml | 22 + .../luasrc/uvldoc/proto/xhtml/scheme.xml | 16 + .../luasrc/uvldoc/proto/xhtml/section.xml | 198 + .../luasrc/uvldoc/proto/xhtml/uvldoc.css | 135 + .../libs/uvldoc/luasrc/uvldoc/renderer.lua | 124 + openwrt/packages/luci/libs/web/Makefile | 2 + .../luci/libs/web/luasrc/cacheloader.lua | 23 + .../packages/luci/libs/web/luasrc/config.lua | 42 + .../luci/libs/web/luasrc/dispatcher.lua | 720 +++ .../packages/luci/libs/web/luasrc/http.lua | 293 + .../packages/luci/libs/web/luasrc/i18n.lua | 98 + .../packages/luci/libs/web/luasrc/sauth.lua | 106 + .../luci/libs/web/luasrc/template.lua | 239 + .../luci/libs/web/root/etc/config/luci | 28 + .../packages/luci/modules/admin-core/Makefile | 2 + .../luci/modules/admin-core/ipkg/postinst | 7 + .../admin-core/luasrc/tools/webadmin.lua | 173 + .../modules/admin-core/luasrc/view/about.htm | 45 + .../admin-core/luasrc/view/error404.htm | 19 + .../admin-core/luasrc/view/error500.htm | 19 + .../modules/admin-core/luasrc/view/footer.htm | 15 + .../modules/admin-core/luasrc/view/header.htm | 15 + .../admin-core/luasrc/view/indexer.htm | 15 + .../admin-core/luasrc/view/sysauth.htm | 49 + .../admin-core/root/etc/config/luci_ethers | 1 + .../admin-core/root/etc/config/luci_hosts | 1 + .../admin-core/root/etc/init.d/luci_ethers | 37 + .../admin-core/root/etc/init.d/luci_fixtime | 11 + .../admin-core/root/etc/init.d/luci_hosts | 36 + .../root/lib/uci/schema/default/dhcp | 240 + .../root/lib/uci/schema/default/dropbear | 24 + .../root/lib/uci/schema/default/fstab | 54 + .../root/lib/uci/schema/default/httpd | 37 + .../root/lib/uci/schema/default/luci_hosts | 21 + .../root/lib/uci/schema/default/network | 495 ++ .../root/lib/uci/schema/default/system | 103 + .../root/lib/uci/schema/default/wireless | 523 ++ .../modules/admin-core/root/sbin/luci-flash | 89 + .../packages/luci/modules/admin-full/Makefile | 2 + .../luasrc/controller/admin/filebrowser.lua | 20 + .../luasrc/controller/admin/index.lua | 67 + .../luasrc/controller/admin/network.lua | 97 + .../luasrc/controller/admin/services.lua | 54 + .../luasrc/controller/admin/status.lua | 33 + .../luasrc/controller/admin/system.lua | 235 + .../luasrc/controller/admin/uci.lua | 90 + .../luasrc/model/cbi/admin_index/luci.lua | 52 + .../model/cbi/admin_network/conntrack.lua | 49 + .../luasrc/model/cbi/admin_network/dhcp.lua | 72 + .../model/cbi/admin_network/dhcpleases.lua | 61 + .../luasrc/model/cbi/admin_network/hosts.lua | 33 + .../luasrc/model/cbi/admin_network/ifaces.lua | 343 ++ .../model/cbi/admin_network/network.lua | 128 + .../luasrc/model/cbi/admin_network/routes.lua | 120 + .../luasrc/model/cbi/admin_network/vlan.lua | 22 + .../luasrc/model/cbi/admin_network/wifi.lua | 373 ++ .../model/cbi/admin_network/wireless.lua | 134 + .../model/cbi/admin_services/crontab.lua | 35 + .../model/cbi/admin_services/dnsmasq.lua | 45 + .../model/cbi/admin_services/dropbear.lua | 27 + .../luasrc/model/cbi/admin_services/httpd.lua | 31 + .../model/cbi/admin_services/lucittpd.lua | 25 + .../luasrc/model/cbi/admin_system/buttons.lua | 31 + .../luasrc/model/cbi/admin_system/fstab.lua | 86 + .../luasrc/model/cbi/admin_system/ipkg.lua | 35 + .../luasrc/model/cbi/admin_system/leds.lua | 86 + .../luasrc/model/cbi/admin_system/passwd.lua | 45 + .../model/cbi/admin_system/processes.lua | 44 + .../luasrc/model/cbi/admin_system/sshkeys.lua | 35 + .../luasrc/model/cbi/admin_system/system.lua | 73 + .../luasrc/view/admin_index/index.htm | 24 + .../luasrc/view/admin_services/index.htm | 19 + .../luasrc/view/admin_status/dmesg.htm | 20 + .../luasrc/view/admin_status/index.htm | 19 + .../luasrc/view/admin_status/syslog.htm | 20 + .../luasrc/view/admin_system/applyreboot.htm | 21 + .../luasrc/view/admin_system/backup.htm | 40 + .../luasrc/view/admin_system/ipkg.htm | 18 + .../luasrc/view/admin_system/packages.htm | 98 + .../luasrc/view/admin_system/reboot.htm | 33 + .../luasrc/view/admin_system/upgrade.htm | 52 + .../luasrc/view/admin_uci/apply.htm | 42 + .../luasrc/view/admin_uci/changes.htm | 45 + .../luasrc/view/admin_uci/revert.htm | 31 + .../packages/luci/modules/admin-mini/Makefile | 2 + .../luasrc/controller/mini/index.lua | 53 + .../luasrc/controller/mini/network.lua | 26 + .../luasrc/controller/mini/system.lua | 130 + .../admin-mini/luasrc/model/cbi/mini/dhcp.lua | 105 + .../luasrc/model/cbi/mini/index.lua | 14 + .../admin-mini/luasrc/model/cbi/mini/luci.lua | 37 + .../luasrc/model/cbi/mini/network.lua | 196 + .../luasrc/model/cbi/mini/passwd.lua | 45 + .../luasrc/model/cbi/mini/system.lua | 55 + .../admin-mini/luasrc/model/cbi/mini/wifi.lua | 277 + .../luasrc/view/mini/applyreboot.htm | 21 + .../admin-mini/luasrc/view/mini/backup.htm | 40 + .../admin-mini/luasrc/view/mini/index.htm | 21 + .../admin-mini/luasrc/view/mini/reboot.htm | 33 + .../admin-mini/luasrc/view/mini/upgrade.htm | 52 + .../packages/luci/modules/freifunk/Makefile | 2 + .../luci/modules/freifunk/ipkg/postinst | 5 + .../luasrc/controller/freifunk/freifunk.lua | 192 + .../freifunk/luasrc/i18n/freifunk.de.lua | 21 + .../freifunk/luasrc/i18n/freifunk.de.xml | 28 + .../freifunk/luasrc/i18n/freifunk.en.lua | 21 + .../freifunk/luasrc/i18n/freifunk.en.xml | 28 + .../luasrc/model/cbi/freifunk/contact.lua | 34 + .../luasrc/model/cbi/freifunk/freifunk.lua | 24 + .../model/cbi/freifunk/public_status.lua | 216 + .../freifunk/luasrc/view/freifunk/contact.htm | 27 + .../freifunk/luasrc/view/freifunk/index.htm | 24 + .../modules/freifunk/root/etc/config/freifunk | 126 + .../root/etc/config/freifunk_augsburg | 2 + .../freifunk/root/etc/config/freifunk_berlin | 2 + .../root/etc/config/freifunk_hannover | 5 + .../freifunk/root/etc/firewall.freifunk | 53 + .../etc/hotplug.d/iface/22-firewall-nat-fix | 61 + .../modules/freifunk/root/etc/init.d/freifunk | 24 + .../luci/modules/freifunk/root/etc/rc.local | 2 + .../freifunk/root/usr/sbin/ff_olsr_test_gw | 41 + openwrt/packages/luci/modules/rpc/Makefile | 2 + .../modules/rpc/luasrc/controller/rpc.lua | 179 + .../luci/modules/rpc/luasrc/jsonrpc.lua | 94 + .../modules/rpc/luasrc/jsonrpcbind/uci.lua | 94 + .../modules/rpc/luasrc/jsonrpcbind/uvl.lua | 41 + openwrt/packages/luci/themes/base/Makefile | 2 + .../htdocs/luci-static/resources/Dropdowns.js | 120 + .../htdocs/luci-static/resources/VarType.js | 91 + .../htdocs/luci-static/resources/XHTML1.js | 271 + .../packages/luci/themes/fledermaus/Makefile | 2 + .../htdocs/luci-static/fledermaus/cascade.css | 626 +++ .../luci-static/fledermaus/fledermaus.png | Bin 0 -> 7321 bytes .../htdocs/luci-static/fledermaus/logo.png | Bin 0 -> 4002 bytes .../luci/themes/fledermaus/ipkg/postinst | 4 + .../luasrc/view/themes/fledermaus/footer.htm | 22 + .../luasrc/view/themes/fledermaus/header.htm | 180 + .../etc/uci-defaults/luci-theme-fledermaus | 6 + .../luci/themes/freifunk-bno/Makefile | 2 + .../luci-static/freifunk-bno/cascade.css | 726 +++ .../freifunk-bno/images/bgoption.png | Bin 0 -> 141 bytes .../freifunk-bno/images/favicon.ico | Bin 0 -> 5310 bytes .../freifunk-bno/images/header-back.gif | Bin 0 -> 127 bytes .../freifunk-bno/images/header-left.gif | Bin 0 -> 293 bytes .../freifunk-bno/images/header-right.gif | Bin 0 -> 365 bytes .../luci-static/freifunk-bno/images/logo.gif | Bin 0 -> 2415 bytes .../freifunk-bno/images/main-back.png | Bin 0 -> 404 bytes .../freifunk-bno/images/schriftzug.gif | Bin 0 -> 3606 bytes .../luci/themes/freifunk-bno/ipkg/postinst | 4 + .../view/themes/freifunk-bno/footer.htm | 29 + .../view/themes/freifunk-bno/header.htm | 196 + .../etc/uci-defaults/luci-theme-freifunk-bno | 6 + .../packages/luci/themes/freifunk/Makefile | 2 + .../htdocs/luci-static/freifunk/cascade.css | 726 +++ .../luci-static/freifunk/images/bgoption.png | Bin 0 -> 141 bytes .../luci-static/freifunk/images/favicon.ico | Bin 0 -> 4286 bytes .../freifunk/images/header-back.gif | Bin 0 -> 127 bytes .../freifunk/images/header-left.gif | Bin 0 -> 293 bytes .../freifunk/images/header-right.gif | Bin 0 -> 365 bytes .../luci-static/freifunk/images/logo.png | Bin 0 -> 6400 bytes .../luci-static/freifunk/images/main-back.png | Bin 0 -> 404 bytes .../freifunk/images/schriftzug.png | Bin 0 -> 4487 bytes .../luci/themes/freifunk/ipkg/postinst | 4 + .../luasrc/view/themes/freifunk/footer.htm | 29 + .../luasrc/view/themes/freifunk/header.htm | 196 + .../root/etc/uci-defaults/luci-theme-freifunk | 6 + .../luci/themes/openwrt-light/Makefile | 2 + .../luci-static/openwrt-light/cascade.css | 790 +++ .../htdocs/luci-static/openwrt-light/ie6.css | 77 + .../htdocs/luci-static/openwrt-light/ie7.css | 20 + .../luci/themes/openwrt-light/ipkg/postinst | 4 + .../view/themes/openwrt-light/footer.htm | 21 + .../view/themes/openwrt-light/header.htm | 163 + .../etc/uci-defaults/luci-theme-openwrtlight | 6 + .../luci/themes/openwrt.org-oxygen/Makefile | 2 + .../luci-static/openwrt.org-oxygen/bg.jpg | Bin 0 -> 40537 bytes .../openwrt.org-oxygen/cascade.css | 803 +++ .../openwrt.org-oxygen/dashboard.css | 99 + .../luci-static/openwrt.org-oxygen/header.png | Bin 0 -> 33244 bytes .../openwrt.org-oxygen/icons/COPYING.oxygen | 48 + .../openwrt.org-oxygen/icons/datetime.png | Bin 0 -> 5250 bytes .../openwrt.org-oxygen/icons/default.png | Bin 0 -> 5022 bytes .../openwrt.org-oxygen/icons/desktop.png | Bin 0 -> 6487 bytes .../openwrt.org-oxygen/icons/flash.png | Bin 0 -> 5065 bytes .../openwrt.org-oxygen/icons/freifunk.png | Bin 0 -> 2404 bytes .../openwrt.org-oxygen/icons/harddisk.png | Bin 0 -> 3317 bytes .../openwrt.org-oxygen/icons/key.png | Bin 0 -> 4129 bytes .../openwrt.org-oxygen/icons/lightbulb.png | Bin 0 -> 5550 bytes .../openwrt.org-oxygen/icons/login.png | Bin 0 -> 2918 bytes .../openwrt.org-oxygen/icons/logout.png | Bin 0 -> 3577 bytes .../openwrt.org-oxygen/icons/network.png | Bin 0 -> 6602 bytes .../openwrt.org-oxygen/icons/overview.png | Bin 0 -> 4553 bytes .../openwrt.org-oxygen/icons/package.png | Bin 0 -> 4996 bytes .../openwrt.org-oxygen/icons/restart.png | Bin 0 -> 4081 bytes .../openwrt.org-oxygen/icons/services.png | Bin 0 -> 4630 bytes .../openwrt.org-oxygen/icons/shell.png | Bin 0 -> 2110 bytes .../openwrt.org-oxygen/icons/stats.png | Bin 0 -> 3102 bytes .../openwrt.org-oxygen/icons/status.png | Bin 0 -> 3192 bytes .../openwrt.org-oxygen/icons/switch.png | Bin 0 -> 3940 bytes .../openwrt.org-oxygen/icons/system.png | Bin 0 -> 6296 bytes .../openwrt.org-oxygen/icons/worker.png | Bin 0 -> 4630 bytes .../luci-static/openwrt.org-oxygen/ie6.css | 77 + .../luci-static/openwrt.org-oxygen/ie7.css | 20 + .../themes/openwrt.org-oxygen/ipkg/postinst | 4 + .../themes/openwrt.org-oxygen/dashboard.htm | 46 + .../view/themes/openwrt.org-oxygen/footer.htm | 21 + .../view/themes/openwrt.org-oxygen/header.htm | 166 + .../themes/openwrt.org-oxygen/indexer.htm | 17 + .../uci-defaults/luci-theme-openwrt-oxygen | 6 + .../packages/luci/themes/openwrt.org/Makefile | 2 + .../htdocs/luci-static/openwrt.org/bg.jpg | Bin 0 -> 40537 bytes .../luci-static/openwrt.org/cascade.css | 804 +++ .../htdocs/luci-static/openwrt.org/header.png | Bin 0 -> 33244 bytes .../htdocs/luci-static/openwrt.org/ie6.css | 77 + .../htdocs/luci-static/openwrt.org/ie7.css | 20 + .../luci/themes/openwrt.org/ipkg/postinst | 4 + .../luasrc/view/themes/openwrt.org/footer.htm | 21 + .../luasrc/view/themes/openwrt.org/header.htm | 163 + .../root/etc/uci-defaults/luci-theme-openwrt | 6 + openwrt/packages/luci/themes/oxygen/Makefile | 2 + .../htdocs/luci-static/oxygen/cascade.css | 660 +++ .../htdocs/luci-static/oxygen/dashboard.css | 31 + .../htdocs/luci-static/oxygen/flukso.png | Bin 0 -> 1612 bytes .../luci-static/oxygen/icons/COPYING.oxygen | 48 + .../luci-static/oxygen/icons/network.png | Bin 0 -> 6602 bytes .../htdocs/luci-static/oxygen/icons/wifi.png | Bin 0 -> 7109 bytes .../packages/luci/themes/oxygen/ipkg/postinst | 4 + .../luasrc/view/themes/oxygen/dashboard.htm | 46 + .../luasrc/view/themes/oxygen/footer.htm | 22 + .../luasrc/view/themes/oxygen/header.htm | 129 + .../luasrc/view/themes/oxygen/indexer.htm | 17 + .../root/etc/uci-defaults/luci-theme-oxygen | 6 + openwrt/packages/ntpclient/Makefile | 49 + .../packages/ntpclient/files/ntpclient.config | 22 + .../ntpclient/files/ntpclient.hotplug | 64 + .../ntpclient/patches/100-daemon.patch | 24 + openwrt/packages/xyssl/Makefile | 79 + .../packages/xyssl/patches/100-shared.patch | 12 + openwrt/packages/xyssl/patches/110-make.patch | 13 + openwrt/patches/100.disable.console.patch | 13 + 1492 files changed, 143520 insertions(+) create mode 100644 openwrt/config create mode 100644 openwrt/files/etc/config/dhcp create mode 100644 openwrt/files/etc/config/dropbear create mode 100644 openwrt/files/etc/config/firewall create mode 100644 openwrt/files/etc/config/network create mode 100644 openwrt/files/etc/config/system create mode 100644 openwrt/files/etc/config/wireless create mode 100644 openwrt/files/etc/hosts create mode 100644 openwrt/files/etc/inittab create mode 100644 openwrt/files/etc/passwd create mode 100644 openwrt/packages/expat/Makefile create mode 100644 openwrt/packages/expat/patches/001-destdir.patch create mode 100644 openwrt/packages/expat/patches/110-avr32_compile_fix.patch create mode 100644 openwrt/packages/flukso/Makefile create mode 100644 openwrt/packages/flukso/src/auth.lua create mode 100644 openwrt/packages/flukso/src/data.lua create mode 100644 openwrt/packages/flukso/src/dbg.lua create mode 100755 openwrt/packages/flukso/src/flukso.init create mode 100755 openwrt/packages/flukso/src/flukso.lua create mode 100755 openwrt/packages/flukso/src/heartbeat.lua create mode 100755 openwrt/packages/flukso/src/load.lua create mode 100644 openwrt/packages/luaexpat/Makefile create mode 100644 openwrt/packages/luaexpat/patches/010-compat-5.1.patch create mode 100644 openwrt/packages/luaexpat/patches/010-luaL_findstring.patch create mode 100644 openwrt/packages/luasocket/Makefile create mode 100644 openwrt/packages/luasocket/patches/010-compat-5.1.patch create mode 100644 openwrt/packages/luaxmlrpc/Makefile create mode 100644 openwrt/packages/luaxmlrpc/src/http.lua create mode 100644 openwrt/packages/luaxmlrpc/src/init.lua create mode 100644 openwrt/packages/luaxmlrpc/src/server.lua create mode 100644 openwrt/packages/luaxyssl/Makefile create mode 100644 openwrt/packages/luaxyssl/patches/100-compile-fixes.patch create mode 100644 openwrt/packages/luci/.buildpath create mode 100644 openwrt/packages/luci/.cproject create mode 100644 openwrt/packages/luci/.gitignore create mode 100644 openwrt/packages/luci/.project create mode 100644 openwrt/packages/luci/INSTALL create mode 100644 openwrt/packages/luci/LICENSE create mode 100644 openwrt/packages/luci/Makefile create mode 100644 openwrt/packages/luci/NOTICE create mode 100644 openwrt/packages/luci/THANKYOU create mode 100644 openwrt/packages/luci/applications/freifunk-community/Makefile create mode 100644 openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-nodes.html create mode 100644 openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-status.html create mode 100644 openwrt/packages/luci/applications/luci-ddns/Makefile create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/controller/ddns.lua create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.lua create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.xml create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.lua create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.xml create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.lua create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.xml create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddns.lua create mode 100644 openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddnsmini.lua create mode 100644 openwrt/packages/luci/applications/luci-ddns/root/lib/uci/schema/default/ddns create mode 100644 openwrt/packages/luci/applications/luci-ffwizard-leipzig/Makefile create mode 100644 openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/controller/ffwizard.lua create mode 100644 openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/model/cbi/ffwizard.lua create mode 100644 openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/tools/ffwizard.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/Makefile create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/controller/luci_fw/luci_fw.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.xml create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.xml create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.xml create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/miniportfw.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/redirect.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/rrule.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/traffic.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/trule.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/zones.lua create mode 100644 openwrt/packages/luci/applications/luci-fw/root/lib/uci/schema/default/firewall create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/Makefile create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/controller/hd_idle.lua create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.lua create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.xml create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.lua create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.xml create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/luasrc/model/cbi/hd_idle.lua create mode 100644 openwrt/packages/luci/applications/luci-hd_idle/root/etc/uci-defaults/luci-hd_idle create mode 100644 openwrt/packages/luci/applications/luci-initmgr/Makefile create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/controller/init.lua create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.lua create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.xml create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.lua create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.xml create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-initmgr/luasrc/model/cbi/init/init.lua create mode 100644 openwrt/packages/luci/applications/luci-livestats/Makefile create mode 100644 openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/ExCanvas.js create mode 100644 openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/GraphRPC.js create mode 100644 openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/JsonRpc.js create mode 100644 openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/Legend.js create mode 100644 openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/MochiKit.js create mode 100644 openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/PlotKit.js create mode 100644 openwrt/packages/luci/applications/luci-livestats/luasrc/controller/livestats.lua create mode 100644 openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.de.lua create mode 100644 openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.en.lua create mode 100644 openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/loadavg.htm create mode 100644 openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/traffic.htm create mode 100644 openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/wireless.htm create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/Makefile create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/controller/mmc_over_gpio.lua create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.lua create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.xml create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.lua create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.xml create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/model/cbi/mmc_over_gpio.lua create mode 100644 openwrt/packages/luci/applications/luci-mmc_over_gpio/root/etc/uci-defaults/luci-mmc_over_gpio create mode 100644 openwrt/packages/luci/applications/luci-ntpc/Makefile create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/controller/ntpc.lua create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.lua create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.xml create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.lua create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.xml create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpc.lua create mode 100644 openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpcmini.lua create mode 100644 openwrt/packages/luci/applications/luci-ntpc/root/lib/uci/schema/default/ntpclient create mode 100644 openwrt/packages/luci/applications/luci-olsr/Makefile create mode 100755 openwrt/packages/luci/applications/luci-olsr/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/controller/olsr.lua create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.lua create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.xml create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.lua create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.xml create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrd.lua create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdhna.lua create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdplugins.lua create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/error_olsr.htm create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/hna.htm create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/index.htm create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/mid.htm create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/routes.htm create mode 100644 openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/topology.htm create mode 100644 openwrt/packages/luci/applications/luci-olsr/root/etc/uci-defaults/luci-olsr create mode 100644 openwrt/packages/luci/applications/luci-p910nd/Makefile create mode 100644 openwrt/packages/luci/applications/luci-p910nd/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/controller/p910nd.lua create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.lua create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.xml create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.lua create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.xml create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-p910nd/luasrc/model/cbi/p910nd.lua create mode 100644 openwrt/packages/luci/applications/luci-p910nd/root/etc/uci-defaults/luci-p910nd create mode 100644 openwrt/packages/luci/applications/luci-polipo/Makefile create mode 100755 openwrt/packages/luci/applications/luci-polipo/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-polipo/luasrc/controller/polipo.lua create mode 100644 openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.lua create mode 100644 openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.xml create mode 100644 openwrt/packages/luci/applications/luci-polipo/luasrc/model/cbi/polipo.lua create mode 100644 openwrt/packages/luci/applications/luci-polipo/root/etc/uci-defaults/luci-polipo create mode 100755 openwrt/packages/luci/applications/luci-polipo/root/usr/sbin/polipo_purge create mode 100644 openwrt/packages/luci/applications/luci-qos/Makefile create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/controller/qos.lua create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.lua create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.xml create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.lua create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.xml create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.lua create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.xml create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qos.lua create mode 100644 openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qosmini.lua create mode 100644 openwrt/packages/luci/applications/luci-qos/root/lib/uci/schema/default/qos create mode 100644 openwrt/packages/luci/applications/luci-samba/Makefile create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/controller/samba.lua create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.lua create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.xml create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.lua create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.xml create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-samba/luasrc/model/cbi/samba.lua create mode 100644 openwrt/packages/luci/applications/luci-samba/root/lib/uci/schema/default/samba create mode 100644 openwrt/packages/luci/applications/luci-siitwizard/Makefile create mode 100644 openwrt/packages/luci/applications/luci-siitwizard/luasrc/controller/siitwizard.lua create mode 100644 openwrt/packages/luci/applications/luci-siitwizard/luasrc/model/cbi/siitwizard.lua create mode 100644 openwrt/packages/luci/applications/luci-siitwizard/root/etc/config/siit create mode 100644 openwrt/packages/luci/applications/luci-splash/Makefile create mode 100644 openwrt/packages/luci/applications/luci-splash/htdocs/luci/splash/index.html create mode 100755 openwrt/packages/luci/applications/luci-splash/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-splash/luasrc/controller/splash/splash.lua create mode 100644 openwrt/packages/luci/applications/luci-splash/luasrc/model/cbi/splash/splash.lua create mode 100644 openwrt/packages/luci/applications/luci-splash/luasrc/view/splash/splash.htm create mode 100644 openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/index.htm create mode 100644 openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/splash.htm create mode 100644 openwrt/packages/luci/applications/luci-splash/root/etc/config/luci_splash create mode 100755 openwrt/packages/luci/applications/luci-splash/root/etc/cron.minutely/luci_splash create mode 100755 openwrt/packages/luci/applications/luci-splash/root/etc/init.d/luci_splash create mode 100644 openwrt/packages/luci/applications/luci-splash/root/lib/uci/schema/default/luci_splash create mode 100755 openwrt/packages/luci/applications/luci-splash/root/usr/bin/luci-splashd create mode 100755 openwrt/packages/luci/applications/luci-splash/root/usr/sbin/luci-splash create mode 100644 openwrt/packages/luci/applications/luci-statistics/Makefile create mode 100755 openwrt/packages/luci/applications/luci-statistics/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.xml.hide create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.xml.hide create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.xml.hide create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.xml create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.xml create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/collectd.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/cpu.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/csv.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/df.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/disk.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/dns.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/email.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/exec.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/interface.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/iptables.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/irq.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/load.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/netlink.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/network.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/ping.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/processes.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/rrdtool.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/tcpconns.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/unixsock.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/wireless.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/datatree.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/i18n.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/colors.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/cpu/cpu.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/df/df.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/interface.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_bytes.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_packets.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/irq/irq.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/load/load.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/netlink.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/ping/ping.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/processes.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/wireless.lua create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/index.htm create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/networkplugins.htm create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/outputplugins.htm create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/systemplugins.htm create mode 100644 openwrt/packages/luci/applications/luci-statistics/luasrc/view/public_statistics/graph.htm create mode 100644 openwrt/packages/luci/applications/luci-statistics/root/etc/config/luci_statistics create mode 100755 openwrt/packages/luci/applications/luci-statistics/root/etc/init.d/luci_statistics create mode 100644 openwrt/packages/luci/applications/luci-statistics/root/etc/uci-defaults/luci-statistics create mode 100755 openwrt/packages/luci/applications/luci-statistics/root/usr/bin/stat-genconfig create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/Makefile create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/controller/tinyproxy.lua create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.lua create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.xml create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.lua create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.xml create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.lua create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.xml create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-tinyproxy/luasrc/model/cbi/tinyproxy.lua create mode 100644 openwrt/packages/luci/applications/luci-upnp/Makefile create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/controller/upnp.lua create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.lua create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.xml create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.lua create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.xml create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnp.lua create mode 100644 openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnpmini.lua create mode 100755 openwrt/packages/luci/applications/luci-upnp/root/etc/uci-defaults/luci-upnp create mode 100644 openwrt/packages/luci/applications/luci-upnp/root/lib/uci/schema/default/upnpd create mode 100644 openwrt/packages/luci/applications/luci-ushare/Makefile create mode 100644 openwrt/packages/luci/applications/luci-ushare/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/controller/ushare.lua create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.lua create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.xml create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.lua create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.xml create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-ushare/luasrc/model/cbi/ushare.lua create mode 100644 openwrt/packages/luci/applications/luci-ushare/root/etc/uci-defaults/luci-ushare create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/Makefile create mode 100755 openwrt/packages/luci/applications/luci-uvc_streamer/ipkg/postinst create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/controller/uvc_streamer.lua create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.lua create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.xml create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.lua create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.xml create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.lua create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.xml create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.lua create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.xml create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/model/cbi/uvc_streamer.lua create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/root/etc/uci-defaults/luci-uvc_streamer create mode 100644 openwrt/packages/luci/applications/luci-uvc_streamer/root/lib/uci/schema/default/uvc-streamer create mode 100644 openwrt/packages/luci/applications/myapplication/Makefile create mode 100755 openwrt/packages/luci/build/cbi2uvl.lua create mode 100644 openwrt/packages/luci/build/config.mk create mode 100644 openwrt/packages/luci/build/gccconfig.mk create mode 100755 openwrt/packages/luci/build/hostenv.sh create mode 100644 openwrt/packages/luci/build/i18n-lua-xhtml1.xsl create mode 100755 openwrt/packages/luci/build/i18n-lua2xml.lua create mode 100644 openwrt/packages/luci/build/i18n-xml2lua.sh create mode 100755 openwrt/packages/luci/build/makedocs.sh create mode 100755 openwrt/packages/luci/build/mkversion.sh create mode 100644 openwrt/packages/luci/build/module.mk create mode 100644 openwrt/packages/luci/build/uvl2cbi.lua create mode 100755 openwrt/packages/luci/build/uvl2i18n.lua create mode 100755 openwrt/packages/luci/build/uvldoc create mode 100644 openwrt/packages/luci/build/zoneinfo2lua.pl create mode 100644 openwrt/packages/luci/contrib/axtls/Makefile create mode 100644 openwrt/packages/luci/contrib/axtls/files/axtls-config create mode 100644 openwrt/packages/luci/contrib/axtls/files/axtls-config.h create mode 100644 openwrt/packages/luci/contrib/axtls/patches/001-ld-fix.patch create mode 100644 openwrt/packages/luci/contrib/axtls/patches/002-httpd-fix.patch create mode 100644 openwrt/packages/luci/contrib/axtls/patches/003-content-type.patch create mode 100644 openwrt/packages/luci/contrib/axtls/patches/004-cgi-nph-mode.patch create mode 100644 openwrt/packages/luci/contrib/bitlib/.gitignore create mode 100644 openwrt/packages/luci/contrib/bitlib/Makefile create mode 100644 openwrt/packages/luci/contrib/lpeg/.gitignore create mode 100644 openwrt/packages/luci/contrib/lpeg/Makefile create mode 100644 openwrt/packages/luci/contrib/luacurses/Makefile create mode 100644 openwrt/packages/luci/contrib/luacurses/doc/curses.pdf create mode 100644 openwrt/packages/luci/contrib/luacurses/doc/curses.ps.gz create mode 100644 openwrt/packages/luci/contrib/luacurses/src/curses.c create mode 100644 openwrt/packages/luci/contrib/luacurses/src/luacurses.c create mode 100644 openwrt/packages/luci/contrib/luacurses/src/luacurses.h create mode 100644 openwrt/packages/luci/contrib/luacurses/test/filter.lua create mode 100644 openwrt/packages/luci/contrib/luacurses/test/getnstr.lua create mode 100644 openwrt/packages/luci/contrib/luacurses/test/getyx.lua create mode 100644 openwrt/packages/luci/contrib/luacurses/test/hello.lua create mode 100644 openwrt/packages/luci/contrib/luacurses/test/mouse.lua create mode 100644 openwrt/packages/luci/contrib/luacurses/test/pair.lua create mode 100644 openwrt/packages/luci/contrib/luacurses/test/rain.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/Makefile create mode 100755 openwrt/packages/luci/contrib/luadoc/hostfiles/bin/luadoc create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/config.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/debug.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/formatter.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/constant.lp create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/file.lp create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/function.lp create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/index.lp create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/luadoc.css create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/menu.lp create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/module.lp create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/table.lp create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/raw.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/init.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/lp.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard/tags.lua create mode 100644 openwrt/packages/luci/contrib/luadoc/lua/luadoc/util.lua create mode 100644 openwrt/packages/luci/contrib/luaposix/.gitignore create mode 100644 openwrt/packages/luci/contrib/luaposix/Makefile create mode 100644 openwrt/packages/luci/contrib/luasocket/.gitignore create mode 100644 openwrt/packages/luci/contrib/luasocket/Makefile create mode 100644 openwrt/packages/luci/contrib/package/Makefile create mode 100644 openwrt/packages/luci/contrib/package/lpeg/Makefile create mode 100644 openwrt/packages/luci/contrib/package/luasocket/Makefile create mode 100644 openwrt/packages/luci/contrib/package/luaxyssl/Makefile create mode 100644 openwrt/packages/luci/contrib/package/luaxyssl/patches/100-compile-fixes.patch create mode 100644 openwrt/packages/luci/contrib/package/luci/Makefile create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/Makefile create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/config/olsrd create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/default/olsrd create mode 100755 openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/init.d/olsrd create mode 100755 openwrt/packages/luci/contrib/package/olsrd-luci/ipkg/postinst create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/patches/100-olsrd-hg-r3.patch create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/patches/131-olsrd-tweak-ffetx.patch create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/patches/137-olsrd-192.168.1.1.patch create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/patches/139-olsrd-magicarprefresh.patch create mode 100644 openwrt/packages/luci/contrib/package/olsrd-luci/patches/140-olsrd-optimize-size.patch create mode 100644 openwrt/packages/luci/contrib/package/xrelayd/Makefile create mode 100644 openwrt/packages/luci/contrib/uci/.gitignore create mode 100644 openwrt/packages/luci/contrib/uci/Makefile create mode 100755 openwrt/packages/luci/contrib/uci/hostfiles/bin/uci create mode 100755 openwrt/packages/luci/contrib/uci/hostfiles/bin/uci-defaults create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/batmand create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ddns create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dhcp create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dropbear create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/firewall create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/fstab create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/httpd create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/network create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ntpclient create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/qos create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/system create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/upnpd create mode 100644 openwrt/packages/luci/contrib/uci/hostfiles/etc/config/wireless create mode 100755 openwrt/packages/luci/host/bin/luadoc create mode 100755 openwrt/packages/luci/host/bin/uci create mode 100755 openwrt/packages/luci/host/bin/uci-defaults create mode 100644 openwrt/packages/luci/host/etc/boa/boa.conf create mode 100644 openwrt/packages/luci/host/etc/config/batmand create mode 100644 openwrt/packages/luci/host/etc/config/ddns create mode 100644 openwrt/packages/luci/host/etc/config/dhcp create mode 100644 openwrt/packages/luci/host/etc/config/dropbear create mode 100644 openwrt/packages/luci/host/etc/config/firewall create mode 100644 openwrt/packages/luci/host/etc/config/freifunk create mode 100644 openwrt/packages/luci/host/etc/config/freifunk_augsburg create mode 100644 openwrt/packages/luci/host/etc/config/freifunk_berlin create mode 100644 openwrt/packages/luci/host/etc/config/freifunk_hannover create mode 100644 openwrt/packages/luci/host/etc/config/fstab create mode 100644 openwrt/packages/luci/host/etc/config/httpd create mode 100644 openwrt/packages/luci/host/etc/config/luci create mode 100644 openwrt/packages/luci/host/etc/config/luci_ethers create mode 100644 openwrt/packages/luci/host/etc/config/luci_hosts create mode 100644 openwrt/packages/luci/host/etc/config/luci_splash create mode 100644 openwrt/packages/luci/host/etc/config/luci_statistics create mode 100644 openwrt/packages/luci/host/etc/config/lucittpd create mode 100644 openwrt/packages/luci/host/etc/config/network create mode 100644 openwrt/packages/luci/host/etc/config/ntpclient create mode 100644 openwrt/packages/luci/host/etc/config/qos create mode 100644 openwrt/packages/luci/host/etc/config/siit create mode 100644 openwrt/packages/luci/host/etc/config/system create mode 100644 openwrt/packages/luci/host/etc/config/ucitrack create mode 100644 openwrt/packages/luci/host/etc/config/upnpd create mode 100644 openwrt/packages/luci/host/etc/config/wireless create mode 100755 openwrt/packages/luci/host/etc/cron.minutely/luci_splash create mode 100644 openwrt/packages/luci/host/etc/firewall.freifunk create mode 100644 openwrt/packages/luci/host/etc/hotplug.d/iface/22-firewall-nat-fix create mode 100755 openwrt/packages/luci/host/etc/init.d/boa create mode 100755 openwrt/packages/luci/host/etc/init.d/freifunk create mode 100755 openwrt/packages/luci/host/etc/init.d/luci_ethers create mode 100755 openwrt/packages/luci/host/etc/init.d/luci_fixtime create mode 100755 openwrt/packages/luci/host/etc/init.d/luci_hosts create mode 100755 openwrt/packages/luci/host/etc/init.d/luci_splash create mode 100755 openwrt/packages/luci/host/etc/init.d/luci_statistics create mode 100755 openwrt/packages/luci/host/etc/init.d/lucittpd create mode 100644 openwrt/packages/luci/host/etc/lpk.conf create mode 100644 openwrt/packages/luci/host/etc/mime.types create mode 100644 openwrt/packages/luci/host/etc/rc.local create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/ddns create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/dhcp create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/dropbear create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/firewall create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/fstab create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/httpd create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/luci_hosts create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/luci_splash create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/network create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/ntpclient create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/qos create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/samba create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/system create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/upnpd create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/uvc-streamer create mode 100644 openwrt/packages/luci/host/lib/uci/schema/default/wireless create mode 100644 openwrt/packages/luci/host/lib/uci/schema/meta/schema create mode 120000 openwrt/packages/luci/host/luci create mode 100755 openwrt/packages/luci/host/sbin/luci-flash create mode 100755 openwrt/packages/luci/host/sbin/luci-reload create mode 100644 openwrt/packages/luci/host/tmp/.uci/luci create mode 100755 openwrt/packages/luci/host/usr/bin/boa create mode 100755 openwrt/packages/luci/host/usr/bin/boa_indexer create mode 100755 openwrt/packages/luci/host/usr/bin/lpk create mode 100755 openwrt/packages/luci/host/usr/bin/luci-splashd create mode 100755 openwrt/packages/luci/host/usr/bin/lucittpd create mode 100755 openwrt/packages/luci/host/usr/bin/stat-genconfig create mode 100755 openwrt/packages/luci/host/usr/bin/uci create mode 100755 openwrt/packages/luci/host/usr/bin/uvl create mode 100755 openwrt/packages/luci/host/usr/bin/uvlc create mode 100644 openwrt/packages/luci/host/usr/include/uci.h create mode 100644 openwrt/packages/luci/host/usr/include/uci_config.h create mode 100644 openwrt/packages/luci/host/usr/include/uci_list.h create mode 100644 openwrt/packages/luci/host/usr/include/ucimap.h create mode 100644 openwrt/packages/luci/host/usr/lib/boa/luci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/ltn12.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/config.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/debug.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/formatter.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/constant.lp create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/file.lp create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/function.lp create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/index.lp create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/luadoc.css create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/menu.lp create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/module.lp create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/table.lp create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/raw.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/init.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/lp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard/tags.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luadoc/util.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/cacheloader.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/cbi.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/ccache.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/config.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/filebrowser.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/index.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/network.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/services.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/status.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/system.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/uci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/ddns.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/ffwizard.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/freifunk/freifunk.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/hd_idle.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/init.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/livestats.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_fw/luci_fw.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_statistics/luci_statistics.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/index.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/network.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/system.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/mmc_over_gpio.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/ntpc.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/olsr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/p910nd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/polipo.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/qos.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/rpc.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/samba.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/siitwizard.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/splash/splash.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/tinyproxy.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/upnp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/ushare.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/controller/uvc_streamer.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/debug.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/dispatcher.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/fs.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/http.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/conditionals.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/date.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/mime.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/httpd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/file.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/luci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/httpd/module.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/httpd/server.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.it.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.ru.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.it.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.ru.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.it.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.ru.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/polipo.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.xml.hide create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.xml.hide create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.xml.hide create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.it.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.ru.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.fr.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.de.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.en.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.it.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.pt-br.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/init.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/ip.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/json.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpc.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uvl.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/download.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/install.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/resolve.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/retrieve.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/unpack.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/lpk/util.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/ltn12.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_index/luci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/conntrack.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcpleases.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/hosts.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/ifaces.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/network.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/routes.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/vlan.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wifi.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wireless.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/crontab.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dnsmasq.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dropbear.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/httpd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/lucittpd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/buttons.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/fstab.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/ipkg.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/leds.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/passwd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/processes.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/sshkeys.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/system.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddns.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddnsmini.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ffwizard.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/contact.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/freifunk.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/public_status.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/hd_idle.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/init/init.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/miniportfw.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/redirect.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/rrule.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/traffic.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/trule.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/zones.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/collectd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/cpu.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/csv.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/df.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/disk.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/dns.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/email.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/exec.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/interface.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/iptables.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/irq.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/load.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/netlink.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/network.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/ping.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/processes.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/rrdtool.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/tcpconns.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/unixsock.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/wireless.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/dhcp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/index.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/luci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/network.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/passwd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/system.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/wifi.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mmc_over_gpio.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpc.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpcmini.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdhna.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdplugins.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/p910nd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/polipo.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qos.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qosmini.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/samba.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/siitwizard.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/splash/splash.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/tinyproxy.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnpmini.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ushare.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/uvc_streamer.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/ipkg.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/model/uci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/sauth.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/sgi/cgi.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/sgi/webuci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/sgi/wsapi.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/datatree.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/i18n.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/colors.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/cpu/cpu.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/df/df.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/interface.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_bytes.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_packets.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/irq/irq.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/load/load.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/netlink.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/ping/ping.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/processes.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/wireless.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/sys.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/sys/iptparser.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/sys/zoneinfo.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/template.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/tools/ffwizard.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/tools/webadmin.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/file.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/luci.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/module.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/server.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/util.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvl.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvl/datatypes.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvl/dependencies.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvl/errors.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvl/validation.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/footer.xml create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/header.xml create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/index.xml create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/menu.xml create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/scheme.xml create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/section.xml create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/uvldoc.css create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/renderer.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/version.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/about.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_index/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_services/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/networkplugins.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/outputplugins.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/systemplugins.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/dmesg.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/syslog.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/applyreboot.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/backup.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/ipkg.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/packages.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/reboot.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/upgrade.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/apply.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/changes.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/revert.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/browser.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/button.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valuefooter.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valueheader.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dvalue.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dynlist.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/filebrowser.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valuefooter.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valueheader.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/fvalue.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/lvalue.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/map.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/mvalue.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nsection.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nullsection.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/simpleform.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tblsection.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tsection.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tvalue.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/ucisection.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/upload.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/value.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valuefooter.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valueheader.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/error404.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/error500.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/contact.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/indexer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/loadavg.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/traffic.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/wireless.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/applyreboot.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/backup.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/reboot.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/upgrade.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/public_statistics/graph.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/splash/splash.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/splash.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/error_olsr.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/hna.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/index.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/mid.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/routes.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/topology.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/sysauth.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/dashboard.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/indexer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/dashboard.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/footer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/header.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/indexer.htm create mode 100644 openwrt/packages/luci/host/usr/lib/lua/mime.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/socket.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/socket/ftp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/socket/http.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/socket/smtp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/socket/tp.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lua/socket/url.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lucittpd/plugins/httpd.lua create mode 100644 openwrt/packages/luci/host/usr/lib/lucittpd/plugins/luci-webui.lua create mode 100755 openwrt/packages/luci/host/usr/sbin/ff_olsr_test_gw create mode 100755 openwrt/packages/luci/host/usr/sbin/luci-splash create mode 100755 openwrt/packages/luci/host/usr/sbin/polipo_purge create mode 100644 openwrt/packages/luci/host/www/cgi-bin-nodes.html create mode 100644 openwrt/packages/luci/host/www/cgi-bin-status.html create mode 100755 openwrt/packages/luci/host/www/cgi-bin/luci create mode 100644 openwrt/packages/luci/host/www/index.html create mode 100644 openwrt/packages/luci/host/www/luci-static/fledermaus/cascade.css create mode 100644 openwrt/packages/luci/host/www/luci-static/fledermaus/fledermaus.png create mode 100644 openwrt/packages/luci/host/www/luci-static/fledermaus/logo.png create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/cascade.css create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/bgoption.png create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/favicon.ico create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/header-back.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/header-left.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/header-right.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/logo.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/main-back.png create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/schriftzug.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/cascade.css create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/bgoption.png create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/favicon.ico create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/header-back.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/header-left.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/header-right.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/logo.png create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/main-back.png create mode 100644 openwrt/packages/luci/host/www/luci-static/freifunk/images/schriftzug.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt-light/cascade.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt-light/ie6.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt-light/ie7.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/bg.jpg create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/cascade.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/dashboard.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/header.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/COPYING.oxygen create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/datetime.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/default.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/desktop.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/flash.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/freifunk.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/harddisk.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/key.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/lightbulb.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/login.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/logout.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/network.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/overview.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/package.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/restart.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/services.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/shell.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/stats.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/status.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/switch.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/system.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/worker.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie6.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie7.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org/bg.jpg create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org/cascade.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org/header.png create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org/ie6.css create mode 100644 openwrt/packages/luci/host/www/luci-static/openwrt.org/ie7.css create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/bg.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/cascade.css create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/dashboard.css create mode 100755 openwrt/packages/luci/host/www/luci-static/oxygen/flukso.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/footer.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/header.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/COPYING.oxygen create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/datetime.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/default.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/desktop.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/flash.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/freifunk.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/harddisk.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/key.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/lightbulb.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/login.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/logout.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/network.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/overview.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/package.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/restart.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/services.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/shell.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/stats.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/status.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/switch.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/system.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/wifi.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/wireless.png create mode 100644 openwrt/packages/luci/host/www/luci-static/oxygen/icons/worker.png create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/Dropdowns.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/VarType.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/XHTML1.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/add.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/apply.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/arrow.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/download.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/edit.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/fieldadd.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/find.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/help.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/key.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/link.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/reload.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/remove.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/reset.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/save.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/cbi/user.gif create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/livestats/ExCanvas.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/livestats/GraphRPC.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/livestats/JsonRpc.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/livestats/Legend.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/livestats/MochiKit.js create mode 100644 openwrt/packages/luci/host/www/luci-static/resources/livestats/PlotKit.js create mode 100644 openwrt/packages/luci/host/www/luci/splash/index.html create mode 100644 openwrt/packages/luci/i18n/english/Makefile create mode 100755 openwrt/packages/luci/i18n/english/ipkg/postinst create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.lua create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.xml create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.lua create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.xml create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.lua create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.xml create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.lua create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.xml create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.lua create mode 100644 openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.xml create mode 100755 openwrt/packages/luci/i18n/english/root/etc/uci-defaults/luci-i18n-english create mode 100644 openwrt/packages/luci/i18n/french/Makefile create mode 100755 openwrt/packages/luci/i18n/french/ipkg/postinst create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.lua create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.xml create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.lua create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.xml create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.lua create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.xml create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.lua create mode 100644 openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.xml create mode 100755 openwrt/packages/luci/i18n/french/root/etc/uci-defaults/luci-i18n-french create mode 100644 openwrt/packages/luci/i18n/german/Makefile create mode 100755 openwrt/packages/luci/i18n/german/ipkg/postinst create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.lua create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.xml create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.lua create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.xml create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.lua create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.xml create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.lua create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.xml create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.lua create mode 100644 openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.xml create mode 100755 openwrt/packages/luci/i18n/german/root/etc/uci-defaults/luci-i18n-german create mode 100644 openwrt/packages/luci/i18n/italian/Makefile create mode 100755 openwrt/packages/luci/i18n/italian/ipkg/postinst create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.lua create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.xml create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.lua create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.xml create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.lua create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.xml create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.lua create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.xml create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.lua create mode 100644 openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.xml create mode 100755 openwrt/packages/luci/i18n/italian/root/etc/uci-defaults/luci-i18n-italian create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/Makefile create mode 100755 openwrt/packages/luci/i18n/portuguese_brazilian/ipkg/postinst create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.lua create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.xml create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.lua create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.xml create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.lua create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.xml create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.lua create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.xml create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.lua create mode 100644 openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.xml create mode 100755 openwrt/packages/luci/i18n/portuguese_brazilian/root/etc/uci-defaults/luci-i18n-portuguese_brazilian create mode 100644 openwrt/packages/luci/i18n/russian/Makefile create mode 100755 openwrt/packages/luci/i18n/russian/ipkg/postinst create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.lua create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.xml create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.lua create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.xml create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.lua create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.xml create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.lua create mode 100644 openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.xml create mode 100755 openwrt/packages/luci/i18n/russian/root/etc/uci-defaults/luci-i18n-russian create mode 100644 openwrt/packages/luci/libs/cbi/Makefile create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi.js create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/add.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/apply.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/arrow.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/download.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/edit.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/fieldadd.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/find.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/help.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/key.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/link.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/reload.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/remove.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/reset.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/save.gif create mode 100644 openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/user.gif create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/cbi.lua create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/browser.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/button.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valuefooter.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valueheader.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dvalue.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dynlist.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/filebrowser.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/footer.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valuefooter.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valueheader.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/fvalue.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/header.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/lvalue.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/map.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/mvalue.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nsection.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nullsection.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/simpleform.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tblsection.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tsection.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tvalue.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/ucisection.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/upload.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/value.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valuefooter.htm create mode 100644 openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valueheader.htm create mode 100644 openwrt/packages/luci/libs/core/Makefile create mode 100644 openwrt/packages/luci/libs/core/luasrc/ccache.lua create mode 100644 openwrt/packages/luci/libs/core/luasrc/debug.lua create mode 100644 openwrt/packages/luci/libs/core/luasrc/fs.lua create mode 100644 openwrt/packages/luci/libs/core/luasrc/init.lua create mode 100644 openwrt/packages/luci/libs/core/luasrc/ip.lua create mode 100644 openwrt/packages/luci/libs/core/luasrc/ltn12.lua create mode 100644 openwrt/packages/luci/libs/core/luasrc/util.lua create mode 100644 openwrt/packages/luci/libs/core/luasrc/version.lua create mode 100644 openwrt/packages/luci/libs/fastindex/Makefile create mode 100644 openwrt/packages/luci/libs/fastindex/src/fastindex.c create mode 100644 openwrt/packages/luci/libs/fastindex/src/list.h create mode 100644 openwrt/packages/luci/libs/http/Makefile create mode 100644 openwrt/packages/luci/libs/http/luasrc/http/protocol.lua create mode 100644 openwrt/packages/luci/libs/http/luasrc/http/protocol/conditionals.lua create mode 100644 openwrt/packages/luci/libs/http/luasrc/http/protocol/date.lua create mode 100644 openwrt/packages/luci/libs/http/luasrc/http/protocol/mime.lua create mode 100644 openwrt/packages/luci/libs/httpd/Makefile create mode 100755 openwrt/packages/luci/libs/httpd/host/runluci create mode 100644 openwrt/packages/luci/libs/httpd/hostfiles/www/index.html create mode 100644 openwrt/packages/luci/libs/httpd/luasrc/httpd.lua create mode 100644 openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/file.lua create mode 100644 openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/luci.lua create mode 100644 openwrt/packages/luci/libs/httpd/luasrc/httpd/module.lua create mode 100644 openwrt/packages/luci/libs/httpd/luasrc/httpd/server.lua create mode 100644 openwrt/packages/luci/libs/ipkg/Makefile create mode 100644 openwrt/packages/luci/libs/ipkg/luasrc/model/ipkg.lua create mode 100644 openwrt/packages/luci/libs/json/Makefile create mode 100644 openwrt/packages/luci/libs/json/luasrc/json.lua create mode 100644 openwrt/packages/luci/libs/lpk/Makefile create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk.lua create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk/core.lua create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk/core/download.lua create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk/core/install.lua create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk/core/resolve.lua create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk/core/retrieve.lua create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk/core/unpack.lua create mode 100644 openwrt/packages/luci/libs/lpk/luasrc/lpk/util.lua create mode 100644 openwrt/packages/luci/libs/lpk/root/etc/lpk.conf create mode 100755 openwrt/packages/luci/libs/lpk/root/usr/bin/lpk create mode 100644 openwrt/packages/luci/libs/lucittpd/Makefile create mode 100644 openwrt/packages/luci/libs/lucittpd/hostfiles/usr/lib/lucittpd/plugins/httpd.lua create mode 100755 openwrt/packages/luci/libs/lucittpd/ipkg/postinst create mode 100644 openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/handler/file.lua create mode 100644 openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/module.lua create mode 100644 openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/server.lua create mode 100644 openwrt/packages/luci/libs/lucittpd/root/etc/config/lucittpd create mode 100755 openwrt/packages/luci/libs/lucittpd/root/etc/init.d/lucittpd create mode 100644 openwrt/packages/luci/libs/lucittpd/root/usr/lib/lucittpd/plugins/httpd.lua create mode 100644 openwrt/packages/luci/libs/lucittpd/src/.gitignore create mode 100644 openwrt/packages/luci/libs/lucittpd/src/Makefile create mode 100644 openwrt/packages/luci/libs/lucittpd/src/include/lib/list.h create mode 100644 openwrt/packages/luci/libs/lucittpd/src/include/lib/log.h create mode 100644 openwrt/packages/luci/libs/lucittpd/src/include/lib/luaplugin.h create mode 100644 openwrt/packages/luci/libs/lucittpd/src/include/lib/signal.h create mode 100644 openwrt/packages/luci/libs/lucittpd/src/include/lib/uci.h create mode 100644 openwrt/packages/luci/libs/lucittpd/src/include/uci.h create mode 100644 openwrt/packages/luci/libs/lucittpd/src/include/uci_config.h create mode 100644 openwrt/packages/luci/libs/lucittpd/src/lib/log.c create mode 100644 openwrt/packages/luci/libs/lucittpd/src/lib/luaplugin.c create mode 100644 openwrt/packages/luci/libs/lucittpd/src/lib/signal.c create mode 100644 openwrt/packages/luci/libs/lucittpd/src/lib/uci.c create mode 100644 openwrt/packages/luci/libs/lucittpd/src/main.c create mode 100644 openwrt/packages/luci/libs/sgi-cgi/Makefile create mode 100755 openwrt/packages/luci/libs/sgi-cgi/htdocs/cgi-bin/luci create mode 100644 openwrt/packages/luci/libs/sgi-cgi/htdocs/index.html create mode 100644 openwrt/packages/luci/libs/sgi-cgi/luasrc/sgi/cgi.lua create mode 100644 openwrt/packages/luci/libs/sgi-luci/Makefile create mode 100644 openwrt/packages/luci/libs/sgi-luci/hostfiles/usr/lib/lucittpd/plugins/luci-webui.lua create mode 100644 openwrt/packages/luci/libs/sgi-luci/luasrc/ttpd/handler/luci.lua create mode 100644 openwrt/packages/luci/libs/sgi-luci/root/usr/lib/lucittpd/plugins/luci-webui.lua create mode 100644 openwrt/packages/luci/libs/sgi-webuci/.gitignore create mode 100644 openwrt/packages/luci/libs/sgi-webuci/Makefile create mode 100644 openwrt/packages/luci/libs/sgi-webuci/boa-patches/100-no_tz.patch create mode 100644 openwrt/packages/luci/libs/sgi-webuci/boa-patches/110-host_lookup.patch create mode 100644 openwrt/packages/luci/libs/sgi-webuci/boa-patches/120-setuid_fix.patch create mode 100644 openwrt/packages/luci/libs/sgi-webuci/boa-patches/200-plugin_api.patch create mode 100644 openwrt/packages/luci/libs/sgi-webuci/boa-patches/210-accept_fix.patch create mode 100644 openwrt/packages/luci/libs/sgi-webuci/boa-patches/220-ipv6-vs-ipv4.patch create mode 100755 openwrt/packages/luci/libs/sgi-webuci/host/buildconfig.sh create mode 100644 openwrt/packages/luci/libs/sgi-webuci/luasrc/sgi/webuci.lua create mode 100644 openwrt/packages/luci/libs/sgi-webuci/root/etc/boa/boa.conf create mode 100755 openwrt/packages/luci/libs/sgi-webuci/root/etc/init.d/boa create mode 100644 openwrt/packages/luci/libs/sgi-webuci/root/etc/mime.types create mode 100644 openwrt/packages/luci/libs/sgi-webuci/root/usr/lib/boa/luci.lua create mode 100644 openwrt/packages/luci/libs/sgi-webuci/src/cgi.c create mode 100644 openwrt/packages/luci/libs/sgi-webuci/src/luci.c create mode 100644 openwrt/packages/luci/libs/sgi-wsapi/Makefile create mode 100644 openwrt/packages/luci/libs/sgi-wsapi/luasrc/sgi/wsapi.lua create mode 100644 openwrt/packages/luci/libs/sys/Makefile create mode 100644 openwrt/packages/luci/libs/sys/luasrc/sys.lua create mode 100644 openwrt/packages/luci/libs/sys/luasrc/sys/iptparser.lua create mode 100644 openwrt/packages/luci/libs/sys/luasrc/sys/zoneinfo.lua create mode 100644 openwrt/packages/luci/libs/uci/Makefile create mode 100644 openwrt/packages/luci/libs/uci/luasrc/model/uci.lua create mode 100644 openwrt/packages/luci/libs/uci/root/etc/config/ucitrack create mode 100755 openwrt/packages/luci/libs/uci/root/sbin/luci-reload create mode 100644 openwrt/packages/luci/libs/uvl/Makefile create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.lua create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.xml create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.lua create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.xml create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.lua create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.xml create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/uvl.lua create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/uvl/datatypes.lua create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/uvl/dependencies.lua create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/uvl/errors.lua create mode 100644 openwrt/packages/luci/libs/uvl/luasrc/uvl/validation.lua create mode 100644 openwrt/packages/luci/libs/uvl/root/lib/uci/schema/meta/schema create mode 100755 openwrt/packages/luci/libs/uvl/root/usr/bin/uvl create mode 100755 openwrt/packages/luci/libs/uvl/root/usr/bin/uvlc create mode 100644 openwrt/packages/luci/libs/uvldoc/Makefile create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/footer.xml create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/header.xml create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/index.xml create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/menu.xml create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/scheme.xml create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/section.xml create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/uvldoc.css create mode 100644 openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/renderer.lua create mode 100644 openwrt/packages/luci/libs/web/Makefile create mode 100644 openwrt/packages/luci/libs/web/luasrc/cacheloader.lua create mode 100644 openwrt/packages/luci/libs/web/luasrc/config.lua create mode 100644 openwrt/packages/luci/libs/web/luasrc/dispatcher.lua create mode 100644 openwrt/packages/luci/libs/web/luasrc/http.lua create mode 100644 openwrt/packages/luci/libs/web/luasrc/i18n.lua create mode 100644 openwrt/packages/luci/libs/web/luasrc/sauth.lua create mode 100644 openwrt/packages/luci/libs/web/luasrc/template.lua create mode 100644 openwrt/packages/luci/libs/web/root/etc/config/luci create mode 100644 openwrt/packages/luci/modules/admin-core/Makefile create mode 100755 openwrt/packages/luci/modules/admin-core/ipkg/postinst create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/tools/webadmin.lua create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/view/about.htm create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/view/error404.htm create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/view/error500.htm create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/view/footer.htm create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/view/header.htm create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/view/indexer.htm create mode 100644 openwrt/packages/luci/modules/admin-core/luasrc/view/sysauth.htm create mode 100644 openwrt/packages/luci/modules/admin-core/root/etc/config/luci_ethers create mode 100644 openwrt/packages/luci/modules/admin-core/root/etc/config/luci_hosts create mode 100755 openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_ethers create mode 100755 openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_fixtime create mode 100755 openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_hosts create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dhcp create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dropbear create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/fstab create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/httpd create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/luci_hosts create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/network create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/system create mode 100644 openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/wireless create mode 100755 openwrt/packages/luci/modules/admin-core/root/sbin/luci-flash create mode 100644 openwrt/packages/luci/modules/admin-full/Makefile create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/filebrowser.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/index.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/network.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/services.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/status.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/system.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/uci.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_index/luci.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/conntrack.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcp.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcpleases.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/hosts.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/ifaces.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/network.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/vlan.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wifi.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wireless.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/crontab.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dnsmasq.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dropbear.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/httpd.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/lucittpd.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/buttons.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/fstab.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/ipkg.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/leds.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/passwd.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/processes.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/sshkeys.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/system.lua create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_index/index.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_services/index.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/dmesg.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/index.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/syslog.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/applyreboot.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/backup.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/ipkg.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/packages.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/reboot.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/upgrade.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/apply.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/changes.htm create mode 100644 openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/revert.htm create mode 100644 openwrt/packages/luci/modules/admin-mini/Makefile create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/index.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/network.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/system.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/dhcp.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/index.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/luci.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/network.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/passwd.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/system.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/wifi.lua create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/applyreboot.htm create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/backup.htm create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/index.htm create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/reboot.htm create mode 100644 openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/upgrade.htm create mode 100644 openwrt/packages/luci/modules/freifunk/Makefile create mode 100755 openwrt/packages/luci/modules/freifunk/ipkg/postinst create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/controller/freifunk/freifunk.lua create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.lua create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.xml create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.lua create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.xml create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/contact.lua create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/freifunk.lua create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/contact.htm create mode 100644 openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/index.htm create mode 100644 openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk create mode 100644 openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_augsburg create mode 100644 openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_berlin create mode 100644 openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_hannover create mode 100644 openwrt/packages/luci/modules/freifunk/root/etc/firewall.freifunk create mode 100644 openwrt/packages/luci/modules/freifunk/root/etc/hotplug.d/iface/22-firewall-nat-fix create mode 100755 openwrt/packages/luci/modules/freifunk/root/etc/init.d/freifunk create mode 100644 openwrt/packages/luci/modules/freifunk/root/etc/rc.local create mode 100755 openwrt/packages/luci/modules/freifunk/root/usr/sbin/ff_olsr_test_gw create mode 100644 openwrt/packages/luci/modules/rpc/Makefile create mode 100644 openwrt/packages/luci/modules/rpc/luasrc/controller/rpc.lua create mode 100644 openwrt/packages/luci/modules/rpc/luasrc/jsonrpc.lua create mode 100644 openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uci.lua create mode 100644 openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uvl.lua create mode 100644 openwrt/packages/luci/themes/base/Makefile create mode 100644 openwrt/packages/luci/themes/base/htdocs/luci-static/resources/Dropdowns.js create mode 100644 openwrt/packages/luci/themes/base/htdocs/luci-static/resources/VarType.js create mode 100644 openwrt/packages/luci/themes/base/htdocs/luci-static/resources/XHTML1.js create mode 100644 openwrt/packages/luci/themes/fledermaus/Makefile create mode 100644 openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/cascade.css create mode 100644 openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/fledermaus.png create mode 100644 openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/logo.png create mode 100755 openwrt/packages/luci/themes/fledermaus/ipkg/postinst create mode 100644 openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/footer.htm create mode 100644 openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm create mode 100755 openwrt/packages/luci/themes/fledermaus/root/etc/uci-defaults/luci-theme-fledermaus create mode 100644 openwrt/packages/luci/themes/freifunk-bno/Makefile create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/cascade.css create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/bgoption.png create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/favicon.ico create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/header-back.gif create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/header-left.gif create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/header-right.gif create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/logo.gif create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/main-back.png create mode 100644 openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/schriftzug.gif create mode 100755 openwrt/packages/luci/themes/freifunk-bno/ipkg/postinst create mode 100644 openwrt/packages/luci/themes/freifunk-bno/luasrc/view/themes/freifunk-bno/footer.htm create mode 100644 openwrt/packages/luci/themes/freifunk-bno/luasrc/view/themes/freifunk-bno/header.htm create mode 100755 openwrt/packages/luci/themes/freifunk-bno/root/etc/uci-defaults/luci-theme-freifunk-bno create mode 100644 openwrt/packages/luci/themes/freifunk/Makefile create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/cascade.css create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/bgoption.png create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/favicon.ico create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/header-back.gif create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/header-left.gif create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/header-right.gif create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/logo.png create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/main-back.png create mode 100644 openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/schriftzug.png create mode 100755 openwrt/packages/luci/themes/freifunk/ipkg/postinst create mode 100644 openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/footer.htm create mode 100644 openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/header.htm create mode 100755 openwrt/packages/luci/themes/freifunk/root/etc/uci-defaults/luci-theme-freifunk create mode 100644 openwrt/packages/luci/themes/openwrt-light/Makefile create mode 100644 openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/cascade.css create mode 100644 openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie6.css create mode 100644 openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie7.css create mode 100755 openwrt/packages/luci/themes/openwrt-light/ipkg/postinst create mode 100644 openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/footer.htm create mode 100644 openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/header.htm create mode 100755 openwrt/packages/luci/themes/openwrt-light/root/etc/uci-defaults/luci-theme-openwrtlight create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/Makefile create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/bg.jpg create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/cascade.css create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/dashboard.css create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/header.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/COPYING.oxygen create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/datetime.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/default.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/desktop.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/flash.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/freifunk.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/harddisk.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/key.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/lightbulb.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/login.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/logout.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/network.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/overview.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/package.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/restart.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/services.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/shell.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/stats.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/status.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/switch.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/system.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/worker.png create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie6.css create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie7.css create mode 100755 openwrt/packages/luci/themes/openwrt.org-oxygen/ipkg/postinst create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/dashboard.htm create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/footer.htm create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/header.htm create mode 100644 openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/indexer.htm create mode 100755 openwrt/packages/luci/themes/openwrt.org-oxygen/root/etc/uci-defaults/luci-theme-openwrt-oxygen create mode 100644 openwrt/packages/luci/themes/openwrt.org/Makefile create mode 100644 openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/bg.jpg create mode 100644 openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/cascade.css create mode 100644 openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/header.png create mode 100644 openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/ie6.css create mode 100644 openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/ie7.css create mode 100755 openwrt/packages/luci/themes/openwrt.org/ipkg/postinst create mode 100644 openwrt/packages/luci/themes/openwrt.org/luasrc/view/themes/openwrt.org/footer.htm create mode 100644 openwrt/packages/luci/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm create mode 100755 openwrt/packages/luci/themes/openwrt.org/root/etc/uci-defaults/luci-theme-openwrt create mode 100644 openwrt/packages/luci/themes/oxygen/Makefile create mode 100644 openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/cascade.css create mode 100644 openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/dashboard.css create mode 100644 openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/flukso.png create mode 100644 openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/icons/COPYING.oxygen create mode 100644 openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/icons/network.png create mode 100644 openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/icons/wifi.png create mode 100755 openwrt/packages/luci/themes/oxygen/ipkg/postinst create mode 100644 openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/dashboard.htm create mode 100644 openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/footer.htm create mode 100644 openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/header.htm create mode 100644 openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/indexer.htm create mode 100755 openwrt/packages/luci/themes/oxygen/root/etc/uci-defaults/luci-theme-oxygen create mode 100644 openwrt/packages/ntpclient/Makefile create mode 100644 openwrt/packages/ntpclient/files/ntpclient.config create mode 100644 openwrt/packages/ntpclient/files/ntpclient.hotplug create mode 100644 openwrt/packages/ntpclient/patches/100-daemon.patch create mode 100644 openwrt/packages/xyssl/Makefile create mode 100644 openwrt/packages/xyssl/patches/100-shared.patch create mode 100644 openwrt/packages/xyssl/patches/110-make.patch create mode 100644 openwrt/patches/100.disable.console.patch diff --git a/openwrt/config b/openwrt/config new file mode 100644 index 0000000..664914c --- /dev/null +++ b/openwrt/config @@ -0,0 +1,1315 @@ +# +# Automatically generated make config: don't edit +# OpenWrt version: Kamikaze (r16491) +# Thu Jun 18 23:48:14 2009 +# +CONFIG_HAVE_DOT_CONFIG=y +# CONFIG_TARGET_ppc40x is not set +# CONFIG_TARGET_ppc44x is not set +CONFIG_TARGET_atheros=y +# CONFIG_TARGET_ar71xx is not set +# CONFIG_TARGET_avr32 is not set +# CONFIG_TARGET_brcm_2_4 is not set +# CONFIG_TARGET_brcm47xx is not set +# CONFIG_TARGET_ifxmips is not set +# CONFIG_TARGET_adm5120 is not set +# CONFIG_TARGET_ixp4xx is not set +# CONFIG_TARGET_magicbox is not set +# CONFIG_TARGET_rb532 is not set +# CONFIG_TARGET_rdc is not set +# CONFIG_TARGET_au1000 is not set +# CONFIG_TARGET_ar7 is not set +# CONFIG_TARGET_uml is not set +# CONFIG_TARGET_x86 is not set +# CONFIG_TARGET_ixp4xx_generic_Default is not set +# CONFIG_TARGET_ixp4xx_generic_Atheros-ath5k is not set +# CONFIG_TARGET_ixp4xx_generic_NSLU2 is not set +# CONFIG_TARGET_ixp4xx_generic_NAS100d is not set +# CONFIG_TARGET_ixp4xx_generic_DSMG600RevA is not set +# CONFIG_TARGET_ixp4xx_harddisk_FSG3 is not set +# CONFIG_TARGET_adm5120_router_le_Generic is not set +# CONFIG_TARGET_adm5120_router_le_CAS630 is not set +# CONFIG_TARGET_adm5120_router_le_CAS630W is not set +# CONFIG_TARGET_adm5120_router_le_CAS670 is not set +# CONFIG_TARGET_adm5120_router_le_CAS670W is not set +# CONFIG_TARGET_adm5120_router_le_CAS700 is not set +# CONFIG_TARGET_adm5120_router_le_CAS700W is not set +# CONFIG_TARGET_adm5120_router_le_CAS771 is not set +# CONFIG_TARGET_adm5120_router_le_CAS771W is not set +# CONFIG_TARGET_adm5120_router_le_CAS790 is not set +# CONFIG_TARGET_adm5120_router_le_CAS861 is not set +# CONFIG_TARGET_adm5120_router_le_CAS861W is not set +# CONFIG_TARGET_adm5120_router_le_NFS101U is not set +# CONFIG_TARGET_adm5120_router_le_NFS101WU is not set +# CONFIG_TARGET_adm5120_router_le_NP27G is not set +# CONFIG_TARGET_adm5120_router_le_NP28G is not set +# CONFIG_TARGET_adm5120_router_le_WP54 is not set +# CONFIG_TARGET_adm5120_router_le_BR6104K is not set +# CONFIG_TARGET_adm5120_router_le_BR6104KP is not set +# CONFIG_TARGET_adm5120_router_le_BR6104WG is not set +# CONFIG_TARGET_adm5120_router_le_BR6114WG is not set +# CONFIG_TARGET_adm5120_router_le_EASY5120RT is not set +# CONFIG_TARGET_adm5120_router_le_EASY5120PATA is not set +# CONFIG_TARGET_adm5120_router_le_PMUGW is not set +# CONFIG_TARGET_adm5120_router_le_RouterBoard is not set +# CONFIG_TARGET_adm5120_router_be_Generic is not set +# CONFIG_TARGET_adm5120_router_be_P334WT is not set +# CONFIG_TARGET_adm5120_router_be_P335WT is not set +# CONFIG_TARGET_magicbox_Default is not set +# CONFIG_TARGET_au1000_Atheros is not set +# CONFIG_TARGET_au1000_Broadcom is not set +# CONFIG_TARGET_au1000_Intel is not set +# CONFIG_TARGET_au1000_InternetBox is not set +# CONFIG_TARGET_au1000_MeshCube is not set +# CONFIG_TARGET_avr32_Default is not set +# CONFIG_TARGET_ppc40x_Default is not set +# CONFIG_TARGET_ar7_Texas is not set +# CONFIG_TARGET_ar7_None is not set +# CONFIG_TARGET_ar71xx_Default is not set +# CONFIG_TARGET_uml_Default is not set +# CONFIG_TARGET_ppc44x_Default is not set +# CONFIG_TARGET_rdc_ar525w is not set +# CONFIG_TARGET_rdc_dir450 is not set +# CONFIG_TARGET_rdc_wl153 is not set +# CONFIG_TARGET_ifxmips_Atheros is not set +# CONFIG_TARGET_ifxmips_Ralink is not set +# CONFIG_TARGET_rb532_Default is not set +# CONFIG_TARGET_brcm_2_4_Broadcom is not set +# CONFIG_TARGET_brcm_2_4_BroadcomMimo is not set +# CONFIG_TARGET_brcm_2_4_Atheros is not set +# CONFIG_TARGET_brcm_2_4_None is not set +# CONFIG_TARGET_brcm_2_4_USBGeneric is not set +# CONFIG_TARGET_brcm_2_4_WL500G is not set +# CONFIG_TARGET_brcm_2_4_WL500GD is not set +# CONFIG_TARGET_brcm_2_4_WL500GP is not set +# CONFIG_TARGET_brcm_2_4_WL700GE is not set +# CONFIG_TARGET_brcm_2_4_WLHDD is not set +# CONFIG_TARGET_brcm_2_4_WRT54G3G is not set +# CONFIG_TARGET_x86_generic_Generic is not set +# CONFIG_TARGET_x86_generic_Alix is not set +# CONFIG_TARGET_x86_generic_Pcengines is not set +# CONFIG_TARGET_x86_generic_Soekris is not set +# CONFIG_TARGET_brcm47xx_Broadcom-b43 is not set +# CONFIG_TARGET_brcm47xx_Atheros is not set +# CONFIG_TARGET_brcm47xx_Atheros-ath5k is not set +# CONFIG_TARGET_brcm47xx_None is not set +# CONFIG_TARGET_brcm47xx_WGT634U is not set +# CONFIG_TARGET_brcm47xx_WL500GPv1 is not set +# CONFIG_TARGET_brcm47xx_WRTSL54GS is not set +CONFIG_TARGET_atheros_Default=y +CONFIG_TARGET_BOARD="atheros" +CONFIG_LINUX_2_6_26=y +CONFIG_DEFAULT_base-files=y +CONFIG_DEFAULT_bridge=y +CONFIG_DEFAULT_busybox=y +CONFIG_DEFAULT_dnsmasq=y +CONFIG_DEFAULT_dropbear=y +CONFIG_DEFAULT_firewall=y +CONFIG_DEFAULT_gpioctl=y +CONFIG_DEFAULT_hostapd-mini=y +CONFIG_DEFAULT_hotplug2=y +CONFIG_DEFAULT_iptables=y +CONFIG_DEFAULT_kmod-ipt-nathelper=y +CONFIG_DEFAULT_kmod-madwifi=y +CONFIG_DEFAULT_libgcc=y +CONFIG_DEFAULT_mtd=y +CONFIG_DEFAULT_opkg=y +CONFIG_DEFAULT_ppp=y +CONFIG_DEFAULT_ppp-mod-pppoe=y +CONFIG_DEFAULT_uci=y +CONFIG_DEFAULT_uclibc=y +CONFIG_DEFAULT_udevtrigger=y +CONFIG_LINUX_2_6=y +CONFIG_GPIO_SUPPORT=y +CONFIG_PCI_SUPPORT=y +CONFIG_USB_SUPPORT=y +CONFIG_BIG_ENDIAN=y +CONFIG_USES_SQUASHFS=y +CONFIG_USES_JFFS2=y +CONFIG_mips=y +CONFIG_ARCH="mips" + +# +# Target Images +# +# CONFIG_TARGET_ROOTFS_INITRAMFS is not set +CONFIG_TARGET_ROOTFS_JFFS2=y +CONFIG_TARGET_ROOTFS_SQUASHFS=y +# CONFIG_TARGET_ROOTFS_TGZ is not set +# CONFIG_TARGET_ROOTFS_CPIOGZ is not set +# CONFIG_TARGET_ROOTFS_EXT2FS is not set + +# +# Image Options +# +CONFIG_X86_GRUB_ROOTPART="/dev/hda2" +CONFIG_X86_GRUB_BOOTOPTS="" +# CONFIG_ALL is not set +# CONFIG_DEVEL is not set +# CONFIG_BROKEN is not set +CONFIG_DOWNLOAD_FOLDER="" +# CONFIG_DEBUG is not set +# CONFIG_NO_STRIP is not set +# CONFIG_CLEAN_IPKG is not set +CONFIG_AUTOREBUILD=y +CONFIG_BUILD_SUFFIX="" +# CONFIG_TAR_VERBOSITY is not set +# CONFIG_CCACHE is not set +CONFIG_EXTERNAL_KERNEL_TREE="" +# CONFIG_NATIVE_TOOLCHAIN is not set +# CONFIG_EXTRA_TARGET_ARCH is not set +CONFIG_EXTRA_BINUTILS_CONFIG_OPTIONS="" +CONFIG_BINUTILS_VERSION="2.17" +CONFIG_EXTRA_GCC_CONFIG_OPTIONS="" +# CONFIG_SSP_SUPPORT is not set +CONFIG_INSTALL_LIBSTDCPP=y +# CONFIG_INSTALL_LIBGCJ is not set +CONFIG_UCLIBC_EXTRA_VERSION="" +# CONFIG_GDB is not set +CONFIG_LARGEFILE=y +CONFIG_SHADOW_PASSWORDS=y +CONFIG_TARGET_OPTIMIZATION="-Os -pipe -mips32 -mtune=mips32 -funit-at-a-time" +CONFIG_GCC_VERSION="4.1.2" +CONFIG_UCLIBC_VERSION="0.9.29" +# CONFIG_IB is not set +# CONFIG_SDK is not set +# CONFIG_UCI_PRECONFIG is not set +CONFIG_UCI_PRECONFIG_network_lan_dns="" +CONFIG_UCI_PRECONFIG_network_lan_proto="static" +CONFIG_UCI_PRECONFIG_network_lan_gateway="" +CONFIG_UCI_PRECONFIG_network_lan_netmask="255.255.255.0" +CONFIG_UCI_PRECONFIG_network_lan_ipaddr="192.168.1.1" + +# +# Base system +# +CONFIG_PACKAGE_base-files=y +# CONFIG_PACKAGE_br2684ctl is not set +CONFIG_PACKAGE_bridge=y +CONFIG_PACKAGE_busybox=y + +# +# Configuration +# +# CONFIG_BUSYBOX_CONFIG_FEATURE_DEVFS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_2_4_MODULES is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_2_6_MODULES=y +CONFIG_BUSYBOX_CONFIG_HAVE_DOT_CONFIG=y + +# +# Busybox Settings +# + +# +# General Configuration +# +# CONFIG_BUSYBOX_CONFIG_DESKTOP is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_ASSUME_UNICODE is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_BUSYBOX_CONFIG_SHOW_USAGE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VERBOSE_USAGE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_COMPRESS_USAGE=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_INSTALLER is not set +# CONFIG_BUSYBOX_CONFIG_LOCALE_SUPPORT is not set +CONFIG_BUSYBOX_CONFIG_GETOPT_LONG=y +CONFIG_BUSYBOX_CONFIG_FEATURE_DEVPTS=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_CLEAN_UP is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_PIDFILE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_SUID=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_SUID_CONFIG is not set +# CONFIG_BUSYBOX_CONFIG_SELINUX is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS=y +CONFIG_BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" +CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HAVE_RPC=y + +# +# Build Options +# +# CONFIG_BUSYBOX_CONFIG_STATIC is not set +# CONFIG_BUSYBOX_CONFIG_PIE is not set +# CONFIG_BUSYBOX_CONFIG_NOMMU is not set +CONFIG_BUSYBOX_CONFIG_LFS=y +CONFIG_BUSYBOX_CONFIG_CROSS_COMPILER_PREFIX="" + +# +# Debugging Options +# +# CONFIG_BUSYBOX_CONFIG_DEBUG is not set +# CONFIG_BUSYBOX_CONFIG_WERROR is not set +CONFIG_BUSYBOX_CONFIG_NO_DEBUG_LIB=y +# CONFIG_BUSYBOX_CONFIG_DMALLOC is not set +# CONFIG_BUSYBOX_CONFIG_EFENCE is not set +CONFIG_BUSYBOX_CONFIG_INCLUDE_SUSv2=y + +# +# Installation Options +# +# CONFIG_BUSYBOX_CONFIG_INSTALL_NO_USR is not set +CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS=y +# CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_DONT is not set +CONFIG_BUSYBOX_CONFIG_PREFIX="./_install" + +# +# Busybox Library Tuning +# +CONFIG_BUSYBOX_CONFIG_PASSWORD_MINLEN=6 +CONFIG_BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED=2 +CONFIG_BUSYBOX_CONFIG_FEATURE_FAST_TOP=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_ETC_NETWORKS is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING=y +CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_MAX_LEN=512 +# CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_VI is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_HISTORY=256 +# CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_USERNAME_COMPLETION is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_COPYBUF_KB=4 +# CONFIG_BUSYBOX_CONFIG_MONOTONIC_SYSCALL is not set +CONFIG_BUSYBOX_CONFIG_IOCTL_HEX2STR_ERROR=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_HWIB is not set + +# +# Applets +# + +# +# Archival Utilities +# +# CONFIG_BUSYBOX_CONFIG_AR is not set +CONFIG_BUSYBOX_CONFIG_BUNZIP2=y +# CONFIG_BUSYBOX_CONFIG_BZIP2 is not set +# CONFIG_BUSYBOX_CONFIG_CPIO is not set +# CONFIG_BUSYBOX_CONFIG_DPKG is not set +# CONFIG_BUSYBOX_CONFIG_DPKG_DEB is not set +CONFIG_BUSYBOX_CONFIG_GUNZIP=y +CONFIG_BUSYBOX_CONFIG_FEATURE_GUNZIP_UNCOMPRESS=y +CONFIG_BUSYBOX_CONFIG_GZIP=y +# CONFIG_BUSYBOX_CONFIG_RPM2CPIO is not set +# CONFIG_BUSYBOX_CONFIG_RPM is not set +CONFIG_BUSYBOX_CONFIG_TAR=y +CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_CREATE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_GZIP=y +CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_BZIP2=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_LZMA is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_COMPRESS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_AUTODETECT is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_FROM=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_UNAME_GNAME is not set +# CONFIG_BUSYBOX_CONFIG_UNCOMPRESS is not set +# CONFIG_BUSYBOX_CONFIG_UNLZMA is not set +# CONFIG_BUSYBOX_CONFIG_UNZIP is not set + +# +# Common options for cpio and tar +# + +# +# Coreutils +# +CONFIG_BUSYBOX_CONFIG_BASENAME=y +# CONFIG_BUSYBOX_CONFIG_CAL is not set +CONFIG_BUSYBOX_CONFIG_CAT=y +# CONFIG_BUSYBOX_CONFIG_CATV is not set +CONFIG_BUSYBOX_CONFIG_CHGRP=y +CONFIG_BUSYBOX_CONFIG_CHMOD=y +CONFIG_BUSYBOX_CONFIG_CHOWN=y +CONFIG_BUSYBOX_CONFIG_CHROOT=y +# CONFIG_BUSYBOX_CONFIG_CKSUM is not set +# CONFIG_BUSYBOX_CONFIG_COMM is not set +CONFIG_BUSYBOX_CONFIG_CP=y +CONFIG_BUSYBOX_CONFIG_CUT=y +CONFIG_BUSYBOX_CONFIG_DATE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_DATE_ISOFMT=y +CONFIG_BUSYBOX_CONFIG_DD=y +CONFIG_BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_DD_IBS_OBS is not set +CONFIG_BUSYBOX_CONFIG_DF=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_DF_INODE is not set +CONFIG_BUSYBOX_CONFIG_DIRNAME=y +# CONFIG_BUSYBOX_CONFIG_DOS2UNIX is not set +CONFIG_BUSYBOX_CONFIG_DU=y +CONFIG_BUSYBOX_CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y +CONFIG_BUSYBOX_CONFIG_ECHO=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_ECHO=y +CONFIG_BUSYBOX_CONFIG_ENV=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_ENV_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_CONFIG_EXPAND is not set +CONFIG_BUSYBOX_CONFIG_EXPR=y +# CONFIG_BUSYBOX_CONFIG_EXPR_MATH_SUPPORT_64 is not set +CONFIG_BUSYBOX_CONFIG_FALSE=y +# CONFIG_BUSYBOX_CONFIG_FOLD is not set +CONFIG_BUSYBOX_CONFIG_HEAD=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_HEAD=y +CONFIG_BUSYBOX_CONFIG_HOSTID=y +CONFIG_BUSYBOX_CONFIG_ID=y +# CONFIG_BUSYBOX_CONFIG_INSTALL is not set +CONFIG_BUSYBOX_CONFIG_LENGTH=y +CONFIG_BUSYBOX_CONFIG_LN=y +# CONFIG_BUSYBOX_CONFIG_LOGNAME is not set +CONFIG_BUSYBOX_CONFIG_LS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_FILETYPES=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_FOLLOWLINKS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_RECURSIVE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_SORTFILES=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_TIMESTAMPS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_USERNAME=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_COLOR=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y +CONFIG_BUSYBOX_CONFIG_MD5SUM=y +CONFIG_BUSYBOX_CONFIG_MKDIR=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set +CONFIG_BUSYBOX_CONFIG_MKFIFO=y +CONFIG_BUSYBOX_CONFIG_MKNOD=y +CONFIG_BUSYBOX_CONFIG_MV=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_MV_LONG_OPTIONS is not set +CONFIG_BUSYBOX_CONFIG_NICE=y +# CONFIG_BUSYBOX_CONFIG_NOHUP is not set +# CONFIG_BUSYBOX_CONFIG_OD is not set +# CONFIG_BUSYBOX_CONFIG_PRINTENV is not set +CONFIG_BUSYBOX_CONFIG_PRINTF=y +CONFIG_BUSYBOX_CONFIG_PWD=y +# CONFIG_BUSYBOX_CONFIG_READLINK is not set +# CONFIG_BUSYBOX_CONFIG_REALPATH is not set +CONFIG_BUSYBOX_CONFIG_RM=y +CONFIG_BUSYBOX_CONFIG_RMDIR=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set +CONFIG_BUSYBOX_CONFIG_SEQ=y +# CONFIG_BUSYBOX_CONFIG_SHA1SUM is not set +CONFIG_BUSYBOX_CONFIG_SLEEP=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP=y +CONFIG_BUSYBOX_CONFIG_SORT=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_SORT_BIG is not set +# CONFIG_BUSYBOX_CONFIG_SPLIT is not set +# CONFIG_BUSYBOX_CONFIG_STAT is not set +CONFIG_BUSYBOX_CONFIG_STTY=y +# CONFIG_BUSYBOX_CONFIG_SUM is not set +CONFIG_BUSYBOX_CONFIG_SYNC=y +# CONFIG_BUSYBOX_CONFIG_TAC is not set +CONFIG_BUSYBOX_CONFIG_TAIL=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_TAIL=y +CONFIG_BUSYBOX_CONFIG_TEE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_TEE_USE_BLOCK_IO=y +CONFIG_BUSYBOX_CONFIG_TEST=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_TEST_64 is not set +CONFIG_BUSYBOX_CONFIG_TOUCH=y +CONFIG_BUSYBOX_CONFIG_TR=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_TR_CLASSES is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_TR_EQUIV is not set +CONFIG_BUSYBOX_CONFIG_TRUE=y +# CONFIG_BUSYBOX_CONFIG_TTY is not set +CONFIG_BUSYBOX_CONFIG_UNAME=y +# CONFIG_BUSYBOX_CONFIG_UNEXPAND is not set +CONFIG_BUSYBOX_CONFIG_UNIQ=y +# CONFIG_BUSYBOX_CONFIG_USLEEP is not set +# CONFIG_BUSYBOX_CONFIG_UUDECODE is not set +# CONFIG_BUSYBOX_CONFIG_UUENCODE is not set +CONFIG_BUSYBOX_CONFIG_WC=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_WC_LARGE is not set +# CONFIG_BUSYBOX_CONFIG_WHO is not set +# CONFIG_BUSYBOX_CONFIG_WHOAMI is not set +CONFIG_BUSYBOX_CONFIG_YES=y + +# +# Common options for cp and mv +# +CONFIG_BUSYBOX_CONFIG_FEATURE_PRESERVE_HARDLINKS=y + +# +# Common options for ls, more and telnet +# +CONFIG_BUSYBOX_CONFIG_FEATURE_AUTOWIDTH=y + +# +# Common options for df, du, ls +# +CONFIG_BUSYBOX_CONFIG_FEATURE_HUMAN_READABLE=y + +# +# Common options for md5sum, sha1sum +# +CONFIG_BUSYBOX_CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y + +# +# Console Utilities +# +# CONFIG_BUSYBOX_CONFIG_CHVT is not set +CONFIG_BUSYBOX_CONFIG_CLEAR=y +# CONFIG_BUSYBOX_CONFIG_DEALLOCVT is not set +# CONFIG_BUSYBOX_CONFIG_DUMPKMAP is not set +# CONFIG_BUSYBOX_CONFIG_KBD_MODE is not set +# CONFIG_BUSYBOX_CONFIG_LOADFONT is not set +# CONFIG_BUSYBOX_CONFIG_LOADKMAP is not set +# CONFIG_BUSYBOX_CONFIG_OPENVT is not set +CONFIG_BUSYBOX_CONFIG_RESET=y +# CONFIG_BUSYBOX_CONFIG_RESIZE is not set +# CONFIG_BUSYBOX_CONFIG_SETCONSOLE is not set +# CONFIG_BUSYBOX_CONFIG_SETKEYCODES is not set +# CONFIG_BUSYBOX_CONFIG_SETLOGCONS is not set + +# +# Debian Utilities +# +CONFIG_BUSYBOX_CONFIG_MKTEMP=y +# CONFIG_BUSYBOX_CONFIG_PIPE_PROGRESS is not set +# CONFIG_BUSYBOX_CONFIG_RUN_PARTS is not set +CONFIG_BUSYBOX_CONFIG_START_STOP_DAEMON=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +CONFIG_BUSYBOX_CONFIG_WHICH=y + +# +# Editors +# +CONFIG_BUSYBOX_CONFIG_AWK=y +CONFIG_BUSYBOX_CONFIG_FEATURE_AWK_MATH=y +# CONFIG_BUSYBOX_CONFIG_CMP is not set +CONFIG_BUSYBOX_CONFIG_DIFF=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_DIFF_BINARY is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_DIFF_DIR is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_DIFF_MINIMAL is not set +# CONFIG_BUSYBOX_CONFIG_ED is not set +CONFIG_BUSYBOX_CONFIG_PATCH=y +CONFIG_BUSYBOX_CONFIG_SED=y +CONFIG_BUSYBOX_CONFIG_VI=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_MAX_LEN=1024 +# CONFIG_BUSYBOX_CONFIG_FEATURE_VI_8BIT is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_COLON=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_YANKMARK=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SEARCH=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_USE_SIGNALS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_DOT_CMD=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_READONLY=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SETOPTS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SET=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_WIN_RESIZE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y +CONFIG_BUSYBOX_CONFIG_FEATURE_ALLOW_EXEC=y + +# +# Finding Utilities +# +CONFIG_BUSYBOX_CONFIG_FIND=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PRINT0=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MTIME is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MMIN is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PERM=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_TYPE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_XDEV=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MAXDEPTH=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_NEWER is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_INUM is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_EXEC=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_USER=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_GROUP=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_NOT=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_DEPTH=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PAREN=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_SIZE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PRUNE=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_DELETE is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PATH=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_REGEX=y +CONFIG_BUSYBOX_CONFIG_GREP=y +CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_EGREP_ALIAS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_FGREP_ALIAS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_CONTEXT=y +CONFIG_BUSYBOX_CONFIG_XARGS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y +CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y +CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y +CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y + +# +# Init Utilities +# +CONFIG_BUSYBOX_CONFIG_INIT=y +# CONFIG_BUSYBOX_CONFIG_DEBUG_INIT is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_USE_INITTAB=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_KILL_DELAY=0 +# CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_SCTTY is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_SYSLOG=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_EXTRA_QUIET is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_COREDUMPS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_INITRD is not set +CONFIG_BUSYBOX_CONFIG_HALT=y +CONFIG_BUSYBOX_CONFIG_MESG=y + +# +# Login/Password Management Utilities +# +# CONFIG_BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS is not set +# CONFIG_BUSYBOX_CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_BUSYBOX_CONFIG_USE_BB_CRYPT is not set +# CONFIG_BUSYBOX_CONFIG_ADDGROUP is not set +# CONFIG_BUSYBOX_CONFIG_DELGROUP is not set +# CONFIG_BUSYBOX_CONFIG_ADDUSER is not set +# CONFIG_BUSYBOX_CONFIG_DELUSER is not set +# CONFIG_BUSYBOX_CONFIG_GETTY is not set +# CONFIG_BUSYBOX_CONFIG_LOGIN is not set +CONFIG_BUSYBOX_CONFIG_PASSWD=y +CONFIG_BUSYBOX_CONFIG_FEATURE_PASSWD_WEAK_CHECK=y +# CONFIG_BUSYBOX_CONFIG_CRYPTPW is not set +# CONFIG_BUSYBOX_CONFIG_CHPASSWD is not set +# CONFIG_BUSYBOX_CONFIG_SU is not set +# CONFIG_BUSYBOX_CONFIG_SULOGIN is not set +# CONFIG_BUSYBOX_CONFIG_VLOCK is not set + +# +# Linux Ext2 FS Progs +# +# CONFIG_BUSYBOX_CONFIG_CHATTR is not set +# CONFIG_BUSYBOX_CONFIG_FSCK is not set +# CONFIG_BUSYBOX_CONFIG_LSATTR is not set + +# +# Linux Module Utilities +# +# CONFIG_BUSYBOX_CONFIG_DEPMOD is not set +CONFIG_BUSYBOX_CONFIG_INSMOD=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +CONFIG_BUSYBOX_CONFIG_RMMOD=y +CONFIG_BUSYBOX_CONFIG_LSMOD=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y +# CONFIG_BUSYBOX_CONFIG_MODPROBE is not set + +# +# Options common to multiple modutils +# +CONFIG_BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE=y +CONFIG_BUSYBOX_CONFIG_DEFAULT_MODULES_DIR="/lib/modules" +CONFIG_BUSYBOX_CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" + +# +# Linux System Utilities +# +CONFIG_BUSYBOX_CONFIG_DMESG=y +CONFIG_BUSYBOX_CONFIG_FEATURE_DMESG_PRETTY=y +# CONFIG_BUSYBOX_CONFIG_FBSET is not set +# CONFIG_BUSYBOX_CONFIG_FDFLUSH is not set +# CONFIG_BUSYBOX_CONFIG_FDFORMAT is not set +# CONFIG_BUSYBOX_CONFIG_FDISK is not set +CONFIG_BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS=y +# CONFIG_BUSYBOX_CONFIG_FINDFS is not set +# CONFIG_BUSYBOX_CONFIG_FREERAMDISK is not set +# CONFIG_BUSYBOX_CONFIG_FSCK_MINIX is not set +# CONFIG_BUSYBOX_CONFIG_MKFS_MINIX is not set +# CONFIG_BUSYBOX_CONFIG_GETOPT is not set +CONFIG_BUSYBOX_CONFIG_HEXDUMP=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_HEXDUMP_REVERSE is not set +# CONFIG_BUSYBOX_CONFIG_HD is not set +CONFIG_BUSYBOX_CONFIG_HWCLOCK=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set +# CONFIG_BUSYBOX_CONFIG_IPCRM is not set +# CONFIG_BUSYBOX_CONFIG_IPCS is not set +# CONFIG_BUSYBOX_CONFIG_LOSETUP is not set +# CONFIG_BUSYBOX_CONFIG_MDEV is not set +# CONFIG_BUSYBOX_CONFIG_MKSWAP is not set +# CONFIG_BUSYBOX_CONFIG_MORE is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_USE_TERMIOS is not set +# CONFIG_BUSYBOX_CONFIG_VOLUMEID is not set +CONFIG_BUSYBOX_CONFIG_MOUNT=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_VERBOSE is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_HELPERS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_LABEL is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_NFS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_CIFS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FLAGS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FSTAB=y +CONFIG_BUSYBOX_CONFIG_PIVOT_ROOT=y +CONFIG_BUSYBOX_CONFIG_RDATE=y +# CONFIG_BUSYBOX_CONFIG_READPROFILE is not set +# CONFIG_BUSYBOX_CONFIG_RTCWAKE is not set +# CONFIG_BUSYBOX_CONFIG_SCRIPT is not set +# CONFIG_BUSYBOX_CONFIG_SETARCH is not set +# CONFIG_BUSYBOX_CONFIG_SWAPONOFF is not set +CONFIG_BUSYBOX_CONFIG_SWITCH_ROOT=y +CONFIG_BUSYBOX_CONFIG_UMOUNT=y +CONFIG_BUSYBOX_CONFIG_FEATURE_UMOUNT_ALL=y + +# +# Common options for mount/umount +# +CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_MTAB_SUPPORT is not set + +# +# Miscellaneous Utilities +# +# CONFIG_BUSYBOX_CONFIG_ADJTIMEX is not set +# CONFIG_BUSYBOX_CONFIG_BBCONFIG is not set +# CONFIG_BUSYBOX_CONFIG_CHAT is not set +# CONFIG_BUSYBOX_CONFIG_CHRT is not set +CONFIG_BUSYBOX_CONFIG_CROND=y +# CONFIG_BUSYBOX_CONFIG_DEBUG_CROND_OPTION is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +CONFIG_BUSYBOX_CONFIG_CRONTAB=y +# CONFIG_BUSYBOX_CONFIG_DC is not set +# CONFIG_BUSYBOX_CONFIG_DEVFSD is not set +# CONFIG_BUSYBOX_CONFIG_EJECT is not set +# CONFIG_BUSYBOX_CONFIG_FBSPLASH is not set +# CONFIG_BUSYBOX_CONFIG_INOTIFYD is not set +# CONFIG_BUSYBOX_CONFIG_LAST is not set +CONFIG_BUSYBOX_CONFIG_LESS=y +CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_MAXLINES=9999999 +# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_BRACKETS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_FLAGS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_FLAGCS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_MARKS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_BUSYBOX_CONFIG_HDPARM is not set +CONFIG_BUSYBOX_CONFIG_LOCK=y +# CONFIG_BUSYBOX_CONFIG_MAKEDEVS is not set +# CONFIG_BUSYBOX_CONFIG_MAN is not set +# CONFIG_BUSYBOX_CONFIG_MICROCOM is not set +# CONFIG_BUSYBOX_CONFIG_MOUNTPOINT is not set +# CONFIG_BUSYBOX_CONFIG_MT is not set +# CONFIG_BUSYBOX_CONFIG_RAIDAUTORUN is not set +# CONFIG_BUSYBOX_CONFIG_READAHEAD is not set +# CONFIG_BUSYBOX_CONFIG_RUNLEVEL is not set +# CONFIG_BUSYBOX_CONFIG_RX is not set +# CONFIG_BUSYBOX_CONFIG_SETSID is not set +CONFIG_BUSYBOX_CONFIG_STRINGS=y +# CONFIG_BUSYBOX_CONFIG_TASKSET is not set +CONFIG_BUSYBOX_CONFIG_TIME=y +# CONFIG_BUSYBOX_CONFIG_TTYSIZE is not set +CONFIG_BUSYBOX_CONFIG_WATCHDOG=y + +# +# Networking Utilities +# +CONFIG_BUSYBOX_CONFIG_FEATURE_IPV6=y +CONFIG_BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y +CONFIG_BUSYBOX_CONFIG_VERBOSE_RESOLUTION_ERRORS=y +# CONFIG_BUSYBOX_CONFIG_ARP is not set +CONFIG_BUSYBOX_CONFIG_ARPING=y +# CONFIG_BUSYBOX_CONFIG_BRCTL is not set +# CONFIG_BUSYBOX_CONFIG_DNSD is not set +# CONFIG_BUSYBOX_CONFIG_ETHER_WAKE is not set +# CONFIG_BUSYBOX_CONFIG_FAKEIDENTD is not set +# CONFIG_BUSYBOX_CONFIG_FTPGET is not set +# CONFIG_BUSYBOX_CONFIG_FTPPUT is not set +# CONFIG_BUSYBOX_CONFIG_HOSTNAME is not set +CONFIG_BUSYBOX_CONFIG_HTTPD=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_RANGES=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_BASIC_AUTH=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_AUTH_MD5=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_CGI=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_ERROR_PAGES=y +CONFIG_BUSYBOX_CONFIG_FEATURE_HTTPD_PROXY=y +CONFIG_BUSYBOX_CONFIG_IFCONFIG=y +CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_STATUS=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_HW=y +CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y +# CONFIG_BUSYBOX_CONFIG_IFENSLAVE is not set +# CONFIG_BUSYBOX_CONFIG_IFUPDOWN is not set +# CONFIG_BUSYBOX_CONFIG_INETD is not set +# CONFIG_BUSYBOX_CONFIG_IP is not set +# CONFIG_BUSYBOX_CONFIG_IPCALC is not set +# CONFIG_BUSYBOX_CONFIG_NAMEIF is not set +# CONFIG_BUSYBOX_CONFIG_NC is not set +CONFIG_BUSYBOX_CONFIG_NETMSG=y +CONFIG_BUSYBOX_CONFIG_NETSTAT=y +CONFIG_BUSYBOX_CONFIG_FEATURE_NETSTAT_WIDE=y +CONFIG_BUSYBOX_CONFIG_NSLOOKUP=y +CONFIG_BUSYBOX_CONFIG_PING=y +CONFIG_BUSYBOX_CONFIG_PING6=y +CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_PING=y +# CONFIG_BUSYBOX_CONFIG_PSCAN is not set +CONFIG_BUSYBOX_CONFIG_ROUTE=y +# CONFIG_BUSYBOX_CONFIG_SENDMAIL is not set +# CONFIG_BUSYBOX_CONFIG_FETCHMAIL is not set +# CONFIG_BUSYBOX_CONFIG_SLATTACH is not set +# CONFIG_BUSYBOX_CONFIG_TELNET is not set +# CONFIG_BUSYBOX_CONFIG_TELNETD is not set +# CONFIG_BUSYBOX_CONFIG_TFTP is not set +# CONFIG_BUSYBOX_CONFIG_TFTPD is not set +CONFIG_BUSYBOX_CONFIG_TRACEROUTE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_VERBOSE=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_BUSYBOX_CONFIG_APP_UDHCPD is not set +CONFIG_BUSYBOX_CONFIG_APP_UDHCPC=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCPC_ARPING is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCP_PORT is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCP_DEBUG is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_RFC3397=y +CONFIG_BUSYBOX_CONFIG_DHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +CONFIG_BUSYBOX_CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 +CONFIG_BUSYBOX_CONFIG_VCONFIG=y +CONFIG_BUSYBOX_CONFIG_WGET=y +CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_STATUSBAR=y +CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_AUTHENTICATION=y +CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS=y +# CONFIG_BUSYBOX_CONFIG_ZCIP is not set +# CONFIG_BUSYBOX_CONFIG_TCPSVD is not set +# CONFIG_BUSYBOX_CONFIG_UDPSVD is not set + +# +# Process Utilities +# +CONFIG_BUSYBOX_CONFIG_FREE=y +# CONFIG_BUSYBOX_CONFIG_FUSER is not set +CONFIG_BUSYBOX_CONFIG_KILL=y +CONFIG_BUSYBOX_CONFIG_KILLALL=y +CONFIG_BUSYBOX_CONFIG_KILLALL5=y +# CONFIG_BUSYBOX_CONFIG_NMETER is not set +CONFIG_BUSYBOX_CONFIG_PGREP=y +CONFIG_BUSYBOX_CONFIG_PIDOF=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_PIDOF_SINGLE is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_PIDOF_OMIT is not set +CONFIG_BUSYBOX_CONFIG_PKILL=y +CONFIG_BUSYBOX_CONFIG_PS=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_PS_WIDE is not set +# CONFIG_BUSYBOX_CONFIG_RENICE is not set +CONFIG_BUSYBOX_CONFIG_BB_SYSCTL=y +CONFIG_BUSYBOX_CONFIG_TOP=y +CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_DECIMALS is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_TOPMEM is not set +CONFIG_BUSYBOX_CONFIG_UPTIME=y +# CONFIG_BUSYBOX_CONFIG_WATCH is not set + +# +# Shells +# +CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_ASH=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_MSH is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_NONE is not set +CONFIG_BUSYBOX_CONFIG_ASH=y + +# +# Ash Shell Options +# +CONFIG_BUSYBOX_CONFIG_ASH_BASH_COMPAT=y +CONFIG_BUSYBOX_CONFIG_ASH_JOB_CONTROL=y +# CONFIG_BUSYBOX_CONFIG_ASH_READ_NCHARS is not set +CONFIG_BUSYBOX_CONFIG_ASH_READ_TIMEOUT=y +CONFIG_BUSYBOX_CONFIG_ASH_ALIAS=y +CONFIG_BUSYBOX_CONFIG_ASH_MATH_SUPPORT=y +CONFIG_BUSYBOX_CONFIG_ASH_MATH_SUPPORT_64=y +CONFIG_BUSYBOX_CONFIG_ASH_GETOPTS=y +CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_ECHO=y +CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_PRINTF=y +CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_TEST=y +CONFIG_BUSYBOX_CONFIG_ASH_CMDCMD=y +# CONFIG_BUSYBOX_CONFIG_ASH_MAIL is not set +# CONFIG_BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set +# CONFIG_BUSYBOX_CONFIG_ASH_RANDOM_SUPPORT is not set +CONFIG_BUSYBOX_CONFIG_ASH_EXPAND_PRMT=y +# CONFIG_BUSYBOX_CONFIG_HUSH is not set +# CONFIG_BUSYBOX_CONFIG_LASH is not set +# CONFIG_BUSYBOX_CONFIG_MSH is not set + +# +# Bourne Shell Options +# +# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_STANDALONE is not set +# CONFIG_BUSYBOX_CONFIG_FEATURE_SH_NOFORK is not set +# CONFIG_BUSYBOX_CONFIG_CTTYHACK is not set + +# +# System Logging Utilities +# +CONFIG_BUSYBOX_CONFIG_SYSLOGD=y +CONFIG_BUSYBOX_CONFIG_FEATURE_ROTATE_LOGFILE=y +CONFIG_BUSYBOX_CONFIG_FEATURE_REMOTE_LOG=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOGD_DUP is not set +CONFIG_BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG=y +CONFIG_BUSYBOX_CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16 +CONFIG_BUSYBOX_CONFIG_LOGREAD=y +# CONFIG_BUSYBOX_CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set +CONFIG_BUSYBOX_CONFIG_KLOGD=y +CONFIG_BUSYBOX_CONFIG_LOGGER=y + +# +# Runit Utilities +# +# CONFIG_BUSYBOX_CONFIG_RUNSV is not set +# CONFIG_BUSYBOX_CONFIG_RUNSVDIR is not set +# CONFIG_BUSYBOX_CONFIG_SV is not set +# CONFIG_BUSYBOX_CONFIG_SVLOGD is not set +# CONFIG_BUSYBOX_CONFIG_CHPST is not set +# CONFIG_BUSYBOX_CONFIG_SETUIDGID is not set +# CONFIG_BUSYBOX_CONFIG_ENVUIDGID is not set +# CONFIG_BUSYBOX_CONFIG_ENVDIR is not set +# CONFIG_BUSYBOX_CONFIG_SOFTLIMIT is not set + +# +# Print Utilities +# +# CONFIG_BUSYBOX_CONFIG_LPD is not set +# CONFIG_BUSYBOX_CONFIG_LPR is not set +# CONFIG_BUSYBOX_CONFIG_LPQ is not set +CONFIG_PACKAGE_dnsmasq=y +CONFIG_PACKAGE_dropbear=y +CONFIG_PACKAGE_firewall=y +CONFIG_PACKAGE_hotplug2=y +CONFIG_PACKAGE_iptables=y +CONFIG_PACKAGE_iptables-mod-conntrack=y +# CONFIG_PACKAGE_iptables-mod-conntrack-extra is not set +# CONFIG_PACKAGE_iptables-mod-extra is not set +# CONFIG_PACKAGE_iptables-mod-filter is not set +# CONFIG_PACKAGE_iptables-mod-imq is not set +# CONFIG_PACKAGE_iptables-mod-ipopt is not set +# CONFIG_PACKAGE_iptables-mod-iprange is not set +# CONFIG_PACKAGE_iptables-mod-ipsec is not set +# CONFIG_PACKAGE_iptables-mod-ipset is not set +CONFIG_PACKAGE_iptables-mod-nat=y +# CONFIG_PACKAGE_iptables-mod-nat-extra is not set +# CONFIG_PACKAGE_iptables-mod-ulog is not set +# CONFIG_PACKAGE_iptables-utils is not set +# CONFIG_PACKAGE_ldconfig is not set +# CONFIG_PACKAGE_ldd is not set +CONFIG_PACKAGE_libgcc=y +# CONFIG_PACKAGE_libpthread is not set +# CONFIG_PACKAGE_libstdcpp is not set +CONFIG_PACKAGE_mtd=y +CONFIG_PACKAGE_opkg=y +# CONFIG_PACKAGE_qos-scripts is not set +CONFIG_PACKAGE_uci=y +CONFIG_PACKAGE_uclibc=y +CONFIG_PACKAGE_udevtrigger=y +CONFIG_PACKAGE_wireless-tools=y + +# +# Libraries +# + +# +# disc +# +# CONFIG_PACKAGE_libfuse is not set +# CONFIG_PACKAGE_libblkid is not set +CONFIG_PACKAGE_libexpat=y +# CONFIG_PACKAGE_libext2fs is not set +# CONFIG_PACKAGE_libiw is not set +# CONFIG_PACKAGE_libltdl is not set +CONFIG_PACKAGE_liblua=y +# CONFIG_PACKAGE_libncurses is not set +# CONFIG_PACKAGE_libnl is not set +# CONFIG_PACKAGE_libopenssl is not set +# CONFIG_PACKAGE_libpcap is not set +# CONFIG_PACKAGE_libreadline is not set +CONFIG_PACKAGE_libuci=y +CONFIG_PACKAGE_libuci-lua=y +# CONFIG_PACKAGE_libuuid is not set +CONFIG_PACKAGE_libxyssl=y +# CONFIG_PACKAGE_linux-atm is not set +# CONFIG_PACKAGE_zlib is not set + +# +# Network +# + +# +# Time Synchronization +# +CONFIG_PACKAGE_ntpclient=y +# CONFIG_PACKAGE_arptables is not set +# CONFIG_PACKAGE_chat is not set +# CONFIG_PACKAGE_ebtables is not set +# CONFIG_PACKAGE_ebtables-utils is not set +# CONFIG_PACKAGE_genl is not set +# CONFIG_PACKAGE_hostapd is not set +CONFIG_PACKAGE_hostapd-mini=y +# CONFIG_PACKAGE_hostapd-utils is not set +# CONFIG_PACKAGE_ifenslave is not set +# CONFIG_PACKAGE_ip is not set +# CONFIG_PACKAGE_ipset is not set +# CONFIG_PACKAGE_iw is not set +CONFIG_PACKAGE_ppp=y +# CONFIG_PACKAGE_ppp-mod-pppoa is not set +CONFIG_PACKAGE_ppp-mod-pppoe=y +CONFIG_PACKAGE_ppp-mod-radius=y +# CONFIG_PACKAGE_pppdump is not set +# CONFIG_PACKAGE_pppstats is not set +CONFIG_PACKAGE_pptp=y +# CONFIG_PACKAGE_tc is not set +CONFIG_PACKAGE_wpa-supplicant=y +# CONFIG_WPA_SUPPLICANT_NO_TIMESTAMP_CHECK is not set +CONFIG_WPA_SUPPLICANT_INTERNAL=y +# CONFIG_WPA_SUPPLICANT_OPENSSL is not set +CONFIG_PACKAGE_wpa-cli=y + +# +# IPv6 +# +# CONFIG_PACKAGE_ip6tables is not set + +# +# Kernel modules +# + +# +# Block Devices +# +# CONFIG_PACKAGE_kmod-ata-core is not set +# CONFIG_PACKAGE_kmod-ide-aec62xx is not set +# CONFIG_PACKAGE_kmod-ide-core is not set +# CONFIG_PACKAGE_kmod-loop is not set +# CONFIG_PACKAGE_kmod-nbd is not set +# CONFIG_PACKAGE_kmod-scsi-core is not set +# CONFIG_PACKAGE_kmod-scsi-generic is not set + +# +# Cryptographic API modules +# +# CONFIG_PACKAGE_kmod-crypto-aead is not set +# CONFIG_PACKAGE_kmod-crypto-aes is not set +# CONFIG_PACKAGE_kmod-crypto-arc4 is not set +# CONFIG_PACKAGE_kmod-crypto-authenc is not set +# CONFIG_PACKAGE_kmod-crypto-core is not set +# CONFIG_PACKAGE_kmod-crypto-des is not set +# CONFIG_PACKAGE_kmod-crypto-hmac is not set +# CONFIG_PACKAGE_kmod-crypto-hw-geode is not set +# CONFIG_PACKAGE_kmod-crypto-hw-hifn-795x is not set +# CONFIG_PACKAGE_kmod-crypto-hw-padlock is not set +# CONFIG_PACKAGE_kmod-crypto-md5 is not set +# CONFIG_PACKAGE_kmod-crypto-michael-mic is not set +# CONFIG_PACKAGE_kmod-crypto-misc is not set +# CONFIG_PACKAGE_kmod-crypto-null is not set +# CONFIG_PACKAGE_kmod-crypto-ocf is not set +# CONFIG_PACKAGE_kmod-crypto-sha1 is not set +# CONFIG_PACKAGE_kmod-crypto-test is not set + +# +# Filesystems +# +# CONFIG_PACKAGE_kmod-fs-cifs is not set +# CONFIG_PACKAGE_kmod-fs-ext2 is not set +# CONFIG_PACKAGE_kmod-fs-ext3 is not set +# CONFIG_PACKAGE_kmod-fs-hfs is not set +# CONFIG_PACKAGE_kmod-fs-hfsplus is not set +# CONFIG_PACKAGE_kmod-fs-isofs is not set +# CONFIG_PACKAGE_kmod-fs-mbcache is not set +# CONFIG_PACKAGE_kmod-fs-minix is not set +# CONFIG_PACKAGE_kmod-fs-msdos is not set +# CONFIG_PACKAGE_kmod-fs-nfs-common is not set +# CONFIG_PACKAGE_kmod-fs-ntfs is not set +# CONFIG_PACKAGE_kmod-fs-reiserfs is not set +# CONFIG_PACKAGE_kmod-fs-udf is not set +# CONFIG_PACKAGE_kmod-fs-vfat is not set +# CONFIG_PACKAGE_kmod-fs-xfs is not set +# CONFIG_PACKAGE_kmod-fuse is not set +# CONFIG_PACKAGE_kmod-nls-base is not set +# CONFIG_PACKAGE_kmod-nls-cp1250 is not set +# CONFIG_PACKAGE_kmod-nls-cp1251 is not set +# CONFIG_PACKAGE_kmod-nls-cp437 is not set +# CONFIG_PACKAGE_kmod-nls-cp850 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-1 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-15 is not set +# CONFIG_PACKAGE_kmod-nls-iso8859-2 is not set +# CONFIG_PACKAGE_kmod-nls-koi8r is not set +# CONFIG_PACKAGE_kmod-nls-utf8 is not set + +# +# Hardware Monitoring Support +# +# CONFIG_PACKAGE_kmod-hwmon-core is not set + +# +# I2C support +# +# CONFIG_PACKAGE_kmod-i2c-core is not set + +# +# Netfilter Extensions +# +# CONFIG_PACKAGE_kmod-arptables is not set +# CONFIG_PACKAGE_kmod-ebtables is not set +# CONFIG_PACKAGE_kmod-ip6tables is not set +CONFIG_PACKAGE_kmod-ipt-core=y +CONFIG_PACKAGE_kmod-ipt-conntrack=y +# CONFIG_PACKAGE_kmod-ipt-conntrack-extra is not set +# CONFIG_PACKAGE_kmod-ipt-extra is not set +# CONFIG_PACKAGE_kmod-ipt-filter is not set +# CONFIG_PACKAGE_kmod-ipt-imq is not set +# CONFIG_PACKAGE_kmod-ipt-ipopt is not set +# CONFIG_PACKAGE_kmod-ipt-iprange is not set +# CONFIG_PACKAGE_kmod-ipt-ipsec is not set +# CONFIG_PACKAGE_kmod-ipt-ipset is not set +CONFIG_PACKAGE_kmod-ipt-nat=y +# CONFIG_PACKAGE_kmod-ipt-nat-extra is not set +CONFIG_PACKAGE_kmod-ipt-nathelper=y +# CONFIG_PACKAGE_kmod-ipt-nathelper-extra is not set +# CONFIG_PACKAGE_kmod-ipt-queue is not set +# CONFIG_PACKAGE_kmod-ipt-ulog is not set + +# +# Network Devices +# +# CONFIG_PACKAGE_kmod-siit is not set +# CONFIG_PACKAGE_kmod-tg3 is not set + +# +# Network Support +# +# CONFIG_PACKAGE_kmod-atm is not set +# CONFIG_PACKAGE_kmod-ax25 is not set +# CONFIG_PACKAGE_kmod-bonding is not set +# CONFIG_PACKAGE_kmod-capi is not set +CONFIG_PACKAGE_kmod-gre=y +# CONFIG_PACKAGE_kmod-ip6-tunnel is not set +# CONFIG_PACKAGE_kmod-ipip is not set +# CONFIG_PACKAGE_kmod-ipsec is not set +# CONFIG_PACKAGE_kmod-iptunnel4 is not set +# CONFIG_PACKAGE_kmod-iptunnel6 is not set +# CONFIG_PACKAGE_kmod-ipv6 is not set +# CONFIG_PACKAGE_kmod-mp-alg is not set +CONFIG_PACKAGE_kmod-ppp=y +# CONFIG_PACKAGE_kmod-mppe is not set +# CONFIG_PACKAGE_kmod-pktgen is not set +# CONFIG_PACKAGE_kmod-ppp-synctty is not set +# CONFIG_PACKAGE_kmod-pppoa is not set +CONFIG_PACKAGE_kmod-pppoe=y +# CONFIG_PACKAGE_kmod-sched is not set +# CONFIG_PACKAGE_kmod-sit is not set +# CONFIG_PACKAGE_kmod-tun is not set + +# +# OCF Configuration +# + +# +# Other modules +# +# CONFIG_PACKAGE_kmod-bluetooth is not set +# CONFIG_PACKAGE_kmod-button-hotplug is not set +# CONFIG_PACKAGE_kmod-crc-itu-t is not set +# CONFIG_PACKAGE_kmod-crc7 is not set +# CONFIG_PACKAGE_kmod-eeprom-93cx6 is not set +# CONFIG_PACKAGE_kmod-gpio-dev is not set +# CONFIG_PACKAGE_kmod-hid is not set +# CONFIG_PACKAGE_kmod-input-core is not set +# CONFIG_PACKAGE_kmod-input-evdev is not set +# CONFIG_PACKAGE_kmod-input-gpio-buttons is not set +# CONFIG_PACKAGE_kmod-input-polldev is not set +CONFIG_PACKAGE_kmod-leds-gpio=y +# CONFIG_PACKAGE_kmod-ledtrig-morse is not set +# CONFIG_PACKAGE_kmod-ledtrig-netdev is not set +# CONFIG_PACKAGE_kmod-mmc is not set +# CONFIG_PACKAGE_kmod-mmc-over-gpio is not set +# CONFIG_PACKAGE_kmod-mmc-spi is not set +# CONFIG_PACKAGE_kmod-softdog is not set +# CONFIG_PACKAGE_kmod-spi-bitbang is not set +# CONFIG_PACKAGE_kmod-spi-dev is not set +# CONFIG_PACKAGE_kmod-spi-gpio is not set +# CONFIG_PACKAGE_kmod-spi-ks8995 is not set +# CONFIG_PACKAGE_kmod-wrt55agv2-spidevs is not set + +# +# Sound Support +# +# CONFIG_PACKAGE_kmod-sound-core is not set + +# +# USB Support +# +# CONFIG_PACKAGE_kmod-usb-core is not set + +# +# Video Support +# +# CONFIG_PACKAGE_kmod-video-core is not set +# CONFIG_PACKAGE_kmod-video-cpia2 is not set +# CONFIG_PACKAGE_kmod-video-ov511 is not set +# CONFIG_PACKAGE_kmod-video-ovcamchip is not set +# CONFIG_PACKAGE_kmod-video-pwc is not set + +# +# W1 support +# +# CONFIG_PACKAGE_kmod-w1 is not set + +# +# Wireless Drivers +# +# CONFIG_PACKAGE_kmod-ath5k is not set +# CONFIG_PACKAGE_kmod-hostap is not set +# CONFIG_PACKAGE_kmod-ieee80211 is not set +# CONFIG_PACKAGE_kmod-ieee80211-softmac is not set +# CONFIG_PACKAGE_kmod-mac80211 is not set +CONFIG_PACKAGE_kmod-madwifi=y +CONFIG_MADWIFI_STABLE=y +# CONFIG_MADWIFI_UPSTREAM is not set +CONFIG_MADWIFI_RCA_MINSTREL=y +# CONFIG_MADWIFI_RCA_ONOE is not set +# CONFIG_MADWIFI_RCA_AMRR is not set +# CONFIG_MADWIFI_RCA_SAMPLERATE is not set +# CONFIG_PACKAGE_kmod-net-airo is not set +# CONFIG_PACKAGE_kmod-net-hermes is not set +# CONFIG_PACKAGE_kmod-net-ipw2100 is not set +# CONFIG_PACKAGE_kmod-net-ipw2200 is not set +# CONFIG_PACKAGE_kmod-net-prism54 is not set +# CONFIG_PACKAGE_kmod-rt2400-pci is not set +# CONFIG_PACKAGE_kmod-rt2500-pci is not set +# CONFIG_PACKAGE_kmod-rt2500-usb is not set +# CONFIG_PACKAGE_kmod-rt2x00-lib is not set +# CONFIG_PACKAGE_kmod-rt2x00-pci is not set +# CONFIG_PACKAGE_kmod-rt2x00-usb is not set +# CONFIG_PACKAGE_kmod-rt61-pci is not set +# CONFIG_PACKAGE_kmod-rt73-usb is not set + +# +# Boot Loaders +# + +# +# Administration +# + +# +# LuCI Components +# +CONFIG_PACKAGE_luci-admin-core=y +# CONFIG_PACKAGE_luci-admin-full is not set +CONFIG_PACKAGE_luci-admin-mini=y +# CONFIG_PACKAGE_luci-admin-rpc is not set +# CONFIG_PACKAGE_luci-app-ddns is not set +# CONFIG_PACKAGE_luci-app-firewall is not set +# CONFIG_PACKAGE_luci-app-hd_idle is not set +# CONFIG_PACKAGE_luci-app-initmgr is not set +# CONFIG_PACKAGE_luci-app-livestats is not set +# CONFIG_PACKAGE_luci-app-mmc_over_gpio is not set +# CONFIG_PACKAGE_luci-app-ntpc is not set +# CONFIG_PACKAGE_luci-app-olsr is not set +# CONFIG_PACKAGE_luci-app-p910nd is not set +# CONFIG_PACKAGE_luci-app-polipo is not set +# CONFIG_PACKAGE_luci-app-qos is not set +# CONFIG_PACKAGE_luci-app-samba is not set +# CONFIG_PACKAGE_luci-app-statistics is not set +# CONFIG_PACKAGE_luci-app-tinyproxy is not set +# CONFIG_PACKAGE_luci-app-upnp is not set +# CONFIG_PACKAGE_luci-app-ushare is not set +# CONFIG_PACKAGE_luci-app-uvc_streamer is not set + +# +# LuCI Freifunk Support +# +# CONFIG_PACKAGE_luci-app-ffwizard-leipzig is not set +# CONFIG_PACKAGE_luci-app-splash is not set +# CONFIG_PACKAGE_luci-freifunk-community is not set +# CONFIG_PACKAGE_luci-mod-freifunk is not set +# CONFIG_PACKAGE_luci-theme-fledermaus is not set +# CONFIG_PACKAGE_luci-theme-freifunk is not set +# CONFIG_PACKAGE_luci-theme-freifunk-bno is not set + +# +# LuCI Libraries +# +CONFIG_PACKAGE_luci-cbi=y +CONFIG_PACKAGE_luci-core=y +CONFIG_PACKAGE_luci-core_compile=y +# CONFIG_PACKAGE_luci-core_stripped is not set +# CONFIG_PACKAGE_luci-core_source is not set +# CONFIG_PACKAGE_luci-fastindex is not set +CONFIG_PACKAGE_luci-http=y +# CONFIG_PACKAGE_luci-ipkg is not set +# CONFIG_PACKAGE_luci-json is not set +CONFIG_PACKAGE_luci-sgi-cgi=y +# CONFIG_PACKAGE_luci-sgi-luci is not set +# CONFIG_PACKAGE_luci-sgi-webuci is not set +CONFIG_PACKAGE_luci-sys=y +CONFIG_PACKAGE_luci-uci=y +CONFIG_PACKAGE_luci-uvl=y +CONFIG_PACKAGE_luci-web=y + +# +# LuCI Themes +# +CONFIG_PACKAGE_luci-theme-base=y +# CONFIG_PACKAGE_luci-theme-openwrt is not set +# CONFIG_PACKAGE_luci-theme-openwrtlight is not set +CONFIG_PACKAGE_luci-theme-oxygen=y + +# +# LuCI Translations +# +CONFIG_PACKAGE_luci-i18n-english=y +# CONFIG_PACKAGE_luci-i18n-french is not set +# CONFIG_PACKAGE_luci-i18n-german is not set +# CONFIG_PACKAGE_luci-i18n-italian is not set +# CONFIG_PACKAGE_luci-i18n-portuguese_brazilian is not set +# CONFIG_PACKAGE_luci-i18n-russian is not set + +# +# LuCIttpd +# +# CONFIG_PACKAGE_luci-httpd is not set + +# +# Utilities +# + +# +# disc +# +# CONFIG_PACKAGE_cfdisk is not set +# CONFIG_PACKAGE_fdisk is not set +# CONFIG_PACKAGE_fuse-utils is not set +# CONFIG_PACKAGE_swap-utils is not set +# CONFIG_PACKAGE_comgt is not set +# CONFIG_PACKAGE_dropbearconvert is not set +# CONFIG_PACKAGE_e2fsprogs is not set +# CONFIG_PACKAGE_fconfig is not set +CONFIG_PACKAGE_flukso=m +CONFIG_PACKAGE_gpioctl=y +# CONFIG_PACKAGE_hwclock is not set +CONFIG_KEXEC_TOOLS_TARGET_NAME="mips" +# CONFIG_PACKAGE_losetup is not set +# CONFIG_PACKAGE_mount-utils is not set +# CONFIG_PACKAGE_ocf-crypto-headers is not set +# CONFIG_PACKAGE_openssl-util is not set +# CONFIG_PACKAGE_robocfg is not set +# CONFIG_PACKAGE_udev is not set +# CONFIG_PACKAGE_udevextras is not set +# CONFIG_UDEVEXTRAS_ata_id is not set +# CONFIG_UDEVEXTRAS_cdrom_id is not set +# CONFIG_UDEVEXTRAS_dasd_id is not set +# CONFIG_UDEVEXTRAS_edd_id is not set +# CONFIG_UDEVEXTRAS_path_id is not set +# CONFIG_UDEVEXTRAS_scsi_id is not set +# CONFIG_UDEVEXTRAS_usb_id is not set +# CONFIG_UDEVEXTRAS_volume_id is not set +# CONFIG_PACKAGE_xyssl-progs is not set + +# +# Languages +# + +# +# LUA +# +CONFIG_PACKAGE_liblua-expat=y +CONFIG_PACKAGE_liblua-socket=y +CONFIG_PACKAGE_liblua-xmlrpc=y +CONFIG_PACKAGE_lua=y +# CONFIG_PACKAGE_lua-examples is not set +CONFIG_PACKAGE_luac=y +CONFIG_PACKAGE_luaxyssl=y diff --git a/openwrt/files/etc/config/dhcp b/openwrt/files/etc/config/dhcp new file mode 100644 index 0000000..38a8676 --- /dev/null +++ b/openwrt/files/etc/config/dhcp @@ -0,0 +1,23 @@ +config dnsmasq + option domainneeded 1 + option boguspriv 1 + option filterwin2k '0' #enable for dial on demand + option localise_queries 1 + option local '/lan/' + option domain 'home' + option expandhosts 1 + option nonegcache 0 + option authoritative 1 + option readethers 1 + option leasefile '/tmp/dhcp.leases' + option resolvfile '/tmp/resolv.conf.auto' + +config dhcp + option interface lan + option start 100 + option limit 150 + option leasetime 12h + +config dhcp + option interface wan + option ignore 1 diff --git a/openwrt/files/etc/config/dropbear b/openwrt/files/etc/config/dropbear new file mode 100644 index 0000000..ccce4a6 --- /dev/null +++ b/openwrt/files/etc/config/dropbear @@ -0,0 +1,3 @@ +config dropbear + option PasswordAuth 'off' + option Port '22' diff --git a/openwrt/files/etc/config/firewall b/openwrt/files/etc/config/firewall new file mode 100644 index 0000000..60f5f27 --- /dev/null +++ b/openwrt/files/etc/config/firewall @@ -0,0 +1,87 @@ +config defaults + option syn_flood 1 + option input ACCEPT + option output ACCEPT + option forward REJECT + +config zone + option name lan + option input ACCEPT + option output ACCEPT + option forward REJECT + +config zone + option name wan + option input REJECT + option output ACCEPT + option forward REJECT + option masq 1 + +config forwarding + option src lan + option dest wan + +## Enable this option if you encounter any MTU problems +## e.g. some websites work, others do not, submitting +## forms causes problems, ... +# option mtu_fix 1 + + +### EXAMPLE CONFIG SECTIONS +# do not allow a specific ip to access wan +#config rule +# option src lan +# option src_ip 192.168.45.2 +# option dest wan +# option proto tcp +# option target REJECT + +# block a specific mac on wan +#config rule +# option dest wan +# option src_mac 00:11:22:33:44:66 +# option target REJECT + +# block incoming ICMP traffic on a zone +#config rule +# option src lan +# option proto ICMP +# option target DROP + +# port redirect port coming in on wan to lan +#config redirect +# option src wan +# option src_dport 80 +# option dest lan +# option dest_ip 192.168.16.235 +# option dest_port 80 +# option proto tcp + +# include a file with users custom iptables rules +config include + option path /etc/firewall.user + + +### FULL CONFIG SECTIONS +#config rule +# option src lan +# option src lan +# option src_ip 192.168.45.2 +# option src_mac 00:11:22:33:44:55 +# option src_port 80 +# option dest wan +# option dest_ip 194.25.2.129 +# option dest_port 120 +# option proto tcp +# option target REJECT + +#config redirect +# option src lan +# option src_ip 192.168.45.2 +# option src_mac 00:11:22:33:44:55 +# option src_port 1024 +# option src_dport 80 +# option dest_ip 194.25.2.129 +# option dest_port 120 +# option proto tcp + diff --git a/openwrt/files/etc/config/network b/openwrt/files/etc/config/network new file mode 100644 index 0000000..ef1743b --- /dev/null +++ b/openwrt/files/etc/config/network @@ -0,0 +1,17 @@ +# Copyright (C) 2006 OpenWrt.org + +config interface loopback + option ifname lo + option proto static + option ipaddr 127.0.0.1 + option netmask 255.0.0.0 + +config interface wan + option ifname ath0 + option proto dhcp + +config interface lan + option ifname eth0 + option proto static + option ipaddr 192.168.255.1 + option netmask 255.255.255.0 diff --git a/openwrt/files/etc/config/system b/openwrt/files/etc/config/system new file mode 100644 index 0000000..0188be5 --- /dev/null +++ b/openwrt/files/etc/config/system @@ -0,0 +1,10 @@ +config system + option hostname flukso + option device 0123456789abcdef0123456789abcdef + option key 00112233445566778899aabbccddeeff + option version 5 + +config button + option button reset + option action pressed + option handler 'gpioctl set 7; gpioctl clear 7' diff --git a/openwrt/files/etc/config/wireless b/openwrt/files/etc/config/wireless new file mode 100644 index 0000000..65b0699 --- /dev/null +++ b/openwrt/files/etc/config/wireless @@ -0,0 +1,19 @@ +config wifi-device wifi0 + option type atheros + option channel auto + option diversity 0 + option txantenna 1 + option rxantenna 1 + option disabled 0 + +config wifi-iface + option device wifi0 + option network wan + option mode sta + option nosbeacon 1 + option hidden 0 + option txpower 16 + option ssid zwaluw + option encryption wep + option key 4ae56b7820f6b6b3cba78da46b + diff --git a/openwrt/files/etc/hosts b/openwrt/files/etc/hosts new file mode 100644 index 0000000..8b0d1ae --- /dev/null +++ b/openwrt/files/etc/hosts @@ -0,0 +1,2 @@ +127.0.0.1 localhost +192.168.255.1 flukso diff --git a/openwrt/files/etc/inittab b/openwrt/files/etc/inittab new file mode 100644 index 0000000..e8f1146 --- /dev/null +++ b/openwrt/files/etc/inittab @@ -0,0 +1,2 @@ +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K stop diff --git a/openwrt/files/etc/passwd b/openwrt/files/etc/passwd new file mode 100644 index 0000000..208c93d --- /dev/null +++ b/openwrt/files/etc/passwd @@ -0,0 +1,3 @@ +root:$1$VtdkJasi$HdGYp/XcbJmQ3BInhA/ki/:0:0:root:/root:/bin/ash +nobody:*:65534:65534:nobody:/var:/bin/false +daemon:*:65534:65534:daemon:/var:/bin/false diff --git a/openwrt/packages/expat/Makefile b/openwrt/packages/expat/Makefile new file mode 100644 index 0000000..730d9a0 --- /dev/null +++ b/openwrt/packages/expat/Makefile @@ -0,0 +1,58 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: Makefile 9947 2007-12-27 02:12:04Z nbd $ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=expat +PKG_VERSION:=1.95.8 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_MD5SUM:=aff487543845a82fe262e6e2922b4c8e +PKG_SOURCE_URL:=@SF/expat + +PKG_FIXUP = libtool + +include $(INCLUDE_DIR)/package.mk + + +define Package/libexpat + SECTION:=libs + CATEGORY:=Libraries + TITLE:=An XML parsing library + URL:=http://expat.sourceforge.net/ +endef + +define Package/libexpat/description + A fast, non-validating, stream-oriented XML parsing library. +endef + + +CONFIGURE_ARGS += \ + --enable-shared \ + --enable-static + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) DESTDIR="$(PKG_INSTALL_DIR)" install +endef + +define Build/InstallDev + mkdir -p $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/expat{,_external}.h $(1)/usr/include/ + mkdir -p $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libexpat.{a,so*} $(1)/usr/lib/ +endef + +define Package/libexpat/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libexpat.so.* $(1)/usr/lib/ +endef + + +$(eval $(call BuildPackage,libexpat)) + diff --git a/openwrt/packages/expat/patches/001-destdir.patch b/openwrt/packages/expat/patches/001-destdir.patch new file mode 100644 index 0000000..e7ff9fc --- /dev/null +++ b/openwrt/packages/expat/patches/001-destdir.patch @@ -0,0 +1,45 @@ +diff -ruN expat-1.95.8-orig/Makefile.in expat-1.95.8-1/Makefile.in +--- expat-1.95.8-orig/Makefile.in 2004-05-07 22:00:48.000000000 +0200 ++++ expat-1.95.8-1/Makefile.in 2005-04-04 22:53:09.000000000 +0200 +@@ -34,6 +34,8 @@ + + top_builddir = . + ++DESTDIR = ++ + + INSTALL = @INSTALL@ + INSTALL_PROGRAM = @INSTALL_PROGRAM@ +@@ -73,22 +75,22 @@ + tests/runtests + + install: xmlwf/xmlwf installlib +- $(mkinstalldirs) $(bindir) $(man1dir) +- $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) xmlwf/xmlwf $(bindir)/xmlwf +- $(INSTALL_DATA) $(MANFILE) $(man1dir) ++ $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) ++ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) xmlwf/xmlwf $(DESTDIR)$(bindir)/xmlwf ++ $(INSTALL_DATA) $(MANFILE) $(DESTDIR)$(man1dir) + + installlib: $(LIBRARY) $(APIHEADER) +- $(mkinstalldirs) $(libdir) $(includedir) +- $(LIBTOOL) --mode=install $(INSTALL) $(LIBRARY) $(libdir)/$(LIBRARY) +- $(INSTALL_DATA) $(APIHEADER) $(includedir) ++ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) ++ $(LIBTOOL) --mode=install $(INSTALL) $(LIBRARY) $(DESTDIR)$(libdir)/$(LIBRARY) ++ $(INSTALL_DATA) $(APIHEADER) $(DESTDIR)$(includedir) + + uninstall: uninstalllib +- $(LIBTOOL) --mode=uninstall rm -f $(bindir)/xmlwf +- rm -f $(man1dir)/xmlwf.1 ++ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/xmlwf ++ rm -f $(DESTDIR)$(man1dir)/xmlwf.1 + + uninstalllib: +- $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(LIBRARY) +- rm -f $(includedir)/$(APIHEADER) ++ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$(LIBRARY) ++ rm -f $(DESTDIR)$(includedir)/$(APIHEADER) + + # for VPATH builds (invoked by configure) + mkdir-init: diff --git a/openwrt/packages/expat/patches/110-avr32_compile_fix.patch b/openwrt/packages/expat/patches/110-avr32_compile_fix.patch new file mode 100644 index 0000000..2239a80 --- /dev/null +++ b/openwrt/packages/expat/patches/110-avr32_compile_fix.patch @@ -0,0 +1,21 @@ +diff -urN expat-1.95.8.orig/conftools/config.sub expat-1.95.8/conftools/config.sub +--- expat-1.95.8.orig/conftools/config.sub 2002-06-02 00:29:30.000000000 +0200 ++++ expat-1.95.8/conftools/config.sub 2008-04-14 18:27:28.000000000 +0200 +@@ -251,7 +251,7 @@ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ +- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ ++ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ +@@ -305,7 +305,7 @@ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ +- | avr-* \ ++ | avr-* | avr32-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cydra-* \ diff --git a/openwrt/packages/flukso/Makefile b/openwrt/packages/flukso/Makefile new file mode 100644 index 0000000..b31c84e --- /dev/null +++ b/openwrt/packages/flukso/Makefile @@ -0,0 +1,44 @@ +# Copyright (c) 2008 jokamajo.org +# $Id: Makefile 3 2008-08-07 16:00:00Z icarus75 $ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=flukso +PKG_VERSION:=0.1 +PKG_RELEASE:=5 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/flukso + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+liblua-xmlrpc +ntpclient +netcat + TITLE:=Flukso - community metering +endef + +define Package/flukso/description + This package contains the necessary openwrt files for the Flukso [www.flukso.net] community metering application. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Build/Compile +endef + +define Package/flukso/install + $(INSTALL_DIR) $(1)/usr/share/lua/flukso/ + $(CP) $(PKG_BUILD_DIR)/flukso.lua $(1)/usr/share/lua/flukso/ + $(CP) $(PKG_BUILD_DIR)/data.lua $(1)/usr/share/lua/flukso/ + $(CP) $(PKG_BUILD_DIR)/dbg.lua $(1)/usr/share/lua/flukso/ + $(CP) $(PKG_BUILD_DIR)/auth.lua $(1)/usr/share/lua/flukso/ + $(CP) $(PKG_BUILD_DIR)/heartbeat.lua $(1)/usr/share/lua/flukso/ + $(INSTALL_DIR) $(1)/etc/init.d/ + $(CP) $(PKG_BUILD_DIR)/flukso.init $(1)/etc/init.d/flukso +endef + +$(eval $(call BuildPackage,flukso)) diff --git a/openwrt/packages/flukso/src/auth.lua b/openwrt/packages/flukso/src/auth.lua new file mode 100644 index 0000000..e2fcf5f --- /dev/null +++ b/openwrt/packages/flukso/src/auth.lua @@ -0,0 +1,73 @@ +-- +-- auth.lua: property and methods for generating hmac-sha1 authentication +-- Copyright (c) 2009 jokamajo.org +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 +-- of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-- +-- $Id: auth.lua 1 2009-03-13 13:40:00Z icarus75 $ +-- + +require 'luci.model.uci' +require 'lxyssl' + +local string, table, os, luci, lxyssl = + string, table, os, luci, lxyssl + +local getfenv, setmetatable, type, pairs, tostring = + getfenv, setmetatable, type, pairs, tostring + +module(...) +local modenv = getfenv() + +function new() + return setmetatable({}, {__index = modenv}) +end + +function load(T) + local uci = luci.model.uci.cursor() + uci:foreach ('system', 'system', + function(section) + T.device, T.key, T.version = section.device, section.key, section.version + end + ) +end + +function hmac(T, M, timestamp) + function string.hex(x) + local t={} + for c in x:gmatch('(.)') do t[#t+1]=string.format('%02x', c:byte()) end + return table.concat(t,'') + end + + function serialise(M) + if type(M) == 'table' then + local sequence = '' + for k, v in pairs(M) do + if v ~= nil then + sequence = sequence..tostring(k)..serialise(v) + end + end + return sequence + else + return tostring(M) + end + end + + T.timestamp = timestamp or os.time() + T.message = T.timestamp..':'..serialise(M)..':'..T.key -- or T.timestamp..':'..T.nonce..':'..T.key + T.signature = lxyssl.hash('hmac-sha1', T.key):digest(T.message):hex() + + T.message, T.key, T.version = nil, nil, nil +end \ No newline at end of file diff --git a/openwrt/packages/flukso/src/data.lua b/openwrt/packages/flukso/src/data.lua new file mode 100644 index 0000000..a709ea1 --- /dev/null +++ b/openwrt/packages/flukso/src/data.lua @@ -0,0 +1,62 @@ +-- +-- data.lua: property and methods for manipulating incoming measurements +-- Copyright (c) 2009 jokamajo.org +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 +-- of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-- +-- $Id: data.lua 1 2009-01-31 22:30:00Z icarus75 $ +-- + +local os, math, table = + os, math, table + +local getfenv, setmetatable, pairs = + getfenv, setmetatable, pairs + +module (...) +local modenv = getfenv() -- module environment + +function new() + return setmetatable({}, {__index = modenv}) +end + +function add(M, meter, timestamp, value) + if not M[meter] then M[meter] = {} end + M[meter][timestamp] = value +end + +function clear(M) + for meter in pairs(M) do + M[meter] = nil + end +end + +function filter(M, span, offset) + for meter, T in pairs(M) do + local H = {} -- helper table, an indexed array containing all the measurement's timestamps + for timestamp in pairs(T) do H[#H+1] = timestamp end + table.sort(H) -- sort in ascending order, oldest timestamps will be treated first + + local i = 2 + while not (H[i+1] == nil or H[i] > os.time()-offset) do + if math.floor(H[i-1]/span) == math.floor(H[i]/span) and math.floor(H[i]/span) == math.floor(H[i+1]/span) then + T[H[i]] = nil + table.remove(H, i) + else + i = i+1 + end + end + end +end \ No newline at end of file diff --git a/openwrt/packages/flukso/src/dbg.lua b/openwrt/packages/flukso/src/dbg.lua new file mode 100644 index 0000000..7891365 --- /dev/null +++ b/openwrt/packages/flukso/src/dbg.lua @@ -0,0 +1,50 @@ +-- +-- dbg.lua: library for debugging with vardump in Lua +-- Lua Programming Gems Chapter 3 +-- Vardump: The Power of Seeing What's Behind +-- Copyright 2008 by Tobias Sülzenbrück and Christoph Beckmann +-- +-- $Id: dbg.lua 1 2009-01-31 22:30:00Z icarus75 $ +-- + +local getfenv, getmetatable, print, pairs, type, tostring = getfenv, getmetatable, print, pairs, type, tostring + +module(...) +local modenv = getfenv() -- module environment + +function vardump(value, depth, key) + local linePrefix = "" + local spaces = "" + + if key ~= nil then + linePrefix = "["..key.."] = " + end + + if depth == nil then + depth = 0 + else + depth = depth + 1 + for i = 1,depth do spaces = spaces.." " end + end + + if type(value) == 'table' then +-- mTable = getmetatable(value) +-- if mTable == nil then + print(spaces..linePrefix.."(table) ") +-- else +-- print(spaces.."(metatable) ") +-- value = mTable +-- end + for tableKey, tableValue in pairs(value) do + vardump(tableValue, depth, tableKey) + end + elseif type(value) == 'function' + or type(value) == 'thread' + or type(value) == 'userdata' + or value == nil + then + print(spaces..tostring(value)) + else + print(spaces..linePrefix.."("..type(value)..") "..tostring(value)) + end +end diff --git a/openwrt/packages/flukso/src/flukso.init b/openwrt/packages/flukso/src/flukso.init new file mode 100755 index 0000000..298550c --- /dev/null +++ b/openwrt/packages/flukso/src/flukso.init @@ -0,0 +1,17 @@ +#!/bin/sh /etc/rc.common +# Copyroght (c) 2008 jokamajo.org +# $Id: flukso.init 7 2009-02-16 23:13:00Z icarus75 $ + +START=98 + +start() { + stty 4800 < /dev/ttyS0 + /usr/share/lua/flukso/flukso.lua >&- 2>&- <&- & + /usr/share/lua/flukso/heartbeat.lua 1 >&- 2>&- <&- + echo -e "$(date '+%M') * * * * /usr/share/lua/flukso/heartbeat.lua 0\n"'*/15 * * * * [ -z "$(ps | grep '\'fluks[o]\'')" ] && reboot' | crontab - + } + +stop() { + crontab -r + kill $(ps | grep 'fluks[o]' | awk '{print $1}') + } diff --git a/openwrt/packages/flukso/src/flukso.lua b/openwrt/packages/flukso/src/flukso.lua new file mode 100755 index 0000000..552a939 --- /dev/null +++ b/openwrt/packages/flukso/src/flukso.lua @@ -0,0 +1,154 @@ +#!/usr/bin/env lua + +-- +-- flukso.lua: flukso deamon running on openwrt +-- Copyright (c) 2008-2009 jokamajo.org +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 +-- of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-- +-- $Id: deamon.lua 12 2009-03-04 22:30:00Z icarus75 $ +-- + +require 'posix' +require 'xmlrpc.http' + +data = require 'flukso.data' +auth = require 'flukso.auth' +dbg = require 'flukso.dbg' + +local param = {xmlrpcaddress = 'http://logger.flukso.net/xmlrpc', + xmlrpcversion = '1', + xmlrpcmethod = 'logger.measurementAdd', + device = '/dev/ttyS0', + interval = 300} + +function receive(device) + return coroutine.wrap(function() + -- open the connection to the syslog deamon, specifying our identity + posix.openlog('flukso') + posix.syslog(30, 'starting the flukso deamon') + posix.syslog(30, 'listening for pulses on '..device..'...') + + for line in io.lines(device) do + if line:sub(1, 3) == 'pls' and line:len() == 47 and line:find(':') == 37 then -- user data + additional data integrity checks + posix.syslog(30, 'received pulse from '..device..': '..line:sub(5)) + + -- flash the power led for 50ms + os.execute('gpioctl set 7') + socket.select(nil, nil, 0.05) + os.execute('gpioctl clear 7') + + local meter, value = line:sub(5, 36), tonumber(line:sub(38)) + coroutine.yield(meter, os.time(), value) + elseif line:sub(1, 3) == 'msg' then -- control data + posix.syslog(31, 'received message from '..device..': '..line:sub(5)) + else + posix.syslog(27, 'input error on '..device..': '..line) + end + end + + posix.syslog(30, 'closing down the flukso deamon') + os.exit() + end) +end + +function buffer(source, interval) + return coroutine.wrap(function() + local measurements = data.new() + local threshold = os.time() + interval + + while true do + local meter, timestamp, value = source() + if meter ~= nil and timestamp > 1234567890 then measurements:add(meter, timestamp, value) end + if timestamp > threshold and next(measurements) then --checking whether table is not empty + coroutine.yield(measurements) + threshold = timestamp + interval + end + end + end) +end + +function filter(source, span, offset) + return coroutine.wrap(function() + while true do + local measurements = source() + measurements:filter(span, offset) + coroutine.yield(measurements) + end + end) +end + +function send(source, address, version, method) + return coroutine.wrap(function() + while true do + local measurements = source() + local auth = auth.new() + auth:load() + auth:hmac(measurements) + + local status, ret_or_err, res = pcall(xmlrpc.http.call, + address..'/'..version, + method, + auth, + measurements) + + if status then + posix.syslog(30, tostring(res)) + if ret_or_err then --successful xmlrpc call + measurements:clear() + end + else + posix.syslog(27, tostring(ret_or_err)..' '..address..' '..tostring(res)) + end + coroutine.yield(measurements) + end + end) +end + +function gc(source) + return coroutine.wrap(function() + while true do + local measurements = source() + posix.syslog(31, tostring(collectgarbage('count')*1024)..' bytes of memory used by Lua before garbage collection cycle') + collectgarbage() -- force a complete garbage collection cycle + posix.syslog(31, tostring(collectgarbage('count')*1024)..' bytes of memory used by Lua after garbage collection cycle') + coroutine.yield(measurements) + end + end) +end + +-- receive: listen to the serial port for incoming pulses +-- buffer: buffer the pulses in a measurement object +-- filter: sweep recursively to filter all redundant entries +-- send: report the measurements to the server via xmlrpc +-- gc: perform a full garbage collection cycle + +local aggregator = gc( + send( + filter( + filter( + filter( + buffer( + receive(param.device) + , param.interval) + , 60, 0) + , 900, 7200) + , 86400, 172800) + , param.xmlrpcaddress, param.xmlrpcversion, param.xmlrpcmethod) + ) + +while true do + dbg.vardump(aggregator()) +end \ No newline at end of file diff --git a/openwrt/packages/flukso/src/heartbeat.lua b/openwrt/packages/flukso/src/heartbeat.lua new file mode 100755 index 0000000..4ad5e7d --- /dev/null +++ b/openwrt/packages/flukso/src/heartbeat.lua @@ -0,0 +1,90 @@ +#!/usr/bin/env lua + +-- +-- Lua 5.1 heartbeat script running on openwrt +-- Copyright (c) 2008-2009 jokamajo.org +-- +-- This program is free software; you can redistribute it and/or +-- modify it under the terms of the GNU General Public License +-- as published by the Free Software Foundation; either version 2 +-- of the License, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +-- +-- $Id: heartbeat.lua 6 2008-03-17 21:17:00Z icarus75 $ +-- + +if not arg[1] then + print ('Please pass the reset argument as a boolean to the script.') +else + -- load libraries + require 'posix' + require 'xmlrpc.http' + require 'luci.sys' + + auth = require 'flukso.auth' + dbg = require 'flukso.dbg' + + -- config parameters + local param = {server = 'logger.flukso.net', + xmlrpcaddress = 'http://logger.flukso.net/xmlrpc', + xmlrpcversion = '1', + xmlrpcmethod = 'logger.heartbeat'} + + local monitor = {reset = tonumber(arg[1])} + + -- open the connection to the syslog deamon, specifying our identity + posix.openlog('heartbeat') + + -- calculate hmac and collect relevant monitoring points + local auth = auth.new() + auth:load() + monitor.version = tonumber(auth.version) + + monitor.uptime = math.floor(luci.sys.uptime()) + monitor.uart_oe = string.match(luci.sys.exec('cat /proc/tty/driver/serial'), 'oe:(%d+)') or 0 + system, model, monitor.memtotal, monitor.memcached, monitor.membuffers, monitor.memfree = luci.sys.sysinfo() + + auth:hmac(monitor) + + dbg.vardump(auth) + dbg.vardump(monitor) + + -- send a heartbeat method call + local pcall_ok, return_or_err, pong = pcall(xmlrpc.http.call, + param.xmlrpcaddress..'/'..param.xmlrpcversion, + param.xmlrpcmethod, + auth, + monitor) + + dbg.vardump(pong) + + if pcall_ok and return_or_err then + auth:load() + auth:hmac(pong.upgrade, pong.timestamp) + + if auth.signature == pong.signature and pong.timestamp > os.time() - 300 then + posix.syslog(31, 'successful heartbeat authentication') + + if tonumber(pong.upgrade) == monitor.version then --reset device + os.execute('reboot') + elseif tonumber(pong.upgrade) > monitor.version then -- upgrade device to specified version + os.execute('wget -P /tmp http://'..param.server..'/files/upgrade/upgrade.'..pong.upgrade) + os.execute('chmod a+x /tmp/upgrade.'..pong.upgrade) + os.execute('/tmp/upgrade.'..pong.upgrade) + os.execute('rm /tmp/upgrade.'..pong.upgrade) + end + end + else + posix.syslog(11, tostring(return_or_err)) + end + -- close the connection to the syslog deamon + posix.closelog() +end diff --git a/openwrt/packages/flukso/src/load.lua b/openwrt/packages/flukso/src/load.lua new file mode 100755 index 0000000..221a374 --- /dev/null +++ b/openwrt/packages/flukso/src/load.lua @@ -0,0 +1,14 @@ +#! /usr/bin/env lua + +require 'socket' + +local fd = assert(io.open('/dev/ttyUSB0', 'w')) + +for i = tonumber(arg[1]), tonumber(arg[2]) do + local data = 'pls ' .. arg[3] .. ':' .. string.sub(string.rep('0', 10) .. i, -10, -1) .. '\n' + fd:write(data) + socket.select(nil, nil, 0.001) + +end + +fd:close() diff --git a/openwrt/packages/luaexpat/Makefile b/openwrt/packages/luaexpat/Makefile new file mode 100644 index 0000000..8034f91 --- /dev/null +++ b/openwrt/packages/luaexpat/Makefile @@ -0,0 +1,93 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: Makefile 6994 2007-04-18 00:46:40Z nico $ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luaexpat +PKG_VERSION:=1.0.2 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://luaforge.net/frs/download.php/1506/ +PKG_MD5SUM:=e99892c4b6b879ae649a491a07c3bed6 +PKG_CAT:=zcat + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +include $(INCLUDE_DIR)/package.mk + +define Package/liblua-expat + SECTION:=lang + SUBMENU:=LUA + CATEGORY:=Languages + TITLE:=luaexpat library for the LUA programming language + URL:=http://www.luaforge.net/projects/luaexpat + DEPENDS:=+liblua +libexpat +endef + +define Package/liblua-expat/description + This package contains the luaexpat library, a binding for the expat XML parser for lua. +endef + +define Build/Configure +endef + +define Build/Compile + cd $(PKG_BUILD_DIR)/ && \ + $(TARGET_CROSS)gcc -shared -o luaexpat.so src/lxplib.c -Wall -fPIC \ + $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS) \ + $(TARGET_CFLAGS) $(TARGET_LDFLAGS) \ + -I$(STAGING_DIR)/usr/include \ + -lexpat -llua -lm -ldl &&\ + $(TARGET_CROSS)strip luaexpat.so &&\ + $(TARGET_CROSS)gcc -c src/lxplib.c -Wall \ + $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS) \ + $(TARGET_CFLAGS) $(TARGET_LDFLAGS) \ + -I$(STAGING_DIR)/usr/include &&\ + $(TARGET_CROSS)ar r liblua-expat.a lxplib.o +endef + +define Build/InstallDev + mkdir -p $(STAGING_DIR)/usr/include + mkdir -p $(STAGING_DIR)/usr/lib/lua + mkdir -p $(STAGING_DIR)/usr/share/lua/lxp + $(CP) $(PKG_BUILD_DIR)/src/lxplib.h $(STAGING_DIR)/usr/include + $(CP) $(PKG_BUILD_DIR)/src/lxp/lom.lua $(STAGING_DIR)/usr/share/lua/lxp/ + $(CP) $(PKG_BUILD_DIR)/luaexpat.so \ + $(STAGING_DIR)/usr/lib/liblua-expat.so.0.0.0 + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-expat.so.0.0.0 liblua-expat.so + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-expat.so.0.0.0 liblua-expat.so.0 + cd $(STAGING_DIR)/usr/lib/lua/ && \ + ln -fs ../liblua-expat.so.0.0.0 lxp.so + $(CP) $(PKG_BUILD_DIR)/liblua-expat.a $(STAGING_DIR)/usr/lib +endef + +define Build/UninstallDev + $(RM) -f $(STAGING_DIR)/usr/include/lxplib.h + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-expat.so.0.0.0 + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-expat.so.0 + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-expat.a + $(RM) -f $(STAGING_DIR)/usr/lib/lua/lxp.so + $(RM) -rf $(STAGING_DIR)/usr/share/lua/lxp/ +endef + +define Package/liblua-expat/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(INSTALL_DIR) $(1)/usr/share/lua/lxp + $(CP) $(PKG_BUILD_DIR)/luaexpat.so \ + $(1)/usr/lib/liblua-expat.so.0.0.0 + cd $(1)/usr/lib/lua/ && \ + ln -fs ../liblua-expat.so.0.0.0 lxp.so + cd $(1)/usr/lib/ && ln -sf liblua-expat.so.0.0.0 liblua-expat.so + $(CP) $(PKG_BUILD_DIR)/src/lxp/lom.lua $(1)/usr/share/lua/lxp/ +endef + +$(eval $(call BuildPackage,liblua-expat)) diff --git a/openwrt/packages/luaexpat/patches/010-compat-5.1.patch b/openwrt/packages/luaexpat/patches/010-compat-5.1.patch new file mode 100644 index 0000000..bed4e73 --- /dev/null +++ b/openwrt/packages/luaexpat/patches/010-compat-5.1.patch @@ -0,0 +1,22 @@ +diff -urNad trunk~/src/lxplib.c trunk/src/lxplib.c +--- trunk~/src/lxplib.c 2006-03-20 20:55:53.000000000 +0100 ++++ trunk/src/lxplib.c 2006-09-03 10:10:14.000000000 +0200 +@@ -13,7 +13,6 @@ + + #include "lua.h" + #include "lauxlib.h" +-#include "compat-5.1.h" + + + #include "lxplib.h" +@@ -530,8 +529,8 @@ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); + lua_rawset(L, -3); +- luaL_openlib (L, NULL, lxp_meths, 0); +- luaL_openlib (L, "lxp", lxp_funcs, 0); ++ luaL_register (L, NULL, lxp_meths); ++ luaL_register (L, "lxp", lxp_funcs); + set_info (L); + + return 1; diff --git a/openwrt/packages/luaexpat/patches/010-luaL_findstring.patch b/openwrt/packages/luaexpat/patches/010-luaL_findstring.patch new file mode 100644 index 0000000..03334f3 --- /dev/null +++ b/openwrt/packages/luaexpat/patches/010-luaL_findstring.patch @@ -0,0 +1,18 @@ +diff -urNad trunk~/src/lxplib.c trunk/src/lxplib.c +--- trunk~/src/lxplib.c 2006-03-20 20:55:53.000000000 +0100 ++++ trunk/src/lxplib.c 2006-08-22 14:00:43.000000000 +0200 +@@ -18,7 +18,13 @@ + + #include "lxplib.h" + +- ++static int luaL_findstring (const char *name, const char *const list[]) { ++ int i; ++ for (i=0; list[i]; i++) ++ if (strcmp(list[i], name) == 0) ++ return i; ++ return -1; /* name not found */ ++} + + enum XPState { + XPSpre, /* parser just initialized */ diff --git a/openwrt/packages/luasocket/Makefile b/openwrt/packages/luasocket/Makefile new file mode 100644 index 0000000..6975ea3 --- /dev/null +++ b/openwrt/packages/luasocket/Makefile @@ -0,0 +1,184 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: Makefile 6994 2007-04-18 00:46:40Z nico $ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luasocket +PKG_VERSION:=2.0.2 +PKG_VERSION_MAJOR:=$(shell echo $(PKG_VERSION) | cut -d . -f 1) +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://luaforge.net/frs/download.php/2664/ +PKG_MD5SUM:=41445b138deb7bcfe97bff957503da8e +PKG_CAT:=zcat + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +include $(INCLUDE_DIR)/package.mk + +define Package/liblua-socket + SECTION:=lang + SUBMENU:=LUA + CATEGORY:=Languages + DEPENDS:=+liblua + URL:=http://luasocket.luaforge.net/ + TITLE:=TCP/UDP socket library for LUA programming language +endef + +define Package/liblua-socket/description + Luasocket provides a TCP/UDP socket library for Lua 5.1. Also provided are HTTP and SMTP implementations, a simple FTP implementation and some URL parsing functions. Luasocket supports blocking and non-blocking sockets and also provides a select() interface to the language. + +endef + +define Build/Configure +endef + +# omitted static libraries +define Build/Compile + cd $(PKG_BUILD_DIR)/ && \ + $(TARGET_CROSS)gcc -shared -o src/socket.so \ + src/luasocket.c \ + src/timeout.c \ + src/buffer.c \ + src/io.c \ + src/auxiliar.c \ + src/options.c \ + src/inet.c \ + src/tcp.c \ + src/udp.c \ + src/except.c \ + src/select.c \ + src/usocket.c -Wall -fPIC \ + $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS) \ + $(TARGET_CFLAGS) $(TARGET_LDFLAGS) \ + -I$(STAGING_DIR)/usr/include \ + -llua -lm -ldl &&\ + $(TARGET_CROSS)strip src/socket.so &&\ + $(TARGET_CROSS)gcc -shared -o src/mime.so \ + src/mime.c -Wall -fPIC \ + $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS) \ + $(TARGET_CFLAGS) $(TARGET_LDFLAGS) \ + -I$(STAGING_DIR)/usr/include \ + -llua -lm -ldl &&\ + $(TARGET_CROSS)strip src/mime.so &&\ + $(TARGET_CROSS)gcc -shared -o src/unix.so \ + src/buffer.c \ + src/auxiliar.c \ + src/options.c \ + src/timeout.c \ + src/io.c \ + src/usocket.c \ + src/unix.c -Wall -fPIC \ + $(EXTRA_CFLAGS) $(EXTRA_LDFLAGS) \ + $(TARGET_CFLAGS) $(TARGET_LDFLAGS) \ + -I$(STAGING_DIR)/usr/include \ + -llua -lm -ldl &&\ + $(TARGET_CROSS)strip src/unix.so +endef + +# omitted static libraries +define Build/InstallDev + mkdir -p $(STAGING_DIR)/usr/include/lua + mkdir -p $(STAGING_DIR)/usr/lib/lua/mime + mkdir -p $(STAGING_DIR)/usr/lib/lua/socket + mkdir -p $(STAGING_DIR)/usr/share/lua/socket + $(CP) $(PKG_BUILD_DIR)/src/ltn12.lua $(STAGING_DIR)/usr/share/lua/ + $(CP) $(PKG_BUILD_DIR)/src/mime.lua $(STAGING_DIR)/usr/share/lua/ + $(CP) $(PKG_BUILD_DIR)/src/socket.lua $(STAGING_DIR)/usr/share/lua/ + $(CP) $(PKG_BUILD_DIR)/src/ftp.lua $(STAGING_DIR)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/http.lua $(STAGING_DIR)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/smtp.lua $(STAGING_DIR)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/tp.lua $(STAGING_DIR)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/url.lua $(STAGING_DIR)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/socket.h $(STAGING_DIR)/usr/include/lua + $(CP) $(PKG_BUILD_DIR)/src/socket.so \ + $(STAGING_DIR)/usr/lib/liblua-socket.so.$(PKG_VERSION) + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-socket.so.$(PKG_VERSION) liblua-socket.so + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-socket.so.$(PKG_VERSION) liblua-socket.so.$(PKG_VERSION_MAJOR) + cd $(STAGING_DIR)/usr/lib/lua/socket && \ + ln -fs ../../liblua-socket.so.$(PKG_VERSION) core.so + $(CP) $(PKG_BUILD_DIR)/src/mime.h $(STAGING_DIR)/usr/include/lua + $(CP) $(PKG_BUILD_DIR)/src/mime.so \ + $(STAGING_DIR)/usr/lib/liblua-socket-mime.so.$(PKG_VERSION) + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-socket-mime.so.$(PKG_VERSION) liblua-socket-mime.so + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-socket-mime.so.$(PKG_VERSION) liblua-socket-mime.so.$(PKG_VERSION_MAJOR) + cd $(STAGING_DIR)/usr/lib/lua/mime && \ + ln -fs ../../liblua-socket-mime.so.$(PKG_VERSION) core.so + $(CP) $(PKG_BUILD_DIR)/src/unix.h $(STAGING_DIR)/usr/include/lua + $(CP) $(PKG_BUILD_DIR)/src/unix.so \ + $(STAGING_DIR)/usr/lib/liblua-socket-unix.so.$(PKG_VERSION) + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-socket-unix.so.$(PKG_VERSION) liblua-socket-unix.so + cd $(STAGING_DIR)/usr/lib/ && \ + ln -fs liblua-socket-unix.so.$(PKG_VERSION) liblua-socket-unix.so.$(PKG_VERSION_MAJOR) + cd $(STAGING_DIR)/usr/lib/lua/socket && \ + ln -fs ../../liblua-socket-unix.so.$(PKG_VERSION) unix.so +endef + +define Build/UninstallDev + $(RM) -f $(STAGING_DIR)/usr/share/lua/ltn12.lua + $(RM) -f $(STAGING_DIR)/usr/share/lua/mime.lua + $(RM) -f $(STAGING_DIR)/usr/share/lua/socket.lua + $(RM) -f $(STAGING_DIR)/usr/share/lua/socket/ftp.lua + $(RM) -f $(STAGING_DIR)/usr/share/lua/socket/http.lua + $(RM) -f $(STAGING_DIR)/usr/share/lua/socket/smtp.lua + $(RM) -f $(STAGING_DIR)/usr/share/lua/socket/tp.lua + $(RM) -f $(STAGING_DIR)/usr/share/lua/socket/url.lua + $(RM) -f $(STAGING_DIR)/usr/include/lua/socket.h + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-socket.so.$(PKG_VERSION) + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-socket.so.$(PKG_VERSION_MAJOR) + $(RM) -f $(STAGING_DIR)/usr/lib/lua/socket/core.so + $(RM) -f $(STAGING_DIR)/usr/include/lua/mime.h + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-socket-mime.so.$(PKG_VERSION) + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-socket-mime.so.$(PKG_VERSION_MAJOR) + $(RM) -f $(STAGING_DIR)/usr/lib/lua/mime/core.so + $(RM) -f $(STAGING_DIR)/usr/include/lua/unix.h + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-socket-unix.so.$(PKG_VERSION) + $(RM) -f $(STAGING_DIR)/usr/lib/liblua-socket-unix.so.$(PKG_VERSION_MAJOR) + $(RM) -f $(STAGING_DIR)/usr/lib/lua/socket/unix.so +endef + +define Package/liblua-socket/install + $(INSTALL_DIR) $(1)/usr/lib/lua/mime + $(INSTALL_DIR) $(1)/usr/lib/lua/socket + $(INSTALL_DIR) $(1)/usr/share/lua/socket + $(CP) $(PKG_BUILD_DIR)/src/ltn12.lua $(1)/usr/share/lua/ + $(CP) $(PKG_BUILD_DIR)/src/mime.lua $(1)/usr/share/lua/ + $(CP) $(PKG_BUILD_DIR)/src/socket.lua $(1)/usr/share/lua/ + $(CP) $(PKG_BUILD_DIR)/src/ftp.lua $(1)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/http.lua $(1)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/smtp.lua $(1)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/tp.lua $(1)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/url.lua $(1)/usr/share/lua/socket/ + $(CP) $(PKG_BUILD_DIR)/src/socket.so \ + $(1)/usr/lib/liblua-socket.so.$(PKG_VERSION) + cd $(1)/usr/lib/ && \ + ln -fs liblua-socket.so.$(PKG_VERSION) liblua-socket.so + cd $(1)/usr/lib/lua/socket && \ + ln -fs ../../liblua-socket.so.$(PKG_VERSION) core.so + $(CP) $(PKG_BUILD_DIR)/src/mime.so \ + $(1)/usr/lib/liblua-socket-mime.so.$(PKG_VERSION) + cd $(1)/usr/lib/ && \ + ln -fs liblua-socket-mime.so.$(PKG_VERSION) liblua-socket-mime.so + cd $(1)/usr/lib/lua/mime && \ + ln -fs ../../liblua-socket-mime.so.$(PKG_VERSION) core.so + $(CP) $(PKG_BUILD_DIR)/src/unix.so \ + $(1)/usr/lib/liblua-socket-unix.so.$(PKG_VERSION) + cd $(1)/usr/lib/ && \ + ln -fs liblua-socket-unix.so.$(PKG_VERSION) liblua-socket-unix.so + cd $(1)/usr/lib/lua/socket && \ + ln -fs ../../liblua-socket-unix.so.$(PKG_VERSION) unix.so +endef + +$(eval $(call BuildPackage,liblua-socket)) diff --git a/openwrt/packages/luasocket/patches/010-compat-5.1.patch b/openwrt/packages/luasocket/patches/010-compat-5.1.patch new file mode 100644 index 0000000..07a88fc --- /dev/null +++ b/openwrt/packages/luasocket/patches/010-compat-5.1.patch @@ -0,0 +1,14 @@ +diff -urNad trunk~/src/luasocket.c trunk/src/luasocket.c +--- trunk~/src/luasocket.c 2006-04-27 05:23:22.000000000 +0200 ++++ trunk/src/luasocket.c 2007-08-12 23:57:43.000000000 +0200 +@@ -20,10 +20,6 @@ + #include "lua.h" + #include "lauxlib.h" + +-#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501) +-#include "compat-5.1.h" +-#endif +- + /*=========================================================================*\ + * LuaSocket includes + \*=========================================================================*/ diff --git a/openwrt/packages/luaxmlrpc/Makefile b/openwrt/packages/luaxmlrpc/Makefile new file mode 100644 index 0000000..165902f --- /dev/null +++ b/openwrt/packages/luaxmlrpc/Makefile @@ -0,0 +1,45 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: Makefile 6994 2008-07-31 21:12:40Z icarus75 $ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=luaxmlrpc +PKG_VERSION:=1.0x +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/liblua-xmlrpc + SECTION:=lang + SUBMENU:=LUA + CATEGORY:=Languages + DEPENDS:=+liblua-expat +liblua-socket + URL:=http://luaforge.net/projects/luaxmlrpc/ + TITLE:=XML-RPC library for LUA programming language +endef + +define Package/liblua-xmlrpc/description + LuaXMLRPC is a Lua library to make remote procedure calls using XML-RPC. +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR)/src/ + $(CP) ./src/* $(PKG_BUILD_DIR)/src/ +endef + +define Build/Compile +endef + +define Package/liblua-xmlrpc/install + $(INSTALL_DIR) $(1)/usr/share/lua/xmlrpc/ + $(CP) $(PKG_BUILD_DIR)/src/*.lua $(1)/usr/share/lua/xmlrpc/ +endef + +$(eval $(call BuildPackage,liblua-xmlrpc)) diff --git a/openwrt/packages/luaxmlrpc/src/http.lua b/openwrt/packages/luaxmlrpc/src/http.lua new file mode 100644 index 0000000..7e52b00 --- /dev/null +++ b/openwrt/packages/luaxmlrpc/src/http.lua @@ -0,0 +1,44 @@ +--------------------------------------------------------------------- +-- XML-RPC over HTTP. +-- See Copyright Notice in license.html +-- $Id: http.lua,v 1.5 2007/03/30 04:17:14 tomas Exp $ +--------------------------------------------------------------------- + +local error, tonumber, tostring, unpack = error, tonumber, tostring, unpack + +local ltn12 = require"ltn12" +local request = require"socket.http".request +local string = require"string" +local table = require"table" +local xmlrpc = require"xmlrpc" + +module("xmlrpc.http") + +--------------------------------------------------------------------- +-- Call a remote method. +-- @param url String with the location of the server. +-- @param method String with the name of the method to be called. +-- @return Table with the response (could be a `fault' or a `params' +-- XML-RPC element). +--------------------------------------------------------------------- +function call (url, method, ...) + local request_sink, tbody = ltn12.sink.table() + local request_body = xmlrpc.clEncode(method, ...) + local err, code, headers, status = request { + url = url, + method = "POST", + source = ltn12.source.string (request_body), + sink = request_sink, + headers = { + ["User-agent"] = "LuaXMLRPC", + ["Content-type"] = "text/xml", + ["content-length"] = tostring (string.len (request_body)), + }, + } + local body = table.concat (tbody) + if tonumber (code) == 200 then + return xmlrpc.clDecode (body) + else + error (tostring (err or code).."\n\n"..tostring(body)) + end +end diff --git a/openwrt/packages/luaxmlrpc/src/init.lua b/openwrt/packages/luaxmlrpc/src/init.lua new file mode 100644 index 0000000..3daf5eb --- /dev/null +++ b/openwrt/packages/luaxmlrpc/src/init.lua @@ -0,0 +1,593 @@ +--------------------------------------------------------------------- +-- XML-RPC implementation for Lua. +-- See Copyright Notice in license.html +-- $Id: init.lua,v 1.2 2007/03/30 04:18:54 tomas Exp $ +--------------------------------------------------------------------- + +local lxp = require "lxp" +local lom = require "lxp.lom" + +local assert, error, ipairs, pairs, select, type, tonumber, unpack = assert, error, ipairs, pairs, select, type, tonumber, unpack +local format, gsub, strfind, strsub = string.format, string.gsub, string.find, string.sub +local concat, tinsert = table.concat, table.insert +local ceil = math.ceil +local parse = lxp.lom.parse + +module (...) + +_COPYRIGHT = "Copyright (C) 2003-2007 Kepler Project" +_DESCRIPTION = "LuaXMLRPC is a library to make remote procedure calls using XML-RPC" +_VERSION = "LuaXMLRPC 1.1.0" + +--------------------------------------------------------------------- +-- XML-RPC Parser +--------------------------------------------------------------------- + +--------------------------------------------------------------------- +local function trim (s) + return (type(s) == "string" and gsub (s, "^%s*(.-)%s*$", "%1")) +end + +--------------------------------------------------------------------- +local function is_space (s) + return type(s) == "string" and trim(s) == "" +end + +--------------------------------------------------------------------- +-- Get next non-space element from tab starting from index i. +-- @param tab Table. +-- @param i Numeric index. +-- @return Object and its position on table; nil and an invalid index +-- when there is no more elements. +--------------------------------------------------------------------- +function next_nonspace (tab, i) + if not i then i = 1 end + while is_space (tab[i]) do i = i+1 end + return tab[i], i +end + +--------------------------------------------------------------------- +-- Get next element of tab with the given tag starting from index i. +-- @param tab Table. +-- @param tag String with the name of the tag. +-- @param i Numeric index. +-- @return Object and its position on table; nil and an invalid index +-- when there is no more elements. +--------------------------------------------------------------------- +local function next_tag (tab, tag, i) + if not i then i = 1 end + while tab[i] do + if type (tab[i]) == "table" and tab[i].tag == tag then + return tab[i], i + end + i = i + 1 + end + return nil, i +end + +--------------------------------------------------------------------- +local function x2number (tab) + if tab.tag == "int" or tab.tag == "i4" or tab.tag == "double" then + return tonumber (next_nonspace (tab, 1), 10) + end +end + +--------------------------------------------------------------------- +local function x2boolean (tab) + if tab.tag == "boolean" then + local v = next_nonspace (tab, 1) + return tonumber (v) == 1 or false + end +end + +--------------------------------------------------------------------- +local function x2string (tab) + return tab.tag == "string" and tab[1] +end + +--------------------------------------------------------------------- +local function x2date (tab) + return tab.tag == "dateTime.iso8601" and next_nonspace (tab, 1) +end + +--------------------------------------------------------------------- +local function x2base64 (tab) + return tab.tag == "base64" and next_nonspace (tab, 1) +end + +--------------------------------------------------------------------- +local function x2name (tab) + return tab.tag == "name" and next_nonspace (tab, 1) +end + +local x2value + +--------------------------------------------------------------------- +-- Disassemble a member object in its name and value parts. +-- @param tab Table with a DOM representation. +-- @return String (name) and Object (value). +-- @see x2name, x2value. +--------------------------------------------------------------------- +local function x2member (tab) + return + x2name (next_tag(tab,"name")), + x2value (next_tag(tab,"value")) +end + +--------------------------------------------------------------------- +-- Disassemble a struct object into a Lua table. +-- @param tab Table with DOM representation. +-- @return Table with "name = value" pairs. +--------------------------------------------------------------------- +local function x2struct (tab) + if tab.tag == "struct" then + local res = {} + for i = 1, #tab do + if not is_space (tab[i]) then + local name, val = x2member (tab[i]) + res[name] = val + end + end + return res + end +end + +--------------------------------------------------------------------- +-- Disassemble an array object into a Lua table. +-- @param tab Table with DOM representation. +-- @return Table. +--------------------------------------------------------------------- +local function x2array (tab) + if tab.tag == "array" then + local d = next_tag (tab, "data") + local res = {} + for i = 1, #d do + if not is_space (d[i]) then + tinsert (res, x2value (d[i])) + end + end + return res + end +end + +--------------------------------------------------------------------- +local xmlrpc_types = { + int = x2number, + i4 = x2number, + boolean = x2boolean, + string = x2string, + double = x2number, + ["dateTime.iso8601"] = x2date, + base64 = x2base64, + struct = x2struct, + array = x2array, +} + +local x2param, x2fault + +--------------------------------------------------------------------- +-- Disassemble a methodResponse into a Lua object. +-- @param tab Table with DOM representation. +-- @return Boolean (indicating wether the response was successful) +-- and (a Lua object representing the return values OR the fault +-- string and the fault code). +--------------------------------------------------------------------- +local function x2methodResponse (tab) + assert (type(tab) == "table", "Not a table") + assert (tab.tag == "methodResponse", + "Not a `methodResponse' tag: "..tab.tag) + local t = next_nonspace (tab, 1) + if t.tag == "params" then + return true, unpack (x2param (t)) + elseif t.tag == "fault" then + local f = x2fault (t) + return false, f.faultString, f.faultCode + else + error ("Couldn't find a nor a element") + end +end + +--------------------------------------------------------------------- +-- Disassemble a value element into a Lua object. +-- @param tab Table with DOM representation. +-- @return Object. +--------------------------------------------------------------------- +x2value = function (tab) + local t = tab.tag + assert (t == "value", "Not a `value' tag: "..t) + local n = next_nonspace (tab) + if type(n) == "string" or type(n) == "number" then + return n + elseif type (n) == "table" then + local t = n.tag + local get = xmlrpc_types[t] + if not get then error ("Invalid <"..t.."> element") end + return get (next_nonspace (tab)) + end +end + +--------------------------------------------------------------------- +-- Disassemble a fault element into a Lua object. +-- @param tab Table with DOM representation. +-- @return Object. +--------------------------------------------------------------------- +x2fault = function (tab) + assert (tab.tag == "fault", "Not a `fault' tag: "..tab.tag) + return x2value (next_nonspace (tab)) +end + +--------------------------------------------------------------------- +-- Disassemble a param element into a Lua object. +-- Ignore white spaces between elements. +-- @param tab Table with DOM representation. +-- @return Object. +--------------------------------------------------------------------- +x2param = function (tab) + assert (tab.tag == "params", "Not a `params' tag") + local res = {} + local p, i = next_nonspace (tab, 1) + while p do + if p.tag == "param" then + tinsert (res, x2value (next_tag (p, "value"))) + end + p, i = next_nonspace (tab, i+1) + end + return res +end + +--------------------------------------------------------------------- +-- Disassemble a methodName element into a Lua object. +-- @param tab Table with DOM representation. +-- @return Object. +--------------------------------------------------------------------- +local function x2methodName (tab) + assert (tab.tag == "methodName", "Not a `methodName' tag: "..tab.tag) + return (next_nonspace (tab, 1)) +end + +--------------------------------------------------------------------- +-- Disassemble a methodCall element into its name and a list of parameters. +-- @param tab Table with DOM representation. +-- @return Object. +--------------------------------------------------------------------- +local function x2methodCall (tab) + assert (tab.tag == "methodCall", "Not a `methodCall' tag: "..tab.tag) + return + x2methodName (next_tag (tab,"methodName")), + x2param (next_tag (tab,"params")) +end + +--------------------------------------------------------------------- +-- End of XML-RPC Parser +--------------------------------------------------------------------- + +--------------------------------------------------------------------- +-- Convert a Lua Object into an XML-RPC string. +--------------------------------------------------------------------- + +--------------------------------------------------------------------- +local formats = { + boolean = "%d", + number = "%d", + string = "%s", + + array = "\n%s\n", + double = "%s", + int = "%s", + struct = "%s", + + member = "%s%s", + value = "%s", + + param = "%s", + + params = [[ + + %s + ]], + + fault = [[ + + %s + ]], + + methodCall = [[ + + + %s +%s + +]], + + methodResponse = [[ + + +%s +]], +} +formats.table = formats.struct + +local toxml = {} +toxml.double = function (v,t) return format (formats.double, v) end +toxml.int = function (v,t) return format (formats.int, v) end +toxml.string = function (v,t) return format (formats.string, v) end + +--------------------------------------------------------------------- +-- Build a XML-RPC representation of a boolean. +-- @param v Object. +-- @return String. +--------------------------------------------------------------------- +function toxml.boolean (v) + local n = (v and 1) or 0 + return format (formats.boolean, n) +end + +--------------------------------------------------------------------- +-- Build a XML-RPC representation of a number. +-- @param v Object. +-- @param t Object representing the XML-RPC type of the value. +-- @return String. +--------------------------------------------------------------------- +function toxml.number (v, t) + local tt = (type(t) == "table") and t["*type"] + if tt == "int" or tt == "i4" then + return toxml.int (v, t) + elseif tt == "double" then + return toxml.double (v, t) + elseif v == ceil(v) then + return toxml.int (v, t) + else + return toxml.double (v, t) + end +end + +--------------------------------------------------------------------- +-- @param typ Object representing a type. +-- @return Function that generate an XML element of the given type. +-- The object could be a string (as usual in Lua) or a table with +-- a field named "type" that should be a string with the XML-RPC +-- type name. +--------------------------------------------------------------------- +local function format_func (typ) + if type (typ) == "table" then + return toxml[typ.type] + else + return toxml[typ] + end +end + +--------------------------------------------------------------------- +-- @param val Object representing an array of values. +-- @param typ Object representing the type of the value. +-- @return String representing the equivalent XML-RPC value. +--------------------------------------------------------------------- +function toxml.array (val, typ) + local ret = {} + local et = typ.elemtype + local f = format_func (et) + for i,v in ipairs (val) do + tinsert (ret, format (formats.value, f (v, et))) + end + return format (formats.array, concat (ret, '\n')) +end + +--------------------------------------------------------------------- +--------------------------------------------------------------------- +function toxml.struct (val, typ) + local ret = {} + if type (typ) == "table" then + for n,t in pairs (typ.elemtype) do + local f = format_func (t) + tinsert (ret, format (formats.member, n, f (val[n], t))) + end + else + for i, v in pairs (val) do + tinsert (ret, toxml.member (i, v)) + end + end + return format (formats.struct, concat (ret)) +end + +toxml.table = toxml.struct + +--------------------------------------------------------------------- +--------------------------------------------------------------------- +function toxml.member (n, v) + return format (formats.member, n, toxml.value (v)) +end + +--------------------------------------------------------------------- +-- Get type and value of object. +--------------------------------------------------------------------- +local function type_val (obj) + local t = type (obj) + local v = obj + if t == "table" then + t = obj["*type"] or "table" + v = obj["*value"] or obj + end + return t, v +end + +--------------------------------------------------------------------- +-- Convert a Lua object to a XML-RPC object (plain string). +--------------------------------------------------------------------- +function toxml.value (obj) + local to, val = type_val (obj) + if type(to) == "table" then + return format (formats.value, toxml[to.type] (val, to)) + else + -- primitive (not structured) types. + --return format (formats[to], val) + return format (formats.value, toxml[to] (val, to)) + end +end + +--------------------------------------------------------------------- +-- @param ... List of parameters. +-- @return String representing the `params' XML-RPC element. +--------------------------------------------------------------------- +function toxml.params (...) + local params_list = {} + for i = 1, select ("#", ...) do + params_list[i] = format (formats.param, toxml.value (select (i, ...))) + end + return format (formats.params, concat (params_list, '\n ')) +end + +--------------------------------------------------------------------- +-- @param method String with method's name. +-- @param ... List of parameters. +-- @return String representing the `methodCall' XML-RPC element. +--------------------------------------------------------------------- +function toxml.methodCall (method, ...) + local idx = strfind (method, "[^A-Za-z_.:/0-9]") + if idx then + error (format ("Invalid character `%s'", strsub (method, idx, idx))) + end + return format (formats.methodCall, method, toxml.params (...)) +end + +--------------------------------------------------------------------- +-- @param err String with error message. +-- @return String representing the `fault' XML-RPC element. +--------------------------------------------------------------------- +function toxml.fault (err) + local code + local message = err + if type (err) == "table" then + code = err.code + message = err.message + end + return format (formats.fault, toxml.value { + faultCode = { ["*type"] = "int", ["*value"] = code or err.faultCode or 1 }, + faultString = message or err.faultString or "fatal error", + }) +end + +--------------------------------------------------------------------- +-- @param ok Boolean indicating if the response was correct or a +-- fault one. +-- @param params Object containing the response contents. +-- @return String representing the `methodResponse' XML-RPC element. +--------------------------------------------------------------------- +function toxml.methodResponse (ok, params) + local resp + if ok then + resp = toxml.params (params) + else + resp = toxml.fault (params) + end + return format (formats.methodResponse, resp) +end + +--------------------------------------------------------------------- +-- End of converter from Lua to XML-RPC. +--------------------------------------------------------------------- + + +--------------------------------------------------------------------- +-- Create a representation of an array with the given element type. +--------------------------------------------------------------------- +function newArray (elemtype) + return { type = "array", elemtype = elemtype, } +end + +--------------------------------------------------------------------- +-- Create a representation of a structure with the given members. +--------------------------------------------------------------------- +function newStruct (members) + return { type = "struct", elemtype = members, } +end + +--------------------------------------------------------------------- +-- Create a representation of a value according to a type. +-- @param val Any Lua value. +-- @param typ A XML-RPC type. +--------------------------------------------------------------------- +function newTypedValue (val, typ) + return { ["*type"] = typ, ["*value"] = val } +end + +--------------------------------------------------------------------- +-- Create the XML-RPC string used to call a method. +-- @param method String with method name. +-- @param ... Parameters to the call. +-- @return String with the XML string/document. +--------------------------------------------------------------------- +function clEncode (method, ...) + return toxml.methodCall (method, ...) +end + +--------------------------------------------------------------------- +-- Convert the method response document to a Lua table. +-- @param meth_resp String with XML document. +-- @return Boolean indicating whether the call was successful or not; +-- and a Lua object with the converted response element. +--------------------------------------------------------------------- +function clDecode (meth_resp) + local d = parse (meth_resp) + if type(d) ~= "table" then + error ("Not an XML document: "..meth_resp) + end + return x2methodResponse (d) +end + +--------------------------------------------------------------------- +-- Convert the method call (client request) document to a name and +-- a list of parameters. +-- @param request String with XML document. +-- @return String with method's name AND the table of arguments. +--------------------------------------------------------------------- +function srvDecode (request) + local d = parse (request) + if type(d) ~= "table" then + error ("Not an XML document: "..request) + end + return x2methodCall (d) +end + +--------------------------------------------------------------------- +-- Convert a table into an XML-RPC methodReponse element. +-- @param obj Lua object. +-- @param is_fault Boolean indicating wether the result should be +-- a `fault' element (default = false). +-- @return String with XML-RPC response. +--------------------------------------------------------------------- +function srvEncode (obj, is_fault) + local ok = not (is_fault or false) + return toxml.methodResponse (ok, obj) +end + +--------------------------------------------------------------------- +-- Register the methods. +-- @param tab_or_func Table or mapping function. +-- If a table is given, it can have one level of objects and then the +-- methods; +-- if a function is given, it will be used as the dispatcher. +-- The given function should return a Lua function that implements. +--------------------------------------------------------------------- +dispatch = error +function srvMethods (tab_or_func) + local t = type (tab_or_func) + if t == "function" then + dispatch = tab_or_func + elseif t == "table" then + dispatch = function (name) + local ok, _, obj, method = strfind (name, "^([^.]+)%.(.+)$") + if not ok then + return tab_or_func[name] + else + if tab_or_func[obj] and tab_or_func[obj][method] then + return function (...) + return tab_or_func[obj][method] (obj, ...) + end + else + return nil + end + end + end + else + error ("Argument is neither a table nor a function") + end +end diff --git a/openwrt/packages/luaxmlrpc/src/server.lua b/openwrt/packages/luaxmlrpc/src/server.lua new file mode 100644 index 0000000..f400562 --- /dev/null +++ b/openwrt/packages/luaxmlrpc/src/server.lua @@ -0,0 +1,90 @@ +--------------------------------------------------------------------- +-- XML-RPC server +-- See Copyright Notice in license.html +-- $Id: server.lua,v 1.4 2007/03/30 04:18:54 tomas Exp $ +--------------------------------------------------------------------- + +local assert, pcall, setmetatable, type, unpack = assert, pcall, setmetatable, type, unpack +local cgilua = require"cgilua" +local os = require"os" +local string = require"string" +local table = require"table" +local xmlrpc = require"xmlrpc" + +module("xmlrpc.server") + +--------------------------------------------------------------------- +local function respond (resp) + cgilua.header ("Date", os.date()) + cgilua.header ("Server", "Me") + cgilua.header ("Content-length", string.len (resp)) + cgilua.header ("Connection", "close") + cgilua.contentheader ("text", "xml") + cgilua.put (resp) +end + +--------------------------------------------------------------------- +function assert (cond, msg) + if not cond then + respond (xmlrpc.srvEncode ( + { code = 2, message = msg, }, + true + )) + --os.exit() -- !!!!!!!!!!! + end +end + +cgilua.seterroroutput (function (msg) + respond (xmlrpc.srvEncode ({ code = 2, message = msg, }, true)) +end) + +--------------------------------------------------------------------- +local function decodedata (doc) + local method, arg_table = xmlrpc.srvDecode (doc) + assert (type(method) == "string", "Invalid `method': string expected") + local t = type(arg_table) + assert (t == "table" or t == "nil", "Invalid table of arguments: not a table nor nil") + + local func = xmlrpc.dispatch (method) + assert (type(func) == "function", "Unavailable method") + + return func, (arg_table or {}) +end + +--------------------------------------------------------------------- +local function callfunc (func, arg_table) + local result = { pcall (func, unpack (arg_table)) } + local ok = result[1] + if not ok then + result = { code = 3, message = result[2], } + else + table.remove (result, 1) + if #result == 1 then + result = result[1] + end + end + return ok, result +end + +--------------------------------------------------------------------- +function xmlrpc.server:new() + local o = { methods = { } } + setmetatable (o, self) + self.__index = self + return o +end + +--------------------------------------------------------------------- +function xmlrpc.server:register(name, service) + assert (type(name) == "string", "Invalid `name': string expected") + self.methods[name] = service +end + +--------------------------------------------------------------------- +function xmlrpc.server:handle() + xmlrpc.srvMethods (self.methods) + local func, arg_table = decodedata (cgi[1]) + local ok, result = callfunc (func, arg_table) + local r = xmlrpc.srvEncode (result, not ok) + respond (r) +end diff --git a/openwrt/packages/luaxyssl/Makefile b/openwrt/packages/luaxyssl/Makefile new file mode 100644 index 0000000..bd74926 --- /dev/null +++ b/openwrt/packages/luaxyssl/Makefile @@ -0,0 +1,43 @@ +include $(TOPDIR)/rules.mk + +PKG_BRANCH:=trunk +PKG_NAME:=luaxyssl +PKG_RELEASE:=1 +PKG_SOURCE_URL:=http://luaxyssl.googlecode.com/svn/$(PKG_BRANCH) +PKG_REV:=65 +PKG_VERSION:=0.2+svn$(PKG_REV) +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz +PKG_SOURCE_PROTO:=svn +PKG_SOURCE_VERSION:=$(PKG_REV) + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +include $(INCLUDE_DIR)/package.mk + +define Package/luaxyssl + SECTION:=lang + CATEGORY:=Languages + SUBMENU:=LUA + TITLE:=xyssl-Bindings for Lua + URL:=http://code.google.com/p/luaxyssl + DEPENDS:=+liblua +libxyssl +endef + +define Build/Configure +endef + +define Build/Compile + $(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) -shared -fpic -pedantic -Wall \ + -I$(STAGING_DIR)/usr/include \ + -DXYSSL=9 \ + -o $(PKG_BUILD_DIR)/lxyssl.so -lxyssl $(PKG_BUILD_DIR)/lxyssl.c +endef + +define Package/luaxyssl/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(INSTALL_DATA) $(PKG_BUILD_DIR)/lxyssl.so $(1)/usr/lib/lua +endef + +$(eval $(call BuildPackage,luaxyssl)) diff --git a/openwrt/packages/luaxyssl/patches/100-compile-fixes.patch b/openwrt/packages/luaxyssl/patches/100-compile-fixes.patch new file mode 100644 index 0000000..94091f5 --- /dev/null +++ b/openwrt/packages/luaxyssl/patches/100-compile-fixes.patch @@ -0,0 +1,273 @@ +Index: luaxyssl-0.2+svn65/lxyssl.c +=================================================================== +--- luaxyssl-0.2+svn65.orig/lxyssl.c 2008-07-01 17:28:52.000000000 +0200 ++++ luaxyssl-0.2+svn65/lxyssl.c 2008-07-01 17:32:00.000000000 +0200 +@@ -5,6 +5,7 @@ + * This code can be distributed under the LGPL license + */ + ++#include + #include + #include + #include +@@ -12,6 +13,7 @@ + #include + #include + #include ++#include + #else + #include + #include +@@ -326,7 +328,7 @@ + return 1; + } + if (lua_isstring(L, -1)) { +- int len; ++ size_t len; + const char *master = luaL_checklstring(L, -1, &len); + memcpy(ssl->session->master, master, len < sizeof(ssl->session->master) ? len : sizeof(ssl->session->master)); + lua_pop(L, 1); +@@ -479,7 +481,7 @@ + + static int Laes(lua_State *L) + { +- int klen; ++ size_t klen; + const unsigned char *key = luaL_checklstring(L, 1, &klen); + int bits = luaL_optinteger(L, 2, 128); + dual_aes_context *aes = lua_newuserdata(L,sizeof(dual_aes_context)); +@@ -503,7 +505,7 @@ + + static int Lrc4(lua_State *L) + { +- int klen; ++ size_t klen; + const unsigned char *key = luaL_checklstring(L, 1, &klen); + arc4_context *rc4 = lua_newuserdata(L,sizeof(arc4_context)); + arc4_setup(rc4, (unsigned char *)key, klen); +@@ -750,7 +752,7 @@ + static int Lhash(lua_State *L) + { + const char *type = luaL_checkstring(L,1); +- int klen=0; ++ size_t klen=0; + const unsigned char *key = luaL_optlstring(L, 2, NULL, &klen); + hash_context *obj = lua_newuserdata(L,sizeof(hash_context)); + +@@ -869,7 +871,7 @@ + static int Laes_encrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + int i; + luaL_Buffer B; +@@ -890,7 +892,7 @@ + static int Laes_decrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + int i; + luaL_Buffer B; +@@ -911,7 +913,7 @@ + static int Lrc4_crypt(lua_State *L) + { + arc4_context *obj=Pget_rc4(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + luaL_Buffer B; + unsigned char temp[256]; +@@ -938,9 +940,9 @@ + static int Laes_cbc_encrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int i=0; + luaL_Buffer B; +@@ -970,9 +972,9 @@ + static int Laes_cbc_decrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int i; + luaL_Buffer B; +@@ -1002,9 +1004,9 @@ + static int Laes_cfb_encrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int start = luaL_optinteger(L,4,0); + int i; +@@ -1039,9 +1041,9 @@ + static int Laes_cfb_decrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int start = luaL_optinteger(L,4,0); + int i; +@@ -1079,7 +1081,7 @@ + static int Lhash_update(lua_State *L) + { + hash_context *obj=Pget_hash(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + obj->update(&obj->eng, (unsigned char *)data, len); + lua_pushvalue(L, 1); +@@ -1091,7 +1093,7 @@ + { + hash_context *obj=Pget_hash(L,1); + unsigned char out[64]; +- int len; ++ size_t len; + const char *data = luaL_optlstring(L, 2, "", &len); + obj->update(&obj->eng, (unsigned char *)data, len); + obj->finish(&obj->eng, out); +@@ -1166,7 +1168,7 @@ + static int LaddTrustedCA(lua_State *L) + { + int ret; +- int ca_len; ++ size_t ca_len; + const char *ca = luaL_checklstring(L, 1, &ca_len); + + ret = x509_add_certs( &trustedCA, (unsigned char *) ca, ca_len); +@@ -1311,9 +1313,9 @@ + static int Lsessinfo(lua_State *L) /** sessinfo(c) */ + { + xyssl_context *xyssl=Pget(L,1); +- int id_len; ++ size_t id_len; + char *sessid = (char *)luaL_optlstring(L, 2, NULL, &id_len); +- int master_len; ++ size_t master_len; + char *master = (char *)luaL_optlstring(L, 3, NULL, &master_len); + int cipher = (int) luaL_optnumber(L,4,0); + time_t start = (time_t) luaL_optnumber(L,5,time(NULL)); +@@ -1597,7 +1599,7 @@ + static int LsessionCA(lua_State *L) /** setca(ca) **/ + { + int top = lua_gettop(L); +- int ca_len; ++ size_t ca_len; + int ret; + xyssl_context *xyssl=Pget(L,1); + x509_cert *cacert = &xyssl->cacert; +@@ -1624,9 +1626,9 @@ + ssl_context *ssl=&xyssl->ssl; + x509_cert *mycert= &xyssl->mycert; + rsa_context *rsa = &xyssl->mykey; +- int cert_len; +- int key_len; +- int pwd_len; ++ size_t cert_len; ++ size_t key_len; ++ size_t pwd_len; + int ret; + const char *cert = luaL_optlstring(L, 2, ssl->endpoint ? test_srv_crt: NULL, &cert_len); + const char *key = luaL_optlstring(L, 3, ssl->endpoint ? test_srv_key: NULL, &key_len); +@@ -1694,7 +1696,7 @@ + ssl_context *ssl=&xyssl->ssl; + x509_cert *cacert = &xyssl->cacert; + int verification = luaL_optinteger(L,2,0); +- int peer_len; ++ size_t peer_len; + const char *expected_peer= luaL_optlstring(L, 3, NULL, &peer_len); + ssl_set_authmode( ssl, verification ); + if (xyssl->peer_cn) free(xyssl->peer_cn); +@@ -1748,8 +1750,8 @@ + static int Lx509verify(lua_State *L) /** x509verify(ca, crt) */ + { + int top = lua_gettop(L); +- int crt_size; +- int ca_size; ++ size_t crt_size; ++ size_t ca_size; + int ret; + int flag; + x509_cert ca; +@@ -1797,9 +1799,9 @@ + static int Lrsaverify(lua_State *L) /** rsaverify(data, sig, [crt]) */ + { + int top = lua_gettop(L); +- int crt_size; +- int data_size; +- int sig_size; ++ size_t crt_size; ++ size_t data_size; ++ size_t sig_size; + int ret; + x509_cert cert; + const char *data = luaL_checklstring(L, 1, &data_size); +@@ -1833,8 +1835,8 @@ + static int Lrsaencrypt(lua_State *L) /** rsaencrypt(data, [crt]) */ + { + int top = lua_gettop(L); +- int crt_size; +- int data_size; ++ size_t crt_size; ++ size_t data_size; + unsigned char m[512]; + int ret; + x509_cert cert; +@@ -1868,9 +1870,9 @@ + static int Lrsasign(lua_State *L) /** rsasign(data, [key, [pw]]) */ + { + int top = lua_gettop(L); +- int key_size; +- int data_size; +- int pwd_len; ++ size_t key_size; ++ size_t data_size; ++ size_t pwd_len; + int ret; + unsigned char sig[512]; + rsa_context rsa; +@@ -1905,9 +1907,9 @@ + static int Lrsadecrypt(lua_State *L) /** rsadecrypt(data, [key, [pw]]) */ + { + int top = lua_gettop(L); +- int key_size; +- int data_size; +- int pwd_len; ++ size_t key_size; ++ size_t data_size; ++ size_t pwd_len; + int out_len; + int ret; + unsigned char m[512]; +@@ -2076,8 +2078,8 @@ + static int Ldhmsecret(lua_State *L) /** dhsecret(public, private, [P, [G]]) */ + { + int top = lua_gettop(L); +- int public_size; +- int private_size; ++ size_t public_size; ++ size_t private_size; + int ret; + dhm_context dhm; + unsigned char buf[512]; diff --git a/openwrt/packages/luci/.buildpath b/openwrt/packages/luci/.buildpath new file mode 100644 index 0000000..81fa646 --- /dev/null +++ b/openwrt/packages/luci/.buildpath @@ -0,0 +1,5 @@ + + + + + diff --git a/openwrt/packages/luci/.cproject b/openwrt/packages/luci/.cproject new file mode 100644 index 0000000..e1a4774 --- /dev/null +++ b/openwrt/packages/luci/.cproject @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openwrt/packages/luci/.gitignore b/openwrt/packages/luci/.gitignore new file mode 100644 index 0000000..27b6e75 --- /dev/null +++ b/openwrt/packages/luci/.gitignore @@ -0,0 +1,6 @@ +dist/ +/host +*.o +*.so +*.swp +/docs diff --git a/openwrt/packages/luci/.project b/openwrt/packages/luci/.project new file mode 100644 index 0000000..11b398b --- /dev/null +++ b/openwrt/packages/luci/.project @@ -0,0 +1,78 @@ + + + luci + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.cnature + org.eclipse.dltk.lua.core.nature + + diff --git a/openwrt/packages/luci/INSTALL b/openwrt/packages/luci/INSTALL new file mode 100644 index 0000000..42cf706 --- /dev/null +++ b/openwrt/packages/luci/INSTALL @@ -0,0 +1,27 @@ +LuCI Installation Instructions + +TOC: +1. Kamikaze Feed +2. Kamikaze Packages + + +1. Kamikaze Feed + 1. Change to your OpenWrt buildroot + + 2. Add the following line to your OpenWrt feeds.conf: + src-svn luci http://svn.luci.subsignal.org/luci/trunk/contrib/package + + 3. Run ./scripts/feeds update + + 4. Run ./scripts/feeds install -a -p luci + + 5. Type make menuconfig and you will find luci in the menu "Administration" + + +2. Kamikaze Packages + 1. cd to the "package" directory of your kamikaze buildroot + + 3. Type: ln -s /path/to/luci/contrib/package/* ./ + + 4. cd to your kamikaze build root and type: make menuconfig + You will find luci in the menu "Administration" diff --git a/openwrt/packages/luci/LICENSE b/openwrt/packages/luci/LICENSE new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/openwrt/packages/luci/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/openwrt/packages/luci/Makefile b/openwrt/packages/luci/Makefile new file mode 100644 index 0000000..cbebd45 --- /dev/null +++ b/openwrt/packages/luci/Makefile @@ -0,0 +1,84 @@ +include build/config.mk + +MODULES = contrib/* applications/* libs/* modules/* themes/* i18n/* + +OS:=$(shell uname) +export OS + +.PHONY: all build gccbuild luabuild clean host gcchost luahost hostcopy hostclean + +all: build + +build: gccbuild luabuild + +gccbuild: + for i in $(MODULES); do make -C$$i compile; done + +luabuild: + for i in $(MODULES); do make -C$$i luabuild; done + +clean: + rm -rf docs + for i in $(MODULES); do make -C$$i clean; done + + +host: build hostcopy + +gcchost: gccbuild hostcopy + +luahost: luabuild hostcopy + +hostcopy: + mkdir -p host/tmp + for i in $(MODULES); do cp -pR $$i/dist/* host/ 2>/dev/null || true; done + for i in $(MODULES); do cp -pR $$i/hostfiles/* host/ 2>/dev/null || true; done + rm -f host/luci + ln -s .$(LUCI_MODULEDIR) host/luci + rm -rf /tmp/luci-* || true + +hostenv: host ucidefaults + +ucidefaults: + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) "$(realpath host)/bin/uci-defaults --exclude luci-freifunk-*" + +runboa: hostenv + libs/sgi-webuci/host/buildconfig.sh $(realpath host) > host/etc/boa/boa.conf + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) "$(realpath host/usr/bin/boa) -c $(realpath host/etc/boa) -d" + +runhttpd: hostenv + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) "$(realpath host/usr/bin/lucittpd) $(realpath host)/usr/lib/lucittpd/plugins" + +runluci: luahost + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) "$(realpath libs/httpd/host/runluci) $(realpath host) $(HTDOCS)" + +runlua: hostenv + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) lua + +runshell: hostenv + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) $$SHELL + +hostclean: clean + rm -rf host + +apidocs: hostenv + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) "build/makedocs.sh host/luci/ docs" + +uvldocs: hostenv + build/hostenv.sh $(realpath host) $(LUA_MODULEDIR) $(LUA_LIBRARYDIR) \ + "build/uvldoc $(realpath host) $(UVL_SCHEMEDIR) uvldocs $(DOCS)" + +run: + # make run is deprecated # + # Please use: # + # # + # To run LuCI WebUI using LuCIttpd # + # make runhttpd # + # # + # To run LuCI WebUI using Boa/Webuci # + # make runboa # + # # + # To start a shell in the LuCI environment # + # make runshell # + # # + # To run Lua CLI in the LuCI environment # + # make runlua # diff --git a/openwrt/packages/luci/NOTICE b/openwrt/packages/luci/NOTICE new file mode 100644 index 0000000..1828792 --- /dev/null +++ b/openwrt/packages/luci/NOTICE @@ -0,0 +1,8 @@ +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich +Licensed under the Apache License, Version 2.0. + +Contains code from: +coxpcall - Copyright 2005 - Kepler Project (www.keplerproject.org) +ltn12/luasocket - Copyright 2004-2007 Diego Nehab diff --git a/openwrt/packages/luci/THANKYOU b/openwrt/packages/luci/THANKYOU new file mode 100644 index 0000000..f0519bd --- /dev/null +++ b/openwrt/packages/luci/THANKYOU @@ -0,0 +1,26 @@ +I'd like to thank the following people for contributing to this software: + +* Anton Popov + - for rewriting the openwrt.org theme + +* Florian Fainelli (OpenWrt) + - for the french translation + +* Alina Friedrichsen + - for the reworked translation system, help on standards compliance and accessibility + +* Yanira + - several applications and bugreports + + +Also a big thank you goes to: + +* Mono (Freifunk Halle) + - for donating a Linksys WRT54GL for development purposes + +* tetzlav (Freifunk Leipzig) + - for donating several boards for testing and his feedback + +* Mickey (Freifunk Hannover) + - for his feedback and fixes for the OpenWrt builds + diff --git a/openwrt/packages/luci/applications/freifunk-community/Makefile b/openwrt/packages/luci/applications/freifunk-community/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/freifunk-community/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-nodes.html b/openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-nodes.html new file mode 100644 index 0000000..8dd86b0 --- /dev/null +++ b/openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-nodes.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-status.html b/openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-status.html new file mode 100644 index 0000000..8dd86b0 --- /dev/null +++ b/openwrt/packages/luci/applications/freifunk-community/htdocs/cgi-bin-status.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/openwrt/packages/luci/applications/luci-ddns/Makefile b/openwrt/packages/luci/applications/luci-ddns/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/controller/ddns.lua b/openwrt/packages/luci/applications/luci-ddns/luasrc/controller/ddns.lua new file mode 100644 index 0000000..e964c5e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/controller/ddns.lua @@ -0,0 +1,32 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ddns.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.ddns", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("ddns") + if not luci.fs.access("/etc/config/ddns") then + return + end + + local page = entry({"admin", "services", "ddns"}, cbi("ddns/ddns"), luci.i18n.translate("ddns"), 60) + page.i18n = "ddns" + page.dependent = true + + + local page = entry({"mini", "network", "ddns"}, cbi("ddns/ddnsmini", {autoapply=true}), luci.i18n.translate("ddns"), 60) + page.i18n = "ddns" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.lua b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.lua new file mode 100644 index 0000000..f731b7c --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.lua @@ -0,0 +1,8 @@ +ddns = 'Dynamisches DNS' +ddns_desc = 'Dynamisches DNS erlaubt es, den Router bei dynamischer IP-Adresse über einen festen DNS-Namen zu erreichen.' +ddns_service_ipsource = 'Quelle der IP-Adresse' +ddns_service_checkinterval = 'Teste auf neue IP alle' +ddns_service_checkunit = 'Test-Zeiteinheit' +ddns_service_forceinterval = 'Erzwinge Aktualisierung alle' +ddns_service_forceunit = 'Erzwinge-Zeiteinheit' +ddns_service_updateurl = 'Eigene Update-URL' diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.xml b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.xml new file mode 100644 index 0000000..2130740 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.de.xml @@ -0,0 +1,13 @@ + + + + +Dynamisches DNS +Dynamisches DNS erlaubt es, den Router bei dynamischer IP-Adresse über einen festen DNS-Namen zu erreichen. +Quelle der IP-Adresse +Teste auf neue IP alle +Test-Zeiteinheit +Erzwinge Aktualisierung alle +Erzwinge-Zeiteinheit +Eigene Update-URL + diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.lua b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.lua new file mode 100644 index 0000000..b8afdf4 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.lua @@ -0,0 +1,8 @@ +ddns = 'Dynamic DNS' +ddns_desc = 'Dynamic DNS allows that your router can be reached with a fixed hostname while having a dynamically changing IP-Address.' +ddns_service_ipsource = 'Source of IP-Address' +ddns_service_checkinterval = 'Check for changed IP every' +ddns_service_checkunit = 'Check-Time unit' +ddns_service_forceinterval = 'Force update every' +ddns_service_forceunit = 'Force-Time unit' +ddns_service_updateurl = 'Custom Update-URL' diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.xml b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.xml new file mode 100644 index 0000000..9b09c77 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.en.xml @@ -0,0 +1,13 @@ + + + + +Dynamic DNS +Dynamic DNS allows that your router can be reached with a fixed hostname while having a dynamically changing IP-Address. +Source of IP-Address +Check for changed IP every +Check-Time unit +Force update every +Force-Time unit +Custom Update-URL + diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.lua b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.lua new file mode 100644 index 0000000..8e5b6fa --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.lua @@ -0,0 +1,8 @@ +ddns = 'DNS Dynamique' +ddns_desc = 'Le DNS Dynamique permet au routeur d'être joint avec un nom d'hôte fixe bien que changeant dynamiquement d'adresse IP.' +ddns_service_ipsource = 'Source de l'adresse IP' +ddns_service_checkinterval = 'Vérifier l'adresse IP toutes les' +ddns_service_checkunit = 'Unité de temps' +ddns_service_forceinterval = 'Vérification forcée toutes les' +ddns_service_forceunit = 'Unité de temps' +ddns_service_updateurl = 'Url de mise à jour personnalisée' diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.xml b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.xml new file mode 100644 index 0000000..2b697cb --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.fr.xml @@ -0,0 +1,13 @@ + + + + +DNS Dynamique +Le DNS Dynamique permet au routeur d'être joint avec un nom d'hôte fixe bien que changeant dynamiquement d'adresse IP. +Source de l'adresse IP +Vérifier l'adresse IP toutes les +Unité de temps +Vérification forcée toutes les +Unité de temps +Url de mise à jour personnalisée + diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.lua b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.lua new file mode 100644 index 0000000..58375c2 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.lua @@ -0,0 +1,8 @@ +ddns = 'DNS Dinâmico' +ddns_desc = 'DNS dinâmico permite que o seu router possa ser encontrado a partir de um hostname fixo, mesmo usando um Endereço-IP dinâmico.' +ddns_service_ipsource = 'Origem do Endereço-IP' +ddns_service_checkinterval = 'Verificar a cada mudança de IP' +ddns_service_checkunit = 'Unidade de tempo para verificação' +ddns_service_forceinterval = 'Forçar atualização a cada' +ddns_service_forceunit = 'Unidade de tempo para atualização forçada' +ddns_service_updateurl = 'URL para atualização customizada' diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.xml b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.xml new file mode 100644 index 0000000..c77ff3e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/i18n/ddns.pt-br.xml @@ -0,0 +1,13 @@ + + + + +DNS Dinâmico +DNS dinâmico permite que o seu router possa ser encontrado a partir de um hostname fixo, mesmo usando um Endereço-IP dinâmico. +Origem do Endereço-IP +Verificar a cada mudança de IP +Unidade de tempo para verificação +Forçar atualização a cada +Unidade de tempo para atualização forçada +URL para atualização customizada + diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddns.lua b/openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddns.lua new file mode 100644 index 0000000..b1877d8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddns.lua @@ -0,0 +1,74 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ddns.lua 3643 2008-10-29 05:34:34Z jow $ +]]-- +require("luci.tools.webadmin") +m = Map("ddns", translate("ddns"), translate("ddns_desc")) + +s = m:section(TypedSection, "service", "") +s.addremove = true + +s:option(Flag, "enabled", translate("enable")) + +svc = s:option(ListValue, "service_name", translate("service")) +svc.rmempty = true +svc:value("") +svc:value("dyndns.org") +svc:value("changeip.com") +svc:value("zoneedit.com") +svc:value("no-ip.com") +svc:value("freedns.afraid.org") + +s:option(Value, "domain", translate("hostname")).rmempty = true +s:option(Value, "username", translate("username")).rmempty = true +pw = s:option(Value, "password", translate("password")) +pw.rmempty = true +pw.password = true + +src = s:option(ListValue, "ip_source") +src:value("network", translate("network")) +src:value("interface", translate("interface")) +src:value("web", "URL") + +iface = s:option(ListValue, "ip_network", translate("network")) +iface:depends("ip_source", "network") +iface.rmempty = true +luci.tools.webadmin.cbi_add_networks(iface) + +iface = s:option(ListValue, "ip_interface", translate("interface")) +iface:depends("ip_source", "interface") +iface.rmempty = true +for k, v in pairs(luci.sys.net.devices()) do + iface:value(v) +end + +web = s:option(Value, "ip_url", "URL") +web:depends("ip_source", "web") +web.rmempty = true + +s:option(Value, "update_url").optional = true + +s:option(Value, "check_interval").default = 10 +unit = s:option(ListValue, "check_unit") +unit.default = "minutes" +unit:value("minutes", "min") +unit:value("hours", "h") + +s:option(Value, "force_interval").default = 72 +unit = s:option(ListValue, "force_unit") +unit.default = "hours" +unit:value("minutes", "min") +unit:value("hours", "h") + + +return m diff --git a/openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddnsmini.lua b/openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddnsmini.lua new file mode 100644 index 0000000..8a898a9 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/luasrc/model/cbi/ddns/ddnsmini.lua @@ -0,0 +1,52 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ddnsmini.lua 3643 2008-10-29 05:34:34Z jow $ +]]-- +m = Map("ddns", translate("ddns"), translate("ddns_desc")) + +s = m:section(TypedSection, "service", "") +s.addremove = true + +s:option(Flag, "enabled", translate("enable")) + +svc = s:option(ListValue, "service_name", translate("service")) +svc.rmempty = true +svc:value("dyndns.org") +svc:value("changeip.com") +svc:value("zoneedit.com") +svc:value("no-ip.com") +svc:value("freedns.afraid.org") + +s:option(Value, "domain", translate("hostname")).rmempty = true +s:option(Value, "username", translate("username")).rmempty = true +pw = s:option(Value, "password", translate("password")) +pw.rmempty = true +pw.password = true + +s.defaults.ip_source = "network" +s.defaults.ip_network = "wan" + +s:option(Value, "check_interval").default = 10 +unit = s:option(ListValue, "check_unit") +unit.default = "minutes" +unit:value("minutes", "min") +unit:value("hours", "h") + +s:option(Value, "force_interval").default = 72 +unit = s:option(ListValue, "force_unit") +unit.default = "hours" +unit:value("minutes", "min") +unit:value("hours", "h") + + +return m diff --git a/openwrt/packages/luci/applications/luci-ddns/root/lib/uci/schema/default/ddns b/openwrt/packages/luci/applications/luci-ddns/root/lib/uci/schema/default/ddns new file mode 100644 index 0000000..f947aff --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ddns/root/lib/uci/schema/default/ddns @@ -0,0 +1,147 @@ +package ddns + +config package + option title 'Dynamic DNS configuration' + +config section + option name 'service' + option title 'DynDNS service entry' + option package 'ddns' + option named true + option required true + +config variable + option name 'enabled' + option title 'Enable this service entry' + option section 'ddns.service' + option datatype 'boolean' + +config variable + option name 'service_name' + option title 'Name of the DynDNS provider' + option section 'ddns.service' + option datatype 'string' + +config variable + option name 'domain' + option title 'Own DynDNS domain' + option section 'ddns.service' + option required true + +config variable + option name 'username' + option title 'Account username' + option section 'ddns.service' + option required true + +config variable + option name 'password' + option title 'Account password' + option section 'ddns.service' + option required true + +config variable + option name 'ip_source' + option title 'Method to determine current IP address' + option section 'ddns.service' + option type 'enum' + option required true + +config enum + option variable 'ddns.service.ip_source' + option value 'network' + option title 'Read ip address from /etc/config/network' + +config enum + option variable 'ddns.service.ip_source' + option value 'interface' + option title 'Determine ip address from given hardware interface' + +config enum + option variable 'ddns.service.ip_source' + option value 'web' + option title 'Determine own IP using a remote web page' + +config variable + option name 'ip_network' + option title 'Configured network to use IP from' + option section 'ddns.service' + option depends 'ip_source=network' + option valueof 'network.interface' + +config variable + option name 'ip_interface' + option title 'Physical network interface to read IP from' + option section 'ddns.service' + option depends 'ip_source=interface' + +config variable + option name 'ip_url' + option title 'Web page used to determine IP address' + option section 'ddns.service' + option depends 'ip_source=web' + +config variable + option name 'update_url' + option title 'URL format to use for updating DNS information (for yet-unknown providers)' + option section 'ddns.service' + +config variable + option name 'check_interval' + option title 'Update check interval' + option section 'ddns.service' + option datatype 'integer' + option required true + +config variable + option name 'check_unit' + option title 'Unit for update check interval' + option section 'ddns.service' + option type 'enum' + option required true + +config enum + option variable 'ddns.service.check_unit' + option value 'seconds' + +config enum + option variable 'ddns.service.check_unit' + option value 'minutes' + +config enum + option variable 'ddns.service.check_unit' + option value 'hours' + +config enum + option variable 'ddns.service.check_unit' + option value 'days' + +config variable + option name 'force_interval' + option title 'Forced update interval' + option section 'ddns.service' + option datatype 'integer' + option required true + +config variable + option name 'force_unit' + option title 'Unit of forced update interval' + option section 'ddns.service' + option type 'enum' + option required true + +config enum + option variable 'ddns.service.force_unit' + option value 'seconds' + +config enum + option variable 'ddns.service.force_unit' + option value 'minutes' + +config enum + option variable 'ddns.service.force_unit' + option value 'hours' + +config enum + option variable 'ddns.service.force_unit' + option value 'days' diff --git a/openwrt/packages/luci/applications/luci-ffwizard-leipzig/Makefile b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/controller/ffwizard.lua b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/controller/ffwizard.lua new file mode 100644 index 0000000..f0e700d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/controller/ffwizard.lua @@ -0,0 +1,21 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ffwizard.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +module "luci.controller.ffwizard" + +function index() + entry({"admin", "freifunk", "ffwizard"}, form("ffwizard"), "Freifunkassistent", 50) +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/model/cbi/ffwizard.lua b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/model/cbi/ffwizard.lua new file mode 100644 index 0000000..f93f0c1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/model/cbi/ffwizard.lua @@ -0,0 +1,391 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ffwizard.lua 4187 2009-01-30 15:07:36Z jow $ + +]]-- + + +local uci = require "luci.model.uci".cursor() +local tools = require "luci.tools.ffwizard" +local util = require "luci.util" +local sys = require "luci.sys" + + +-------------------- View -------------------- +f = SimpleForm("ffwizward", "Freifunkassistent", + "Dieser Assistent unterstüzt bei der Einrichtung des Routers für das Freifunknetz.") + + +dev = f:field(ListValue, "device", "WLAN-Gerät") +uci:foreach("wireless", "wifi-device", + function(section) + dev:value(section[".name"]) + end) + + +main = f:field(Flag, "wifi", "Freifunkzugang einrichten") + +net = f:field(Value, "net", "Freifunknetz", "1. Teil der IP-Adresse") +net.rmempty = true +net:depends("wifi", "1") +uci:foreach("freifunk", "community", function(s) + net:value(s[".name"], "%s (%s)" % {s.name, s.prefix}) +end) + +function net.cfgvalue(self, section) + return uci:get("freifunk", "wizard", "net") +end +function net.write(self, section, value) + uci:set("freifunk", "wizard", "net", value) + uci:save("freifunk") +end + + +subnet = f:field(Value, "subnet", "Subnetz (Projekt)", "2. Teil der IP-Adresse") +subnet.rmempty = true +subnet:depends("wifi", "1") +function subnet.cfgvalue(self, section) + return uci:get("freifunk", "wizard", "subnet") +end +function subnet.write(self, section, value) + uci:set("freifunk", "wizard", "subnet", value) + uci:save("freifunk") +end + +node = f:field(Value, "node", "Knoten", "3. Teil der IP-Adresse") +node.rmempty = true +node:depends("wifi", "1") +for i=1, 51 do + node:value(i) +end +function node.cfgvalue(self, section) + return uci:get("freifunk", "wizard", "node") +end +function node.write(self, section, value) + uci:set("freifunk", "wizard", "node", value) + uci:save("freifunk") +end + +client = f:field(Flag, "client", "WLAN-DHCP anbieten") +client:depends("wifi", "1") +client.rmempty = true + + +olsr = f:field(Flag, "olsr", "OLSR einrichten") +olsr.rmempty = true + +share = f:field(Flag, "sharenet", "Eigenen Internetzugang freigeben") +share.rmempty = true + + + +-------------------- Control -------------------- +function f.handle(self, state, data) + if state == FORM_VALID then + luci.http.redirect(luci.dispatcher.build_url("admin", "uci", "changes")) + return false + elseif state == FORM_INVALID then + self.errmessage = "Ungültige Eingabe: Bitte die Formularfelder auf Fehler prüfen." + end + return true +end + +local function _strip_internals(tbl) + tbl = tbl or {} + for k, v in pairs(tbl) do + if k:sub(1, 1) == "." then + tbl[k] = nil + end + end + return tbl +end + +-- Configure Freifunk checked +function main.write(self, section, value) + if value == "0" then + return + end + + local device = dev:formvalue(section) + local community, external + + -- Collect IP-Address + local inet = net:formvalue(section) + local isubnet = subnet:formvalue(section) + local inode = node:formvalue(section) + + -- Invalidate fields + if not inet then + net.tag_missing[section] = true + else + community = inet + external = uci:get("freifunk", community, "external") or "" + inet = uci:get("freifunk", community, "prefix") or inet + end + if not isubnet then + subnet.tag_missing[section] = true + end + if not inode then + node.tag_missing[section] = true + end + + if not inet or not isubnet or not inode then + return + end + + local ip = "%s.%s.%s" % {inet, isubnet, inode} + + + -- Cleanup + tools.wifi_delete_ifaces(device) + tools.network_remove_interface(device) + tools.firewall_zone_remove_interface("freifunk", device) + + -- Tune community settings + if community and uci:get("freifunk", community) then + uci:tset("freifunk", "community", uci:get_all("freifunk", community)) + end + + -- Tune wifi device + local devconfig = uci:get_all("freifunk", "wifi_device") + util.update(devconfig, uci:get_all(external, "wifi_device") or {}) + uci:tset("wireless", device, devconfig) + + -- Create wifi iface + local ifconfig = uci:get_all("freifunk", "wifi_iface") + util.update(ifconfig, uci:get_all(external, "wifi_iface") or {}) + ifconfig.device = device + ifconfig.network = device + ifconfig.ssid = uci:get("freifunk", community, "ssid") + uci:section("wireless", "wifi-iface", nil, ifconfig) + + -- Save wifi + uci:save("wireless") + + -- Create firewall zone and add default rules (first time) + local newzone = tools.firewall_create_zone("freifunk", "REJECT", "ACCEPT", "REJECT", true) + if newzone then + uci:foreach("freifunk", "fw_forwarding", function(section) + uci:section("firewall", "forwarding", nil, section) + end) + uci:foreach(external, "fw_forwarding", function(section) + uci:section("firewall", "forwarding", nil, section) + end) + + uci:foreach("freifunk", "fw_rule", function(section) + uci:section("firewall", "rule", nil, section) + end) + uci:foreach(external, "fw_rule", function(section) + uci:section("firewall", "rule", nil, section) + end) + end + + -- Enforce firewall include + local has_include = false + uci:foreach("firewall", "include", + function(section) + if section.path == "/etc/firewall.freifunk" then + has_include = true + end + end) + + if not has_include then + uci:section("firewall", "include", nil, + { path = "/etc/firewall.freifunk" }) + end + + -- Allow state: invalid packets + uci:foreach("firewall", "defaults", + function(section) + uci:set("firewall", section[".name"], "drop_invalid", "0") + end) + + -- Prepare advanced config + local has_advanced = false + uci:foreach("firewall", "advanced", + function(section) has_advanced = true end) + + if not has_advanced then + uci:section("firewall", "advanced", nil, + { tcp_ecn = "0" }) + end + + uci:save("firewall") + + + -- Create network interface + local netconfig = uci:get_all("freifunk", "interface") + util.update(netconfig, uci:get_all(external, "interface") or {}) + netconfig.proto = "static" + netconfig.ipaddr = ip + uci:section("network", "interface", device, netconfig) + + uci:save("network") + + tools.firewall_zone_add_interface("freifunk", device) + + + -- Set hostname + local new_hostname = ip:gsub("%.", "-") + local old_hostname = sys.hostname() + + if old_hostname == "OpenWrt" or old_hostname:match("^%d+-%d+-%d+-%d+$") then + uci:foreach("system", "system", + function(s) + uci:set("system", s['.name'], "hostname", new_hostname) + end) + + luci.fs.writefile( "/proc/sys/kernel/hostname", new_hostname.."\n" ) + uci:save("system") + end +end + + +function olsr.write(self, section, value) + if value == "0" then + return + end + + + local device = dev:formvalue(section) + + local community = net:formvalue(section) + local external = community and uci:get("freifunk", community, "external") or "" + + -- Configure nameservice + local hostname + uci:foreach("system", "system", function(s) hostname = s.hostname end) + + if hostname then + uci:foreach("olsrd", "LoadPlugin", + function(s) + if s.library == "olsrd_nameservice.so.0.3" then + uci:set("olsrd", s['.name'], "name", hostname) + end + end) + end + + -- Delete old interface + uci:delete_all("olsrd", "Interface", {interface=device}) + + -- Write new interface + local olsrbase = uci:get_all("freifunk", "olsr_interface") + util.update(olsrbase, uci:get_all(external, "olsr_interface") or {}) + olsrbase.interface = device + olsrbase.ignore = "0" + uci:section("olsrd", "Interface", nil, olsrbase) + uci:save("olsrd") + + -- Import hosts + uci:foreach("dhcp", "dnsmasq", function(s) + uci:set("dhcp", s[".name"], "addnhosts", "/var/etc/hosts.olsr") + end) + uci:save("dhcp") +end + + +function share.write(self, section, value) + uci:delete_all("firewall", "forwarding", {src="freifunk", dest="wan"}) + uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw_plain.so.0.4"}) + + if value == "1" then + uci:section("firewall", "forwarding", nil, {src="freifunk", dest="wan"}) + uci:section("olsrd", "LoadPlugin", nil, {library="olsrd_dyn_gw_plain.so.0.4"}) + end + uci:save("firewall") + uci:save("olsrd") +end + + +function client.write(self, section, value) + if value == "0" then + return + end + + local device = dev:formvalue(section) + + -- Collect IP-Address + local inet = net:formvalue(section) + local isubnet = subnet:formvalue(section) + local inode = node:formvalue(section) + + if not inet or not isubnet or not inode then + return + end + local community = inet + local external = community and uci:get("freifunk", community, "external") or "" + inet = uci:get("freifunk", community, "prefix") or inet + + local dhcpbeg = 48 + tonumber(inode) * 4 + local dclient = "%s.%s.%s" % {inet:gsub("^[0-9]+", "10"), isubnet, dhcpbeg} + local limit = dhcpbeg < 252 and 3 or 2 + + -- Delete old alias + uci:delete("network", device .. "dhcp") + + -- Create alias + local aliasbase = uci:get_all("freifunk", "alias") + util.update(aliasbase, uci:get_all(external, "alias") or {}) + aliasbase.interface = device + aliasbase.ipaddr = dclient + aliasbase.proto = "static" + uci:section("network", "alias", device .. "dhcp", aliasbase) + uci:save("network") + + + -- Create dhcp + local dhcpbase = uci:get_all("freifunk", "dhcp") + util.update(dhcpbase, uci:get_all(external, "dhcp") or {}) + dhcpbase.interface = device .. "dhcp" + dhcpbase.start = dhcpbeg + dhcpbase.limit = limit + + uci:section("dhcp", "dhcp", device .. "dhcp", dhcpbase) + uci:save("dhcp") + + uci:delete_all("firewall", "rule", { + src="freifunk", + proto="udp", + src_port="68", + dest_port="67" + }) + uci:section("firewall", "rule", nil, { + src="freifunk", + proto="udp", + src_port="68", + dest_port="67", + target="ACCEPT" + }) + uci:delete_all("firewall", "rule", { + src="freifunk", + proto="tcp", + dest_port="8082", + }) + uci:section("firewall", "rule", nil, { + src="freifunk", + proto="tcp", + dest_port="8082", + target="ACCEPT" + }) + + + + -- Delete old splash + uci:delete_all("luci_splash", "iface", {net=device, zone="freifunk"}) + + -- Register splash + uci:section("luci_splash", "iface", nil, {net=device, zone="freifunk"}) + uci:save("luci_splash") +end + +return f diff --git a/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/tools/ffwizard.lua b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/tools/ffwizard.lua new file mode 100644 index 0000000..3f5e17a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ffwizard-leipzig/luasrc/tools/ffwizard.lua @@ -0,0 +1,149 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ffwizard.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +local uci = require "luci.model.uci" +local util = require "luci.util" +local table = require "table" + +local type = type + +module "luci.tools.ffwizard" + +-- Deletes all references of a wifi device +function wifi_delete_ifaces(device) + local cursor = uci.cursor() + cursor:delete_all("wireless", "wifi-iface", {device=device}) + cursor:save("wireless") +end + +-- Deletes a network interface and all occurences of it in firewall zones and dhcp +function network_remove_interface(iface) + local cursor = uci.cursor() + + if not cursor:delete("network", iface) then + return false + end + + local aliases = {iface} + cursor:foreach("network", "alias", + function(section) + if section.interface == iface then + table.insert(aliases, section[".name"]) + end + end) + + -- Delete Aliases and Routes + cursor:delete_all("network", "route", {interface=iface}) + cursor:delete_all("network", "alias", {interface=iface}) + + -- Delete DHCP sections + cursor:delete_all("dhcp", "dhcp", + function(section) + return util.contains(aliases, section.interface) + end) + + -- Remove OLSR sections + cursor:delete_all("olsrd", "Interface", {Interface=iface}) + + -- Remove Splash sections + cursor:delete_all("luci-splash", "iface", {network=iface}) + + cursor:save("network") + cursor:save("olsr") + cursor:save("dhcp") + cursor:save("luci-splash") +end + +-- Creates a firewall zone +function firewall_create_zone(zone, input, output, forward, masq) + local cursor = uci.cursor() + if not firewall_find_zone(zone) then + local stat = cursor:section("firewall", "zone", nil, { + input = input, + output = output, + forward = forward, + masq = masq and "1", + name = zone + }) + cursor:save("firewall") + return stat + end +end + +-- Adds interface to zone, creates zone on-demand +function firewall_zone_add_interface(name, interface) + local cursor = uci.cursor() + local zone = firewall_find_zone(name) + local net = cursor:get("firewall", zone, "network") + local old = net or (cursor:get("network", name) and name) + cursor:set("firewall", zone, "network", (old and old .. " " or "") .. interface) + cursor:save("firewall") +end + +-- Removes interface from zone +function firewall_zone_remove_interface(name, interface) + local cursor = uci.cursor() + local zone = firewall_find_zone(name) + if zone then + local net = cursor:get("firewall", zone, "network") + local new = remove_list_entry(net, interface) + if new then + if #new > 0 then + cursor:set("firewall", zone, "network", new) + else + cursor:delete("firewall", zone, "network") + end + cursor:save("firewall") + end + end +end + + +-- Finds the firewall zone with given name +function firewall_find_zone(name) + local find + + uci.cursor():foreach("firewall", "zone", + function (section) + if section.name == name then + find = section[".name"] + end + end) + + return find +end + + + +-- Helpers -- + +-- Removes a listentry, handles real and pseduo lists transparently +function remove_list_entry(value, entry) + if type(value) == "nil" then + return nil + end + + local result = type(value) == "table" and value or util.split(value, " ") + local key = util.contains(result, entry) + + while key do + table.remove(result, key) + key = util.contains(result, entry) + end + + result = type(value) == "table" and result or table.concat(result, " ") + return result ~= value and result +end diff --git a/openwrt/packages/luci/applications/luci-fw/Makefile b/openwrt/packages/luci/applications/luci-fw/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/controller/luci_fw/luci_fw.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/controller/luci_fw/luci_fw.lua new file mode 100644 index 0000000..2be03d6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/controller/luci_fw/luci_fw.lua @@ -0,0 +1,13 @@ +module("luci.controller.luci_fw.luci_fw", package.seeall) + +function index() + require("luci.i18n").loadc("luci-fw") + local i18n = luci.i18n.translate + + entry({"admin", "network", "firewall"}, alias("admin", "network", "firewall", "zones"), i18n("fw_fw"), 60).i18n = "luci-fw" + entry({"admin", "network", "firewall", "zones"}, cbi("luci_fw/zones"), i18n("fw_zones"), 10) + entry({"admin", "network", "firewall", "redirect"}, arcombine(cbi("luci_fw/redirect"), cbi("luci_fw/rrule")), i18n("fw_redirect"), 30).leaf = true + entry({"admin", "network", "firewall", "rule"}, arcombine(cbi("luci_fw/traffic"), cbi("luci_fw/trule")), i18n("fw_traffic"), 20).leaf = true + + entry({"mini", "network", "portfw"}, cbi("luci_fw/miniportfw", {autoapply=true}), i18n("fw_portfw", "Portweiterleitung"), 70).i18n = "luci-fw" +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.lua new file mode 100644 index 0000000..9659839 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Portweiterleitung' +fw_redirect = 'Umleitungen' +fw_redirect_desc = 'Umleitungen erlauben es das Ziel von weitergeleiteten Paketen zu verändern.' +fw_forwarding = 'Zone-zu-Zone Verkehr' +fw_fw = 'Firewall' +fw_zone = 'Zone' +fw_zones = 'Zonen' +fw_custfwd = 'Erweiterte Weiterleitung' +firewall_rule = 'Erweiterte Regeln' +firewall_rule_desc = 'Mit erweiterten Regeln kann die Firewall an die eigenen Bedürfnisse angepasst werden. Es werden nur neue Verbindungen betrachtet. Pakete, die zu bereits bestehenden Verbindungen gehören werden automatisch akzeptiert.' +fw_fw1 = 'Die Firewall erstellt Netzwerkzonen über bestimmte Netzwerkschnittstellen um den Netzverkehr zu trennen.' +fw_src = 'Quelle' +fw_dest = 'Ziel' +fw_traffic = 'Verkehrskontrolle' +fw_mtufix = 'MSS Clamping' +fw_dropinvalid = 'Ungültige Pakete verwerfen' +firewall_rule_src = 'Eingangszone' +firewall_rule_dest = 'Ausgangszone' +firewall_rule_srcip = 'Quelladresse' +firewall_rule_destip = 'Zieladresse' +firewall_rule_srcmac = 'Quell-MAC-Adresse' +firewall_rule_srcport = 'Quellport' +firewall_rule_destport = 'Zielport' +firewall_rule_target = 'Aktion' +fw_accept = 'annehmen' +fw_reject = 'zurückweisen' +fw_drop = 'verwerfen' +fw_portfw1 = 'Portweiterleitungen ermöglichen es interne Netzwerkdienste aus einem externen Netzwerk heraus erreichbar zu machen.' +firewall_redirect_src_desc = 'Externe Zone' +firewall_redirect_srcdport = 'Externer Port' +firewall_redirect_srcdport_desc = 'Port od. Erster-Letzter Port' +firewall_redirect_destip = 'Interne Adresse' +firewall_redirect_destip_desc = 'IP-Adresse' +firewall_redirect_destport = 'Interner Port (optional)' +firewall_redirect_destport_desc = 'Port od. Erster-Letzter Port' +firewall_redirect_srcip = 'Quelladresse' +firewall_redirect_srcmac = 'Quell-MAC-Adresse' +fw_forwarding1 = 'An dieser Stelle kann festgelegt zwischen welchen Zonen Netzverkehr hin und her fließen kann. Es werden nur neue Verbindungen betrachtet. Pakete, die zu bereits bestehenden Verbindungen gehören werden automatisch akzeptiert. Bei gelegentlich auftretenden Verbindungsproblemen kann MSS Clamping helfen, ansonsten sollte dies aus Performancegründen deaktiviert bleiben.' +firewall_forwarding_src = 'Eingang' +firewall_forwarding_dest = 'Ausgang' +firewall_defaults = 'Grundeinstellungen' +firewall_defaults_desc = 'Grundeinstellungen die verwendet werden, wenn keine andere Regel angewandt werden kann.' +firewall_defaults_synflood = 'Schutz vor SYN-flood-Attacken' +firewall_defaults_input = 'Eingehender Verkehr' +firewall_defaults_output = 'Ausgehender Verkehr' +firewall_defaults_forward = 'Weitergeleiteter Verkehr' +firewall_zone_desc = 'Zonen teilen das Netzwerk in mehrere Bereiche ein um Netzverkehr sicher zu trennen. Ein oder mehrere Netzwerke gehören zu einer Zone. Das MASQ-Flag legt fest, dass aller ausgehende Netzverkehr einer Zone NAT-maskiert wird.' +firewall_zone_input = 'Eingehender Verkehr' +firewall_zone_input_desc = 'Standardaktion' +firewall_zone_output = 'Ausgehender Verkehr' +firewall_zone_output_desc = 'Standardaktion' +firewall_zone_forward = 'Weitergeleiteter Verkehr' +firewall_zone_forward_desc = 'Standardaktion' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Netzwerke' +firewall_zone_network_desc = 'verbundene Netzwerke' diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.xml b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.xml new file mode 100644 index 0000000..8578753 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.de.xml @@ -0,0 +1,67 @@ + + + + +Portweiterleitung +Umleitungen +Umleitungen erlauben es das Ziel von weitergeleiteten Paketen zu verändern. +Zone-zu-Zone Verkehr +Firewall +Zone +Zonen +Erweiterte Weiterleitung +Erweiterte Regeln +Mit erweiterten Regeln kann die Firewall an die eigenen Bedürfnisse angepasst werden. Es werden nur neue Verbindungen betrachtet. Pakete, die zu bereits bestehenden Verbindungen gehören werden automatisch akzeptiert. +Die Firewall erstellt Netzwerkzonen über bestimmte Netzwerkschnittstellen um den Netzverkehr zu trennen. +Quelle +Ziel +Verkehrskontrolle +MSS Clamping +Ungültige Pakete verwerfen +Eingangszone +Ausgangszone +Quelladresse +Zieladresse +Quell-MAC-Adresse +Quellport +Zielport +Aktion +annehmen +zurückweisen +verwerfen + +Portweiterleitungen ermöglichen es interne Netzwerkdienste aus einem externen Netzwerk heraus erreichbar zu machen. +Externe Zone +Externer Port +Port od. Erster-Letzter Port +Interne Adresse +IP-Adresse +Interner Port (optional) +Port od. Erster-Letzter Port +Quelladresse +Quell-MAC-Adresse + + +An dieser Stelle kann festgelegt zwischen welchen Zonen Netzverkehr hin und her fließen kann. Es werden nur neue Verbindungen betrachtet. Pakete, die zu bereits bestehenden Verbindungen gehören werden automatisch akzeptiert. Bei gelegentlich auftretenden Verbindungsproblemen kann MSS Clamping helfen, ansonsten sollte dies aus Performancegründen deaktiviert bleiben. +Eingang +Ausgang + +Grundeinstellungen +Grundeinstellungen die verwendet werden, wenn keine andere Regel angewandt werden kann. +Schutz vor SYN-flood-Attacken +Eingehender Verkehr +Ausgehender Verkehr +Weitergeleiteter Verkehr + +Zonen teilen das Netzwerk in mehrere Bereiche ein um Netzverkehr sicher zu trennen. Ein oder mehrere Netzwerke gehören zu einer Zone. Das MASQ-Flag legt fest, dass aller ausgehende Netzverkehr einer Zone NAT-maskiert wird. +Eingehender Verkehr +Standardaktion +Ausgehender Verkehr +Standardaktion +Weitergeleiteter Verkehr +Standardaktion +MASQ +Netzwerke +verbundene Netzwerke + + diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.lua new file mode 100644 index 0000000..14bfa3c --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Port forwarding' +fw_redirect = 'Traffic Redirection' +fw_redirect_desc = 'Traffic redirection allows you to change the destination address of forwarded packets.' +fw_forwarding = 'Zone-to-Zone traffic' +fw_fw = 'Firewall' +fw_zone = 'Zone' +fw_zones = 'Zones' +fw_custfwd = 'Custom forwarding' +fw_fw1 = 'The firewall creates zones over your network interfaces to control network traffic flow.' +firewall_rule = 'Advanced Rules' +firewall_rule_desc = 'Advanced rules let you customize the firewall to your needs. Only new connections will be matched. Packets belonging to already open connections are automatically allowed to pass the firewall.' +firewall_rule_src = 'Input Zone' +firewall_rule_dest = 'Output Zone' +firewall_rule_srcip = 'Source address' +firewall_rule_destip = 'Destination address' +firewall_rule_srcmac = 'Source MAC-Address' +firewall_rule_srcport = 'Source port' +firewall_rule_destport = 'Destination port' +firewall_rule_target = 'Action' +fw_accept = 'accept' +fw_reject = 'reject' +fw_drop = 'drop' +fw_src = 'Source' +fw_dest = 'Destination' +fw_traffic = 'Traffic Control' +fw_mtufix = 'MSS Clamping' +fw_dropinvalid = 'Drop invalid packets' +fw_portfw1 = 'Port forwarding allows to provide network services in the internal network to an external network.' +firewall_redirect_src_desc = 'External Zone' +firewall_redirect_srcdport = 'External port' +firewall_redirect_srcdport_desc = 'port or range as first-last' +firewall_redirect_srcip = 'Source address' +firewall_redirect_srcmac = 'Source MAC' +firewall_redirect_destip = 'Internal address' +firewall_redirect_destip_desc = 'IP-Address' +firewall_redirect_destport = 'Internal port (optional)' +firewall_redirect_destport_desc = 'port or range as first-last' +fw_forwarding1 = 'Here you can specify which network traffic is allowed to flow between network zones. Only new connections will be matched. Packets belonging to already open connections are automatically allowed to pass the firewall. If you experience occasional connection problems try enabling MSS Clamping otherwise disable it for performance reasons.' +firewall_forwarding_src = 'Input' +firewall_forwarding_dest = 'Output' +firewall_defaults = 'Defaults' +firewall_defaults_desc = 'These are the default settings that are used if no other rules match.' +firewall_defaults_synflood = 'SYN-flood protection' +firewall_defaults_input = 'Incoming Traffic' +firewall_defaults_output = 'Outgoing Traffic' +firewall_defaults_forward = 'Forwarded Traffic' +firewall_zone_desc = 'Zones part the network interfaces into certain isolated areas to separate network traffic. One or more networks can belong to a zone. The MASQ-flag enables NAT masquerading for all outgoing traffic on this zone.' +firewall_zone_input = 'Incoming Traffic' +firewall_zone_input_desc = 'Default Policy' +firewall_zone_output = 'Outgoing Traffic' +firewall_zone_output_desc = 'Default Policy' +firewall_zone_forward = 'Forwarded Traffic' +firewall_zone_forward_desc = 'Default Policy' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Networks' +firewall_zone_network_desc = 'contained networks' diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.xml b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.xml new file mode 100644 index 0000000..72856e0 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.en.xml @@ -0,0 +1,66 @@ + + + + +Port forwarding +Traffic Redirection +Traffic redirection allows you to change the destination address of forwarded packets. +Zone-to-Zone traffic +Firewall +Zone +Zones +Custom forwarding +The firewall creates zones over your network interfaces to control network traffic flow. +Advanced Rules +Advanced rules let you customize the firewall to your needs. Only new connections will be matched. Packets belonging to already open connections are automatically allowed to pass the firewall. +Input Zone +Output Zone +Source address +Destination address +Source MAC-Address +Source port +Destination port +Action +accept +reject +drop +Source +Destination +Traffic Control +MSS Clamping +Drop invalid packets + +Port forwarding allows to provide network services in the internal network to an external network. +External Zone +External port +port or range as first-last +Source address +Source MAC +Internal address +IP-Address +Internal port (optional) +port or range as first-last + +Here you can specify which network traffic is allowed to flow between network zones. Only new connections will be matched. Packets belonging to already open connections are automatically allowed to pass the firewall. If you experience occasional connection problems try enabling MSS Clamping otherwise disable it for performance reasons. +Input +Output + +Defaults +These are the default settings that are used if no other rules match. +SYN-flood protection +Incoming Traffic +Outgoing Traffic +Forwarded Traffic + +Zones part the network interfaces into certain isolated areas to separate network traffic. One or more networks can belong to a zone. The MASQ-flag enables NAT masquerading for all outgoing traffic on this zone. +Incoming Traffic +Default Policy +Outgoing Traffic +Default Policy +Forwarded Traffic +Default Policy +MASQ +Networks +contained networks + + diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.lua new file mode 100644 index 0000000..a3b11e8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Redirection de port' +fw_redirect = 'Redirection de trafic' +fw_redirect_desc = 'La redirection de trafic vous permet de changer l'adresse de destination des paquets transférés.' +fw_forwarding = 'Trafic inter-zone' +fw_fw = 'Pare-Feu' +fw_zone = 'Zone' +fw_zones = 'Zones' +fw_custfwd = 'Transfert particulière' +fw_fw1 = 'Le pare-feu crée des zone à partir des interfaces réseaux pour controller le trafic réseau.' +firewall_rule = 'Règles Avancées' +firewall_rule_desc = 'Les règles avancées vous laisse personnaliser le pare-feu selon vos besoins. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu.' +firewall_rule_src = 'Zone d'Entrée (Input)' +firewall_rule_dest = 'Zone de Sortie (Output)' +firewall_rule_srcip = 'Adresse source' +firewall_rule_destip = 'Adresse de destination' +firewall_rule_srcmac = 'Adresse MAC source' +firewall_rule_srcport = 'Port source' +firewall_rule_destport = 'Port de destination' +firewall_rule_target = 'Action' +fw_accept = 'accepter' +fw_reject = 'rejeter' +fw_drop = 'ignorer (drop)' +fw_src = 'Source' +fw_dest = 'Destination' +fw_traffic = 'Contrôle de Trafic' +fw_mtufix = 'MSS-Correction' +fw_dropinvalid = 'Drop incorrect packets' +fw_portfw1 = 'La redirection de port vous permet d'exposer des services réseaux de votre réseau local au réseau externe.' +firewall_redirect_src_desc = 'Zone externe' +firewall_redirect_srcdport = 'Port externe' +firewall_redirect_srcdport_desc = 'port ou plage de ports (premier-dernier)' +firewall_redirect_srcip = 'Adresse source' +firewall_redirect_srcmac = 'MAC source' +firewall_redirect_destip = 'Adresse interne' +firewall_redirect_destip_desc = 'Adresse IP' +firewall_redirect_destport = 'Port interne' +firewall_redirect_destport_desc = 'port ou plage de ports (premier-dernier)' +fw_forwarding1 = 'Ici, vous pouvez spécifier quel trafic réseau est autorisé à transiter entre les zones réseaux. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu.' +firewall_forwarding_src = 'Entrée (Input)' +firewall_forwarding_dest = 'Sortie (Output)' +firewall_defaults = 'Défauts' +firewall_defaults_desc = 'Ceci sont les paramètres par défaut qui sont utilisés si aucune autre règle ne s'applique.' +firewall_defaults_synflood = 'Protection anti SYN-flood' +firewall_defaults_input = 'Trafic Entrant' +firewall_defaults_output = 'Trafic Sortant' +firewall_defaults_forward = 'Trafic Transféré' +firewall_zone_desc = 'Les zones partagent les interfaces réseaux en régions isolées pour séparer les trafic réseaux. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu.' +firewall_zone_input = 'Trafic Entrant' +firewall_zone_input_desc = 'Politique par Défaut' +firewall_zone_output = 'Trafic Sortant' +firewall_zone_output_desc = 'Politique par Défaut' +firewall_zone_forward = 'Trafic Transféré' +firewall_zone_forward_desc = 'Politique par Défaut' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Réseaux' +firewall_zone_network_desc = 'réseaux compris' diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.xml b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.xml new file mode 100644 index 0000000..d007ccb --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.fr.xml @@ -0,0 +1,66 @@ + + + + +Redirection de port +Redirection de trafic +La redirection de trafic vous permet de changer l'adresse de destination des paquets transférés. +Trafic inter-zone +Pare-Feu +Zone +Zones +Transfert particulière +Le pare-feu crée des zone à partir des interfaces réseaux pour controller le trafic réseau. +Règles Avancées +Les règles avancées vous laisse personnaliser le pare-feu selon vos besoins. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu. +Zone d'Entrée (Input) +Zone de Sortie (Output) +Adresse source +Adresse de destination +Adresse MAC source +Port source +Port de destination +Action +accepter +rejeter +ignorer (drop) +Source +Destination +Contrôle de Trafic +MSS-Correction +Drop incorrect packets + +La redirection de port vous permet d'exposer des services réseaux de votre réseau local au réseau externe. +Zone externe +Port externe +port ou plage de ports (premier-dernier) +Adresse source +MAC source +Adresse interne +Adresse IP +Port interne +port ou plage de ports (premier-dernier) + +Ici, vous pouvez spécifier quel trafic réseau est autorisé à transiter entre les zones réseaux. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu. +Entrée (Input) +Sortie (Output) + +Défauts +Ceci sont les paramètres par défaut qui sont utilisés si aucune autre règle ne s'applique. +Protection anti SYN-flood +Trafic Entrant +Trafic Sortant +Trafic Transféré + +Les zones partagent les interfaces réseaux en régions isolées pour séparer les trafic réseaux. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu. +Trafic Entrant +Politique par Défaut +Trafic Sortant +Politique par Défaut +Trafic Transféré +Politique par Défaut +MASQ +Réseaux +réseaux compris + + diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.lua new file mode 100644 index 0000000..3b38dc5 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Redirecionamento de portas' +fw_redirect = 'Redirecionamento de Tráfego' +fw_redirect_desc = 'Redirecionamento do tráfego permite que você altere o endereço de destino dos pacotes enviados.' +fw_forwarding = 'Tráfego de Zona-para-Zona' +fw_fw = 'Firewall' +fw_zone = 'Zona' +fw_zones = 'Zonas' +fw_custfwd = 'Redirecionamento customizado' +fw_fw1 = 'O firewall cria zonas sobre suas interfaces de rede para controlar o fluxo do tráfego.' +firewall_rule = 'Regras Avançadas' +firewall_rule_desc = 'As regras avançadas permitem que você personalize o firewall de acordo com suas necessidades. Somente novas conexões serão processadas. Pacotes pertencentes às conexões já abertas estão automaticamente permitidos para passar pelo firewall.' +firewall_rule_src = 'Zona de Entrada' +firewall_rule_dest = 'Zona de Saída' +firewall_rule_srcip = 'Endereço de origem' +firewall_rule_destip = 'Endereço de destino' +firewall_rule_srcmac = 'Endereço-MAC de origem' +firewall_rule_srcport = 'Porta de origem' +firewall_rule_destport = 'Porta de destino' +firewall_rule_target = 'Ação' +fw_accept = 'aceitar' +fw_reject = 'rejeitar' +fw_drop = 'dropar' +fw_src = 'Origem' +fw_dest = 'Destino' +fw_traffic = 'Controle de Tráfego' +fw_mtufix = 'MSS-Correction' +fw_dropinvalid = 'Drop invalid packets' +fw_portfw1 = 'O redirecionamento de portas permite prover serviços de rede na rede interna para uma rede externa.' +firewall_redirect_src_desc = 'Zona Externa' +firewall_redirect_srcdport = 'Porta Externa' +firewall_redirect_srcdport_desc = 'porta ou intervalo primeira-última' +firewall_redirect_srcip = 'Endereço de origem' +firewall_redirect_srcmac = 'MAC de origem' +firewall_redirect_destip = 'Endereço interno' +firewall_redirect_destip_desc = 'Endereço-IP' +firewall_redirect_destport = 'Porta interna (opcional)' +firewall_redirect_destport_desc = 'porta ou intervalo primeira-última' +fw_forwarding1 = 'Aqui você pode especificar qual tráfego de rede será permitido para o fluxo entre zonas das redes. Somente novas conexões serão processadas. Pacotes pertencentes à conexões já abertas estão automaticamente permitidos para passar pelo firewall.' +firewall_forwarding_src = 'Entrada' +firewall_forwarding_dest = 'Saída' +firewall_defaults = 'Padrões' +firewall_defaults_desc = 'Estas são as configurações padrões, que serão usadas se não houver outras regras.' +firewall_defaults_synflood = 'Proteção SYN-flood' +firewall_defaults_input = 'Tráfego de Entrada' +firewall_defaults_output = 'Tráfego de Saída' +firewall_defaults_forward = 'Tráfego Redirecionado' +firewall_zone_desc = 'Zonas são interfaces de redes usadas para separar o tráfego da rede. Uma ou mais redes podem pertencer a uma zona. A flag-MASQ ativa o mascaramento NAT para todo o tráfego de saída desta zona.' +firewall_zone_input = 'Tráfego de Entrada' +firewall_zone_input_desc = 'Política Padrão' +firewall_zone_output = 'Tráfego de Saída' +firewall_zone_output_desc = 'Política Padrão' +firewall_zone_forward = 'Tráfego Redirecionado' +firewall_zone_forward_desc = 'Política Padrão' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Redes' +firewall_zone_network_desc = 'redes contidas' diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.xml b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.xml new file mode 100644 index 0000000..1ca6877 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/i18n/luci-fw.pt-br.xml @@ -0,0 +1,66 @@ + + + + +Redirecionamento de portas +Redirecionamento de Tráfego +Redirecionamento do tráfego permite que você altere o endereço de destino dos pacotes enviados. +Tráfego de Zona-para-Zona +Firewall +Zona +Zonas +Redirecionamento customizado +O firewall cria zonas sobre suas interfaces de rede para controlar o fluxo do tráfego. +Regras Avançadas +As regras avançadas permitem que você personalize o firewall de acordo com suas necessidades. Somente novas conexões serão processadas. Pacotes pertencentes às conexões já abertas estão automaticamente permitidos para passar pelo firewall. +Zona de Entrada +Zona de Saída +Endereço de origem +Endereço de destino +Endereço-MAC de origem +Porta de origem +Porta de destino +Ação +aceitar +rejeitar +dropar +Origem +Destino +Controle de Tráfego +MSS-Correction +Drop invalid packets + +O redirecionamento de portas permite prover serviços de rede na rede interna para uma rede externa. +Zona Externa +Porta Externa +porta ou intervalo primeira-última +Endereço de origem +MAC de origem +Endereço interno +Endereço-IP +Porta interna (opcional) +porta ou intervalo primeira-última + +Aqui você pode especificar qual tráfego de rede será permitido para o fluxo entre zonas das redes. Somente novas conexões serão processadas. Pacotes pertencentes à conexões já abertas estão automaticamente permitidos para passar pelo firewall. +Entrada +Saída + +Padrões +Estas são as configurações padrões, que serão usadas se não houver outras regras. +Proteção SYN-flood +Tráfego de Entrada +Tráfego de Saída +Tráfego Redirecionado + +Zonas são interfaces de redes usadas para separar o tráfego da rede. Uma ou mais redes podem pertencer a uma zona. A flag-MASQ ativa o mascaramento NAT para todo o tráfego de saída desta zona. +Tráfego de Entrada +Política Padrão +Tráfego de Saída +Política Padrão +Tráfego Redirecionado +Política Padrão +MASQ +Redes +redes contidas + + diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/miniportfw.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/miniportfw.lua new file mode 100644 index 0000000..8d27375 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/miniportfw.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: miniportfw.lua 3070 2008-09-02 11:27:00Z Cyrus $ +]]-- +require("luci.sys") +m = Map("firewall", translate("fw_portfw"), translate("fw_portfw1")) + + +s = m:section(TypedSection, "redirect", "") +s:depends("src", "wan") +s.defaults.src = "wan" + +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true + +name = s:option(Value, "_name", translate("name"), translate("cbi_optional")) +name.size = 10 + +proto = s:option(ListValue, "proto", translate("protocol")) +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("tcpudp", "TCP+UDP") + +dport = s:option(Value, "src_dport") +dport.size = 5 + +to = s:option(Value, "dest_ip") +for i, dataset in ipairs(luci.sys.net.arptable()) do + to:value(dataset["IP address"]) +end + +toport = s:option(Value, "dest_port") +toport.size = 5 + +return m diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/redirect.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/redirect.lua new file mode 100644 index 0000000..12a738e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/redirect.lua @@ -0,0 +1,50 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: redirect.lua 3500 2008-10-03 16:23:43Z Cyrus $ +]]-- +require("luci.sys") +m = Map("firewall", translate("fw_redirect"), translate("fw_redirect_desc")) + + +s = m:section(TypedSection, "redirect", "") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true +s.extedit = luci.dispatcher.build_url("admin", "network", "firewall", "redirect", "%s") + +name = s:option(Value, "_name", translate("name"), translate("cbi_optional")) +name.size = 10 + +iface = s:option(ListValue, "src", translate("fw_zone")) +iface.default = "wan" +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + end) + +proto = s:option(ListValue, "proto", translate("protocol")) +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("tcpudp", "TCP+UDP") + +dport = s:option(Value, "src_dport") +dport.size = 5 + +to = s:option(Value, "dest_ip") +for i, dataset in ipairs(luci.sys.net.arptable()) do + to:value(dataset["IP address"]) +end + +toport = s:option(Value, "dest_port") +toport.size = 5 + +return m diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/rrule.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/rrule.lua new file mode 100644 index 0000000..d9222ec --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/rrule.lua @@ -0,0 +1,69 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: rrule.lua 4200 2009-01-30 18:57:14Z Cyrus $ +]]-- +require("luci.sys") +arg[1] = arg[1] or "" + +m = Map("firewall", translate("fw_redirect"), translate("fw_redirect_desc")) + + +s = m:section(NamedSection, arg[1], "redirect", "") +s.anonymous = true +s.addremove = false + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "redirect") + +name = s:option(Value, "_name", translate("name")) +name.rmempty = true +name.size = 10 + +iface = s:option(ListValue, "src", translate("fw_zone")) +iface.default = "wan" +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + end) + +s:option(Value, "src_ip", translate("firewall_redirect_srcip")).optional = true +s:option(Value, "src_mac", translate("firewall_redirect_srcmac")).optional = true + +sport = s:option(Value, "src_port", translate("firewall_rule_srcport")) +sport:depends("proto", "tcp") +sport:depends("proto", "udp") +sport:depends("proto", "tcpudp") + +proto = s:option(ListValue, "proto", translate("protocol")) +proto.optional = true +proto:value("") +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("tcpudp", "TCP+UDP") + +dport = s:option(Value, "src_dport", translate("firewall_redirect_srcdport")) +dport.size = 5 +dport:depends("proto", "tcp") +dport:depends("proto", "udp") +dport:depends("proto", "tcpudp") + +to = s:option(Value, "dest_ip", translate("firewall_redirect_destip")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + to:value(dataset["IP address"]) +end + +toport = s:option(Value, "dest_port", translate("firewall_redirect_destport")) +toport.optional = true +toport.size = 5 + +return m diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/traffic.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/traffic.lua new file mode 100644 index 0000000..994e3de --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/traffic.lua @@ -0,0 +1,82 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: traffic.lua 4181 2009-01-29 15:04:16Z Cyrus $ +]]-- + +m = Map("firewall", translate("fw_traffic")) +s = m:section(TypedSection, "forwarding", translate("fw_forwarding"), translate("fw_forwarding1")) +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true + +iface = s:option(ListValue, "src", translate("fw_src")) +oface = s:option(ListValue, "dest", translate("fw_dest")) +s:option(Flag, "mtu_fix", translate("fw_mtufix")) + +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + oface:value(section.name) + end) + + + +s = m:section(TypedSection, "rule") +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" +s.extedit = luci.dispatcher.build_url("admin", "network", "firewall", "rule", "%s") +s.defaults.target = "ACCEPT" + +local created = nil + +function s.create(self, section) + created = TypedSection.create(self, section) +end + +function s.parse(self, ...) + TypedSection.parse(self, ...) + if created then + m.uci:save("firewall") + luci.http.redirect(luci.dispatcher.build_url( + "admin", "network", "firewall", "rule", created + )) + end +end + +s:option(DummyValue, "_name", translate("name")) +s:option(DummyValue, "proto", translate("protocol")) + +src = s:option(DummyValue, "src", translate("fw_src")) +function src.cfgvalue(self, s) + return "%s:%s:%s" % { + self.map:get(s, "src") or "*", + self.map:get(s, "src_ip") or "0.0.0.0/0", + self.map:get(s, "src_port") or "*" + } +end + +dest = s:option(DummyValue, "dest", translate("fw_dest")) +function dest.cfgvalue(self, s) + return "%s:%s:%s" % { + self.map:get(s, "dest") or translate("device", "device"), + self.map:get(s, "dest_ip") or "0.0.0.0/0", + self.map:get(s, "dest_port") or "*" + } +end + + +s:option(DummyValue, "target") + + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/trule.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/trule.lua new file mode 100644 index 0000000..cda4e52 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/trule.lua @@ -0,0 +1,72 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: trule.lua 4012 2009-01-09 10:05:59Z Cyrus $ +]]-- +arg[1] = arg[1] or "" +m = Map("firewall", translate("firewall_rule"), translate("firewall_rule_desc")) + +s = m:section(NamedSection, arg[1], "rule", "") +s.anonymous = true +s.addremove = false + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "rule") + + +name = s:option(Value, "_name", translate("name")..translate("cbi_optional")) +name.rmempty = true + +iface = s:option(ListValue, "src", translate("fw_src")) +iface.rmempty = true + +oface = s:option(ListValue, "dest", translate("fw_dest")) +oface:value("", translate("device", "device")) +oface.rmempty = true + +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + oface:value(section.name) + end) + +proto = s:option(Value, "proto", translate("protocol")) +proto.optional = true +proto:value("") +proto:value("tcpudp", "TCP+UDP") +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("icmp", "ICMP") + +s:option(Value, "src_ip", translate("firewall_rule_srcip")).optional = true +s:option(Value, "dest_ip", translate("firewall_rule_destip")).optional = true +s:option(Value, "src_mac", translate("firewall_rule_srcmac")).optional = true + +sport = s:option(Value, "src_port", translate("firewall_rule_srcport")) +sport:depends("proto", "tcp") +sport:depends("proto", "udp") +sport:depends("proto", "tcpudp") + +dport = s:option(Value, "dest_port", translate("firewall_rule_destport")) +dport:depends("proto", "tcp") +dport:depends("proto", "udp") +dport:depends("proto", "tcpudp") + +jump = s:option(ListValue, "target", translate("firewall_rule_target")) +jump.rmempty = true +jump.default = "ACCEPT" +jump:value("DROP", translate("fw_drop")) +jump:value("ACCEPT", translate("fw_accept")) +jump:value("REJECT", translate("fw_reject")) + + +return m diff --git a/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/zones.lua b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/zones.lua new file mode 100644 index 0000000..a07149f --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/luasrc/model/cbi/luci_fw/zones.lua @@ -0,0 +1,71 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: zones.lua 4051 2009-01-16 20:29:47Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("firewall", translate("fw_fw"), translate("fw_fw1")) + +s = m:section(TypedSection, "defaults") +s.anonymous = true + +s:option(Flag, "syn_flood") + +local di = s:option(Flag, "drop_invalid", translate("fw_dropinvalid")) +di.rmempty = false +function di.cfgvalue(...) + return AbstractValue.cfgvalue(...) or "1" +end + +p = {} +p[1] = s:option(ListValue, "input") +p[2] = s:option(ListValue, "output") +p[3] = s:option(ListValue, "forward") + +for i, v in ipairs(p) do + v:value("REJECT", translate("fw_reject")) + v:value("DROP", translate("fw_drop")) + v:value("ACCEPT", translate("fw_accept")) +end + + +s = m:section(TypedSection, "zone", translate("fw_zones")) +s.template = "cbi/tblsection" +s.anonymous = true +s.addremove = true + +name = s:option(Value, "name", translate("name")) +name.size = 8 + +p = {} +p[1] = s:option(ListValue, "input") +p[2] = s:option(ListValue, "output") +p[3] = s:option(ListValue, "forward") + +for i, v in ipairs(p) do + v:value("REJECT", translate("fw_reject")) + v:value("DROP", translate("fw_drop")) + v:value("ACCEPT", translate("fw_accept")) +end + +s:option(Flag, "masq") + +net = s:option(MultiValue, "network") +net.widget = "select" +net.rmempty = true +luci.tools.webadmin.cbi_add_networks(net) + +function net.cfgvalue(self, section) + local value = MultiValue.cfgvalue(self, section) + return value or name:cfgvalue(section) +end + +return m diff --git a/openwrt/packages/luci/applications/luci-fw/root/lib/uci/schema/default/firewall b/openwrt/packages/luci/applications/luci-fw/root/lib/uci/schema/default/firewall new file mode 100644 index 0000000..35ff056 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-fw/root/lib/uci/schema/default/firewall @@ -0,0 +1,255 @@ +package firewall + +config package + option title 'Firewall configuration' + +config section + option name 'zone' + option title 'Firewall zones' + option package 'firewall' + +config variable + option name 'name' + option title 'Name' + option section 'firewall.zone' + option required true + +config variable + option name 'network' + option title 'Networks belonging to this zone' + option section 'firewall.zone' + option valueof 'network.interface' + option multival true + +config variable + option name 'forward' + option title 'Zone specific action for forwarded traffic' + option section 'firewall.zone' + option required true + +config variable + option name 'input' + option title 'Zone specific action for incoming traffic' + option section 'firewall.zone' + option required true + +config variable + option name 'output' + option title 'Zone specific action for outgoing traffic' + option section 'firewall.zone' + option required true + +config variable + option name 'masq' + option title 'Enable masquerading for outgoing zone traffic' + option section 'firewall.zone' + option datatype 'boolean' + + + +config section + option name 'defaults' + option title 'Global firewall defaults' + option package 'firewall' + option unique true + option required true + +config variable + option name 'forward' + option title 'Action for forwarded traffic' + option section 'firewall.defaults' + option required true + +config variable + option name 'input' + option title 'Action for incoming traffic' + option section 'firewall.defaults' + option required true + +config variable + option name 'output' + option title 'Action for outgoing traffic' + option section 'firewall.defaults' + option required true + +config variable + option name 'syn_flood' + option title 'Enable syn-flood protection' + option section 'firewall.defaults' + option datatype 'boolean' + +config variable + option name 'drop_invalid' + option title 'Do not drop packages with state invalid' + option section 'firewall.defaults' + option datatype 'boolean' + + + +config section + option name 'forwarding' + option title 'Forwarding rules' + option package 'firewall' + +config variable + option name 'src' + option title 'Source zone' + option section 'firewall.forwarding' + option valueof 'firewall.zone.name' + option required true + +config variable + option name 'dest' + option title 'Destination zone' + option section 'firewall.forwarding' + option valueof 'firewall.zone.name' + option required true + +config variable + option name 'mtu_fix' + option title 'Fixup MTU of outgoing packages' + option section 'firewall.forwarding' + option datatype 'boolean' + + + +config section + option name 'rule' + option title 'Custom rules' + option package 'firewall' + list depends 'target, src' + list depends 'target, dest' + list depends 'target, src_ip' + list depends 'target, src_port' + list depends 'target, src_mac' + list depends 'target, dest_ip' + list depends 'target, dest_port' + list depends 'target, proto' + +config variable + option name 'src' + option title 'Source zone' + option section 'firewall.rule' + option valueof 'firewall.zone.name' + +config variable + option name 'src_ip' + option title 'Source IP address' + option section 'firewall.rule' + option datatype 'ipaddr' + +config variable + option name 'src_port' + option title 'Source port' + option section 'firewall.rule' + option datatype 'portrange' + +config variable + option name 'src_mac' + option title 'Source MAC address' + option section 'firewall.rule' + option datatype 'macaddr' + +config variable + option name 'dest' + option title 'Destination zone' + option section 'firewall.rule' + option valueof 'firewall.zone.name' + +config variable + option name 'dest_ip' + option title 'Destination IP address' + option section 'firewall.rule' + option datatype 'ipaddr' + +config variable + option name 'dest_port' + option title 'Destination port' + option section 'firewall.rule' + option datatype 'portrange' + +config variable + option name 'proto' + option title 'Protocol' + option section 'firewall.rule' + option datatype 'string' + +config variable + option name 'target' + option title 'Option target' + option section 'firewall.rule' + option datatype 'string' + + + +config section + option name 'redirect' + option title 'Redirection rules' + option package 'firewall' + +config variable + option name 'src' + option title 'Source zone' + option section 'firewall.redirect' + option valueof 'firewall.zone.name' + +config variable + option name 'src_ip' + option title 'Source IP address' + option section 'firewall.redirect' + option datatype 'ipaddr' + +config variable + option name 'src_port' + option title 'Source port' + option section 'firewall.redirect' + option datatype 'portrange' + +config variable + option name 'src_dport' + option title 'Source destination port' + option section 'firewall.redirect' + option datatype 'portrange' + +config variable + option name 'src_mac' + option title 'Option src_mac' + option section 'firewall.redirect' + option datatype 'macaddr' + +config variable + option name 'dest' + option title 'Destination zone' + option section 'firewall.redirect' + option valueof 'firewall.zone.name' + +config variable + option name 'dest_ip' + option title 'Destination IP address' + option section 'firewall.redirect' + option datatype 'ipaddr' + +config variable + option name 'dest_port' + option title 'Destination port' + option section 'firewall.redirect' + option datatype 'portrange' + +config variable + option name 'proto' + option title 'Protocol' + option section 'firewall.redirect' + option datatype 'string' + + + +config section + option name 'include' + option title 'User defined config includes' + option package 'firewall' + +config variable + option name 'path' + option title 'Path to the include file' + option section 'firewall.include' + option datatype 'file' diff --git a/openwrt/packages/luci/applications/luci-hd_idle/Makefile b/openwrt/packages/luci/applications/luci-hd_idle/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-hd_idle/ipkg/postinst b/openwrt/packages/luci/applications/luci-hd_idle/ipkg/postinst new file mode 100644 index 0000000..4c3b4dc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-hd_idle ) && rm -f /etc/uci-defaults/luci-hd_idle +} diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/controller/hd_idle.lua b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/controller/hd_idle.lua new file mode 100644 index 0000000..10a3963 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/controller/hd_idle.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI hd-idle +(c) 2008 Yanira + +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: hd_idle.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.hd_idle", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("hd_idle") + if not luci.fs.access("/etc/config/hd-idle") then + return + end + + local page = entry({"admin", "services", "hd_idle"}, cbi("hd_idle"), luci.i18n.translate("hd_idle", "hd-idle"), 60) + page.i18n = "hd_idle" + page.dependent = true +end diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.lua b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.lua new file mode 100644 index 0000000..ca276ab --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.lua @@ -0,0 +1,7 @@ +disk = 'Festplatte' +enable_debug = 'Debug-Ausgaben aktivieren' +hd_idle = 'hd-idle' +hd_idle_desc = 'hd-idle ist ein Hilfsprogramm um externe Festplatten nach einer festgelegten Leerlaufzeit herunter zu fahren.' +idle_time_interval = 'Leerlaufzeit' +idle_time_unit = 'Leerlaufzeiteinheit' +settings = 'Einstellungen' diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.xml b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.xml new file mode 100644 index 0000000..398df00 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.de.xml @@ -0,0 +1,13 @@ + + + + +Festplatte +Debug-Ausgaben aktivieren +hd-idle +hd-idle ist ein Hilfsprogramm um externe Festplatten nach einer festgelegten Leerlaufzeit herunter zu fahren. +Leerlaufzeit +Leerlaufzeiteinheit +Einstellungen + + diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.lua b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.lua new file mode 100644 index 0000000..2ec7780 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.lua @@ -0,0 +1,7 @@ +disk = 'Disk' +enable_debug = 'Enable debug' +hd_idle = 'hd-idle' +hd_idle_desc = 'hd-idle is a utility program for spinning-down external disks after a period of idle time.' +idle_time_interval = 'Idle-Time' +idle_time_unit = 'Idle-Time unit' +settings = 'Settings' diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.xml b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.xml new file mode 100644 index 0000000..7802a78 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.en.xml @@ -0,0 +1,13 @@ + + + + +Disk +Enable debug +hd-idle +hd-idle is a utility program for spinning-down external disks after a period of idle time. +Idle-Time +Idle-Time unit +Settings + + diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.lua b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.lua new file mode 100644 index 0000000..a1d253d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.lua @@ -0,0 +1,7 @@ +disk = 'Disco' +enable_debug = 'Habilitar debug' +hd_idle = 'Hd-idle' +hd_idle_desc = 'Hd-idle é um programa utilitário para ativar o modo "economia de energia" (spinning-down) de discos externos após um período de ociosidade.' +idle_time_interval = 'Tempo de ociosidade' +idle_time_unit = 'Unidade do tempo de ociosidade' +settings = 'Configurações' diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.xml b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.xml new file mode 100644 index 0000000..22f4346 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/i18n/hd_idle.pt-br.xml @@ -0,0 +1,13 @@ + + + + +Disco +Habilitar debug +Hd-idle +Hd-idle é um programa utilitário para ativar o modo "economia de energia" (spinning-down) de discos externos após um período de ociosidade. +Tempo de ociosidade +Unidade do tempo de ociosidade +Configurações + + diff --git a/openwrt/packages/luci/applications/luci-hd_idle/luasrc/model/cbi/hd_idle.lua b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/model/cbi/hd_idle.lua new file mode 100644 index 0000000..32ca85b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/luasrc/model/cbi/hd_idle.lua @@ -0,0 +1,41 @@ +--[[ + +LuCI hd-idle +(c) 2008 Yanira + +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: hd_idle.lua 3503 2008-10-03 16:49:00Z jow $ + +]]-- + +require("luci.fs") + +m = Map("hd-idle", translate("hd_idle"), translate("hd_idle_desc")) + +s = m:section(TypedSection, "hd-idle", translate("settings")) +s.anonymous = true + +s:option(Flag, "enabled", translate("enable", "Enable")) + +disk = s:option(Value, "disk", translate("disk")) +disk.rmempty = true +for _, dev in ipairs(luci.fs.glob("/dev/[sh]d[a-z]")) do + disk:value(luci.fs.basename(dev)) +end + +s:option(Value, "idle_time_interval", translate("idle_time_interval")).default = 10 +s.rmempty = true +unit = s:option(ListValue, "idle_time_unit", translate("idle_time_unit")) +unit.default = "minutes" +unit:value("minutes", "min") +unit:value("hours", "h") +unit.rmempty = true + +s:option(Flag, "enable_debug", translate("enable_debug")) + +return m diff --git a/openwrt/packages/luci/applications/luci-hd_idle/root/etc/uci-defaults/luci-hd_idle b/openwrt/packages/luci/applications/luci-hd_idle/root/etc/uci-defaults/luci-hd_idle new file mode 100644 index 0000000..6a37176 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-hd_idle/root/etc/uci-defaults/luci-hd_idle @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack hd-idle + set ucitrack.@hd-idle[-1].init=hd-idle + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-initmgr/Makefile b/openwrt/packages/luci/applications/luci-initmgr/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/controller/init.lua b/openwrt/packages/luci/applications/luci-initmgr/luasrc/controller/init.lua new file mode 100644 index 0000000..caae2ba --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/controller/init.lua @@ -0,0 +1,29 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: init.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.init", package.seeall) + +function index() + if not luci.fs.access("/etc/rc.common") then + return + end + + require("luci.i18n") + luci.i18n.loadc("initmgr") + + entry( + {"admin", "system", "init"}, form("init/init"), + luci.i18n.translate("initmgr", "Init Scripts") + ).i18n = "initmgr" +end diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.lua b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.lua new file mode 100644 index 0000000..13b6a4a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.lua @@ -0,0 +1,5 @@ +initmgr = 'Startscripte' +initmgr_desc = 'Hier können installierte Startscripte aktiviert oder deaktiviert werden. Änderungen werden erst mit einem Geräteneustart angewendet.
Warnung: Wenn essentialle Startscripte wie "network" deaktiviert werden könnte das Gerät unerreichbar werden!' +initmgr_index = 'Startpriorität' +initmgr_name = 'Startscript' +initmgr_enabled = 'Aktivieren/Deaktivieren' diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.xml b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.xml new file mode 100644 index 0000000..955ec11 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.de.xml @@ -0,0 +1,11 @@ + + + + +Startscripte +Hier können installierte Startscripte aktiviert oder deaktiviert werden. Änderungen werden erst mit einem Geräteneustart angewendet.
Warnung: Wenn essentialle Startscripte wie "network" deaktiviert werden könnte das Gerät unerreichbar werden!
+Startpriorität +Startscript +Aktivieren/Deaktivieren + +
diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.lua b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.lua new file mode 100644 index 0000000..6e6da7b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.lua @@ -0,0 +1,5 @@ +initmgr = 'Initscripts' +initmgr_desc = 'You can enable or disable installed init scripts here. Changes will applied after a device reboot.
Warning: If you disable essential init scripts like "network", your device might become inaccesable!' +initmgr_index = 'Start priority' +initmgr_name = 'Initscript' +initmgr_enabled = 'Enable/Disable' diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.xml b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.xml new file mode 100644 index 0000000..49a0d7b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.en.xml @@ -0,0 +1,11 @@ + + + + +Initscripts +You can enable or disable installed init scripts here. Changes will applied after a device reboot.
Warning: If you disable essential init scripts like "network", your device might become inaccesable!
+Start priority +Initscript +Enable/Disable + +
diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.lua b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.lua new file mode 100644 index 0000000..f6e3d5d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.lua @@ -0,0 +1,5 @@ +initmgr = 'Scripts de Inicialização' +initmgr_desc = 'Você pode ativar ou desativar os scripts de inicialização instalados aqui. As mudanças serão aplicadas após a reinicialização do equipamento.
Aviso: Se você desativar algum script de inicialização essencial como por exemplo "rede/network", o dispositivo poderá tornar-se inacessível!' +initmgr_index = 'Prioridade de inicialização' +initmgr_name = 'Script de inicialização' +initmgr_enabled = 'Ativar/Desativar' diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.xml b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.xml new file mode 100644 index 0000000..cf3c937 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/i18n/initmgr.pt-br.xml @@ -0,0 +1,11 @@ + + + + +Scripts de Inicialização +Você pode ativar ou desativar os scripts de inicialização instalados aqui. As mudanças serão aplicadas após a reinicialização do equipamento.
Aviso: Se você desativar algum script de inicialização essencial como por exemplo "rede/network", o dispositivo poderá tornar-se inacessível!
+Prioridade de inicialização +Script de inicialização +Ativar/Desativar + +
diff --git a/openwrt/packages/luci/applications/luci-initmgr/luasrc/model/cbi/init/init.lua b/openwrt/packages/luci/applications/luci-initmgr/luasrc/model/cbi/init/init.lua new file mode 100644 index 0000000..0523fe9 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-initmgr/luasrc/model/cbi/init/init.lua @@ -0,0 +1,58 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: init.lua 3528 2008-10-06 20:09:06Z jow $ +]]-- + +require("luci.sys") +require("luci.util") + +local inits = { } + +for _, name in ipairs(luci.sys.init.names()) do + local index = luci.sys.init.index(name) + local enabled = luci.sys.init.enabled(name) + + inits["%02i.%s" % { index, name }] = { + name = name, + index = tostring(index), + enabled = enabled + } +end + + +m = SimpleForm("initmgr", translate("initmgr"), translate("initmgr_desc")) +m.reset = false + +s = m:section(Table, inits) + +i = s:option(DummyValue, "index", translate("initmgr_index")) +n = s:option(DummyValue, "name", translate("initmgr_name")) + +e = s:option(Flag, "enabled", translate("initmgr_enabled")) + +e.cfgvalue = function(self, section) + return inits[section].enabled and "1" or "0" +end + +e.write = function(self, section, value) + if value == "1" and not inits[section].enabled then + inits[section].enabled = true + return luci.sys.init.enable(inits[section].name) + elseif value == "0" and inits[section].enabled then + inits[section].enabled = false + return luci.sys.init.disable(inits[section].name) + end + return true +end + +return m diff --git a/openwrt/packages/luci/applications/luci-livestats/Makefile b/openwrt/packages/luci/applications/luci-livestats/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/ExCanvas.js b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/ExCanvas.js new file mode 100644 index 0000000..9d71658 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/ExCanvas.js @@ -0,0 +1,19 @@ +if(!window.CanvasRenderingContext2D){(function(){var I=Math,i=I.round,L=I.sin,M=I.cos,m=10,A=m/2,Q={init:function(a){var b=a||document;if(/MSIE/.test(navigator.userAgent)&&!window.opera){var c=this;b.attachEvent("onreadystatechange",function(){c.r(b)})}},r:function(a){if(a.readyState=="complete"){if(!a.namespaces["s"]){a.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml")}var b=a.createStyleSheet();b.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}"; +var c=a.getElementsByTagName("canvas");for(var d=0;d"){var d="/"+a.tagName,e;while((e=a.nextSibling)&&e.tagName!=d){e.removeNode()}if(e){e.removeNode()}}a.parentNode.replaceChild(c,a);return c},initElement:function(a){a=this.q(a);a.getContext=function(){if(this.l){return this.l}return this.l=new K(this)};a.attachEvent("onpropertychange",V);a.attachEvent("onresize", +W);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+"px"}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+"px"}else{a.height=a.clientHeight}return a}};function V(a){var b=a.srcElement;switch(a.propertyName){case "width":b.style.width=b.attributes.width.nodeValue+"px";b.getContext().clearRect();break;case "height":b.style.height=b.attributes.height.nodeValue+"px";b.getContext().clearRect();break}}function W(a){var b=a.srcElement; +if(b.firstChild){b.firstChild.style.width=b.clientWidth+"px";b.firstChild.style.height=b.clientHeight+"px"}}Q.init();var R=[];for(var E=0;E<16;E++){for(var F=0;F<16;F++){R[E*16+F]=E.toString(16)+F.toString(16)}}function J(){return[[1,0,0],[0,1,0],[0,0,1]]}function G(a,b){var c=J();for(var d=0;d<3;d++){for(var e=0;e<3;e++){var g=0;for(var h=0;h<3;h++){g+=a[d][h]*b[h][e]}c[d][e]=g}}return c}function N(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit= +a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.d=a.d;b.e=a.e}function O(a){var b,c=1;a=String(a);if(a.substring(0,3)=="rgb"){var d=a.indexOf("(",3),e=a.indexOf(")",d+1),g=a.substring(d+1,e).split(",");b="#";for(var h=0;h<3;h++){b+=R[Number(g[h])]}if(g.length==4&&a.substr(3,1)=="a"){c=g[3]}}else{b=a}return[b,c]}function S(a){switch(a){case "butt":return"flat";case "round":return"round"; +case "square":default:return"square"}}function K(a){this.a=J();this.m=[];this.k=[];this.c=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=m*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement("div");b.style.width=a.clientWidth+"px";b.style.height=a.clientHeight+"px";b.style.overflow="hidden";b.style.position="absolute";a.appendChild(b);this.j=b;this.d=1;this.e=1}var j=K.prototype;j.clearRect=function(){this.j.innerHTML= +"";this.c=[]};j.beginPath=function(){this.c=[]};j.moveTo=function(a,b){this.c.push({type:"moveTo",x:a,y:b});this.f=a;this.g=b};j.lineTo=function(a,b){this.c.push({type:"lineTo",x:a,y:b});this.f=a;this.g=b};j.bezierCurveTo=function(a,b,c,d,e,g){this.c.push({type:"bezierCurveTo",cp1x:a,cp1y:b,cp2x:c,cp2y:d,x:e,y:g});this.f=e;this.g=g};j.quadraticCurveTo=function(a,b,c,d){var e=this.f+0.6666666666666666*(a-this.f),g=this.g+0.6666666666666666*(b-this.g),h=e+(c-this.f)/3,l=g+(d-this.g)/3;this.bezierCurveTo(e, +g,h,l,c,d)};j.arc=function(a,b,c,d,e,g){c*=m;var h=g?"at":"wa",l=a+M(d)*c-A,n=b+L(d)*c-A,o=a+M(e)*c-A,f=b+L(e)*c-A;if(l==o&&!g){l+=0.125}this.c.push({type:h,x:a,y:b,radius:c,xStart:l,yStart:n,xEnd:o,yEnd:f})};j.rect=function(a,b,c,d){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath()};j.strokeRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.stroke()};j.fillRect=function(a, +b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill()};j.createLinearGradient=function(a,b,c,d){var e=new H("gradient");return e};j.createRadialGradient=function(a,b,c,d,e,g){var h=new H("gradientradial");h.n=c;h.o=g;h.i.x=a;h.i.y=b;return h};j.drawImage=function(a,b){var c,d,e,g,h,l,n,o,f=a.runtimeStyle.width,k=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var q=a.width,r=a.height;a.runtimeStyle.width= +f;a.runtimeStyle.height=k;if(arguments.length==3){c=arguments[1];d=arguments[2];h=(l=0);n=(e=q);o=(g=r)}else if(arguments.length==5){c=arguments[1];d=arguments[2];e=arguments[3];g=arguments[4];h=(l=0);n=q;o=r}else if(arguments.length==9){h=arguments[1];l=arguments[2];n=arguments[3];o=arguments[4];c=arguments[5];d=arguments[6];e=arguments[7];g=arguments[8]}else{throw"Invalid number of arguments";}var s=this.b(c,d),t=[],v=10,w=10;t.push(" ','","");this.j.insertAdjacentHTML("BeforeEnd",t.join(""))};j.stroke=function(a){var b=[],c=O(a?this.fillStyle:this.strokeStyle),d=c[0],e=c[1]*this.globalAlpha,g=10,h=10;b.push("n.x){n.x=k.x}if(l.y== +null||k.yn.y){n.y=k.y}}}b.push(' ">');if(typeof this.fillStyle=="object"){var v={x:"50%",y:"50%"},w=n.x-l.x,x=n.y-l.y,p=w>x?w:x;v.x=i(this.fillStyle.i.x/w*100+50)+"%";v.y=i(this.fillStyle.i.y/x*100+50)+"%";var y=[];if(this.fillStyle.p=="gradientradial"){var z=this.fillStyle.n/p*100,B=this.fillStyle.o/p*100-z}else{var z=0,B=100}var C={offset:null,color:null},D={offset:null,color:null};this.fillStyle.h.sort(function(T,U){return T.offset-U.offset});for(var o=0;oC.offset||C.offset==null){C.offset=u.offset;C.color=u.color}if(u.offset')}else if(a){b.push('')}else{b.push("')}b.push("");this.j.insertAdjacentHTML("beforeEnd",b.join(""));this.c=[]};j.fill=function(){this.stroke(true)};j.closePath=function(){this.c.push({type:"close"})};j.b=function(a,b){return{x:m*(a*this.a[0][0]+b*this.a[1][0]+this.a[2][0])-A,y:m*(a*this.a[0][1]+b*this.a[1][1]+this.a[2][1])-A}};j.save=function(){var a={};N(this,a); +this.k.push(a);this.m.push(this.a);this.a=G(J(),this.a)};j.restore=function(){N(this.k.pop(),this);this.a=this.m.pop()};j.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];this.a=G(c,this.a)};j.rotate=function(a){var b=M(a),c=L(a),d=[[b,c,0],[-c,b,0],[0,0,1]];this.a=G(d,this.a)};j.scale=function(a,b){this.d*=a;this.e*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];this.a=G(c,this.a)};j.clip=function(){};j.arcTo=function(){};j.createPattern=function(){return new P};function H(a){this.p=a;this.n=0;this.o= +0;this.h=[];this.i={x:0,y:0}}H.prototype.addColorStop=function(a,b){b=O(b);this.h.push({offset:1-a,color:b})};function P(){}G_vmlCanvasManager=Q;CanvasRenderingContext2D=K;CanvasGradient=H;CanvasPattern=P})()}; diff --git a/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/GraphRPC.js b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/GraphRPC.js new file mode 100644 index 0000000..712d8b1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/GraphRPC.js @@ -0,0 +1,204 @@ +function Graph(container, id, options, transform, legend) { + if( !options ) options = { }; + + this.id = id; + this.cols = 100; + this.type = "line"; + this.options = options; + this.transform = transform; + this.dataset = {}; + this.legend = legend; + this.lastvalue = {}; + + var name = (options.instanceNames && options.instanceNames[id]) + ? options.instanceNames[id] : id; + var graph = document.createElement('div'); + var label = document.createElement('h2'); + label.innerHTML = options.title + ? options.title.replace("%s", name) : name; + + container.appendChild( label ); + container.appendChild( graph ); + + this.canvas = document.createElement('canvas'); + graph.appendChild( this.canvas ); + + this.canvas.id = id; + this.canvas.width = ( options.width || graph.offsetWidth - 20 ); + this.canvas.height = ( options.height || 300 ); +} + +Graph.prototype.addDataset = function(name, ds) { + if( !this.layout ) { + this.layout = new PlotKit.Layout( this.type, this.options ); + } + + if( !ds ) { + ds = new Array(); + for( var i = 0; i < this.cols; i++ ) + ds[i] = new Array( i, 0 ); + } + + this.dataset[name] = ds; + this.layout.addDataset(name, ds); +} + +Graph.prototype.updateDataset = function(name, value) { + if( this.dataset[name] ) { + var ds = this.dataset[name]; + + for( var i = 1; i < this.cols; i++ ) + ds[i-1][1] = ds[i][1]; + + value = Math.abs( parseFloat(value) || 0 ); + + if( this.transform ) { + var orgvalue = value; + value = (this.lastvalue[name]) ? this.transform(value, this.lastvalue[name]) : 0; + this.lastvalue[name] = orgvalue; + } + + ds[this.cols-1][1] = value; + this.layout.addDataset(name, ds); + } +} + +Graph.prototype.draw = function( options ) { + if( this.layout ) { + this.plotter = new PlotKit.CanvasRenderer( + this.canvas, this.layout, this.options || options || {} + ); + + this.layout.evaluate(); + this.plotter.render(); + + legend_opt = { + "legendStyle": 'li' + }; + + legend = new LegendRenderer(this.legend, this.layout, legend_opt); + legend.render(); + } +} + +Graph.prototype.redraw = function() { + if( this.layout && this.plotter ) { + this.layout.evaluate(); + this.plotter.clear(); + this.plotter.render(); + } +} + + +function GraphRPC(container, uri, action, interval, datasources, options, transform, legend) { + this.ds = datasources; + this.uri = uri + this.action = action; + this.options = options || { }; + this.container = container; + this.transform = transform; + this.proxy = new MochiKit.JsonRpc.JsonRpcProxy(uri, [action]); + this.graphs = new Object(); + this.legend = legend; + + this.requestData(); + + if( interval ) { + var self = this; + window.setInterval(function(){self.requestData()}, interval); + } +} + +GraphRPC.prototype.requestData = function() { + var r = this.proxy[this.action](); var self = this; + r.addCallback(function(r){ self.dispatchResponse(r) }); + r.addErrback(function(e){ throw('Error: ' + e) }); +} + +GraphRPC.prototype.dispatchResponse = function(response) { + var instances; + if( this.options.instances ) { + instances = this.options.instances; + } + else { + instances = new Array(); + for( var instance in response ) { + instances[instances.length] = instance; + } + } + + for( var j = 0; j < instances.length; j++ ) { + var instance = instances[j]; + + if( this.options.separateDS ) { + for( var i = 0; i < this.ds.length; i += 2 ) { + var name = this.ds[i+1] || this.ds[i]; + var gid = instance + '-' + name; + var otle = this.options.title || instance; + + if( !this.graphs[gid] ) { + this.options.title = otle.replace('%s', instance) + ': ' + name; + this.graphs[gid] = new Graph( + this.container, gid, this.options, this.transform, this.legend + ); + + this.graphs[gid].addDataset(name); + this.graphs[gid].draw(); + this.options.title = otle; + } + else + { + var datum = null; + if (typeof (this.ds[i]) == "function") { + datum = this.ds[i]( + instance ? response[instance] : response + ); + } else { + datum = instance + ? response[instance][this.ds[i]] + : response[this.ds[i]] + } + this.graphs[gid].updateDataset( + name, datum + ); + this.graphs[gid].redraw(); + } + } + } + else { + var gid = instance || 'livegraph'; + if( !this.graphs[gid] ) { + this.graphs[gid] = new Graph( + this.container, gid, this.options, this.transform, this.legend + ); + + for( var i = 0; i < this.ds.length; i += 2 ) { + var name = this.ds[i+1] || this.ds[i]; + this.graphs[gid].addDataset(name); + } + + this.graphs[gid].draw(); + } + else { + for( var i = 0; i < this.ds.length; i += 2 ) { + var name = this.ds[i+1] || this.ds[i]; + var datum = null; + if (typeof (this.ds[i]) == "function") { + datum = this.ds[i]( + instance ? response[instance] : response + ); + } else { + datum = instance + ? response[instance][this.ds[i]] + : response[this.ds[i]] + } + this.graphs[gid].updateDataset( + name, datum + ); + } + + this.graphs[gid].redraw(); + } + } + } +} diff --git a/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/JsonRpc.js b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/JsonRpc.js new file mode 100644 index 0000000..f1723ec --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/JsonRpc.js @@ -0,0 +1,220 @@ +/* MochiKit.JsonRpc */ + +if (typeof(dojo) != 'undefined') { + dojo.provide("MochiKit.JsonRpc"); + dojo.require("MochiKit.Base"); + dojo.require("MochiKit.DOM"); + dojo.require("MochiKit.Async"); +} + +if (typeof(JSAN) != 'undefined') { + JSAN.use("MochiKit.Base", []); + JSAN.use("MochiKit.DOM", []); + JSAN.use("MochiKit.Async", []); +} + +try { + if (typeof(MochiKit.Base) == 'undefined' || + typeof(MochiKit.DOM) == 'undefined' || + typeof(MochiKit.Async) == 'undefined') { + throw ""; + } +} catch (e) { + throw "MochiKit.JsonRpc depends on MochiKit.Base, MochiKit.DOM and MochiKit.Async"; +} + +if (typeof(MochiKit.JsonRpc) == 'undefined') { + MochiKit.JsonRpc = {}; +} + +MochiKit.JsonRpc.NAME = "MochiKit.JsonRpc"; +MochiKit.JsonRpc.VERSION = "0.90"; + +MochiKit.JsonRpc.__repr__ = function () { + return "[" + this.NAME + " " + this.VERSION + "]"; +} + +MochiKit.JsonRpc.toString = function () { + return this.__repr__(); +} + +MochiKit.JsonRpc.JsonRpcError = function (message) { + this.message = message; + this.name = 'JsonRpcError'; +} + +MochiKit.JsonRpc.JsonRpcError.prototype = new Error(); +MochiKit.JsonRpc.JsonRpcError.prototype.repr = function () { + return 'JsonRpcError(' + this.message + ')'; +} + +MochiKit.JsonRpc.JsonRpcError.prototype.toString = function () { + return this.repr(); +} + +MochiKit.JsonRpc.jsonObject = function (o) { + var attrs=[]; + for(attr in o){ + if(typeof o[attr] != "function"){ + attrs.push('"' + attr + '": ' + json(o[attr])); + } + } + return "{" + attrs.join(", ") + "}"; +} + +MochiKit.JsonRpc.isObject = function (o) { + return true; +} + +MochiKit.JsonRpc.jsonArray = function (o) { + return "[" + MochiKit.Base.map(json, o).join(", ") + "]"; +} + +var MB = MochiKit.Base + +MochiKit.JsonRpc.jsonRegistry = new MochiKit.Base.AdapterRegistry(); +MochiKit.JsonRpc.jsonRegistry.register('arrayLike',MB.isArrayLike,MochiKit.JsonRpc.jsonArray); +MochiKit.JsonRpc.jsonRegistry.register("string", MB.typeMatcher("string"), MB.reprString); +MochiKit.JsonRpc.jsonRegistry.register("numbers", MB.typeMatcher("number", "boolean"), MB.reprNumber); +MochiKit.JsonRpc.jsonRegistry.register("undefined", MB.isUndefined, MB.reprUndefined); +MochiKit.JsonRpc.jsonRegistry.register("null", MB.isNull, MB.reprNull); +MochiKit.JsonRpc.jsonRegistry.register("objectLike", MochiKit.JsonRpc.isObject, MochiKit.JsonRpc.jsonObject); + +MochiKit.JsonRpc.json = function (o) { + try { + if (typeof(o.__json__) == 'function') { + return o.__json__(); + } else if (typeof(o.json) == 'function' && o.json != arguments.callee) { + return o.json(); + } + return jsonRegistry.match(o); + } catch (e) { + if (typeof(o.NAME) == 'string' && ( + o.toString == Function.prototype.toString || + o.toString == Object.prototype.toString + )) { + return o.NAME; + } + return o; + } + +} + + +MochiKit.JsonRpc.JsonRpcCall = function (method,params) { + this.method = method; + this.params = params; + this.id = '0'; +} + +MochiKit.JsonRpc.JsonRpcProxy = function (url,methNames) { + MochiKit.Base.bindMethods(this); + this.url = url; + if (methNames) { + MochiKit.Base.map(this._proxyMethod,methNames); + } +} + +update(MochiKit.JsonRpc.JsonRpcProxy.prototype, { + 'call': function () { + var arglist = MochiKit.Base.map(null,arguments) + var methname = arglist.shift() + log(arglist); + var callobj = new MochiKit.JsonRpc.JsonRpcCall(methname,arglist); + var callstr = json(callobj); + var req = MochiKit.Async.getXMLHttpRequest(); + req.open("POST",this.url,true); + req.setRequestHeader("Content-Type","text/plain"); + req.setRequestHeader("Content-Length",callstr.length); + var d = MochiKit.Async.sendXMLHttpRequest(req,callstr); + d.addCallback(MochiKit.Async.evalJSONRequest); + d.addCallback(this._extractResult); + + return d + }, + 'addSingleMethod': function (methName) { + if (methName) { + this._proxyMethod(methName); + } + }, + 'addMethods': function (methNames) { + if (methNames) { + MochiKit.Base.map(this._proxyMethod,methNames); + } + }, + '_extractResult': function (resp) { + if (!resp.error){ + return resp.result; + } else { + throw new MochiKit.JsonRpc.JsonRpcError(resp.error); + } + }, + '_proxyMethod': function (methname) { + this[methname] = MochiKit.Base.partial(this.call,methname); + } +}); + +MochiKit.JsonRpc.DomObjectFromJson = function (){ + var retval = false; + if (arguments.length == 1) { + var arg = arguments[0]; + if (typeof(arg) == 'string'){ + retval = MochiKit.DOM.SPAN(null,arg); + } else { + var objrepr = arguments[0]; + var elem = document.createElement(objrepr[0]); + var attrs = objrepr[1]; + if (attrs) { + MochiKit.DOM.updateNodeAttributes(elem, attrs); + } + if (objrepr.length >= 3){ + var extraobj = objrepr[2] + for (var i=0;i + For use under the BSD license. + +*/ + +try { + if (typeof(MochiKit.Base) == 'undefined' || + typeof(MochiKit.DOM) == 'undefined' || + typeof(MochiKit.Color) == 'undefined' || + typeof(MochiKit.Format) == 'undefined' || + typeof(PlotKit.Layout) == 'undefined' || + typeof(PlotKit.Base) == 'undefined') + { + throw ""; + } +} +catch (e) { + throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format}" +} + +if (typeof(PlotKit.LegendRenderer) == 'undefined') { + PlotKit.LegendRenderer = {}; +} + +PlotKit.LegendRenderer = function(element, layout, options) { + if (arguments.length > 0) + this.__init__(element, layout, options); +}; + + +PlotKit.LegendRenderer.NAME = "PlotKit.LegendRenderer"; +PlotKit.LegendRenderer.VERSION = PlotKit.VERSION; + +PlotKit.LegendRenderer.__repr__ = function() { + return "[" + this.NAME + " " + this.VERSION + "]"; +}; + +PlotKit.LegendRenderer.toString = function() { + return this.__repr__(); +} + +PlotKit.LegendRenderer.prototype.__init__ = function(element, layout, +options) { + var isNil = MochiKit.Base.isUndefinedOrNull; + var Color = MochiKit.Color.Color; + + this.options = { + "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors() +[0]), + "legendStyle": "table", + "tableColumns": 1 + }; + MochiKit.Base.update(this.options, options ? options : {}); + + this.layout = layout; + this.element = MochiKit.DOM.getElement(element); + // --- check whether everything is ok before we return + + if (isNil(this.element)) + throw "CRILegend() - passed legend is not found"; +}; + +PlotKit.LegendRenderer.prototype.render = function() { + var colorScheme = this.options.colorScheme; + var setNames = PlotKit.Base.keys(this.layout.datasets); + + MochiKit.DOM.updateNodeAttributes(this.element, + {"style": + {"margin":"0" + ,"padding":"0" + } + }); + + + var ul = null; + if (this.options.legendStyle == "table") + ul = this._renderListTable(colorScheme, setNames); + else + ul = this._renderList(colorScheme, setNames); + MochiKit.DOM.appendChildNodes(this.element, ul); + +}; + +PlotKit.LegendRenderer.prototype._renderList = function(colorScheme, +setNames) { + var ul = document.createElement("ul"); + ul.style.listStyle="none"; + ul.style.margin="0"; + ul.style.padding="0"; + + var colorCount = colorScheme.length; + var setCount = setNames.length; + + for (var i = 0; i < setCount; i++) { + var setName = setNames[i]; + var color = colorScheme[i%colorCount]; + var le = this._renderElement(setName, color.toRGBString()); + ul.appendChild(le); + } + + return ul; +}; + +PlotKit.LegendRenderer.prototype._renderElement = function(title, +color) { + var le = MochiKit.DOM.createDOM("li"); + le.style.listStyle="none"; + le.style.margin="0 0 5px 0"; + le.style.padding="0"; + + var box = MochiKit.DOM.createDOM("div"); + box.style.backgroundColor=color; + box.style.width="2em"; + box.style.height=".9em"; + box.style.border="1px solid black"; + box.style.margin="0 5px 0 0"; + box.style.padding="0"; + box.style.float="left"; + box.style.cssFloat="left"; + box.style.clear="left"; + box.style.cssClear="left"; + + var span = MochiKit.DOM.createDOM("span"); + MochiKit.DOM.appendChildNodes(span, +document.createTextNode(title)); + + MochiKit.DOM.appendChildNodes(le, box, span); + + return le; +}; + +PlotKit.LegendRenderer.prototype._renderListTable = +function(colorScheme, setNames) { + var tabhead = THEAD(null); + var tabfoot = TFOOT(null); + + var tabbody = partial(TBODY, null); + var i = 0; + var colorcount = colorScheme.length; + var tabrow; + var columns = this.options.tableColumns; + for (var label in setNames) + { + var legendcolor = colorScheme[i%colorcount]; + var legendbox = DIV({'class': 'legendbox', 'className': +'legendbox'}); + legendbox.style.width = "10px"; + legendbox.style.height = "10px"; + legendbox.style.backgroundColor = legendcolor.toHexString(); + legendbox.style.borderWidth = "1px"; + legendbox.style.borderStyle = "solid"; + legendbox.style.borderColor = "#000000"; + var boxcell = TD(null, legendbox); + + var labelcell = TD({'class': 'legendlabel', 'className': +'legendlabel'}, setNames[i]); + labelcell.style.font = 'normal 10pt arial'; + + if (!(i % columns)) + { + tabrow = partial(TR, null); + } + tabrow = partial(tabrow, boxcell, labelcell); + if (i % columns) + { + tabrow = tabrow(null); + tabbody = partial(tabbody, tabrow); + } + i++; + } + if ((setNames % columns)) + { + tabrow = tabrow(TD(null), TD(null)); + tabbody = partial(tabbody, tabrow); + } + tabbody = tabbody(null); + + tab = TABLE({'class': 'legendcontainer', 'className': +'legendcontainer'}, tabhead, tabfoot, tabbody); + tab.style.marginTop = '1em'; + tab.style.marginLeft = '1.5em'; + tab.style.marginBottom = '1em'; + tab.style.borderWidth = '1px'; + tab.style.borderStyle = 'solid'; + tab.style.borderColor = '#000000'; + + return tab; +}; + +// Namespace Iniitialisation + +PlotKit.Legend = {} +PlotKit.Legend.LegendRenderer = PlotKit.LegendRenderer; + + +PlotKit.Legend.EXPORT = [ + "LegendRenderer" +]; + +PlotKit.Legend.EXPORT_OK = [ + "LegendRenderer" +]; + +PlotKit.Legend.__new__ = function() { + var m = MochiKit.Base; + + m.nameFunctions(this); + + this.EXPORT_TAGS = { + ":common": this.EXPORT, + ":all": m.concat(this.EXPORT, this.EXPORT_OK) + }; +}; + +PlotKit.Legend.__new__(); +MochiKit.Base._exportSymbols(this, PlotKit.Legend); \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/MochiKit.js b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/MochiKit.js new file mode 100644 index 0000000..c023c1e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/MochiKit.js @@ -0,0 +1,4800 @@ +/*** + + MochiKit.MochiKit 1.3.1 : PACKED VERSION + + THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please + diff against the source tree, not this file. + + See for documentation, downloads, license, etc. + + (c) 2005 Bob Ippolito. All rights Reserved. + +***/ + +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Base"); +} +if(typeof (MochiKit)=="undefined"){ +MochiKit={}; +} +if(typeof (MochiKit.Base)=="undefined"){ +MochiKit.Base={}; +} +MochiKit.Base.VERSION="1.3.1"; +MochiKit.Base.NAME="MochiKit.Base"; +MochiKit.Base.update=function(_1,_2){ +if(_1===null){ +_1={}; +} +for(var i=1;i=0;i--){ +_12.unshift(o[i]); +} +}else{ +res.push(o); +} +} +return res; +},extend:function(_13,obj,_15){ +if(!_15){ +_15=0; +} +if(obj){ +var l=obj.length; +if(typeof (l)!="number"){ +if(typeof (MochiKit.Iter)!="undefined"){ +obj=MochiKit.Iter.list(obj); +l=obj.length; +}else{ +throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); +} +} +if(!_13){ +_13=[]; +} +for(var i=_15;i>b; +},zrshift:function(a,b){ +return a>>>b; +},eq:function(a,b){ +return a==b; +},ne:function(a,b){ +return a!=b; +},gt:function(a,b){ +return a>b; +},ge:function(a,b){ +return a>=b; +},lt:function(a,b){ +return al){ +_41=l; +} +} +_40=[]; +for(i=0;i<_41;i++){ +var _42=[]; +for(var j=1;j0){ +_57=m.concat(me.im_preargs,_57); +} +var _52=me.im_self; +if(!_52){ +_52=this; +} +return me.im_func.apply(_52,_57); +}; +_56.im_self=_55; +_56.im_func=_53; +_56.im_preargs=_54; +return _56; +},bindMethods:function(_58){ +var _59=MochiKit.Base.bind; +for(var k in _58){ +var _60=_58[k]; +if(typeof (_60)=="function"){ +_58[k]=_59(_60,_58); +} +} +},registerComparator:function(_61,_62,_63,_64){ +MochiKit.Base.comparatorRegistry.register(_61,_62,_63,_64); +},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){ +if(a==b){ +return 0; +} +var _65=(typeof (a)=="undefined"||a===null); +var _66=(typeof (b)=="undefined"||b===null); +if(_65&&_66){ +return 0; +}else{ +if(_65){ +return -1; +}else{ +if(_66){ +return 1; +} +} +} +var m=MochiKit.Base; +var _67=m._primitives; +if(!(typeof (a) in _67&&typeof (b) in _67)){ +try{ +return m.comparatorRegistry.match(a,b); +} +catch(e){ +if(e!=m.NotFound){ +throw e; +} +} +} +if(ab){ +return 1; +} +} +var _68=m.repr; +throw new TypeError(_68(a)+" and "+_68(b)+" can not be compared"); +},compareDateLike:function(a,b){ +return MochiKit.Base.compare(a.getTime(),b.getTime()); +},compareArrayLike:function(a,b){ +var _69=MochiKit.Base.compare; +var _70=a.length; +var _71=0; +if(_70>b.length){ +_71=1; +_70=b.length; +}else{ +if(_700))){ +var kv=MochiKit.DOM.formContents(_113); +_113=kv[0]; +_114=kv[1]; +}else{ +if(arguments.length==1){ +var o=_113; +_113=[]; +_114=[]; +for(var k in o){ +var v=o[k]; +if(typeof (v)!="function"){ +_113.push(k); +_114.push(v); +} +} +} +} +var rval=[]; +var len=Math.min(_113.length,_114.length); +var _118=MochiKit.Base.urlEncode; +for(var i=0;i=stop){ +throw self.StopIteration; +} +_147+=step; +return rval; +}}; +},imap:function(fun,p,q){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +var _151=m.map(self.iter,m.extend(null,arguments,1)); +var map=m.map; +var next=self.next; +return {repr:function(){ +return "imap(...)"; +},toString:m.forwardCall("repr"),next:function(){ +return fun.apply(this,map(next,_151)); +}}; +},applymap:function(fun,seq,self){ +seq=MochiKit.Iter.iter(seq); +var m=MochiKit.Base; +return {repr:function(){ +return "applymap(...)"; +},toString:m.forwardCall("repr"),next:function(){ +return fun.apply(self,seq.next()); +}}; +},chain:function(p,q){ +var self=MochiKit.Iter; +var m=MochiKit.Base; +if(arguments.length==1){ +return self.iter(arguments[0]); +} +var _153=m.map(self.iter,arguments); +return {repr:function(){ +return "chain(...)"; +},toString:m.forwardCall("repr"),next:function(){ +while(_153.length>1){ +try{ +return _153[0].next(); +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +_153.shift(); +} +} +if(_153.length==1){ +var arg=_153.shift(); +this.next=m.bind("next",arg); +return this.next(); +} +throw self.StopIteration; +}}; +},takewhile:function(pred,seq){ +var self=MochiKit.Iter; +seq=self.iter(seq); +return {repr:function(){ +return "takewhile(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +var rval=seq.next(); +if(!pred(rval)){ +this.next=function(){ +throw self.StopIteration; +}; +this.next(); +} +return rval; +}}; +},dropwhile:function(pred,seq){ +seq=MochiKit.Iter.iter(seq); +var m=MochiKit.Base; +var bind=m.bind; +return {"repr":function(){ +return "dropwhile(...)"; +},"toString":m.forwardCall("repr"),"next":function(){ +while(true){ +var rval=seq.next(); +if(!pred(rval)){ +break; +} +} +this.next=bind("next",seq); +return rval; +}}; +},_tee:function(_155,sync,_157){ +sync.pos[_155]=-1; +var m=MochiKit.Base; +var _158=m.listMin; +return {repr:function(){ +return "tee("+_155+", ...)"; +},toString:m.forwardCall("repr"),next:function(){ +var rval; +var i=sync.pos[_155]; +if(i==sync.max){ +rval=_157.next(); +sync.deque.push(rval); +sync.max+=1; +sync.pos[_155]+=1; +}else{ +rval=sync.deque[i-sync.min]; +sync.pos[_155]+=1; +if(i==sync.min&&_158(sync.pos)!=sync.min){ +sync.min+=1; +sync.deque.shift(); +} +} +return rval; +}}; +},tee:function(_159,n){ +var rval=[]; +var sync={"pos":[],"deque":[],"max":-1,"min":-1}; +if(arguments.length==1){ +n=2; +} +var self=MochiKit.Iter; +_159=self.iter(_159); +var _tee=self._tee; +for(var i=0;i0&&_165>=stop)||(step<0&&_165<=stop)){ +throw MochiKit.Iter.StopIteration; +} +var rval=_165; +_165+=step; +return rval; +},repr:function(){ +return "range("+[_165,stop,step].join(", ")+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +},sum:function(_166,_167){ +var x=_167||0; +var self=MochiKit.Iter; +_166=self.iter(_166); +try{ +while(true){ +x+=_166.next(); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +return x; +},exhaust:function(_168){ +var self=MochiKit.Iter; +_168=self.iter(_168); +try{ +while(true){ +_168.next(); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +},forEach:function(_169,func,self){ +var m=MochiKit.Base; +if(arguments.length>2){ +func=m.bind(func,self); +} +if(m.isArrayLike(_169)){ +try{ +for(var i=0;i<_169.length;i++){ +func(_169[i]); +} +} +catch(e){ +if(e!=MochiKit.Iter.StopIteration){ +throw e; +} +} +}else{ +self=MochiKit.Iter; +self.exhaust(self.imap(func,_169)); +} +},every:function(_171,func){ +var self=MochiKit.Iter; +try{ +self.ifilterfalse(func,_171).next(); +return false; +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +return true; +} +},sorted:function(_172,cmp){ +var rval=MochiKit.Iter.list(_172); +if(arguments.length==1){ +cmp=MochiKit.Base.compare; +} +rval.sort(cmp); +return rval; +},reversed:function(_173){ +var rval=MochiKit.Iter.list(_173); +rval.reverse(); +return rval; +},some:function(_174,func){ +var self=MochiKit.Iter; +try{ +self.ifilter(func,_174).next(); +return true; +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +return false; +} +},iextend:function(lst,_175){ +if(MochiKit.Base.isArrayLike(_175)){ +for(var i=0;i<_175.length;i++){ +lst.push(_175[i]); +} +}else{ +var self=MochiKit.Iter; +_175=self.iter(_175); +try{ +while(true){ +lst.push(_175.next()); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +} +return lst; +},groupby:function(_176,_177){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +if(arguments.length<2){ +_177=m.operator.identity; +} +_176=self.iter(_176); +var pk=undefined; +var k=undefined; +var v; +function fetch(){ +v=_176.next(); +k=_177(v); +} +function eat(){ +var ret=v; +v=undefined; +return ret; +} +var _180=true; +return {repr:function(){ +return "groupby(...)"; +},next:function(){ +while(k==pk){ +fetch(); +if(_180){ +_180=false; +break; +} +} +pk=k; +return [k,{next:function(){ +if(v==undefined){ +fetch(); +} +if(k!=pk){ +throw self.StopIteration; +} +return eat(); +}}]; +}}; +},groupby_as_array:function(_181,_182){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +if(arguments.length<2){ +_182=m.operator.identity; +} +_181=self.iter(_181); +var _183=[]; +var _184=true; +var _185; +while(true){ +try{ +var _186=_181.next(); +var key=_182(_186); +} +catch(e){ +if(e==self.StopIteration){ +break; +} +throw e; +} +if(_184||key!=_185){ +var _187=[]; +_183.push([key,_187]); +} +_187.push(_186); +_184=false; +_185=key; +} +return _183; +},arrayLikeIter:function(_188){ +var i=0; +return {repr:function(){ +return "arrayLikeIter(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +if(i>=_188.length){ +throw MochiKit.Iter.StopIteration; +} +return _188[i++]; +}}; +},hasIterateNext:function(_189){ +return (_189&&typeof (_189.iterateNext)=="function"); +},iterateNextIter:function(_190){ +return {repr:function(){ +return "iterateNextIter(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +var rval=_190.iterateNext(); +if(rval===null||rval===undefined){ +throw MochiKit.Iter.StopIteration; +} +return rval; +}}; +}}); +MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter",]; +MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"]; +MochiKit.Iter.__new__=function(){ +var m=MochiKit.Base; +this.StopIteration=new m.NamedError("StopIteration"); +this.iteratorRegistry=new m.AdapterRegistry(); +this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter); +this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Iter.__new__(); +if(!MochiKit.__compat__){ +reduce=MochiKit.Iter.reduce; +} +MochiKit.Base._exportSymbols(this,MochiKit.Iter); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Logging"); +dojo.require("MochiKit.Base"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Logging depends on MochiKit.Base!"; +} +if(typeof (MochiKit.Logging)=="undefined"){ +MochiKit.Logging={}; +} +MochiKit.Logging.NAME="MochiKit.Logging"; +MochiKit.Logging.VERSION="1.3.1"; +MochiKit.Logging.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Logging.toString=function(){ +return this.__repr__(); +}; +MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"]; +MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"]; +MochiKit.Logging.LogMessage=function(num,_192,info){ +this.num=num; +this.level=_192; +this.info=info; +this.timestamp=new Date(); +}; +MochiKit.Logging.LogMessage.prototype={repr:function(){ +var m=MochiKit.Base; +return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_194){ +var self=MochiKit.Logging; +if(typeof (_194)=="string"){ +_194=self.LogLevel[_194]; +} +return function(msg){ +var _196=msg.level; +if(typeof (_196)=="string"){ +_196=self.LogLevel[_196]; +} +return _196>=_194; +}; +},isLogMessage:function(){ +var _197=MochiKit.Logging.LogMessage; +for(var i=0;i=0&&this._messages.length>this.maxSize){ +this._messages.shift(); +} +},getMessages:function(_206){ +var _207=0; +if(!(typeof (_206)=="undefined"||_206===null)){ +_207=Math.max(0,this._messages.length-_206); +} +return this._messages.slice(_207); +},getMessageText:function(_208){ +if(typeof (_208)=="undefined"||_208===null){ +_208=30; +} +var _209=this.getMessages(_208); +if(_209.length){ +var lst=map(function(m){ +return "\n ["+m.num+"] "+m.level+": "+m.info.join(" "); +},_209); +lst.unshift("LAST "+_209.length+" MESSAGES:"); +return lst.join(""); +} +return ""; +},debuggingBookmarklet:function(_210){ +if(typeof (MochiKit.LoggingPane)=="undefined"){ +alert(this.getMessageText()); +}else{ +MochiKit.LoggingPane.createLoggingPane(_210||false); +} +}}; +MochiKit.Logging.__new__=function(){ +this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10}; +var m=MochiKit.Base; +m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage); +var _211=m.partial; +var _212=this.Logger; +var _213=_212.prototype.baseLog; +m.update(this.Logger.prototype,{debug:_211(_213,"DEBUG"),log:_211(_213,"INFO"),error:_211(_213,"ERROR"),fatal:_211(_213,"FATAL"),warning:_211(_213,"WARNING")}); +var self=this; +var _214=function(name){ +return function(){ +self.logger[name].apply(self.logger,arguments); +}; +}; +this.log=_214("log"); +this.logError=_214("error"); +this.logDebug=_214("debug"); +this.logFatal=_214("fatal"); +this.logWarning=_214("warning"); +this.logger=new _212(); +this.logger.useNativeConsole=true; +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){ +printfire=function(){ +printfire.args=arguments; +var ev=document.createEvent("Events"); +ev.initEvent("printfire",false,true); +dispatchEvent(ev); +}; +} +MochiKit.Logging.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.Logging); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.DateTime"); +} +if(typeof (MochiKit)=="undefined"){ +MochiKit={}; +} +if(typeof (MochiKit.DateTime)=="undefined"){ +MochiKit.DateTime={}; +} +MochiKit.DateTime.NAME="MochiKit.DateTime"; +MochiKit.DateTime.VERSION="1.3.1"; +MochiKit.DateTime.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.DateTime.toString=function(){ +return this.__repr__(); +}; +MochiKit.DateTime.isoDate=function(str){ +str=str+""; +if(typeof (str)!="string"||str.length===0){ +return null; +} +var iso=str.split("-"); +if(iso.length===0){ +return null; +} +return new Date(iso[0],iso[1]-1,iso[2]); +}; +MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/; +MochiKit.DateTime.isoTimestamp=function(str){ +str=str+""; +if(typeof (str)!="string"||str.length===0){ +return null; +} +var res=str.match(MochiKit.DateTime._isoRegexp); +if(typeof (res)=="undefined"||res===null){ +return null; +} +var year,month,day,hour,min,sec,msec; +year=parseInt(res[1],10); +if(typeof (res[2])=="undefined"||res[2]===""){ +return new Date(year); +} +month=parseInt(res[2],10)-1; +day=parseInt(res[3],10); +if(typeof (res[4])=="undefined"||res[4]===""){ +return new Date(year,month,day); +} +hour=parseInt(res[4],10); +min=parseInt(res[5],10); +sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0; +if(typeof (res[7])!="undefined"&&res[7]!==""){ +msec=Math.round(1000*parseFloat("0."+res[7])); +}else{ +msec=0; +} +if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){ +return new Date(year,month,day,hour,min,sec,msec); +} +var ofs; +if(typeof (res[9])!="undefined"&&res[9]!==""){ +ofs=parseInt(res[10],10)*3600000; +if(typeof (res[11])!="undefined"&&res[11]!==""){ +ofs+=parseInt(res[11],10)*60000; +} +if(res[9]=="-"){ +ofs=-ofs; +} +}else{ +ofs=0; +} +return new Date(Date.UTC(year,month,day,hour,min,sec,msec)-ofs); +}; +MochiKit.DateTime.toISOTime=function(date,_221){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var hh=date.getHours(); +var mm=date.getMinutes(); +var ss=date.getSeconds(); +var lst=[((_221&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)]; +return lst.join(":"); +}; +MochiKit.DateTime.toISOTimestamp=function(date,_225){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var sep=_225?"T":" "; +var foot=_225?"Z":""; +if(_225){ +date=new Date(date.getTime()+(date.getTimezoneOffset()*60000)); +} +return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_225)+foot; +}; +MochiKit.DateTime.toISODate=function(date){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var _228=MochiKit.DateTime._padTwo; +return [date.getFullYear(),_228(date.getMonth()+1),_228(date.getDate())].join("-"); +}; +MochiKit.DateTime.americanDate=function(d){ +d=d+""; +if(typeof (d)!="string"||d.length===0){ +return null; +} +var a=d.split("/"); +return new Date(a[2],a[0]-1,a[1]); +}; +MochiKit.DateTime._padTwo=function(n){ +return (n>9)?n:"0"+n; +}; +MochiKit.DateTime.toPaddedAmericanDate=function(d){ +if(typeof (d)=="undefined"||d===null){ +return null; +} +var _230=MochiKit.DateTime._padTwo; +return [_230(d.getMonth()+1),_230(d.getDate()),d.getFullYear()].join("/"); +}; +MochiKit.DateTime.toAmericanDate=function(d){ +if(typeof (d)=="undefined"||d===null){ +return null; +} +return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/"); +}; +MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"]; +MochiKit.DateTime.EXPORT_OK=[]; +MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT}; +MochiKit.DateTime.__new__=function(){ +var base=this.NAME+"."; +for(var k in this){ +var o=this[k]; +if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ +try{ +o.NAME=base+k; +} +catch(e){ +} +} +} +}; +MochiKit.DateTime.__new__(); +if(typeof (MochiKit.Base)!="undefined"){ +MochiKit.Base._exportSymbols(this,MochiKit.DateTime); +}else{ +(function(_231,_232){ +if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){ +var all=_232.EXPORT_TAGS[":all"]; +for(var i=0;i_240){ +var i=_246.length-_240; +res=fmt.separator+_246.substring(i,_246.length)+res; +_246=_246.substring(0,i); +} +} +res=_246+res; +if(_238>0){ +while(frac.length<_241){ +frac=frac+"0"; +} +res=res+fmt.decimal+frac; +} +return _242+res+_243; +}; +}; +MochiKit.Format.numberFormatter=function(_248,_249,_250){ +if(typeof (_249)=="undefined"){ +_249=""; +} +var _251=_248.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/); +if(!_251){ +throw TypeError("Invalid pattern"); +} +var _252=_248.substr(0,_251.index); +var _253=_248.substr(_251.index+_251[0].length); +if(_252.search(/-/)==-1){ +_252=_252+"-"; +} +var _254=_251[1]; +var frac=(typeof (_251[2])=="string"&&_251[2]!="")?_251[2]:""; +var _255=(typeof (_251[3])=="string"&&_251[3]!=""); +var tmp=_254.split(/,/); +var _257; +if(typeof (_250)=="undefined"){ +_250="default"; +} +if(tmp.length==1){ +_257=null; +}else{ +_257=tmp[1].length; +} +var _258=_254.length-_254.replace(/0/g,"").length; +var _259=frac.length-frac.replace(/0/g,"").length; +var _260=frac.length; +var rval=MochiKit.Format._numberFormatter(_249,_252,_253,_250,_255,_260,_258,_257,_259); +var m=MochiKit.Base; +if(m){ +var fn=arguments.callee; +var args=m.concat(arguments); +rval.repr=function(){ +return [self.NAME,"(",map(m.repr,args).join(", "),")"].join(""); +}; +} +return rval; +}; +MochiKit.Format.formatLocale=function(_262){ +if(typeof (_262)=="undefined"||_262===null){ +_262="default"; +} +if(typeof (_262)=="string"){ +var rval=MochiKit.Format.LOCALE[_262]; +if(typeof (rval)=="string"){ +rval=arguments.callee(rval); +MochiKit.Format.LOCALE[_262]=rval; +} +return rval; +}else{ +return _262; +} +}; +MochiKit.Format.twoDigitAverage=function(_263,_264){ +if(_264){ +var res=_263/_264; +if(!isNaN(res)){ +return MochiKit.Format.twoDigitFloat(_263/_264); +} +} +return "0"; +}; +MochiKit.Format.twoDigitFloat=function(_265){ +var sign=(_265<0?"-":""); +var s=Math.floor(Math.abs(_265)*100).toString(); +if(s=="0"){ +return s; +} +if(s.length<3){ +while(s.charAt(s.length-1)=="0"){ +s=s.substring(0,s.length-1); +} +return sign+"0."+s; +} +var head=sign+s.substring(0,s.length-2); +var tail=s.substring(s.length-2,s.length); +if(tail=="00"){ +return head; +}else{ +if(tail.charAt(1)=="0"){ +return head+"."+tail.charAt(0); +}else{ +return head+"."+tail; +} +} +}; +MochiKit.Format.lstrip=function(str,_270){ +str=str+""; +if(typeof (str)!="string"){ +return null; +} +if(!_270){ +return str.replace(/^\s+/,""); +}else{ +return str.replace(new RegExp("^["+_270+"]+"),""); +} +}; +MochiKit.Format.rstrip=function(str,_271){ +str=str+""; +if(typeof (str)!="string"){ +return null; +} +if(!_271){ +return str.replace(/\s+$/,""); +}else{ +return str.replace(new RegExp("["+_271+"]+$"),""); +} +}; +MochiKit.Format.strip=function(str,_272){ +var self=MochiKit.Format; +return self.rstrip(self.lstrip(str,_272),_272); +}; +MochiKit.Format.truncToFixed=function(_273,_274){ +_273=Math.floor(_273*Math.pow(10,_274)); +var res=(_273*Math.pow(10,-_274)).toFixed(_274); +if(res.charAt(0)=="."){ +res="0"+res; +} +return res; +}; +MochiKit.Format.roundToFixed=function(_275,_276){ +return MochiKit.Format.truncToFixed(_275+0.5*Math.pow(10,-_276),_276); +}; +MochiKit.Format.percentFormat=function(_277){ +return MochiKit.Format.twoDigitFloat(100*_277)+"%"; +}; +MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"]; +MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"}; +MochiKit.Format.EXPORT_OK=[]; +MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT}; +MochiKit.Format.__new__=function(){ +var base=this.NAME+"."; +var k,v,o; +for(k in this.LOCALE){ +o=this.LOCALE[k]; +if(typeof (o)=="object"){ +o.repr=function(){ +return this.NAME; +}; +o.NAME=base+"LOCALE."+k; +} +} +for(k in this){ +o=this[k]; +if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ +try{ +o.NAME=base+k; +} +catch(e){ +} +} +} +}; +MochiKit.Format.__new__(); +if(typeof (MochiKit.Base)!="undefined"){ +MochiKit.Base._exportSymbols(this,MochiKit.Format); +}else{ +(function(_278,_279){ +if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){ +var all=_279.EXPORT_TAGS[":all"]; +for(var i=0;i=0)){ +this._fire(); +} +},_continue:function(res){ +this._resback(res); +this._unpause(); +},_resback:function(res){ +this.fired=((res instanceof Error)?1:0); +this.results[this.fired]=res; +this._fire(); +},_check:function(){ +if(this.fired!=-1){ +if(!this.silentlyCancelled){ +throw new MochiKit.Async.AlreadyCalledError(this); +} +this.silentlyCancelled=false; +return; +} +},callback:function(res){ +this._check(); +if(res instanceof MochiKit.Async.Deferred){ +throw new Error("Deferred instances can only be chained if they are the result of a callback"); +} +this._resback(res); +},errback:function(res){ +this._check(); +var self=MochiKit.Async; +if(res instanceof self.Deferred){ +throw new Error("Deferred instances can only be chained if they are the result of a callback"); +} +if(!(res instanceof Error)){ +res=new self.GenericError(res); +} +this._resback(res); +},addBoth:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(fn,fn); +},addCallback:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(fn,null); +},addErrback:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(null,fn); +},addCallbacks:function(cb,eb){ +if(this.chained){ +throw new Error("Chained Deferreds can not be re-used"); +} +this.chain.push([cb,eb]); +if(this.fired>=0){ +this._fire(); +} +return this; +},_fire:function(){ +var _284=this.chain; +var _285=this.fired; +var res=this.results[_285]; +var self=this; +var cb=null; +while(_284.length>0&&this.paused===0){ +var pair=_284.shift(); +var f=pair[_285]; +if(f===null){ +continue; +} +try{ +res=f(res); +_285=((res instanceof Error)?1:0); +if(res instanceof MochiKit.Async.Deferred){ +cb=function(res){ +self._continue(res); +}; +this._pause(); +} +} +catch(err){ +_285=1; +if(!(err instanceof Error)){ +err=new MochiKit.Async.GenericError(err); +} +res=err; +} +} +this.fired=_285; +this.results[_285]=res; +if(cb&&this.paused){ +res.addBoth(cb); +res.chained=true; +} +}}; +MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(){ +return eval("("+arguments[0].responseText+")"); +},succeed:function(_287){ +var d=new MochiKit.Async.Deferred(); +d.callback.apply(d,arguments); +return d; +},fail:function(_288){ +var d=new MochiKit.Async.Deferred(); +d.errback.apply(d,arguments); +return d; +},getXMLHttpRequest:function(){ +var self=arguments.callee; +if(!self.XMLHttpRequest){ +var _289=[function(){ +return new XMLHttpRequest(); +},function(){ +return new ActiveXObject("Msxml2.XMLHTTP"); +},function(){ +return new ActiveXObject("Microsoft.XMLHTTP"); +},function(){ +return new ActiveXObject("Msxml2.XMLHTTP.4.0"); +},function(){ +throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); +}]; +for(var i=0;i<_289.length;i++){ +var func=_289[i]; +try{ +self.XMLHttpRequest=func; +return func(); +} +catch(e){ +} +} +} +return self.XMLHttpRequest(); +},_nothing:function(){ +},_xhr_onreadystatechange:function(d){ +if(this.readyState==4){ +try{ +this.onreadystatechange=null; +} +catch(e){ +try{ +this.onreadystatechange=MochiKit.Async._nothing; +} +catch(e){ +} +} +var _290=null; +try{ +_290=this.status; +if(!_290&&MochiKit.Base.isNotEmpty(this.responseText)){ +_290=304; +} +} +catch(e){ +} +if(_290==200||_290==304){ +d.callback(this); +}else{ +var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed"); +if(err.number){ +d.errback(err); +}else{ +d.errback(err); +} +} +} +},_xhr_canceller:function(req){ +try{ +req.onreadystatechange=null; +} +catch(e){ +try{ +req.onreadystatechange=MochiKit.Async._nothing; +} +catch(e){ +} +} +req.abort(); +},sendXMLHttpRequest:function(req,_293){ +if(typeof (_293)=="undefined"||_293===null){ +_293=""; +} +var m=MochiKit.Base; +var self=MochiKit.Async; +var d=new self.Deferred(m.partial(self._xhr_canceller,req)); +try{ +req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d); +req.send(_293); +} +catch(e){ +try{ +req.onreadystatechange=null; +} +catch(ignore){ +} +d.errback(e); +} +return d; +},doSimpleXMLHttpRequest:function(url){ +var self=MochiKit.Async; +var req=self.getXMLHttpRequest(); +if(arguments.length>1){ +var m=MochiKit.Base; +var qs=m.queryString.apply(null,m.extend(null,arguments,1)); +if(qs){ +url+="?"+qs; +} +} +req.open("GET",url,true); +return self.sendXMLHttpRequest(req); +},loadJSONDoc:function(url){ +var self=MochiKit.Async; +var d=self.doSimpleXMLHttpRequest.apply(self,arguments); +d=d.addCallback(self.evalJSONRequest); +return d; +},wait:function(_296,_297){ +var d=new MochiKit.Async.Deferred(); +var m=MochiKit.Base; +if(typeof (_297)!="undefined"){ +d.addCallback(function(){ +return _297; +}); +} +var _298=setTimeout(m.bind("callback",d),Math.floor(_296*1000)); +d.canceller=function(){ +try{ +clearTimeout(_298); +} +catch(e){ +} +}; +return d; +},callLater:function(_299,func){ +var m=MochiKit.Base; +var _300=m.partial.apply(m,m.extend(null,arguments,1)); +return MochiKit.Async.wait(_299).addCallback(function(res){ +return _300(); +}); +}}); +MochiKit.Async.DeferredLock=function(){ +this.waiting=[]; +this.locked=false; +this.id=this._nextId(); +}; +MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){ +d=new MochiKit.Async.Deferred(); +if(this.locked){ +this.waiting.push(d); +}else{ +this.locked=true; +d.callback(this); +} +return d; +},release:function(){ +if(!this.locked){ +throw TypeError("Tried to release an unlocked DeferredLock"); +} +this.locked=false; +if(this.waiting.length>0){ +this.locked=true; +this.waiting.shift().callback(this); +} +},_nextId:MochiKit.Base.counter(),repr:function(){ +var _301; +if(this.locked){ +_301="locked, "+this.waiting.length+" waiting"; +}else{ +_301="unlocked"; +} +return "DeferredLock("+this.id+", "+_301+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +MochiKit.Async.DeferredList=function(list,_303,_304,_305,_306){ +this.list=list; +this.resultList=new Array(this.list.length); +this.chain=[]; +this.id=this._nextId(); +this.fired=-1; +this.paused=0; +this.results=[null,null]; +this.canceller=_306; +this.silentlyCancelled=false; +if(this.list.length===0&&!_303){ +this.callback(this.resultList); +} +this.finishedCount=0; +this.fireOnOneCallback=_303; +this.fireOnOneErrback=_304; +this.consumeErrors=_305; +var _307=0; +MochiKit.Base.map(MochiKit.Base.bind(function(d){ +d.addCallback(MochiKit.Base.bind(this._cbDeferred,this),_307,true); +d.addErrback(MochiKit.Base.bind(this._cbDeferred,this),_307,false); +_307+=1; +},this),this.list); +}; +MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,MochiKit.Async.Deferred.prototype); +MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,{_cbDeferred:function(_308,_309,_310){ +this.resultList[_308]=[_309,_310]; +this.finishedCount+=1; +if(this.fired!==0){ +if(_309&&this.fireOnOneCallback){ +this.callback([_308,_310]); +}else{ +if(!_309&&this.fireOnOneErrback){ +this.errback(_310); +}else{ +if(this.finishedCount==this.list.length){ +this.callback(this.resultList); +} +} +} +} +if(!_309&&this.consumeErrors){ +_310=null; +} +return _310; +}}); +MochiKit.Async.gatherResults=function(_311){ +var d=new MochiKit.Async.DeferredList(_311,false,true,false); +d.addCallback(function(_312){ +var ret=[]; +for(var i=0;i<_312.length;i++){ +ret.push(_312[i][1]); +} +return ret; +}); +return d; +}; +MochiKit.Async.maybeDeferred=function(func){ +var self=MochiKit.Async; +var _313; +try{ +var r=func.apply(null,MochiKit.Base.extend([],arguments,1)); +if(r instanceof self.Deferred){ +_313=r; +}else{ +if(r instanceof Error){ +_313=self.fail(r); +}else{ +_313=self.succeed(r); +} +} +} +catch(e){ +_313=self.fail(e); +} +return _313; +}; +MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred"]; +MochiKit.Async.EXPORT_OK=["evalJSONRequest"]; +MochiKit.Async.__new__=function(){ +var m=MochiKit.Base; +var ne=m.partial(m._newNamedError,this); +ne("AlreadyCalledError",function(_316){ +this.deferred=_316; +}); +ne("CancelledError",function(_317){ +this.deferred=_317; +}); +ne("BrowserComplianceError",function(msg){ +this.message=msg; +}); +ne("GenericError",function(msg){ +this.message=msg; +}); +ne("XMLHttpRequestError",function(req,msg){ +this.req=req; +this.message=msg; +try{ +this.number=req.status; +} +catch(e){ +} +}); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Async.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.Async); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.DOM"); +dojo.require("MochiKit.Iter"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Iter",[]); +} +try{ +if(typeof (MochiKit.Iter)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.DOM depends on MochiKit.Iter!"; +} +if(typeof (MochiKit.DOM)=="undefined"){ +MochiKit.DOM={}; +} +MochiKit.DOM.NAME="MochiKit.DOM"; +MochiKit.DOM.VERSION="1.3.1"; +MochiKit.DOM.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.DOM.toString=function(){ +return this.__repr__(); +}; +MochiKit.DOM.EXPORT=["formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","getNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","replaceChildNodes","removeElement","swapDOM","BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG","getElement","$","computedStyle","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","escapeHTML","toHTML","emitHTML","setDisplayForElement","hideElement","showElement","scrapeText","elementDimensions","elementPosition","setElementDimensions","setElementPosition","getViewportDimensions","setOpacity"]; +MochiKit.DOM.EXPORT_OK=["domConverters"]; +MochiKit.DOM.Dimensions=function(w,h){ +this.w=w; +this.h=h; +}; +MochiKit.DOM.Dimensions.prototype.repr=function(){ +var repr=MochiKit.Base.repr; +return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}"; +}; +MochiKit.DOM.Coordinates=function(x,y){ +this.x=x; +this.y=y; +}; +MochiKit.DOM.Coordinates.prototype.repr=function(){ +var repr=MochiKit.Base.repr; +return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}"; +}; +MochiKit.DOM.Coordinates.prototype.toString=function(){ +return this.repr(); +}; +MochiKit.Base.update(MochiKit.DOM,{setOpacity:function(elem,o){ +elem=MochiKit.DOM.getElement(elem); +MochiKit.DOM.updateNodeAttributes(elem,{"style":{"opacity":o,"-moz-opacity":o,"-khtml-opacity":o,"filter":" alpha(opacity="+(o*100)+")"}}); +},getViewportDimensions:function(){ +var d=new MochiKit.DOM.Dimensions(); +var w=MochiKit.DOM._window; +var b=MochiKit.DOM._document.body; +if(w.innerWidth){ +d.w=w.innerWidth; +d.h=w.innerHeight; +}else{ +if(b.parentElement.clientWidth){ +d.w=b.parentElement.clientWidth; +d.h=b.parentElement.clientHeight; +}else{ +if(b&&b.clientWidth){ +d.w=b.clientWidth; +d.h=b.clientHeight; +} +} +} +return d; +},elementDimensions:function(elem){ +var self=MochiKit.DOM; +if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){ +return new self.Dimensions(elem.w||0,elem.h||0); +} +elem=self.getElement(elem); +if(!elem){ +return undefined; +} +if(self.computedStyle(elem,"display")!="none"){ +return new self.Dimensions(elem.offsetWidth||0,elem.offsetHeight||0); +} +var s=elem.style; +var _322=s.visibility; +var _323=s.position; +s.visibility="hidden"; +s.position="absolute"; +s.display=""; +var _324=elem.offsetWidth; +var _325=elem.offsetHeight; +s.display="none"; +s.position=_323; +s.visibility=_322; +return new self.Dimensions(_324,_325); +},elementPosition:function(elem,_326){ +var self=MochiKit.DOM; +elem=self.getElement(elem); +if(!elem){ +return undefined; +} +var c=new self.Coordinates(0,0); +if(elem.x&&elem.y){ +c.x+=elem.x||0; +c.y+=elem.y||0; +return c; +}else{ +if(elem.parentNode===null||self.computedStyle(elem,"display")=="none"){ +return undefined; +} +} +var box=null; +var _329=null; +var d=MochiKit.DOM._document; +var de=d.documentElement; +var b=d.body; +if(elem.getBoundingClientRect){ +box=elem.getBoundingClientRect(); +c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||b.clientLeft); +c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||b.clientTop); +}else{ +if(d.getBoxObjectFor){ +box=d.getBoxObjectFor(elem); +c.x+=box.x; +c.y+=box.y; +}else{ +if(elem.offsetParent){ +c.x+=elem.offsetLeft; +c.y+=elem.offsetTop; +_329=elem.offsetParent; +if(_329!=elem){ +while(_329){ +c.x+=_329.offsetLeft; +c.y+=_329.offsetTop; +_329=_329.offsetParent; +} +} +var ua=navigator.userAgent.toLowerCase(); +if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("safari")!=-1&&self.computedStyle(elem,"position")=="absolute")){ +c.x-=b.offsetLeft; +c.y-=b.offsetTop; +} +} +} +} +if(typeof (_326)!="undefined"){ +_326=arguments.callee(_326); +if(_326){ +c.x-=(_326.x||0); +c.y-=(_326.y||0); +} +} +if(elem.parentNode){ +_329=elem.parentNode; +}else{ +_329=null; +} +while(_329&&_329.tagName!="BODY"&&_329.tagName!="HTML"){ +c.x-=_329.scrollLeft; +c.y-=_329.scrollTop; +if(_329.parentNode){ +_329=_329.parentNode; +}else{ +_329=null; +} +} +return c; +},setElementDimensions:function(elem,_332,_333){ +elem=MochiKit.DOM.getElement(elem); +if(typeof (_333)=="undefined"){ +_333="px"; +} +MochiKit.DOM.updateNodeAttributes(elem,{"style":{"width":_332.w+_333,"height":_332.h+_333}}); +},setElementPosition:function(elem,_334,_335){ +elem=MochiKit.DOM.getElement(elem); +if(typeof (_335)=="undefined"){ +_335="px"; +} +MochiKit.DOM.updateNodeAttributes(elem,{"style":{"left":_334.x+_335,"top":_334.y+_335}}); +},currentWindow:function(){ +return MochiKit.DOM._window; +},currentDocument:function(){ +return MochiKit.DOM._document; +},withWindow:function(win,func){ +var self=MochiKit.DOM; +var _337=self._document; +var _338=self._win; +var rval; +try{ +self._window=win; +self._document=win.document; +rval=func(); +} +catch(e){ +self._window=_338; +self._document=_337; +throw e; +} +self._window=_338; +self._document=_337; +return rval; +},formContents:function(elem){ +var _339=[]; +var _340=[]; +var m=MochiKit.Base; +var self=MochiKit.DOM; +if(typeof (elem)=="undefined"||elem===null){ +elem=self._document; +}else{ +elem=self.getElement(elem); +} +m.nodeWalk(elem,function(elem){ +var name=elem.name; +if(m.isNotEmpty(name)){ +var _341=elem.nodeName; +if(_341=="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){ +return null; +} +if(_341=="SELECT"){ +if(elem.selectedIndex>=0){ +var opt=elem.options[elem.selectedIndex]; +_339.push(name); +_340.push((opt.value)?opt.value:opt.text); +return null; +} +_339.push(name); +_340.push(""); +return null; +} +if(_341=="FORM"||_341=="P"||_341=="SPAN"||_341=="DIV"){ +return elem.childNodes; +} +_339.push(name); +_340.push(elem.value||""); +return null; +} +return elem.childNodes; +}); +return [_339,_340]; +},withDocument:function(doc,func){ +var self=MochiKit.DOM; +var _344=self._document; +var rval; +try{ +self._document=doc; +rval=func(); +} +catch(e){ +self._document=_344; +throw e; +} +self._document=_344; +return rval; +},registerDOMConverter:function(name,_345,wrap,_346){ +MochiKit.DOM.domConverters.register(name,_345,wrap,_346); +},coerceToDOM:function(node,ctx){ +var im=MochiKit.Iter; +var self=MochiKit.DOM; +var iter=im.iter; +var _350=im.repeat; +var imap=im.imap; +var _352=self.domConverters; +var _353=self.coerceToDOM; +var _354=MochiKit.Base.NotFound; +while(true){ +if(typeof (node)=="undefined"||node===null){ +return null; +} +if(typeof (node.nodeType)!="undefined"&&node.nodeType>0){ +return node; +} +if(typeof (node)=="number"||typeof (node)=="boolean"){ +node=node.toString(); +} +if(typeof (node)=="string"){ +return self._document.createTextNode(node); +} +if(typeof (node.toDOM)=="function"){ +node=node.toDOM(ctx); +continue; +} +if(typeof (node)=="function"){ +node=node(ctx); +continue; +} +var _355=null; +try{ +_355=iter(node); +} +catch(e){ +} +if(_355){ +return imap(_353,_355,_350(ctx)); +} +try{ +node=_352.match(node,ctx); +continue; +} +catch(e){ +if(e!=_354){ +throw e; +} +} +return self._document.createTextNode(node.toString()); +} +return undefined; +},setNodeAttribute:function(node,attr,_357){ +var o={}; +o[attr]=_357; +try{ +return MochiKit.DOM.updateNodeAttributes(node,o); +} +catch(e){ +} +return null; +},getNodeAttribute:function(node,attr){ +var self=MochiKit.DOM; +var _358=self.attributeArray.renames[attr]; +node=self.getElement(node); +try{ +if(_358){ +return node[_358]; +} +return node.getAttribute(attr); +} +catch(e){ +} +return null; +},updateNodeAttributes:function(node,_359){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +} +if(_359){ +var _360=MochiKit.Base.updatetree; +if(self.attributeArray.compliant){ +for(var k in _359){ +var v=_359[k]; +if(typeof (v)=="object"&&typeof (elem[k])=="object"){ +_360(elem[k],v); +}else{ +if(k.substring(0,2)=="on"){ +if(typeof (v)=="string"){ +v=new Function(v); +} +elem[k]=v; +}else{ +elem.setAttribute(k,v); +} +} +} +}else{ +var _361=self.attributeArray.renames; +for(k in _359){ +v=_359[k]; +var _362=_361[k]; +if(k=="style"&&typeof (v)=="string"){ +elem.style.cssText=v; +}else{ +if(typeof (_362)=="string"){ +elem[_362]=v; +}else{ +if(typeof (elem[k])=="object"&&typeof (v)=="object"){ +_360(elem[k],v); +}else{ +if(k.substring(0,2)=="on"){ +if(typeof (v)=="string"){ +v=new Function(v); +} +elem[k]=v; +}else{ +elem.setAttribute(k,v); +} +} +} +} +} +} +} +return elem; +},appendChildNodes:function(node){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +} +var _363=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; +var _364=MochiKit.Base.concat; +while(_363.length){ +var n=_363.shift(); +if(typeof (n)=="undefined"||n===null){ +}else{ +if(typeof (n.nodeType)=="number"){ +elem.appendChild(n); +}else{ +_363=_364(n,_363); +} +} +} +return elem; +},replaceChildNodes:function(node){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +arguments[0]=elem; +} +var _365; +while((_365=elem.firstChild)){ +elem.removeChild(_365); +} +if(arguments.length<2){ +return elem; +}else{ +return self.appendChildNodes.apply(this,arguments); +} +},createDOM:function(name,_366){ +var elem; +var self=MochiKit.DOM; +var m=MochiKit.Base; +if(typeof (_366)=="string"||typeof (_366)=="number"){ +var args=m.extend([name,null],arguments,1); +return arguments.callee.apply(this,args); +} +if(typeof (name)=="string"){ +if(_366&&"name" in _366&&!self.attributeArray.compliant){ +name=("<"+name+" name=\""+self.escapeHTML(_366.name)+"\">"); +} +elem=self._document.createElement(name); +}else{ +elem=name; +} +if(_366){ +self.updateNodeAttributes(elem,_366); +} +if(arguments.length<=2){ +return elem; +}else{ +var args=m.extend([elem],arguments,2); +return self.appendChildNodes.apply(this,args); +} +},createDOMFunc:function(){ +var m=MochiKit.Base; +return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments)); +},swapDOM:function(dest,src){ +var self=MochiKit.DOM; +dest=self.getElement(dest); +var _369=dest.parentNode; +if(src){ +src=self.getElement(src); +_369.replaceChild(src,dest); +}else{ +_369.removeChild(dest); +} +return src; +},getElement:function(id){ +var self=MochiKit.DOM; +if(arguments.length==1){ +return ((typeof (id)=="string")?self._document.getElementById(id):id); +}else{ +return MochiKit.Base.map(self.getElement,arguments); +} +},computedStyle:function(_371,_372,_373){ +if(arguments.length==2){ +_373=_372; +} +var self=MochiKit.DOM; +var el=self.getElement(_371); +var _375=self._document; +if(!el||el==_375){ +return undefined; +} +if(el.currentStyle){ +return el.currentStyle[_372]; +} +if(typeof (_375.defaultView)=="undefined"){ +return undefined; +} +if(_375.defaultView===null){ +return undefined; +} +var _376=_375.defaultView.getComputedStyle(el,null); +if(typeof (_376)=="undefined"||_376===null){ +return undefined; +} +return _376.getPropertyValue(_373); +},getElementsByTagAndClassName:function(_377,_378,_379){ +var self=MochiKit.DOM; +if(typeof (_377)=="undefined"||_377===null){ +_377="*"; +} +if(typeof (_379)=="undefined"||_379===null){ +_379=self._document; +} +_379=self.getElement(_379); +var _380=(_379.getElementsByTagName(_377)||self._document.all); +if(typeof (_378)=="undefined"||_378===null){ +return MochiKit.Base.extend(null,_380); +} +var _381=[]; +for(var i=0;i<_380.length;i++){ +var _382=_380[i]; +var _383=_382.className.split(" "); +for(var j=0;j<_383.length;j++){ +if(_383[j]==_378){ +_381.push(_382); +break; +} +} +} +return _381; +},_newCallStack:function(path,once){ +var rval=function(){ +var _386=arguments.callee.callStack; +for(var i=0;i<_386.length;i++){ +if(_386[i].apply(this,arguments)===false){ +break; +} +} +if(once){ +try{ +this[path]=null; +} +catch(e){ +} +} +}; +rval.callStack=[]; +return rval; +},addToCallStack:function(_387,path,func,once){ +var self=MochiKit.DOM; +var _388=_387[path]; +var _389=_388; +if(!(typeof (_388)=="function"&&typeof (_388.callStack)=="object"&&_388.callStack!==null)){ +_389=self._newCallStack(path,once); +if(typeof (_388)=="function"){ +_389.callStack.push(_388); +} +_387[path]=_389; +} +_389.callStack.push(func); +},addLoadEvent:function(func){ +var self=MochiKit.DOM; +self.addToCallStack(self._window,"onload",func,true); +},focusOnLoad:function(_390){ +var self=MochiKit.DOM; +self.addLoadEvent(function(){ +_390=self.getElement(_390); +if(_390){ +_390.focus(); +} +}); +},setElementClass:function(_391,_392){ +var self=MochiKit.DOM; +var obj=self.getElement(_391); +if(self.attributeArray.compliant){ +obj.setAttribute("class",_392); +}else{ +obj.setAttribute("className",_392); +} +},toggleElementClass:function(_393){ +var self=MochiKit.DOM; +for(var i=1;i/g,">"); +},toHTML:function(dom){ +return MochiKit.DOM.emitHTML(dom).join(""); +},emitHTML:function(dom,lst){ +if(typeof (lst)=="undefined"||lst===null){ +lst=[]; +} +var _409=[dom]; +var self=MochiKit.DOM; +var _410=self.escapeHTML; +var _411=self.attributeArray; +while(_409.length){ +dom=_409.pop(); +if(typeof (dom)=="string"){ +lst.push(dom); +}else{ +if(dom.nodeType==1){ +lst.push("<"+dom.nodeName.toLowerCase()); +var _412=[]; +var _413=_411(dom); +for(var i=0;i<_413.length;i++){ +var a=_413[i]; +_412.push([" ",a.name,"=\"",_410(a.value),"\""]); +} +_412.sort(); +for(i=0;i<_412.length;i++){ +var _414=_412[i]; +for(var j=0;j<_414.length;j++){ +lst.push(_414[j]); +} +} +if(dom.hasChildNodes()){ +lst.push(">"); +_409.push(""); +var _415=dom.childNodes; +for(i=_415.length-1;i>=0;i--){ +_409.push(_415[i]); +} +}else{ +lst.push("/>"); +} +}else{ +if(dom.nodeType==3){ +lst.push(_410(dom.nodeValue)); +} +} +} +} +return lst; +},setDisplayForElement:function(_416,_417){ +var m=MochiKit.Base; +var _418=m.extend(null,arguments,1); +MochiKit.Iter.forEach(m.filter(null,m.map(MochiKit.DOM.getElement,_418)),function(_417){ +_417.style.display=_416; +}); +},scrapeText:function(node,_419){ +var rval=[]; +(function(node){ +var cn=node.childNodes; +if(cn){ +for(var i=0;i0){ +var _424=m.filter; +_423=function(node){ +return _424(_423.ignoreAttrFilter,node.attributes); +}; +_423.ignoreAttr={}; +MochiKit.Iter.forEach(_422.attributes,function(a){ +_423.ignoreAttr[a.name]=a.value; +}); +_423.ignoreAttrFilter=function(a){ +return (_423.ignoreAttr[a.name]!=a.value); +}; +_423.compliant=false; +_423.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor"}; +}else{ +_423=function(node){ +return node.attributes; +}; +_423.compliant=true; +_423.renames={}; +} +this.attributeArray=_423; +var _425=this.createDOMFunc; +this.UL=_425("ul"); +this.OL=_425("ol"); +this.LI=_425("li"); +this.TD=_425("td"); +this.TR=_425("tr"); +this.TBODY=_425("tbody"); +this.THEAD=_425("thead"); +this.TFOOT=_425("tfoot"); +this.TABLE=_425("table"); +this.TH=_425("th"); +this.INPUT=_425("input"); +this.SPAN=_425("span"); +this.A=_425("a"); +this.DIV=_425("div"); +this.IMG=_425("img"); +this.BUTTON=_425("button"); +this.TT=_425("tt"); +this.PRE=_425("pre"); +this.H1=_425("h1"); +this.H2=_425("h2"); +this.H3=_425("h3"); +this.BR=_425("br"); +this.HR=_425("hr"); +this.LABEL=_425("label"); +this.TEXTAREA=_425("textarea"); +this.FORM=_425("form"); +this.P=_425("p"); +this.SELECT=_425("select"); +this.OPTION=_425("option"); +this.OPTGROUP=_425("optgroup"); +this.LEGEND=_425("legend"); +this.FIELDSET=_425("fieldset"); +this.STRONG=_425("strong"); +this.CANVAS=_425("canvas"); +this.hideElement=m.partial(this.setDisplayForElement,"none"); +this.showElement=m.partial(this.setDisplayForElement,"block"); +this.removeElement=this.swapDOM; +this.$=this.getElement; +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}}); +MochiKit.DOM.__new__(((typeof (window)=="undefined")?this:window)); +if(!MochiKit.__compat__){ +withWindow=MochiKit.DOM.withWindow; +withDocument=MochiKit.DOM.withDocument; +} +MochiKit.Base._exportSymbols(this,MochiKit.DOM); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.LoggingPane"); +dojo.require("MochiKit.Logging"); +dojo.require("MochiKit.Base"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Logging",[]); +JSAN.use("MochiKit.Base",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.Logging)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!"; +} +if(typeof (MochiKit.LoggingPane)=="undefined"){ +MochiKit.LoggingPane={}; +} +MochiKit.LoggingPane.NAME="MochiKit.LoggingPane"; +MochiKit.LoggingPane.VERSION="1.3.1"; +MochiKit.LoggingPane.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.LoggingPane.toString=function(){ +return this.__repr__(); +}; +MochiKit.LoggingPane.createLoggingPane=function(_426){ +var m=MochiKit.LoggingPane; +_426=!(!_426); +if(m._loggingPane&&m._loggingPane.inline!=_426){ +m._loggingPane.closePane(); +m._loggingPane=null; +} +if(!m._loggingPane||m._loggingPane.closed){ +m._loggingPane=new m.LoggingPane(_426,MochiKit.Logging.logger); +} +return m._loggingPane; +}; +MochiKit.LoggingPane.LoggingPane=function(_427,_428){ +if(typeof (_428)=="undefined"||_428===null){ +_428=MochiKit.Logging.logger; +} +this.logger=_428; +var _429=MochiKit.Base.update; +var _430=MochiKit.Base.updatetree; +var bind=MochiKit.Base.bind; +var _431=MochiKit.Base.clone; +var win=window; +var uid="_MochiKit_LoggingPane"; +if(typeof (MochiKit.DOM)!="undefined"){ +win=MochiKit.DOM.currentWindow(); +} +if(!_427){ +var url=win.location.href.split("?")[0].replace(/[:\/.><&]/g,"_"); +var name=uid+"_"+url; +var nwin=win.open("",name,"dependent,resizable,height=200"); +if(!nwin){ +alert("Not able to open debugging window due to pop-up blocking."); +return undefined; +} +nwin.document.write(""+"[MochiKit.LoggingPane]"+""); +nwin.document.close(); +nwin.document.title+=" "+win.document.title; +win=nwin; +} +var doc=win.document; +this.doc=doc; +var _434=doc.getElementById(uid); +var _435=!!_434; +if(_434&&typeof (_434.loggingPane)!="undefined"){ +_434.loggingPane.logger=this.logger; +_434.loggingPane.buildAndApplyFilter(); +return _434.loggingPane; +} +if(_435){ +var _436; +while((_436=_434.firstChild)){ +_434.removeChild(_436); +} +}else{ +_434=doc.createElement("div"); +_434.id=uid; +} +_434.loggingPane=this; +var _437=doc.createElement("input"); +var _438=doc.createElement("input"); +var _439=doc.createElement("button"); +var _440=doc.createElement("button"); +var _441=doc.createElement("button"); +var _442=doc.createElement("button"); +var _443=doc.createElement("div"); +var _444=doc.createElement("div"); +var _445=uid+"_Listener"; +this.colorTable=_431(this.colorTable); +var _446=[]; +var _447=null; +var _448=function(msg){ +var _449=msg.level; +if(typeof (_449)=="number"){ +_449=MochiKit.Logging.LogLevel[_449]; +} +return _449; +}; +var _450=function(msg){ +return msg.info.join(" "); +}; +var _451=bind(function(msg){ +var _452=_448(msg); +var text=_450(msg); +var c=this.colorTable[_452]; +var p=doc.createElement("span"); +p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_452; +p.style.cssText="margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: "+c; +p.appendChild(doc.createTextNode(_452+": "+text)); +_444.appendChild(p); +_444.appendChild(doc.createElement("br")); +if(_443.offsetHeight>_443.scrollHeight){ +_443.scrollTop=0; +}else{ +_443.scrollTop=_443.scrollHeight; +} +},this); +var _454=function(msg){ +_446[_446.length]=msg; +_451(msg); +}; +var _455=function(){ +var _456,infore; +try{ +_456=new RegExp(_437.value); +infore=new RegExp(_438.value); +} +catch(e){ +logDebug("Error in filter regex: "+e.message); +return null; +} +return function(msg){ +return (_456.test(_448(msg))&&infore.test(_450(msg))); +}; +}; +var _457=function(){ +while(_444.firstChild){ +_444.removeChild(_444.firstChild); +} +}; +var _458=function(){ +_446=[]; +_457(); +}; +var _459=bind(function(){ +if(this.closed){ +return; +} +this.closed=true; +if(MochiKit.LoggingPane._loggingPane==this){ +MochiKit.LoggingPane._loggingPane=null; +} +this.logger.removeListener(_445); +_434.loggingPane=null; +if(_427){ +_434.parentNode.removeChild(_434); +}else{ +this.win.close(); +} +},this); +var _460=function(){ +_457(); +for(var i=0;i<_446.length;i++){ +var msg=_446[i]; +if(_447===null||_447(msg)){ +_451(msg); +} +} +}; +this.buildAndApplyFilter=function(){ +_447=_455(); +_460(); +this.logger.removeListener(_445); +this.logger.addListener(_445,_447,_454); +}; +var _461=bind(function(){ +_446=this.logger.getMessages(); +_460(); +},this); +var _462=bind(function(_463){ +_463=_463||window.event; +key=_463.which||_463.keyCode; +if(key==13){ +this.buildAndApplyFilter(); +} +},this); +var _464="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont; +if(_427){ +_464+="; height: 10em; border-top: 2px solid black"; +}else{ +_464+="; height: 100%;"; +} +_434.style.cssText=_464; +if(!_435){ +doc.body.appendChild(_434); +} +_464={"cssText":"width: 33%; display: inline; font: "+this.logFont}; +_430(_437,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_462,"style":_464}); +_434.appendChild(_437); +_430(_438,{"value":".*","onkeypress":_462,"style":_464}); +_434.appendChild(_438); +_464="width: 8%; display:inline; font: "+this.logFont; +_439.appendChild(doc.createTextNode("Filter")); +_439.onclick=bind("buildAndApplyFilter",this); +_439.style.cssText=_464; +_434.appendChild(_439); +_440.appendChild(doc.createTextNode("Load")); +_440.onclick=_461; +_440.style.cssText=_464; +_434.appendChild(_440); +_441.appendChild(doc.createTextNode("Clear")); +_441.onclick=_458; +_441.style.cssText=_464; +_434.appendChild(_441); +_442.appendChild(doc.createTextNode("Close")); +_442.onclick=_459; +_442.style.cssText=_464; +_434.appendChild(_442); +_443.style.cssText="overflow: auto; width: 100%"; +_444.style.cssText="width: 100%; height: "+(_427?"8em":"100%"); +_443.appendChild(_444); +_434.appendChild(_443); +this.buildAndApplyFilter(); +_461(); +if(_427){ +this.win=undefined; +}else{ +this.win=win; +} +this.inline=_427; +this.closePane=_459; +this.closed=false; +return this; +}; +MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}}; +MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"]; +MochiKit.LoggingPane.EXPORT=["createLoggingPane"]; +MochiKit.LoggingPane.__new__=function(){ +this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; +MochiKit.Base.nameFunctions(this); +MochiKit.LoggingPane._loggingPane=null; +}; +MochiKit.LoggingPane.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Color"); +dojo.require("MochiKit.Base"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Color depends on MochiKit.Base"; +} +if(typeof (MochiKit.Color)=="undefined"){ +MochiKit.Color={}; +} +MochiKit.Color.NAME="MochiKit.Color"; +MochiKit.Color.VERSION="1.3.1"; +MochiKit.Color.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Color.toString=function(){ +return this.__repr__(); +}; +MochiKit.Color.Color=function(red,_466,blue,_468){ +if(typeof (_468)=="undefined"||_468===null){ +_468=1; +} +this.rgb={r:red,g:_466,b:blue,a:_468}; +}; +MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_469){ +var rgb=this.rgb; +var m=MochiKit.Color; +return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_469); +},colorWithHue:function(hue){ +var hsl=this.asHSL(); +hsl.h=hue; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},colorWithSaturation:function(_473){ +var hsl=this.asHSL(); +hsl.s=_473; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},colorWithLightness:function(_474){ +var hsl=this.asHSL(); +hsl.l=_474; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},darkerColorWithLevel:function(_475){ +var hsl=this.asHSL(); +hsl.l=Math.max(hsl.l-_475,0); +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},lighterColorWithLevel:function(_476){ +var hsl=this.asHSL(); +hsl.l=Math.min(hsl.l+_476,1); +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},blendedColor:function(_477,_478){ +if(typeof (_478)=="undefined"||_478===null){ +_478=0.5; +} +var sf=1-_478; +var s=this.rgb; +var d=_477.rgb; +var df=_478; +return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df)); +},compareRGB:function(_481){ +var a=this.asRGB(); +var b=_481.asRGB(); +return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]); +},isLight:function(){ +return this.asHSL().b>0.5; +},isDark:function(){ +return (!this.isLight()); +},toHSLString:function(){ +var c=this.asHSL(); +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._hslString; +if(!rval){ +var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%"); +var a=c.a; +if(a>=1){ +a=1; +rval="hsl("+mid+")"; +}else{ +if(a<=0){ +a=0; +} +rval="hsla("+mid+","+a+")"; +} +this._hslString=rval; +} +return rval; +},toRGBString:function(){ +var c=this.rgb; +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._rgbString; +if(!rval){ +var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0)); +if(c.a!=1){ +rval="rgba("+mid+","+c.a+")"; +}else{ +rval="rgb("+mid+")"; +} +this._rgbString=rval; +} +return rval; +},asRGB:function(){ +return MochiKit.Base.clone(this.rgb); +},toHexString:function(){ +var m=MochiKit.Color; +var c=this.rgb; +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._hexString; +if(!rval){ +rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255))); +this._hexString=rval; +} +return rval; +},asHSV:function(){ +var hsv=this.hsv; +var c=this.rgb; +if(typeof (hsv)=="undefined"||hsv===null){ +hsv=MochiKit.Color.rgbToHSV(this.rgb); +this.hsv=hsv; +} +return MochiKit.Base.clone(hsv); +},asHSL:function(){ +var hsl=this.hsl; +var c=this.rgb; +if(typeof (hsl)=="undefined"||hsl===null){ +hsl=MochiKit.Color.rgbToHSL(this.rgb); +this.hsl=hsl; +} +return MochiKit.Base.clone(hsl); +},toString:function(){ +return this.toRGBString(); +},repr:function(){ +var c=this.rgb; +var col=[c.r,c.g,c.b,c.a]; +return this.__class__.NAME+"("+col.join(", ")+")"; +}}; +MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_486,blue,_487){ +var _488=MochiKit.Color.Color; +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_486=rgb.g; +blue=rgb.b; +if(typeof (rgb.a)=="undefined"){ +_487=undefined; +}else{ +_487=rgb.a; +} +} +return new _488(red,_486,blue,_487); +},fromHSL:function(hue,_489,_490,_491){ +var m=MochiKit.Color; +return m.Color.fromRGB(m.hslToRGB.apply(m,arguments)); +},fromHSV:function(hue,_492,_493,_494){ +var m=MochiKit.Color; +return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments)); +},fromName:function(name){ +var _495=MochiKit.Color.Color; +if(name.charAt(0)=="\""){ +name=name.substr(1,name.length-2); +} +var _496=_495._namedColors[name.toLowerCase()]; +if(typeof (_496)=="string"){ +return _495.fromHexString(_496); +}else{ +if(name=="transparent"){ +return _495.transparentColor(); +} +} +return null; +},fromString:function(_497){ +var self=MochiKit.Color.Color; +var _498=_497.substr(0,3); +if(_498=="rgb"){ +return self.fromRGBString(_497); +}else{ +if(_498=="hsl"){ +return self.fromHSLString(_497); +}else{ +if(_497.charAt(0)=="#"){ +return self.fromHexString(_497); +} +} +} +return self.fromName(_497); +},fromHexString:function(_499){ +if(_499.charAt(0)=="#"){ +_499=_499.substring(1); +} +var _500=[]; +var i,hex; +if(_499.length==3){ +for(i=0;i<3;i++){ +hex=_499.substr(i,1); +_500.push(parseInt(hex+hex,16)/255); +} +}else{ +for(i=0;i<6;i+=2){ +hex=_499.substr(i,2); +_500.push(parseInt(hex,16)/255); +} +} +var _501=MochiKit.Color.Color; +return _501.fromRGB.apply(_501,_500); +},_fromColorString:function(pre,_503,_504,_505){ +if(_505.indexOf(pre)===0){ +_505=_505.substring(_505.indexOf("(",3)+1,_505.length-1); +} +var _506=_505.split(/\s*,\s*/); +var _507=[]; +for(var i=0;i<_506.length;i++){ +var c=_506[i]; +var val; +var _508=c.substring(c.length-3); +if(c.charAt(c.length-1)=="%"){ +val=0.01*parseFloat(c.substring(0,c.length-1)); +}else{ +if(_508=="deg"){ +val=parseFloat(c)/360; +}else{ +if(_508=="rad"){ +val=parseFloat(c)/(Math.PI*2); +}else{ +val=_504[i]*parseFloat(c); +} +} +} +_507.push(val); +} +return this[_503].apply(this,_507); +},fromComputedStyle:function(elem,_509,_510){ +var d=MochiKit.DOM; +var cls=MochiKit.Color.Color; +for(elem=d.getElement(elem);elem;elem=elem.parentNode){ +var _511=d.computedStyle.apply(d,arguments); +if(!_511){ +continue; +} +var _512=cls.fromString(_511); +if(!_512){ +break; +} +if(_512.asRGB().a>0){ +return _512; +} +} +return null; +},fromBackground:function(elem){ +var cls=MochiKit.Color.Color; +return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor(); +},fromText:function(elem){ +var cls=MochiKit.Color.Color; +return cls.fromComputedStyle(elem,"color","color")||cls.blackColor(); +},namedColors:function(){ +return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); +}}); +MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_513){ +v*=_513; +if(v<0){ +return 0; +}else{ +if(v>_513){ +return _513; +}else{ +return v; +} +} +},_hslValue:function(n1,n2,hue){ +if(hue>6){ +hue-=6; +}else{ +if(hue<0){ +hue+=6; +} +} +var val; +if(hue<1){ +val=n1+(n2-n1)*hue; +}else{ +if(hue<3){ +val=n2; +}else{ +if(hue<4){ +val=n1+(n2-n1)*(4-hue); +}else{ +val=n1; +} +} +} +return val; +},hsvToRGB:function(hue,_516,_517,_518){ +if(arguments.length==1){ +var hsv=hue; +hue=hsv.h; +_516=hsv.s; +_517=hsv.v; +_518=hsv.a; +} +var red; +var _519; +var blue; +if(_516===0){ +red=0; +_519=0; +blue=0; +}else{ +var i=Math.floor(hue*6); +var f=(hue*6)-i; +var p=_517*(1-_516); +var q=_517*(1-(_516*f)); +var t=_517*(1-(_516*(1-f))); +switch(i){ +case 1: +red=q; +_519=_517; +blue=p; +break; +case 2: +red=p; +_519=_517; +blue=t; +break; +case 3: +red=p; +_519=q; +blue=_517; +break; +case 4: +red=t; +_519=p; +blue=_517; +break; +case 5: +red=_517; +_519=p; +blue=q; +break; +case 6: +case 0: +red=_517; +_519=t; +blue=p; +break; +} +} +return {r:red,g:_519,b:blue,a:_518}; +},hslToRGB:function(hue,_521,_522,_523){ +if(arguments.length==1){ +var hsl=hue; +hue=hsl.h; +_521=hsl.s; +_522=hsl.l; +_523=hsl.a; +} +var red; +var _524; +var blue; +if(_521===0){ +red=_522; +_524=_522; +blue=_522; +}else{ +var m2; +if(_522<=0.5){ +m2=_522*(1+_521); +}else{ +m2=_522+_521-(_522*_521); +} +var m1=(2*_522)-m2; +var f=MochiKit.Color._hslValue; +var h6=hue*6; +red=f(m1,m2,h6+2); +_524=f(m1,m2,h6); +blue=f(m1,m2,h6-2); +} +return {r:red,g:_524,b:blue,a:_523}; +},rgbToHSV:function(red,_528,blue,_529){ +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_528=rgb.g; +blue=rgb.b; +_529=rgb.a; +} +var max=Math.max(Math.max(red,_528),blue); +var min=Math.min(Math.min(red,_528),blue); +var hue; +var _532; +var _533=max; +if(min==max){ +hue=0; +_532=0; +}else{ +var _534=(max-min); +_532=_534/max; +if(red==max){ +hue=(_528-blue)/_534; +}else{ +if(_528==max){ +hue=2+((blue-red)/_534); +}else{ +hue=4+((red-_528)/_534); +} +} +hue/=6; +if(hue<0){ +hue+=1; +} +if(hue>1){ +hue-=1; +} +} +return {h:hue,s:_532,v:_533,a:_529}; +},rgbToHSL:function(red,_535,blue,_536){ +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_535=rgb.g; +blue=rgb.b; +_536=rgb.a; +} +var max=Math.max(red,Math.max(_535,blue)); +var min=Math.min(red,Math.min(_535,blue)); +var hue; +var _537; +var _538=(max+min)/2; +var _539=max-min; +if(_539===0){ +hue=0; +_537=0; +}else{ +if(_538<=0.5){ +_537=_539/(max+min); +}else{ +_537=_539/(2-max-min); +} +if(red==max){ +hue=(_535-blue)/_539; +}else{ +if(_535==max){ +hue=2+((blue-red)/_539); +}else{ +hue=4+((red-_535)/_539); +} +} +hue/=6; +if(hue<0){ +hue+=1; +} +if(hue>1){ +hue-=1; +} +} +return {h:hue,s:_537,l:_538,a:_536}; +},toColorPart:function(num){ +num=Math.round(num); +var _540=num.toString(16); +if(num<16){ +return "0"+_540; +} +return _540; +},__new__:function(){ +var m=MochiKit.Base; +this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]); +this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]); +var _541=1/3; +var _542={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_541,_541,_541],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_541,2*_541,2*_541],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]}; +var _543=function(name,r,g,b,a){ +var rval=this.fromRGB(r,g,b,a); +this[name]=function(){ +return rval; +}; +return rval; +}; +for(var k in _542){ +var name=k+"Color"; +var _545=m.concat([_543,this.Color,name],_542[k]); +this.Color[name]=m.bind.apply(null,_545); +} +var _546=function(){ +for(var i=0;i1){ +var src=MochiKit.DOM.getElement(arguments[0]); +var sig=arguments[1]; +var obj=arguments[2]; +var func=arguments[3]; +for(var i=_562.length-1;i>=0;i--){ +var o=_562[i]; +if(o[0]===src&&o[1]===sig&&o[4]===obj&&o[5]===func){ +self._disconnect(o); +_562.splice(i,1); +return true; +} +} +}else{ +var idx=m.findIdentical(_562,_561); +if(idx>=0){ +self._disconnect(_561); +_562.splice(idx,1); +return true; +} +} +return false; +},disconnectAll:function(src,sig){ +src=MochiKit.DOM.getElement(src); +var m=MochiKit.Base; +var _563=m.flattenArguments(m.extend(null,arguments,1)); +var self=MochiKit.Signal; +var _564=self._disconnect; +var _565=self._observers; +if(_563.length===0){ +for(var i=_565.length-1;i>=0;i--){ +var _566=_565[i]; +if(_566[0]===src){ +_564(_566); +_565.splice(i,1); +} +} +}else{ +var sigs={}; +for(var i=0;i<_563.length;i++){ +sigs[_563[i]]=true; +} +for(var i=_565.length-1;i>=0;i--){ +var _566=_565[i]; +if(_566[0]===src&&_566[1] in sigs){ +_564(_566); +_565.splice(i,1); +} +} +} +},signal:function(src,sig){ +var _568=MochiKit.Signal._observers; +src=MochiKit.DOM.getElement(src); +var args=MochiKit.Base.extend(null,arguments,2); +var _569=[]; +for(var i=0;i<_568.length;i++){ +var _570=_568[i]; +if(_570[0]===src&&_570[1]===sig){ +try{ +_570[2].apply(src,args); +} +catch(e){ +_569.push(e); +} +} +} +if(_569.length==1){ +throw _569[0]; +}else{ +if(_569.length>1){ +var e=new Error("Multiple errors thrown in handling 'sig', see errors property"); +e.errors=_569; +throw e; +} +} +}}); +MochiKit.Signal.EXPORT_OK=[]; +MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll"]; +MochiKit.Signal.__new__=function(win){ +var m=MochiKit.Base; +this._document=document; +this._window=win; +try{ +this.connect(window,"onunload",this._unloadCache); +} +catch(e){ +} +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Signal.__new__(this); +if(!MochiKit.__compat__){ +connect=MochiKit.Signal.connect; +disconnect=MochiKit.Signal.disconnect; +disconnectAll=MochiKit.Signal.disconnectAll; +signal=MochiKit.Signal.signal; +} +MochiKit.Base._exportSymbols(this,MochiKit.Signal); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Visual"); +dojo.require("MochiKit.Base"); +dojo.require("MochiKit.DOM"); +dojo.require("MochiKit.Color"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +JSAN.use("MochiKit.DOM",[]); +JSAN.use("MochiKit.Color",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM and MochiKit.Color!"; +} +if(typeof (MochiKit.Visual)=="undefined"){ +MochiKit.Visual={}; +} +MochiKit.Visual.NAME="MochiKit.Visual"; +MochiKit.Visual.VERSION="1.3.1"; +MochiKit.Visual.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Visual.toString=function(){ +return this.__repr__(); +}; +MochiKit.Visual._RoundCorners=function(e,_571){ +e=MochiKit.DOM.getElement(e); +this._setOptions(_571); +if(this.options.__unstable__wrapElement){ +e=this._doWrap(e); +} +var _572=this.options.color; +var C=MochiKit.Color.Color; +if(this.options.color=="fromElement"){ +_572=C.fromBackground(e); +}else{ +if(!(_572 instanceof C)){ +_572=C.fromString(_572); +} +} +this.isTransparent=(_572.asRGB().a<=0); +var _574=this.options.bgColor; +if(this.options.bgColor=="fromParent"){ +_574=C.fromBackground(e.offsetParent); +}else{ +if(!(_574 instanceof C)){ +_574=C.fromString(_574); +} +} +this._roundCornersImpl(e,_572,_574); +}; +MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){ +var _575=e.parentNode; +var doc=MochiKit.DOM.currentDocument(); +if(typeof (doc.defaultView)=="undefined"||doc.defaultView===null){ +return e; +} +var _576=doc.defaultView.getComputedStyle(e,null); +if(typeof (_576)=="undefined"||_576===null){ +return e; +} +var _577=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_576.getPropertyValue("padding-top"),marginRight:_576.getPropertyValue("padding-right"),marginBottom:_576.getPropertyValue("padding-bottom"),marginLeft:_576.getPropertyValue("padding-left"),padding:"0px"}}); +_577.innerHTML=e.innerHTML; +e.innerHTML=""; +e.appendChild(_577); +return e; +},_roundCornersImpl:function(e,_578,_579){ +if(this.options.border){ +this._renderBorder(e,_579); +} +if(this._isTopRounded()){ +this._roundTopCorners(e,_578,_579); +} +if(this._isBottomRounded()){ +this._roundBottomCorners(e,_578,_579); +} +},_renderBorder:function(el,_580){ +var _581="1px solid "+this._borderColor(_580); +var _582="border-left: "+_581; +var _583="border-right: "+_581; +var _584="style='"+_582+";"+_583+"'"; +el.innerHTML="
"+el.innerHTML+"
"; +},_roundTopCorners:function(el,_585,_586){ +var _587=this._createCorner(_586); +for(var i=0;i=0;i--){ +_590.appendChild(this._createCornerSlice(_588,_589,i,"bottom")); +} +el.style.paddingBottom=0; +el.appendChild(_590); +},_createCorner:function(_591){ +var dom=MochiKit.DOM; +return dom.DIV({style:{backgroundColor:_591.toString()}}); +},_createCornerSlice:function(_592,_593,n,_594){ +var _595=MochiKit.DOM.SPAN(); +var _596=_595.style; +_596.backgroundColor=_592.toString(); +_596.display="block"; +_596.height="1px"; +_596.overflow="hidden"; +_596.fontSize="1px"; +var _597=this._borderColor(_592,_593); +if(this.options.border&&n===0){ +_596.borderTopStyle="solid"; +_596.borderTopWidth="1px"; +_596.borderLeftWidth="0px"; +_596.borderRightWidth="0px"; +_596.borderBottomWidth="0px"; +_596.height="0px"; +_596.borderColor=_597.toString(); +}else{ +if(_597){ +_596.borderColor=_597.toString(); +_596.borderStyle="solid"; +_596.borderWidth="0px 1px"; +} +} +if(!this.options.compact&&(n==(this.options.numSlices-1))){ +_596.height="2px"; +} +this._setMargin(_595,n,_594); +this._setBorder(_595,n,_594); +return _595; +},_setOptions:function(_598){ +this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false}; +MochiKit.Base.update(this.options,_598); +this.options.numSlices=(this.options.compact?2:4); +},_whichSideTop:function(){ +var _599=this.options.corners; +if(this._hasString(_599,"all","top")){ +return ""; +} +var _600=(_599.indexOf("tl")!=-1); +var _601=(_599.indexOf("tr")!=-1); +if(_600&&_601){ +return ""; +} +if(_600){ +return "left"; +} +if(_601){ +return "right"; +} +return ""; +},_whichSideBottom:function(){ +var _602=this.options.corners; +if(this._hasString(_602,"all","bottom")){ +return ""; +} +var _603=(_602.indexOf("bl")!=-1); +var _604=(_602.indexOf("br")!=-1); +if(_603&&_604){ +return ""; +} +if(_603){ +return "left"; +} +if(_604){ +return "right"; +} +return ""; +},_borderColor:function(_605,_606){ +if(_605=="transparent"){ +return _606; +}else{ +if(this.options.border){ +return this.options.border; +}else{ +if(this.options.blend){ +return _606.blendedColor(_605); +} +} +} +return ""; +},_setMargin:function(el,n,_607){ +var _608=this._marginSize(n)+"px"; +var _609=(_607=="top"?this._whichSideTop():this._whichSideBottom()); +var _610=el.style; +if(_609=="left"){ +_610.marginLeft=_608; +_610.marginRight="0px"; +}else{ +if(_609=="right"){ +_610.marginRight=_608; +_610.marginLeft="0px"; +}else{ +_610.marginLeft=_608; +_610.marginRight=_608; +} +} +},_setBorder:function(el,n,_611){ +var _612=this._borderSize(n)+"px"; +var _613=(_611=="top"?this._whichSideTop():this._whichSideBottom()); +var _614=el.style; +if(_613=="left"){ +_614.borderLeftWidth=_612; +_614.borderRightWidth="0px"; +}else{ +if(_613=="right"){ +_614.borderRightWidth=_612; +_614.borderLeftWidth="0px"; +}else{ +_614.borderLeftWidth=_612; +_614.borderRightWidth=_612; +} +} +},_marginSize:function(n){ +if(this.isTransparent){ +return 0; +} +var o=this.options; +if(o.compact&&o.blend){ +var _615=[1,0]; +return _615[n]; +}else{ +if(o.compact){ +var _616=[2,1]; +return _616[n]; +}else{ +if(o.blend){ +var _617=[3,2,1,0]; +return _617[n]; +}else{ +var _618=[5,3,2,1]; +return _618[n]; +} +} +} +},_borderSize:function(n){ +var o=this.options; +var _619; +if(o.compact&&(o.blend||this.isTransparent)){ +return 1; +}else{ +if(o.compact){ +_619=[1,0]; +}else{ +if(o.blend){ +_619=[2,1,1,1]; +}else{ +if(o.border){ +_619=[0,2,0,0]; +}else{ +if(this.isTransparent){ +_619=[5,3,2,1]; +}else{ +return 0; +} +} +} +} +} +return _619[n]; +},_hasString:function(str){ +for(var i=1;i"); +} +} +})(); +} diff --git a/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/PlotKit.js b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/PlotKit.js new file mode 100644 index 0000000..363042a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/htdocs/luci-static/resources/livestats/PlotKit.js @@ -0,0 +1,2177 @@ +/*** + + PlotKit.PlotKit 0.9.1 : PACKED VERSION + + THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please + diff against the source tree, not this file. + + For more information, . + + Copyright (c) 2006. Alastair Tse. + +***/ + +try{ +if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"||typeof (MochiKit.Format)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format}"; +} +MochiKit.Base.update(MochiKit.Color.Color.prototype,{asFillColor:function(){ +return this.lighterColorWithLevel(0.3); +},asStrokeColor:function(){ +return this.darkerColorWithLevel(0.1); +},asPointColor:function(){ +return this.lighterColorWithLevel(0.1); +}}); +if(typeof (PlotKit)=="undefined"){ +PlotKit={}; +} +PlotKit.NAME="PlotKit"; +PlotKit.VERSION="0.8"; +PlotKit.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.toString=function(){ +return this.__repr__(); +}; +if(typeof (PlotKit.Base)=="undefined"){ +PlotKit.Base={}; +} +PlotKit.Base.NAME="PlotKit.Base"; +PlotKit.Base.VERSION=PlotKit.VERSION; +PlotKit.Base.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.Base.toString=function(){ +return this.__repr__(); +}; +PlotKit.Base.usingPrototype=function(){ +try{ +return (typeof (Object.extend)=="function"); +} +catch(e){ +return false; +} +}; +MochiKit.Base.update(PlotKit.Base,{roundInterval:function(_1,_2,_3){ +var _4=MochiKit.Format.roundToFixed; +var _5=_1/_2; +return parseFloat(_4(_5,_3)); +},collapse:function(_6){ +var m=MochiKit.Base; +var _8=new Array(); +for(var i=0;i<_6.length;i++){ +_8=m.concat(_8,_6[i]); +} +if(PlotKit.Base.usingPrototype()){ +delete _8.extend; +delete _8.from; +delete _8.inspect; +} +return _8; +},uniq:function(_10){ +var m=MochiKit.Base; +if(!m.isArrayLike(_10)||(_10.length<1)){ +return new Array(); +} +var _11=new Array(); +var _12=_10[0]; +_11.push(_10[0]); +for(var i=1;i<_10.length;i++){ +if(m.compare(_10[i],_12)!=0){ +_12=_10[i]; +_11.push(_10[i]); +} +} +return _11; +},colorScheme:function(){ +var mb=MochiKit.Base; +var mc=MochiKit.Color; +var _15=["red","orange","yellow","green","cyan","blue","purple","magenta"]; +var _16=function(_17){ +return mc.Color[_17+"Color"](); +}; +return mb.map(_16,_15); +},baseDarkPrimaryColors:function(){ +var _18=MochiKit.Color.Color.fromHexString; +return [_18("#ad3f40"),_18("#ddac2c"),_18("#dfdd0c"),_18("#5276c4"),_18("#739c5a")]; +},basePrimaryColors:function(){ +var _19=MochiKit.Color.Color.fromHexString; +return [_19("#d24c4d"),_19("#f2b32f"),_19("#ece90e"),_19("#5d83da"),_19("#78a15d")]; +},baseBlueColors:function(){ +var _20=MochiKit.Color.Color.fromHexString; +return [_20("#4b6b94"),_20("#5d81b4"),_20("#acbad2")]; +},palette:function(_21,_22,_23,_24){ +var _25=MochiKit.Base.isUndefinedOrNull; +var _26=new Array(); +if(_25(_24)){ +_24=0.1; +} +if(_25(_23)){ +_23=0.4; +} +if(_25(_22)){ +_22=-0.2; +} +var _27=_22; +while(_27<=_23){ +_26.push(_27); +_27+=_24; +} +var _28=function(_29,_30){ +return _29.lighterColorWithLevel(_30); +}; +return MochiKit.Base.map(partial(_28,_21),_26); +},excanvasSupported:function(){ +if(/MSIE/.test(navigator.userAgent)&&!window.opera){ +return true; +} +return false; +},findPosX:function(obj){ +var _32=0; +if(obj.offsetParent){ +while(obj.offsetParent){ +_32+=obj.offsetLeft; +obj=obj.offsetParent; +} +}else{ +if(obj.x){ +_32+=obj.x; +} +} +return _32; +},findPosY:function(obj){ +var _33=0; +if(obj.offsetParent){ +while(obj.offsetParent){ +_33+=obj.offsetTop; +obj=obj.offsetParent; +} +}else{ +if(obj.y){ +_33+=obj.y; +} +} +return _33; +},isFuncLike:function(obj){ +return (typeof (obj)=="function"); +}}); +PlotKit.Base.map=function(fn,lst){ +if(PlotKit.Base.usingPrototype()){ +var _36=[]; +for(var x in lst){ +if(typeof (lst[x])=="function"){ +continue; +} +_36.push(fn(lst[x])); +} +return _36; +}else{ +return MochiKit.Base.map(fn,lst); +} +}; +PlotKit.Base.items=function(lst){ +if(PlotKit.Base.usingPrototype()){ +var _38=[]; +for(var x in lst){ +if(typeof (lst[x])=="function"){ +continue; +} +_38.push([x,lst[x]]); +} +return _38; +}else{ +return MochiKit.Base.items(lst); +} +}; +PlotKit.Base.keys=function(lst){ +if(PlotKit.Base.usingPrototype()){ +var _39=[]; +for(var x in lst){ +if(typeof (lst[x])=="function"){ +continue; +} +_39.push(x); +} +return _39; +}else{ +return MochiKit.Base.keys(lst); +} +}; +PlotKit.Base.baseColors=function(){ +var _40=MochiKit.Color.Color.fromHexString; +return [_40("#476fb2"),_40("#be2c2b"),_40("#85b730"),_40("#734a99"),_40("#26a1c5"),_40("#fb8707"),_40("#000000")]; +}; +PlotKit.Base.officeBaseStyle={"axisLineWidth":2,"axisLabelColor":Color.grayColor(),"axisLineColor":Color.whiteColor(),"padding":{top:5,bottom:10,left:30,right:30}}; +MochiKit.Base.update(PlotKit.Base,{officeBlue:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"backgroundColor":PlotKit.Base.baseColors()[0].lighterColorWithLevel(0.45)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeRed:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),"backgroundColor":PlotKit.Base.baseColors()[1].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeGreen:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[2]),"backgroundColor":PlotKit.Base.baseColors()[2].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officePurple:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[3]),"backgroundColor":PlotKit.Base.baseColors()[3].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeCyan:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[4]),"backgroundColor":PlotKit.Base.baseColors()[4].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeOrange:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[5]),"backgroundColor":PlotKit.Base.baseColors()[5].lighterColorWithLevel(0.4)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeBlack:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[6],0,0.6),"backgroundColor":PlotKit.Base.baseColors()[6].lighterColorWithLevel(0.9)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +}}); +PlotKit.Base.EXPORT=["baseColors","collapse","colorScheme","findPosX","findPosY","officeBaseStyle","officeBlue","officeRed","officeGreen","officePurple","officeCyan","officeOrange","officeBlack","roundInterval","uniq","isFuncLike","excanvasSupported"]; +PlotKit.Base.EXPORT_OK=[]; +PlotKit.Base.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.Base.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.Base); +try{ +if(typeof (PlotKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Base"; +} +if(typeof (PlotKit.Layout)=="undefined"){ +PlotKit.Layout={}; +} +PlotKit.Layout.NAME="PlotKit.Layout"; +PlotKit.Layout.VERSION=PlotKit.VERSION; +PlotKit.Layout.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.Layout.toString=function(){ +return this.__repr__(); +}; +PlotKit.Layout.valid_styles=["bar","line","pie","point"]; +PlotKit.Layout=function(_42,_43){ +this.options={"barWidthFillFraction":0.75,"barOrientation":"vertical","xOriginIsZero":true,"yOriginIsZero":true,"xAxis":null,"yAxis":null,"xTicks":null,"yTicks":null,"xNumberOfTicks":10,"yNumberOfTicks":5,"xTickPrecision":1,"yTickPrecision":1,"pieRadius":0.4}; +this.style=_42; +MochiKit.Base.update(this.options,_43?_43:{}); +if(!MochiKit.Base.isUndefinedOrNull(this.options.xAxis)){ +this.minxval=this.options.xAxis[0]; +this.maxxval=this.options.xAxis[1]; +this.xscale=this.maxxval-this.minxval; +}else{ +this.minxval=0; +this.maxxval=null; +this.xscale=null; +} +if(!MochiKit.Base.isUndefinedOrNull(this.options.yAxis)){ +this.minyval=this.options.yAxis[0]; +this.maxyval=this.options.yAxis[1]; +this.yscale=this.maxyval-this.minyval; +}else{ +this.minyval=0; +this.maxyval=null; +this.yscale=null; +} +this.bars=new Array(); +this.points=new Array(); +this.slices=new Array(); +this.xticks=new Array(); +this.yticks=new Array(); +this.datasets=new Array(); +this.minxdelta=0; +this.xrange=1; +this.yrange=1; +this.hitTestCache={x2maxy:null}; +}; +PlotKit.Layout.prototype.addDataset=function(_44,_45){ +this.datasets[_44]=_45; +}; +PlotKit.Layout.prototype.removeDataset=function(_46,_47){ +delete this.datasets[_46]; +}; +PlotKit.Layout.prototype.addDatasetFromTable=function(_48,_49,_50,_51,_52){ +var _53=MochiKit.Base.isUndefinedOrNull; +var _54=MochiKit.DOM.scrapeText; +var _55=MochiKit.Format.strip; +if(_53(_50)){ +_50=0; +} +if(_53(_51)){ +_51=1; +} +if(_53(_52)){ +_52=-1; +} +var _56=_49.tBodies[0].rows; +var _57=new Array(); +var _58=new Array(); +if(!_53(_56)){ +for(var i=0;i<_56.length;i++){ +_57.push([parseFloat(_55(_54(_56[i].cells[_50]))),parseFloat(_55(_54(_56[i].cells[_51])))]); +if(_52>=0){ +_58.push({v:parseFloat(_55(_54(_56[i].cells[_50]))),label:_55(_54(_56[i].cells[_52]))}); +} +} +this.addDataset(_48,_57); +if(_52>=0){ +this.options.xTicks=_58; +} +return true; +} +return false; +}; +PlotKit.Layout.prototype.evaluate=function(){ +this._evaluateLimits(); +this._evaluateScales(); +if(this.style=="bar"){ +if(this.options.barOrientation=="horizontal"){ +this._evaluateHorizBarCharts(); +}else{ +this._evaluateBarCharts(); +} +this._evaluateBarTicks(); +}else{ +if(this.style=="line"){ +this._evaluateLineCharts(); +this._evaluateLineTicks(); +}else{ +if(this.style=="pie"){ +this._evaluatePieCharts(); +this._evaluatePieTicks(); +} +} +} +}; +PlotKit.Layout.prototype.hitTest=function(x,y){ +var f=MochiKit.Format.twoDigitFloat; +if((this.style=="bar")&&this.bars&&(this.bars.length>0)){ +for(var i=0;i=bar.x)&&(x<=bar.x+bar.w)&&(y>=bar.y)&&(y-bar.y<=bar.h)){ +return bar; +} +} +}else{ +if(this.style=="line"){ +if(this.hitTestCache.x2maxy==null){ +this._regenerateHitTestCache(); +} +var _62=x/this.xscale; +var _63=this.hitTestCache.xvalues; +var _64=null; +var _65=null; +for(var i=1;i<_63.length;i++){ +if(_63[i]>_62){ +_64=_63[i-1]; +_65=_63[i]; +break; +} +} +if((_64!=null)){ +var _66=this.hitTestCache.x2maxy[_64]; +var _67=this.hitTestCache.x2maxy[_65]; +var _68=(1-y)/this.yscale; +var _69=(_67-_66)/(_65-_64); +var _70=_66+_69*(_62-_64); +if(_70>=_68){ +var obj={xval:_62,yval:_68,xafter:_65,yafter:_67,xbefore:_64,ybefore:_66,yprojected:_70}; +return obj; +} +} +}else{ +if(this.style=="pie"){ +var _71=Math.sqrt((y-0.5)*(y-0.5)+(x-0.5)*(x-0.5)); +if(_71>this.options.pieRadius){ +return null; +} +var _72=Math.atan2(y-0.5,x-0.5)-Math.PI/2; +for(var i=0;i=_72){ +return _73; +} +} +} +} +} +return null; +}; +PlotKit.Layout.prototype.rectForX=function(x){ +return null; +}; +PlotKit.Layout.prototype.angleRangeForX=function(x){ +return null; +}; +PlotKit.Layout.prototype._evaluateLimits=function(){ +var map=PlotKit.Base.map; +var _75=PlotKit.Base.items; +var _76=MochiKit.Base.itemgetter; +var _77=PlotKit.Base.collapse; +var _78=MochiKit.Base.listMin; +var _79=MochiKit.Base.listMax; +var _80=MochiKit.Base.isUndefinedOrNull; +var all=_77(map(_76(1),_75(this.datasets))); +if(_80(this.options.xAxis)){ +if(this.options.xOriginIsZero){ +this.minxval=0; +}else{ +this.minxval=_78(map(parseFloat,map(_76(0),all))); +} +this.maxxval=_79(map(parseFloat,map(_76(0),all))); +}else{ +this.minxval=this.options.xAxis[0]; +this.maxxval=this.options.xAxis[1]; +this.xscale=this.maxval-this.minxval; +} +if(_80(this.options.yAxis)){ +if(this.options.yOriginIsZero){ +this.minyval=0; +}else{ +this.minyval=_78(map(parseFloat,map(_76(1),all))); +} +this.maxyval=_79(map(parseFloat,map(_76(1),all))); +}else{ +this.minyval=this.options.yAxis[0]; +this.maxyval=this.options.yAxis[1]; +this.yscale=this.maxyval-this.minyval; +} +}; +PlotKit.Layout.prototype._evaluateScales=function(){ +var _82=MochiKit.Base.isUndefinedOrNull; +this.xrange=this.maxxval-this.minxval; +if(this.xrange==0){ +this.xscale=1; +}else{ +this.xscale=1/this.xrange; +} +this.yrange=this.maxyval-this.minyval; +if(this.yrange==0){ +this.yscale=1; +}else{ +this.yscale=1/this.yrange; +} +}; +PlotKit.Layout.prototype._uniqueXValues=function(){ +var _83=PlotKit.Base.collapse; +var map=PlotKit.Base.map; +var _84=PlotKit.Base.uniq; +var _85=MochiKit.Base.itemgetter; +var _86=PlotKit.Base.items; +var _87=map(parseFloat,map(_85(0),_83(map(_85(1),_86(this.datasets))))); +_87.sort(MochiKit.Base.compare); +return _84(_87); +}; +PlotKit.Layout.prototype._evaluateBarCharts=function(){ +var _88=PlotKit.Base.items; +var _89=_88(this.datasets).length; +var _90=10000000; +var _91=this._uniqueXValues(); +for(var i=1;i<_91.length;i++){ +_90=Math.min(Math.abs(_91[i]-_91[i-1]),_90); +} +var _92=0; +var _93=0; +var _94=0; +if(_91.length==1){ +_90=1; +this.xscale=1; +this.minxval=_91[0]; +_92=1*this.options.barWidthFillFraction; +_93=_92/_89; +_94=(1-this.options.barWidthFillFraction)/2; +}else{ +if(this.xrange==1){ +this.xscale=0.5; +}else{ +if(this.xrange==2){ +this.xscale=1/3; +}else{ +this.xscale=(1-_90/this.xrange)/this.xrange; +} +} +_92=_90*this.xscale*this.options.barWidthFillFraction; +_93=_92/_89; +_94=_90*this.xscale*(1-this.options.barWidthFillFraction)/2; +} +this.minxdelta=_90; +this.bars=new Array(); +var i=0; +for(var _95 in this.datasets){ +var _96=this.datasets[_95]; +if(PlotKit.Base.isFuncLike(_96)){ +continue; +} +for(var j=0;j<_96.length;j++){ +var _98=_96[j]; +var _99={x:((parseFloat(_98[0])-this.minxval)*this.xscale)+(i*_93)+_94,y:1-((parseFloat(_98[1])-this.minyval)*this.yscale),w:_93,h:((parseFloat(_98[1])-this.minyval)*this.yscale),xval:parseFloat(_98[0]),yval:parseFloat(_98[1]),name:_95}; +if((_99.x>=0)&&(_99.x<=1)&&(_99.y>=0)&&(_99.y<=1)){ +this.bars.push(_99); +} +} +i++; +} +}; +PlotKit.Layout.prototype._evaluateHorizBarCharts=function(){ +var _100=PlotKit.Base.items; +var _101=_100(this.datasets).length; +var _102=10000000; +var _103=this._uniqueXValues(); +for(var i=1;i<_103.length;i++){ +_102=Math.min(Math.abs(_103[i]-_103[i-1]),_102); +} +var _104=0; +var _105=0; +var _106=0; +if(_103.length==1){ +_102=1; +this.xscale=1; +this.minxval=_103[0]; +_104=1*this.options.barWidthFillFraction; +_105=_104/_101; +_106=(1-this.options.barWidthFillFraction)/2; +}else{ +this.xscale=(1-_102/this.xrange)/this.xrange; +_104=_102*this.xscale*this.options.barWidthFillFraction; +_105=_104/_101; +_106=_102*this.xscale*(1-this.options.barWidthFillFraction)/2; +} +this.minxdelta=_102; +this.bars=new Array(); +var i=0; +for(var _107 in this.datasets){ +var _108=this.datasets[_107]; +if(PlotKit.Base.isFuncLike(_108)){ +continue; +} +for(var j=0;j<_108.length;j++){ +var item=_108[j]; +var rect={y:((parseFloat(item[0])-this.minxval)*this.xscale)+(i*_105)+_106,x:0,h:_105,w:((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_107}; +if(rect.y<=0){ +rect.y=0; +} +if(rect.y>=1){ +rect.y=1; +} +if((rect.x>=0)&&(rect.x<=1)){ +this.bars.push(rect); +} +} +i++; +} +}; +PlotKit.Layout.prototype._evaluateLineCharts=function(){ +var _111=PlotKit.Base.items; +var _112=_111(this.datasets).length; +this.points=new Array(); +var i=0; +for(var _113 in this.datasets){ +var _114=this.datasets[_113]; +if(PlotKit.Base.isFuncLike(_114)){ +continue; +} +_114.sort(function(a,b){ +return compare(parseFloat(a[0]),parseFloat(b[0])); +}); +for(var j=0;j<_114.length;j++){ +var item=_114[j]; +var _117={x:((parseFloat(item[0])-this.minxval)*this.xscale),y:1-((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_113}; +if(_117.y<=0){ +_117.y=0; +} +if(_117.y>=1){ +_117.y=1; +} +if((_117.x>=0)&&(_117.x<=1)){ +this.points.push(_117); +} +} +i++; +} +}; +PlotKit.Layout.prototype._evaluatePieCharts=function(){ +var _118=PlotKit.Base.items; +var sum=MochiKit.Iter.sum; +var _120=MochiKit.Base.itemgetter; +var _121=_118(this.datasets).length; +var _122=_118(this.datasets)[0][1]; +var _123=sum(map(_120(1),_122)); +this.slices=new Array(); +var _124=0; +for(var i=0;i<_122.length;i++){ +var _125=_122[i][1]/_123; +var _126=_124*Math.PI*2; +var _127=(_124+_125)*Math.PI*2; +var _128={fraction:_125,xval:_122[i][0],yval:_122[i][1],startAngle:_126,endAngle:_127}; +if(_122[i][1]!=0){ +this.slices.push(_128); +} +_124+=_125; +} +}; +PlotKit.Layout.prototype._evaluateLineTicksForXAxis=function(){ +var _129=MochiKit.Base.isUndefinedOrNull; +if(this.options.xTicks){ +this.xticks=new Array(); +var _130=function(tick){ +var _132=tick.label; +if(_129(_132)){ +_132=tick.v.toString(); +} +var pos=this.xscale*(tick.v-this.minxval); +if((pos>=0)&&(pos<=1)){ +this.xticks.push([pos,_132]); +} +}; +MochiKit.Iter.forEach(this.options.xTicks,bind(_130,this)); +}else{ +if(this.options.xNumberOfTicks){ +var _134=this._uniqueXValues(); +var _135=this.xrange/this.options.xNumberOfTicks; +var _136=0; +this.xticks=new Array(); +for(var i=0;i<=_134.length;i++){ +if((_134[i]-this.minxval)>=(_136*_135)){ +var pos=this.xscale*(_134[i]-this.minxval); +if((pos>1)||(pos<0)){ +continue; +} +this.xticks.push([pos,_134[i]]); +_136++; +} +if(_136>this.options.xNumberOfTicks){ +break; +} +} +} +} +}; +PlotKit.Layout.prototype._evaluateLineTicksForYAxis=function(){ +var _137=MochiKit.Base.isUndefinedOrNull; +if(this.options.yTicks){ +this.yticks=new Array(); +var _138=function(tick){ +var _139=tick.label; +if(_137(_139)){ +_139=tick.v.toString(); +} +var pos=1-(this.yscale*(tick.v-this.minyval)); +if((pos>=0)&&(pos<=1)){ +this.yticks.push([pos,_139]); +} +}; +MochiKit.Iter.forEach(this.options.yTicks,bind(_138,this)); +}else{ +if(this.options.yNumberOfTicks){ +this.yticks=new Array(); +var _140=PlotKit.Base.roundInterval; +var prec=this.options.yTickPrecision; +var _142=_140(this.yrange,this.options.yNumberOfTicks,prec); +for(var i=0;i<=this.options.yNumberOfTicks;i++){ +var yval=this.minyval+(i*_142); +var pos=1-((yval-this.minyval)*this.yscale); +if((pos>1)||(pos<0)){ +continue; +} +this.yticks.push([pos,MochiKit.Format.roundToFixed(yval,prec)]); +} +} +} +}; +PlotKit.Layout.prototype._evaluateLineTicks=function(){ +this._evaluateLineTicksForXAxis(); +this._evaluateLineTicksForYAxis(); +}; +PlotKit.Layout.prototype._evaluateBarTicks=function(){ +this._evaluateLineTicks(); +var _144=function(tick){ +return [tick[0]+(this.minxdelta*this.xscale)/2,tick[1]]; +}; +this.xticks=MochiKit.Base.map(bind(_144,this),this.xticks); +if(this.options.barOrientation=="horizontal"){ +var _145=this.xticks; +this.xticks=this.yticks; +this.yticks=_145; +var _146=function(tick){ +return [1-tick[0],tick[1]]; +}; +this.xticks=MochiKit.Base.map(_146,this.xticks); +} +}; +PlotKit.Layout.prototype._evaluatePieTicks=function(){ +var _147=MochiKit.Base.isUndefinedOrNull; +var _148=MochiKit.Format.numberFormatter("#%"); +this.xticks=new Array(); +if(this.options.xTicks){ +var _149=new Array(); +for(var i=0;i0){ +this.__init__(_158,_159,_160); +} +}; +PlotKit.CanvasRenderer.prototype.__init__=function(_161,_162,_163){ +var _164=MochiKit.Base.isUndefinedOrNull; +var _165=MochiKit.Color.Color; +this.options={"drawBackground":true,"backgroundColor":_165.whiteColor(),"padding":{left:30,right:30,top:5,bottom:10},"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"strokeColor":_165.whiteColor(),"strokeColorTransform":"asStrokeColor","strokeWidth":0.5,"shouldFill":true,"shouldStroke":true,"drawXAxis":true,"drawYAxis":true,"axisLineColor":_165.blackColor(),"axisLineWidth":0.5,"axisTickSize":3,"axisLabelColor":_165.blackColor(),"axisLabelFont":"Arial","axisLabelFontSize":9,"axisLabelWidth":50,"pieRadius":0.4,"enableEvents":true}; +MochiKit.Base.update(this.options,_163?_163:{}); +this.layout=_162; +this.element=MochiKit.DOM.getElement(_161); +this.container=this.element.parentNode; +this.isIE=PlotKit.Base.excanvasSupported(); +if(this.isIE&&!_164(G_vmlCanvasManager)){ +this.IEDelay=0.5; +this.maxTries=5; +this.renderDelay=null; +this.clearDelay=null; +this.element=G_vmlCanvasManager.initElement(this.element); +} +this.height=this.element.height; +this.width=this.element.width; +if(_164(this.element)){ +throw "CanvasRenderer() - passed canvas is not found"; +} +if(!this.isIE&&!(PlotKit.CanvasRenderer.isSupported(this.element))){ +throw "CanvasRenderer() - Canvas is not supported."; +} +if(_164(this.container)||(this.container.nodeName.toLowerCase()!="div")){ +throw "CanvasRenderer() - needs to be enclosed in
"; +} +this.xlabels=new Array(); +this.ylabels=new Array(); +this.isFirstRender=true; +this.area={x:this.options.padding.left,y:this.options.padding.top,w:this.width-this.options.padding.left-this.options.padding.right,h:this.height-this.options.padding.top-this.options.padding.bottom}; +MochiKit.DOM.updateNodeAttributes(this.container,{"style":{"position":"relative","width":this.width+"px"}}); +}; +PlotKit.CanvasRenderer.prototype.render=function(){ +if(this.isIE){ +try{ +if(this.renderDelay){ +this.renderDelay.cancel(); +this.renderDelay=null; +} +var _166=this.element.getContext("2d"); +} +catch(e){ +this.isFirstRender=false; +if(this.maxTries-->0){ +this.renderDelay=MochiKit.Async.wait(this.IEDelay); +this.renderDelay.addCallback(bind(this.render,this)); +} +return; +} +} +if(this.options.drawBackground){ +this._renderBackground(); +} +if(this.layout.style=="bar"){ +this._renderBarChart(); +this._renderBarAxis(); +}else{ +if(this.layout.style=="pie"){ +this._renderPieChart(); +this._renderPieAxis(); +}else{ +if(this.layout.style=="line"){ +this._renderLineChart(); +this._renderLineAxis(); +} +} +} +}; +PlotKit.CanvasRenderer.prototype._renderBarChartWrap=function(data,_168){ +var _169=this.element.getContext("2d"); +var _170=this.options.colorScheme.length; +var _171=this.options.colorScheme; +var _172=MochiKit.Base.keys(this.layout.datasets); +var _173=_172.length; +for(var i=0;i<_173;i++){ +var _174=_172[i]; +var _175=_171[i%_170]; +_169.save(); +_169.fillStyle=_175.toRGBString(); +if(this.options.strokeColor){ +_169.strokeStyle=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_169.strokeStyle=_175[this.options.strokeColorTransform]().toRGBString(); +} +} +_169.lineWidth=this.options.strokeWidth; +var _176=function(obj){ +if(obj.name==_174){ +_168(_169,obj); +} +}; +MochiKit.Iter.forEach(data,bind(_176,this)); +_169.restore(); +} +}; +PlotKit.CanvasRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _178=function(_179,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +if((w<1)||(h<1)){ +return; +} +if(this.options.shouldFill){ +_179.fillRect(x,y,w,h); +} +if(this.options.shouldStroke){ +_179.strokeRect(x,y,w,h); +} +}; +this._renderBarChartWrap(this.layout.bars,bind(_178,this)); +}; +PlotKit.CanvasRenderer.prototype._renderLineChart=function(){ +var _182=this.element.getContext("2d"); +var _183=this.options.colorScheme.length; +var _184=this.options.colorScheme; +var _185=MochiKit.Base.keys(this.layout.datasets); +var _186=_185.length; +var bind=MochiKit.Base.bind; +var _187=MochiKit.Base.partial; +for(var i=0;i<_186;i++){ +var _188=_185[i]; +var _189=_184[i%_183]; +var _190=this.options.strokeColorTransform; +_182.save(); +_182.fillStyle=_189.toRGBString(); +if(this.options.strokeColor){ +_182.strokeStyle=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_182.strokeStyle=_189[_190]().toRGBString(); +} +} +_182.lineWidth=this.options.strokeWidth; +var _191=function(ctx){ +ctx.beginPath(); +ctx.moveTo(this.area.x,this.area.y+this.area.h); +var _193=function(ctx_,_195){ +if(_195.name==_188){ +ctx_.lineTo(this.area.w*_195.x+this.area.x,this.area.h*_195.y+this.area.y); +} +}; +MochiKit.Iter.forEach(this.layout.points,_187(_193,ctx),this); +ctx.lineTo(this.area.w+this.area.x,this.area.h+this.area.y); +ctx.lineTo(this.area.x,this.area.y+this.area.h); +ctx.closePath(); +}; +if(this.options.shouldFill){ +bind(_191,this)(_182); +_182.fill(); +} +if(this.options.shouldStroke){ +bind(_191,this)(_182); +_182.stroke(); +} +_182.restore(); +} +}; +PlotKit.CanvasRenderer.prototype._renderPieChart=function(){ +var _196=this.element.getContext("2d"); +var _197=this.options.colorScheme.length; +var _198=this.layout.slices; +var _199=this.area.x+this.area.w*0.5; +var _200=this.area.y+this.area.h*0.5; +var _201=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +if(this.isIE){ +_199=parseInt(_199); +_200=parseInt(_200); +_201=parseInt(_201); +} +for(var i=0;i<_198.length;i++){ +var _202=this.options.colorScheme[i%_197]; +_196.save(); +_196.fillStyle=_202.toRGBString(); +var _203=function(){ +_196.beginPath(); +_196.moveTo(_199,_200); +_196.arc(_199,_200,_201,_198[i].startAngle-Math.PI/2,_198[i].endAngle-Math.PI/2,false); +_196.lineTo(_199,_200); +_196.closePath(); +}; +if(Math.abs(_198[i].startAngle-_198[i].endAngle)>0.001){ +if(this.options.shouldFill){ +_203(); +_196.fill(); +} +if(this.options.shouldStroke){ +_203(); +_196.lineWidth=this.options.strokeWidth; +if(this.options.strokeColor){ +_196.strokeStyle=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_196.strokeStyle=_202[this.options.strokeColorTransform]().toRGBString(); +} +} +_196.stroke(); +} +} +_196.restore(); +} +}; +PlotKit.CanvasRenderer.prototype._renderBarAxis=function(){ +this._renderAxis(); +}; +PlotKit.CanvasRenderer.prototype._renderLineAxis=function(){ +this._renderAxis(); +}; +PlotKit.CanvasRenderer.prototype._renderAxis=function(){ +if(!this.options.drawXAxis&&!this.options.drawYAxis){ +return; +} +var _204=this.element.getContext("2d"); +var _205={"style":{"position":"absolute","fontSize":this.options.axisLabelFontSize+"px","zIndex":10,"color":this.options.axisLabelColor.toRGBString(),"width":this.options.axisLabelWidth+"px","overflow":"hidden"}}; +_204.save(); +_204.strokeStyle=this.options.axisLineColor.toRGBString(); +_204.lineWidth=this.options.axisLineWidth; +if(this.options.drawYAxis){ +if(this.layout.yticks){ +var _206=function(tick){ +if(typeof (tick)=="function"){ +return; +} +var x=this.area.x; +var y=this.area.y+tick[0]*this.area.h; +_204.beginPath(); +_204.moveTo(x,y); +_204.lineTo(x-this.options.axisTickSize,y); +_204.closePath(); +_204.stroke(); +var _207=DIV(_205,tick[1]); +_207.style.top=(y-this.options.axisLabelFontSize)+"px"; +_207.style.left=(x-this.options.padding.left-this.options.axisTickSize)+"px"; +_207.style.textAlign="right"; +_207.style.width=(this.options.padding.left-this.options.axisTickSize*2)+"px"; +MochiKit.DOM.appendChildNodes(this.container,_207); +this.ylabels.push(_207); +}; +MochiKit.Iter.forEach(this.layout.yticks,bind(_206,this)); +} +_204.beginPath(); +_204.moveTo(this.area.x,this.area.y); +_204.lineTo(this.area.x,this.area.y+this.area.h); +_204.closePath(); +_204.stroke(); +} +if(this.options.drawXAxis){ +if(this.layout.xticks){ +var _206=function(tick){ +if(typeof (dataset)=="function"){ +return; +} +var x=this.area.x+tick[0]*this.area.w; +var y=this.area.y+this.area.h; +_204.beginPath(); +_204.moveTo(x,y); +_204.lineTo(x,y+this.options.axisTickSize); +_204.closePath(); +_204.stroke(); +var _208=DIV(_205,tick[1]); +_208.style.top=(y+this.options.axisTickSize)+"px"; +_208.style.left=(x-this.options.axisLabelWidth/2)+"px"; +_208.style.textAlign="center"; +_208.style.width=this.options.axisLabelWidth+"px"; +MochiKit.DOM.appendChildNodes(this.container,_208); +this.xlabels.push(_208); +}; +MochiKit.Iter.forEach(this.layout.xticks,bind(_206,this)); +} +_204.beginPath(); +_204.moveTo(this.area.x,this.area.y+this.area.h); +_204.lineTo(this.area.x+this.area.w,this.area.y+this.area.h); +_204.closePath(); +_204.stroke(); +} +_204.restore(); +}; +PlotKit.CanvasRenderer.prototype._renderPieAxis=function(){ +if(!this.options.drawXAxis){ +return; +} +if(this.layout.xticks){ +var _209=new Array(); +for(var i=0;iMath.PI*2){ +_216=_216-Math.PI*2; +}else{ +if(_216<0){ +_216=_216+Math.PI*2; +} +} +var _217=_210+Math.sin(_216)*(_212+10); +var _218=_211-Math.cos(_216)*(_212+10); +var _219={"position":"absolute","zIndex":11,"width":_213+"px","fontSize":this.options.axisLabelFontSize+"px","overflow":"hidden","color":this.options.axisLabelColor.toHexString()}; +if(_216<=Math.PI*0.5){ +_219["textAlign"]="left"; +_219["verticalAlign"]="top"; +_219["left"]=_217+"px"; +_219["top"]=(_218-this.options.axisLabelFontSize)+"px"; +}else{ +if((_216>Math.PI*0.5)&&(_216<=Math.PI)){ +_219["textAlign"]="left"; +_219["verticalAlign"]="bottom"; +_219["left"]=_217+"px"; +_219["top"]=_218+"px"; +}else{ +if((_216>Math.PI)&&(_216<=Math.PI*1.5)){ +_219["textAlign"]="right"; +_219["verticalAlign"]="bottom"; +_219["left"]=(_217-_213)+"px"; +_219["top"]=_218+"px"; +}else{ +_219["textAlign"]="right"; +_219["verticalAlign"]="bottom"; +_219["left"]=(_217-_213)+"px"; +_219["top"]=(_218-this.options.axisLabelFontSize)+"px"; +} +} +} +var _220=DIV({"style":_219},this.layout.xticks[i][1]); +this.xlabels.push(_220); +MochiKit.DOM.appendChildNodes(this.container,_220); +} +} +}; +PlotKit.CanvasRenderer.prototype._renderBackground=function(){ +var _221=this.element.getContext("2d"); +_221.save(); +_221.fillStyle=this.options.backgroundColor.toRGBString(); +_221.fillRect(0,0,this.width,this.height); +_221.restore(); +}; +PlotKit.CanvasRenderer.prototype.clear=function(){ +if(this.isIE){ +try{ +if(this.clearDelay){ +this.clearDelay.cancel(); +this.clearDelay=null; +} +var _222=this.element.getContext("2d"); +} +catch(e){ +this.isFirstRender=false; +this.clearDelay=MochiKit.Async.wait(this.IEDelay); +this.clearDelay.addCallback(bind(this.clear,this)); +return; +} +} +var _222=this.element.getContext("2d"); +_222.clearRect(0,0,this.width,this.height); +MochiKit.Iter.forEach(this.xlabels,MochiKit.DOM.removeElement); +MochiKit.Iter.forEach(this.ylabels,MochiKit.DOM.removeElement); +this.xlabels=new Array(); +this.ylabels=new Array(); +}; +PlotKit.CanvasRenderer.prototype._initialiseEvents=function(){ +var _223=MochiKit.Signal.connect; +var bind=MochiKit.Base.bind; +_223(this.element,"onclick",bind(this.onclick,this)); +}; +PlotKit.CanvasRenderer.prototype._resolveObject=function(e){ +var x=(e.mouse().page.x-PlotKit.Base.findPosX(this.element)-this.area.x)/this.area.w; +var y=(e.mouse().page.y-PlotKit.Base.findPosY(this.element)-this.area.y)/this.area.h; +var _225=this.layout.hitTest(x,y); +if(_225){ +return _225; +} +return null; +}; +PlotKit.CanvasRenderer.prototype._createEventObject=function(_226,e){ +if(_226==null){ +return null; +} +e.chart=_226; +return e; +}; +PlotKit.CanvasRenderer.prototype.onclick=function(e){ +var _227=this._resolveObject(e); +var _228=this._createEventObject(_227,e); +if(_228!=null){ +MochiKit.Signal.signal(this,"onclick",_228); +} +}; +PlotKit.CanvasRenderer.prototype.onmouseover=function(e){ +var _229=this._resolveObject(e); +var _230=this._createEventObject(_229,e); +if(_230!=null){ +signal(this,"onmouseover",_230); +} +}; +PlotKit.CanvasRenderer.prototype.onmouseout=function(e){ +var _231=this._resolveObject(e); +var _232=this._createEventObject(_231,e); +if(_232==null){ +signal(this,"onmouseout",e); +}else{ +signal(this,"onmouseout",_232); +} +}; +PlotKit.CanvasRenderer.prototype.onmousemove=function(e){ +var _233=this._resolveObject(e); +var _234=this._createEventObject(_233,e); +if((_233==null)&&(this.event_isinside==null)){ +return; +} +if((_233!=null)&&(this.event_isinside==null)){ +signal(this,"onmouseover",_234); +} +if((_233==null)&&(this.event_isinside!=null)){ +signal(this,"onmouseout",_234); +} +if((_233!=null)&&(this.event_isinside!=null)){ +signal(this,"onmousemove",_234); +} +this.event_isinside=_233; +}; +PlotKit.CanvasRenderer.isSupported=function(_235){ +var _236=null; +try{ +if(MochiKit.Base.isUndefinedOrNull(_235)){ +_236=MochiKit.DOM.CANVAS({}); +}else{ +_236=MochiKit.DOM.getElement(_235); +} +var _237=_236.getContext("2d"); +} +catch(e){ +var ie=navigator.appVersion.match(/MSIE (\d\.\d)/); +var _239=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1); +if((!ie)||(ie[1]<6)||(_239)){ +return false; +} +return true; +} +return true; +}; +PlotKit.Canvas={}; +PlotKit.Canvas.CanvasRenderer=PlotKit.CanvasRenderer; +PlotKit.Canvas.EXPORT=["CanvasRenderer"]; +PlotKit.Canvas.EXPORT_OK=["CanvasRenderer"]; +PlotKit.Canvas.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.Canvas.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.Canvas); +try{ +if(typeof (PlotKit.Layout)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout"; +} +PlotKit.SVGRenderer=function(_240,_241,_242){ +if(arguments.length>0){ +this.__init__(_240,_241,_242); +} +}; +PlotKit.SVGRenderer.NAME="PlotKit.SVGRenderer"; +PlotKit.SVGRenderer.VERSION=PlotKit.VERSION; +PlotKit.SVGRenderer.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.SVGRenderer.toString=function(){ +return this.__repr__(); +}; +PlotKit.SVGRenderer.SVGNS="http://www.w3.org/2000/svg"; +PlotKit.SVGRenderer.prototype.__init__=function(_243,_244,_245){ +var _246=MochiKit.Base.isUndefinedOrNull; +this.options={"drawBackground":true,"backgroundColor":Color.whiteColor(),"padding":{left:30,right:30,top:5,bottom:10},"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),"strokeColor":Color.whiteColor(),"strokeColorTransform":"asStrokeColor","strokeWidth":0.5,"shouldFill":true,"shouldStroke":true,"drawXAxis":true,"drawYAxis":true,"axisLineColor":Color.blackColor(),"axisLineWidth":0.5,"axisTickSize":3,"axisLabelColor":Color.blackColor(),"axisLabelFont":"Arial","axisLabelFontSize":9,"axisLabelWidth":50,"axisLabelUseDiv":true,"pieRadius":0.4,"enableEvents":true}; +MochiKit.Base.update(this.options,_245?_245:{}); +this.layout=_244; +this.element=MochiKit.DOM.getElement(_243); +this.container=this.element.parentNode; +this.height=parseInt(this.element.getAttribute("height")); +this.width=parseInt(this.element.getAttribute("width")); +this.document=document; +this.root=this.element; +try{ +this.document=this.element.getSVGDocument(); +this.root=_246(this.document.documentElement)?this.element:this.document.documentElement; +} +catch(e){ +} +this.element.style.zIndex=1; +if(_246(this.element)){ +throw "SVGRenderer() - passed SVG object is not found"; +} +if(_246(this.container)||this.container.nodeName.toLowerCase()!="div"){ +throw "SVGRenderer() - No DIV's around the SVG."; +} +this.xlabels=new Array(); +this.ylabels=new Array(); +this.defs=this.createSVGElement("defs"); +this.area={x:this.options.padding.left,y:this.options.padding.top,w:this.width-this.options.padding.left-this.options.padding.right,h:this.height-this.options.padding.top-this.options.padding.bottom}; +MochiKit.DOM.updateNodeAttributes(this.container,{"style":{"position":"relative","width":this.width+"px"}}); +}; +PlotKit.SVGRenderer.prototype.render=function(){ +if(this.options.drawBackground){ +this._renderBackground(); +} +if(this.layout.style=="bar"){ +this._renderBarChart(); +this._renderBarAxis(); +}else{ +if(this.layout.style=="pie"){ +this._renderPieChart(); +this._renderPieAxis(); +}else{ +if(this.layout.style=="line"){ +this._renderLineChart(); +this._renderLineAxis(); +} +} +} +}; +PlotKit.SVGRenderer.prototype._renderBarOrLine=function(data,_247,_248,_249){ +var _250=this.options.colorScheme.length; +var _251=this.options.colorScheme; +var _252=MochiKit.Base.keys(this.layout.datasets); +var _253=_252.length; +for(var i=0;i<_253;i++){ +var _254=_252[i]; +var _255=new Array(); +var _256=_251[i%_250]; +if(this.options.shouldFill){ +_255["fill"]=_256.toRGBString(); +}else{ +_255["fill"]="none"; +} +if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){ +if(this.options.strokeColor){ +_255["stroke"]=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_255["stroke"]=_256[this.options.strokeColorTransform]().toRGBString(); +} +} +_255["strokeWidth"]=this.options.strokeWidth; +} +if(_248){ +_248(_255); +} +var _257=function(obj){ +if(obj.name==_254){ +_247(_255,obj); +} +}; +MochiKit.Iter.forEach(data,bind(_257,this)); +if(_249){ +_249(_255); +} +} +}; +PlotKit.SVGRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _258=function(_259,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +this._drawRect(x,y,w,h,_259); +}; +this._renderBarOrLine(this.layout.bars,bind(_258,this)); +}; +PlotKit.SVGRenderer.prototype._renderLineChart=function(){ +var bind=MochiKit.Base.bind; +var _260=function(_261,_262){ +this._tempPointsBuffer+=(this.area.w*_262.x+this.area.x)+","+(this.area.h*_262.y+this.area.y)+" "; +}; +var _263=function(_264){ +this._tempPointsBuffer=""; +this._tempPointsBuffer+=(this.area.x)+","+(this.area.y+this.area.h)+" "; +}; +var _265=function(_266){ +this._tempPointsBuffer+=(this.area.w+this.area.x)+","+(this.area.h+this.area.y); +_266["points"]=this._tempPointsBuffer; +var elem=this.createSVGElement("polygon",_266); +this.root.appendChild(elem); +}; +this._renderBarOrLine(this.layout.points,bind(_260,this),bind(_263,this),bind(_265,this)); +}; +PlotKit.SVGRenderer.prototype._renderPieChart=function(){ +var _268=this.options.colorScheme.length; +var _269=this.layout.slices; +var _270=this.area.x+this.area.w*0.5; +var _271=this.area.y+this.area.h*0.5; +var _272=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +if(_269.length==1&&(Math.abs(_269[0].startAngle)-Math.abs(_269[0].endAngle)<0.1)){ +var _273={"cx":_270,"cy":_271,"r":_272}; +var _274=this.options.colorScheme[0]; +if(this.options.shouldFill){ +_273["fill"]=_274.toRGBString(); +}else{ +_273["fill"]="none"; +} +if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){ +if(this.options.strokeColor){ +_273["stroke"]=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_273["stroke"]=_274[this.options.strokeColorTransform]().toRGBString(); +} +} +_273["style"]="stroke-width: "+this.options.strokeWidth; +} +this.root.appendChild(this.createSVGElement("circle",_273)); +return; +} +for(var i=0;i<_269.length;i++){ +var _273=new Array(); +var _274=this.options.colorScheme[i%_268]; +if(this.options.shouldFill){ +_273["fill"]=_274.toRGBString(); +}else{ +_273["fill"]="none"; +} +if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){ +if(this.options.strokeColor){ +_273["stroke"]=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_273["stroke"]=_274[this.options.strokeColorTransform]().toRGBString(); +} +} +_273["style"]="stroke-width:"+this.options.strokeWidth; +} +var _275=0; +if(Math.abs(_269[i].endAngle-_269[i].startAngle)>Math.PI){ +_275=1; +} +var x1=Math.cos(_269[i].startAngle-Math.PI/2)*_272; +var y1=Math.sin(_269[i].startAngle-Math.PI/2)*_272; +var x2=Math.cos(_269[i].endAngle-Math.PI/2)*_272; +var y2=Math.sin(_269[i].endAngle-Math.PI/2)*_272; +var rx=x2-x1; +var ry=y2-y1; +var _282="M"+_270+","+_271+" "; +_282+="l"+x1+","+y1+" "; +_282+="a"+_272+","+_272+" 0 "+_275+",1 "+rx+","+ry+" z"; +_273["d"]=_282; +var elem=this.createSVGElement("path",_273); +this.root.appendChild(elem); +} +}; +PlotKit.SVGRenderer.prototype._renderBarAxis=function(){ +this._renderAxis(); +}; +PlotKit.SVGRenderer.prototype._renderLineAxis=function(){ +this._renderAxis(); +}; +PlotKit.SVGRenderer.prototype._renderAxis=function(){ +if(!this.options.drawXAxis&&!this.options.drawYAxis){ +return; +} +var _283={"style":{"position":"absolute","textAlign":"center","fontSize":this.options.axisLabelFontSize+"px","zIndex":10,"color":this.options.axisLabelColor.toRGBString(),"width":this.options.axisLabelWidth+"px","overflow":"hidden"}}; +var _284={"stroke":this.options.axisLineColor.toRGBString(),"strokeWidth":this.options.axisLineWidth}; +if(this.options.drawYAxis){ +if(this.layout.yticks){ +var _285=function(tick){ +var x=this.area.x; +var y=this.area.y+tick[0]*this.area.h; +this._drawLine(x,y,x-3,y,_284); +if(this.options.axisLabelUseDiv){ +var _286=DIV(_283,tick[1]); +_286.style.top=(y-this.options.axisLabelFontSize)+"px"; +_286.style.left=(x-this.options.padding.left+this.options.axisTickSize)+"px"; +_286.style.textAlign="left"; +_286.style.width=(this.options.padding.left-3)+"px"; +MochiKit.DOM.appendChildNodes(this.container,_286); +this.ylabels.push(_286); +}else{ +var _287={y:y+3,x:(x-this.options.padding.left+3),width:(this.options.padding.left-this.options.axisTickSize)+"px",height:(this.options.axisLabelFontSize+3)+"px",fontFamily:"Arial",fontSize:this.options.axisLabelFontSize+"px",fill:this.options.axisLabelColor.toRGBString()}; +var _286=this.createSVGElement("text",_287); +_286.appendChild(this.document.createTextNode(tick[1])); +this.root.appendChild(_286); +} +}; +MochiKit.Iter.forEach(this.layout.yticks,bind(_285,this)); +} +this._drawLine(this.area.x,this.area.y,this.area.x,this.area.y+this.area.h,_284); +} +if(this.options.drawXAxis){ +if(this.layout.xticks){ +var _285=function(tick){ +var x=this.area.x+tick[0]*this.area.w; +var y=this.area.y+this.area.h; +this._drawLine(x,y,x,y+this.options.axisTickSize,_284); +if(this.options.axisLabelUseDiv){ +var _288=DIV(_283,tick[1]); +_288.style.top=(y+this.options.axisTickSize)+"px"; +_288.style.left=(x-this.options.axisLabelWidth/2)+"px"; +_288.style.textAlign="center"; +_288.style.width=this.options.axisLabelWidth+"px"; +MochiKit.DOM.appendChildNodes(this.container,_288); +this.xlabels.push(_288); +}else{ +var _289={y:(y+this.options.axisTickSize+this.options.axisLabelFontSize),x:x-3,width:this.options.axisLabelWidth+"px",height:(this.options.axisLabelFontSize+3)+"px",fontFamily:"Arial",fontSize:this.options.axisLabelFontSize+"px",fill:this.options.axisLabelColor.toRGBString(),textAnchor:"middle"}; +var _288=this.createSVGElement("text",_289); +_288.appendChild(this.document.createTextNode(tick[1])); +this.root.appendChild(_288); +} +}; +MochiKit.Iter.forEach(this.layout.xticks,bind(_285,this)); +} +this._drawLine(this.area.x,this.area.y+this.area.h,this.area.x+this.area.w,this.area.y+this.area.h,_284); +} +}; +PlotKit.SVGRenderer.prototype._renderPieAxis=function(){ +if(this.layout.xticks){ +var _290=new Array(); +for(var i=0;iMath.PI*2){ +_297=_297-Math.PI*2; +}else{ +if(_297<0){ +_297=_297+Math.PI*2; +} +} +var _298=_291+Math.sin(_297)*(_293+10); +var _299=_292-Math.cos(_297)*(_293+10); +var _300={"position":"absolute","zIndex":11,"width":_294+"px","fontSize":this.options.axisLabelFontSize+"px","overflow":"hidden","color":this.options.axisLabelColor.toHexString()}; +var _301={"width":_294+"px","fontSize":this.options.axisLabelFontSize+"px","height":(this.options.axisLabelFontSize+3)+"px","fill":this.options.axisLabelColor.toRGBString()}; +if(_297<=Math.PI*0.5){ +MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"top","left":_298+"px","top":(_299-this.options.axisLabelFontSize)+"px"}); +MochiKit.Base.update(_301,{"x":_298,"y":(_299-this.options.axisLabelFontSize),"textAnchor":"left"}); +}else{ +if((_297>Math.PI*0.5)&&(_297<=Math.PI)){ +MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"bottom","left":_298+"px","top":_299+"px"}); +MochiKit.Base.update(_301,{"textAnchor":"left","x":_298,"y":_299}); +}else{ +if((_297>Math.PI)&&(_297<=Math.PI*1.5)){ +MochiKit.Base.update(_300,{"textAlign":"right","verticalAlign":"bottom","left":_298+"px","top":_299+"px"}); +MochiKit.Base.update(_301,{"textAnchor":"right","x":_298-_294,"y":_299}); +}else{ +MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"bottom","left":_298+"px","top":_299+"px"}); +MochiKit.Base.update(_301,{"textAnchor":"left","x":_298-_294,"y":_299-this.options.axisLabelFontSize}); +} +} +} +if(this.options.axisLabelUseDiv){ +var _302=DIV({"style":_300},this.layout.xticks[i][1]); +this.xlabels.push(_302); +MochiKit.DOM.appendChildNodes(this.container,_302); +}else{ +var _302=this.createSVGElement("text",_301); +_302.appendChild(this.document.createTextNode(this.layout.xticks[i][1])); +this.root.appendChild(_302); +} +} +} +}; +PlotKit.SVGRenderer.prototype._renderBackground=function(){ +var opts={"stroke":"none","fill":this.options.backgroundColor.toRGBString()}; +this._drawRect(0,0,this.width,this.height,opts); +}; +PlotKit.SVGRenderer.prototype._drawRect=function(x,y,w,h,_304){ +var _305={x:x+"px",y:y+"px",width:w+"px",height:h+"px"}; +if(_304){ +MochiKit.Base.update(_305,_304); +} +var elem=this.createSVGElement("rect",_305); +this.root.appendChild(elem); +}; +PlotKit.SVGRenderer.prototype._drawLine=function(x1,y1,x2,y2,_306){ +var _307={x1:x1+"px",y1:y1+"px",x2:x2+"px",y2:y2+"px"}; +if(_306){ +MochiKit.Base.update(_307,_306); +} +var elem=this.createSVGElement("line",_307); +this.root.appendChild(elem); +}; +PlotKit.SVGRenderer.prototype.clear=function(){ +while(this.element.firstChild){ +this.element.removeChild(this.element.firstChild); +} +if(this.options.axisLabelUseDiv){ +for(var i=0;i=6)&&(!_313)){ +var _314=_312["width"]?_312["width"]:"100"; +var _315=_312["height"]?_312["height"]:"100"; +var eid=_312["id"]?_312["id"]:"notunique"; +var html=""; +var _318=document.createElement(html); +var _319=_318.getSVGDocument().createElementNS(PlotKit.SVGRenderer.SVGNS,"svg"); +_319.setAttribute("width",_314); +_319.setAttribute("height",_315); +_318.getSVGDocument().appendChild(_319); +return _318; +}else{ +return PlotKit.SVGRenderer.prototype.createSVGElement("svg",_312); +} +}; +PlotKit.SVGRenderer.isSupported=function(){ +var _320=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1); +var _321=navigator.appVersion.match(/MSIE (\d\.\d)/); +var _322=navigator.userAgent.match(/AppleWebKit\/(\d+)/); +var _323=navigator.userAgent.match(/Opera\/(\d*\.\d*)/); +var _324=navigator.userAgent.match(/rv:(\d*\.\d*).*Gecko/); +var _325="http://www.w3.org/TR/SVG11/feature#SVG"; +if(_321&&(_321[1]>=6)&&!_320){ +return document.implementation.hasFeature(_325,"1.1"); +} +if(_323&&(_323[1]>8.9)){ +return true; +} +if(_324&&(_324>1.7)){ +return true; +} +return false; +}; +PlotKit.SVG={}; +PlotKit.SVG.SVGRenderer=PlotKit.SVGRenderer; +PlotKit.SVG.EXPORT=["SVGRenderer"]; +PlotKit.SVG.EXPORT_OK=["SVGRenderer"]; +PlotKit.SVG.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.SVG.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.SVG); +try{ +if(typeof (PlotKit.CanvasRenderer)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "SweetCanvas depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, Canvas}"; +} +if(typeof (PlotKit.SweetCanvasRenderer)=="undefined"){ +PlotKit.SweetCanvasRenderer={}; +} +PlotKit.SweetCanvasRenderer=function(_326,_327,_328){ +if(arguments.length>0){ +this.__init__(_326,_327,_328); +} +}; +PlotKit.SweetCanvasRenderer.NAME="PlotKit.SweetCanvasRenderer"; +PlotKit.SweetCanvasRenderer.VERSION=PlotKit.VERSION; +PlotKit.SweetCanvasRenderer.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.SweetCanvasRenderer.toString=function(){ +return this.__repr__(); +}; +PlotKit.SweetCanvasRenderer.prototype=new PlotKit.CanvasRenderer(); +PlotKit.SweetCanvasRenderer.prototype.constructor=PlotKit.SweetCanvasRenderer; +PlotKit.SweetCanvasRenderer.__super__=PlotKit.CanvasRenderer.prototype; +PlotKit.SweetCanvasRenderer.prototype.__init__=function(el,_330,opts){ +var _331=PlotKit.Base.officeBlue(); +MochiKit.Base.update(_331,opts); +PlotKit.SweetCanvasRenderer.__super__.__init__.call(this,el,_330,_331); +}; +PlotKit.SweetCanvasRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _332=Color.blackColor().colorWithAlpha(0.1).toRGBString(); +var _333=function(_334,x,y,w,h){ +_334.fillStyle=_332; +_334.fillRect(x-2,y-2,w+4,h+2); +_334.fillStyle=_332; +_334.fillRect(x-1,y-1,w+2,h+1); +}; +var _335=this.options.colorScheme.length; +var _336=this.options.colorScheme; +var _337=PlotKit.Base.keys(this.layout.datasets); +var _338=_337.length; +var _339=function(name){ +for(var i=0;i<_338;i++){ +if(name==_337[i]){ +return _336[i%_335]; +} +} +return _336[0]; +}; +var _340=function(_341,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +if((w<1)||(h<1)){ +return; +} +_341.save(); +_341.shadowBlur=5; +_341.shadowColor=Color.fromHexString("#888888").toRGBString(); +if(this.isIE){ +_341.save(); +_341.fillStyle="#cccccc"; +_341.fillRect(x-2,y-2,w+4,h+2); +_341.restore(); +}else{ +_333(_341,x,y,w,h); +} +if(this.options.shouldFill){ +_341.fillStyle=_339(bar.name).toRGBString(); +_341.fillRect(x,y,w,h); +} +_341.shadowBlur=0; +_341.strokeStyle=Color.whiteColor().toRGBString(); +_341.lineWidth=2; +if(this.options.shouldStroke){ +_341.strokeRect(x,y,w,h); +} +_341.restore(); +}; +this._renderBarChartWrap(this.layout.bars,bind(_340,this)); +}; +PlotKit.SweetCanvasRenderer.prototype._renderLineChart=function(){ +var _342=this.element.getContext("2d"); +var _343=this.options.colorScheme.length; +var _344=this.options.colorScheme; +var _345=PlotKit.Base.keys(this.layout.datasets); +var _346=_345.length; +var bind=MochiKit.Base.bind; +for(var i=0;i<_346;i++){ +var _347=_345[i]; +var _348=_344[i%_343]; +var _349=this.options.strokeColorTransform; +_342.save(); +var _350=function(ctx){ +ctx.beginPath(); +ctx.moveTo(this.area.x,this.area.y+this.area.h); +var _351=function(ctx_,_352){ +if(_352.name==_347){ +ctx_.lineTo(this.area.w*_352.x+this.area.x,this.area.h*_352.y+this.area.y); +} +}; +MochiKit.Iter.forEach(this.layout.points,partial(_351,ctx),this); +ctx.lineTo(this.area.w+this.area.x,this.area.h+this.area.y); +ctx.lineTo(this.area.x,this.area.y+this.area.h); +ctx.closePath(); +}; +if(this.options.shouldFill){ +_342.save(); +if(this.isIE){ +_342.fillStyle="#cccccc"; +}else{ +_342.fillStyle=Color.blackColor().colorWithAlpha(0.2).toRGBString(); +} +_342.translate(-1,-2); +bind(_350,this)(_342); +if(this.options.shouldFill){ +_342.fill(); +} +_342.restore(); +} +_342.shadowBlur=5; +_342.shadowColor=Color.fromHexString("#888888").toRGBString(); +_342.fillStyle=_348.toRGBString(); +_342.lineWidth=2; +_342.strokeStyle=Color.whiteColor().toRGBString(); +if(this.options.shouldFill){ +bind(_350,this)(_342); +_342.fill(); +} +if(this.options.shouldStroke){ +bind(_350,this)(_342); +_342.stroke(); +} +_342.restore(); +} +}; +PlotKit.SweetCanvasRenderer.prototype._renderPieChart=function(){ +var _353=this.element.getContext("2d"); +var _354=this.options.colorScheme.length; +var _355=this.layout.slices; +var _356=this.area.x+this.area.w*0.5; +var _357=this.area.y+this.area.h*0.5; +var _358=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +if(this.isIE){ +_356=parseInt(_356); +_357=parseInt(_357); +_358=parseInt(_358); +} +if(!this.isIE){ +_353.save(); +var _359=Color.blackColor().colorWithAlpha(0.2); +_353.fillStyle=_359.toRGBString(); +_353.shadowBlur=5; +_353.shadowColor=Color.fromHexString("#888888").toRGBString(); +_353.translate(1,1); +_353.beginPath(); +_353.moveTo(_356,_357); +_353.arc(_356,_357,_358+2,0,Math.PI*2,false); +_353.closePath(); +_353.fill(); +_353.restore(); +} +_353.save(); +_353.strokeStyle=Color.whiteColor().toRGBString(); +_353.lineWidth=2; +for(var i=0;i<_355.length;i++){ +var _360=this.options.colorScheme[i%_354]; +_353.fillStyle=_360.toRGBString(); +var _361=function(){ +_353.beginPath(); +_353.moveTo(_356,_357); +_353.arc(_356,_357,_358,_355[i].startAngle-Math.PI/2,_355[i].endAngle-Math.PI/2,false); +_353.lineTo(_356,_357); +_353.closePath(); +}; +if(Math.abs(_355[i].startAngle-_355[i].endAngle)>0.0001){ +if(this.options.shouldFill){ +_361(); +_353.fill(); +} +if(this.options.shouldStroke){ +_361(); +_353.stroke(); +} +} +} +_353.restore(); +}; +PlotKit.SweetCanvasRenderer.prototype._renderBackground=function(){ +var _362=this.element.getContext("2d"); +if(this.layout.style=="bar"||this.layout.style=="line"){ +_362.save(); +_362.fillStyle=this.options.backgroundColor.toRGBString(); +_362.fillRect(this.area.x,this.area.y,this.area.w,this.area.h); +_362.strokeStyle=this.options.axisLineColor.toRGBString(); +_362.lineWidth=1; +var _363=this.layout.yticks; +var _364=false; +if(this.layout.style=="bar"&&this.layout.options.barOrientation=="horizontal"){ +_363=this.layout.xticks; +_364=true; +} +for(var i=0;i<_363.length;i++){ +var x1=0; +var y1=0; +var x2=0; +var y2=0; +if(_364){ +x1=_363[i][0]*this.area.w+this.area.x; +y1=this.area.y; +x2=x1; +y2=y1+this.area.h; +}else{ +x1=this.area.x; +y1=_363[i][0]*this.area.h+this.area.y; +x2=x1+this.area.w; +y2=y1; +} +_362.beginPath(); +_362.moveTo(x1,y1); +_362.lineTo(x2,y2); +_362.closePath(); +_362.stroke(); +} +_362.restore(); +}else{ +PlotKit.SweetCanvasRenderer.__super__._renderBackground.call(this); +} +}; +PlotKit.SweetCanvas={}; +PlotKit.SweetCanvas.SweetCanvasRenderer=PlotKit.SweetCanvasRenderer; +PlotKit.SweetCanvas.EXPORT=["SweetCanvasRenderer"]; +PlotKit.SweetCanvas.EXPORT_OK=["SweetCanvasRenderer"]; +PlotKit.SweetCanvas.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.SweetCanvas.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.SweetCanvas); +try{ +if(typeof (PlotKit.SVGRenderer)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "SweetSVG depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, SVG}"; +} +if(typeof (PlotKit.SweetSVGRenderer)=="undefined"){ +PlotKit.SweetSVGRenderer={}; +} +PlotKit.SweetSVGRenderer=function(_365,_366,_367){ +if(arguments.length>0){ +this.__init__(_365,_366,_367); +} +}; +PlotKit.SweetSVGRenderer.NAME="PlotKit.SweetSVGRenderer"; +PlotKit.SweetSVGRenderer.VERSION=PlotKit.VERSION; +PlotKit.SweetSVGRenderer.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.SweetSVGRenderer.toString=function(){ +return this.__repr__(); +}; +PlotKit.SweetSVGRenderer.prototype=new PlotKit.SVGRenderer(); +PlotKit.SweetSVGRenderer.prototype.constructor=PlotKit.SweetSVGRenderer; +PlotKit.SweetSVGRenderer.__super__=PlotKit.SVGRenderer.prototype; +PlotKit.SweetSVGRenderer.prototype.__init__=function(_368,_369,_370){ +var _371=PlotKit.Base.officeBlue(); +MochiKit.Base.update(_371,_370); +PlotKit.SweetSVGRenderer.__super__.__init__.call(this,_368,_369,_371); +}; +PlotKit.SweetSVGRenderer.prototype._addDropShadowFilter=function(){ +var _372=this.createSVGElement("filter",{x:0,y:0,"id":"dropShadow"}); +var _373=this.createSVGElement("feOffset",{"in":"SourceGraphic","dx":0,"dy":0,"result":"topCopy"}); +var blur=this.createSVGElement("feGaussianBlur",{"in":"SourceAlpha","StdDeviation":2,"result":"shadow"}); +var _375=this.createSVGElement("feOffset",{"in":"shadow","dx":-1,"dy":-2,"result":"movedShadow"}); +var _376=this.createSVGElement("feMerge"); +var _377=this.createSVGElement("feMergeNode",{"in":"topCopy"}); +var _378=this.createSVGElement("feMergeNode",{"in":"movedShadow"}); +_376.appendChild(_377); +_376.appendChild(_378); +_372.appendChild(_373); +_372.appendChild(blur); +_372.appendChild(_375); +_372.appendChild(_376); +this.defs.appendChild(_372); +}; +PlotKit.SweetSVGRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _379=Color.blackColor().toRGBString(); +var _380="fill:"+_379+";fill-opacity:0.15"; +var _381="stroke-width: 2.0; stroke:"+Color.whiteColor().toRGBString(); +var _382=function(_383,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +if((w<1)||(h<1)){ +return; +} +_383["style"]=_381; +this._drawRect(x-2,y-1,w+4,h+2,{"style":_380}); +this._drawRect(x,y,w,h,_383); +}; +this._renderBarOrLine(this.layout.bars,bind(_382,this)); +}; +PlotKit.SweetSVGRenderer.prototype._renderLineChart=function(){ +var bind=MochiKit.Base.bind; +var _384=Color.blackColor().toRGBString(); +var _385="fill:"+_384+";fill-opacity:0.15"; +var _386="stroke-width: 2.0; stroke:"+Color.whiteColor().toRGBString(); +var _387=function(_388,_389){ +this._tempPointsBuffer+=(this.area.w*_389.x+this.area.x)+","+(this.area.h*_389.y+this.area.y)+" "; +}; +var _390=function(_391){ +this._tempPointsBuffer=""; +this._tempPointsBuffer+=(this.area.x)+","+(this.area.y+this.area.h)+" "; +}; +var _392=function(_393){ +this._tempPointsBuffer+=(this.area.w+this.area.x)+","+(this.area.h+this.area.y); +_393["points"]=this._tempPointsBuffer; +_393["stroke"]="none"; +_393["transform"]="translate(-2, -1)"; +_393["style"]=_385; +var _394=this.createSVGElement("polygon",_393); +this.root.appendChild(_394); +_393["transform"]=""; +_393["style"]=_386; +var elem=this.createSVGElement("polygon",_393); +this.root.appendChild(elem); +}; +this._renderBarOrLine(this.layout.points,bind(_387,this),bind(_390,this),bind(_392,this)); +}; +PlotKit.SweetSVGRenderer.prototype._renderPieChart=function(){ +var _395=this.area.x+this.area.w*0.5; +var _396=this.area.y+this.area.h*0.5; +var _397=Color.blackColor().toRGBString(); +var _398=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +var _399="fill:"+_397+";fill-opacity:0.15"; +var _400=this.createSVGElement("circle",{"style":_399,"cx":_395+1,"cy":_396+1,"r":_398+1}); +this.root.appendChild(_400); +PlotKit.SweetSVGRenderer.__super__._renderPieChart.call(this); +}; +PlotKit.SweetSVGRenderer.prototype._renderBackground=function(){ +var _401={"fill":this.options.backgroundColor.toRGBString(),"stroke":"none"}; +if(this.layout.style=="bar"||this.layout.style=="line"){ +this._drawRect(this.area.x,this.area.y,this.area.w,this.area.h,_401); +var _402=this.layout.yticks; +var _403=false; +if(this.layout.style=="bar"&&this.layout.options.barOrientation=="horizontal"){ +_402=this.layout.xticks; +_403=true; +} +for(var i=0;i<_402.length;i++){ +var x=0; +var y=0; +var w=0; +var h=0; +if(_403){ +x=_402[i][0]*this.area.w+this.area.x; +y=this.area.y; +w=1; +h=this.area.w; +}else{ +x=this.area.x; +y=_402[i][0]*this.area.h+this.area.y; +w=this.area.w; +h=1; +} +this._drawRect(x,y,w,h,{"fill":this.options.axisLineColor.toRGBString()}); +} +}else{ +PlotKit.SweetSVGRenderer.__super__._renderBackground.call(this); +} +}; +PlotKit.SweetSVG={}; +PlotKit.SweetSVG.SweetSVGRenderer=PlotKit.SweetSVGRenderer; +PlotKit.SweetSVG.EXPORT=["SweetSVGRenderer"]; +PlotKit.SweetSVG.EXPORT_OK=["SweetSVGRenderer"]; +PlotKit.SweetSVG.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.SweetSVG.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.SweetSVG); +try{ +if(typeof (PlotKit.CanvasRenderer)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit.EasyPlot depends on all of PlotKit's components"; +} +if(typeof (PlotKit.EasyPlot)=="undefined"){ +PlotKit.EasyPlot={}; +} +PlotKit.EasyPlot.NAME="PlotKit.EasyPlot"; +PlotKit.EasyPlot.VERSION=PlotKit.VERSION; +PlotKit.EasyPlot.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.EasyPlot.toString=function(){ +return this.__repr__(); +}; +PlotKit.EasyPlot=function(_404,_405,_406,_407){ +this.layout=new Layout(_404,_405); +this.divElem=_406; +this.width=parseInt(_406.getAttribute("width")); +this.height=parseInt(_406.getAttribute("height")); +this.deferredCount=0; +if(this.width<1){ +this.width=this.divElem.width?this.divElem.width:300; +} +if(this.height<1){ +this.height=this.divElem.height?this.divElem.height:300; +} +if(isArrayLike(_407)){ +for(var i=0;i<_407.length;i++){ +if(typeof (_407[i])=="string"){ +this.deferredCount++; +var d=MochiKit.Async.doSimpleXMLHttpRequest(_407[i]); +d.addCallback(MochiKit.Base.bind(PlotKit.EasyPlot.onDataLoaded,this)); +}else{ +if(isArrayLike(_407[i])){ +this.layout.addDataset("data-"+i,_407[i]); +} +} +} +}else{ +if(!isUndefinedOrNull(_407)){ +throw "Passed datasources are not Array like"; +} +} +if(CanvasRenderer.isSupported()){ +this.element=CANVAS({"id":this.divElem.getAttribute("id")+"-canvas","width":this.width,"height":this.height},""); +this.divElem.appendChild(this.element); +this.renderer=new SweetCanvasRenderer(this.element,this.layout,_405); +}else{ +if(SVGRenderer.isSupported()){ +this.element=SVGRenderer.SVG({"id":this.divElem.getAttribute("id")+"-svg","width":this.width,"height":this.height,"version":"1.1","baseProfile":"full"},""); +this.divElem.appendChild(this.element); +this.renderer=new SweetSVGRenderer(this.element,this.layout,_405); +} +} +if((this.deferredCount==0)&&(PlotKit.Base.keys(this.layout.datasets).length>0)){ +this.layout.evaluate(); +this.renderer.clear(); +this.renderer.render(); +} +}; +PlotKit.EasyPlot.onDataLoaded=function(_409){ +var _410=new Array(); +var _411=_409.responseText.split("\n"); +for(var i=0;i<_411.length;i++){ +var _412=MochiKit.Format.strip(_411[i]); +if((_412.length>1)&&(_412.charAt(0)!="#")){ +_410.push(_412.split(",")); +} +} +this.layout.addDataset("data-ajax-"+this.deferredCount,_410); +this.deferredCount--; +if((this.deferredCount==0)&&(PlotKit.Base.keys(this.layout.datasets).length>0)){ +this.layout.evaluate(); +this.renderer.clear(); +this.renderer.render(); +} +}; +PlotKit.EasyPlot.prototype.reload=function(){ +this.layout.evaluate(); +this.renderer.clear(); +this.renderer.render(); +}; +PlotKit.EasyPlotModule={}; +PlotKit.EasyPlotModule.EasyPlot=PlotKit.EasyPlot; +PlotKit.EasyPlotModule.EXPORT=["EasyPlot"]; +PlotKit.EasyPlotModule.EXPORT_OK=[]; +PlotKit.EasyPlotModule.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.EasyPlotModule.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.EasyPlotModule); + + diff --git a/openwrt/packages/luci/applications/luci-livestats/luasrc/controller/livestats.lua b/openwrt/packages/luci/applications/luci-livestats/luasrc/controller/livestats.lua new file mode 100644 index 0000000..cb7a6a3 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/luasrc/controller/livestats.lua @@ -0,0 +1,29 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: livestats.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +module("luci.controller.livestats", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("livestats") + + entry( {"admin", "status", "wifistat"}, template("livestats/wireless"), luci.i18n.translate("livestats_stat_wireless"), 90 ).i18n = "livestats" + entry( {"admin", "status", "trafstat"}, template("livestats/traffic"), luci.i18n.translate("livestats_stat_traffic"), 91 ).i18n = "livestats" + entry( {"admin", "status", "loadavg"}, template("livestats/loadavg"), luci.i18n.translate("livestats_stat_loadavg"), 92 ).i18n = "livestats" + + entry( {"mini", "network", "wifistat"}, template("livestats/wireless"), luci.i18n.translate("livestats_stat_wireless"), 90 ).i18n = "livestats" + entry( {"mini", "network", "trafstat"}, template("livestats/traffic"), luci.i18n.translate("livestats_stat_traffic"), 91 ).i18n = "livestats" + entry( {"mini", "system", "loadavg"}, template("livestats/loadavg"), luci.i18n.translate("livestats_stat_loadavg"), 92 ).i18n = "livestats" +end diff --git a/openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.de.lua b/openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.de.lua new file mode 100644 index 0000000..33c1eb1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.de.lua @@ -0,0 +1,8 @@ +livestats_incoming = "eingehend" +livestats_outgoing = "ausgehend" +livestats_traffic = "Netzverkehr auf" +livestats_wifi = "Signal-Rauschabstand für" +livestats_loadavg = "Durchschnittliche Systemlast" +livestats_stat_wireless = "Echtzeit-Drahtlosstatus" +livestats_stat_traffic = "Echtzeit-Netzwerkverkehr" +livestats_stat_loadavg = "Echtzeit-Systemlast" \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.en.lua b/openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.en.lua new file mode 100644 index 0000000..04d326a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/luasrc/i18n/livestats.en.lua @@ -0,0 +1,8 @@ +livestats_incoming = "incoming" +livestats_outgoing = "outgoing" +livestats_traffic = "traffic on" +livestats_wifi = "signal-to-noise ratio for" +livestats_loadavg = "load average" +livestats_stat_wireless = "Realtime Wireless Status" +livestats_stat_traffic = "Realtime Network Traffic" +livestats_stat_loadavg = "Realtime System Load" \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/loadavg.htm b/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/loadavg.htm new file mode 100644 index 0000000..49f800e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/loadavg.htm @@ -0,0 +1,33 @@ +<%+header%> + + + + + + + + + + +
+<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/traffic.htm b/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/traffic.htm new file mode 100644 index 0000000..f0c194d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/traffic.htm @@ -0,0 +1,66 @@ +<%+header%> + + + + + + + + +<% + local interfaces = { } + local ifnames = {} + local uci = luci.model.uci.cursor_state() + + uci:foreach("network", "interface", + function(s) + if s.ifname ~= "lo" then + table.insert( interfaces, + "'" .. ( s.ifname or s['.name'] ) .. "'" + ) + ifnames[s.ifname or s['.name']] = s['.name'] + end + end + ) +-%> + + + +
+ +<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/wireless.htm b/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/wireless.htm new file mode 100644 index 0000000..670d9fb --- /dev/null +++ b/openwrt/packages/luci/applications/luci-livestats/luasrc/view/livestats/wireless.htm @@ -0,0 +1,43 @@ +<%+header%> + + + + + + + + + + +
+ +<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/Makefile b/openwrt/packages/luci/applications/luci-mmc_over_gpio/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/ipkg/postinst b/openwrt/packages/luci/applications/luci-mmc_over_gpio/ipkg/postinst new file mode 100644 index 0000000..cf16b8a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-mmc_over_gpio ) && rm -f /etc/uci-defaults/luci-mmc_over_gpio +} diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/controller/mmc_over_gpio.lua b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/controller/mmc_over_gpio.lua new file mode 100644 index 0000000..9c86bfd --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/controller/mmc_over_gpio.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI mmc_over_gpio +(c) 2008 Yanira + +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: mmc_over_gpio.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.mmc_over_gpio", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("mmc_over_gpio") + if not luci.fs.access("/etc/config/mmc_over_gpio") then + return + end + + local page = entry({"admin", "system", "mmc_over_gpio"}, cbi("mmc_over_gpio"), luci.i18n.translate("mmc_over_gpio", "mmc_over_gpio"), 60) + page.i18n = "mmc_over_gpio" + page.dependent = true +end diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.lua b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.lua new file mode 100644 index 0000000..543f98d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.lua @@ -0,0 +1,3 @@ +mmc_over_gpio = 'MMC/SD Treiberkonfiguration' +mmc_over_gpio_desc = 'Konfiguriert die Einstellungen des MMC/SD Karten Treibers' +settings = 'Einstellungen' diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.xml b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.xml new file mode 100644 index 0000000..3aa08d2 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.de.xml @@ -0,0 +1,9 @@ + + + + +MMC/SD Treiberkonfiguration +Konfiguriert die Einstellungen des MMC/SD Karten Treibers +Einstellungen + + diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.lua b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.lua new file mode 100644 index 0000000..a1ee564 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.lua @@ -0,0 +1,3 @@ +mmc_over_gpio = 'MMC/SD driver configuration' +mmc_over_gpio_desc = 'MMC/SD driver configuration' +settings = 'Settings' diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.xml b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.xml new file mode 100644 index 0000000..ecdf363 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.en.xml @@ -0,0 +1,9 @@ + + + + +MMC/SD driver configuration +MMC/SD driver configuration +Settings + + diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.lua b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.lua new file mode 100644 index 0000000..954a89d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.lua @@ -0,0 +1,3 @@ +mmc_over_gpio = 'Configuração do driver MMC/SD' +mmc_over_gpio_desc = 'Configuração do driver MMC/SD' +settings = 'Configurações' diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.xml b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.xml new file mode 100644 index 0000000..dfb3419 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/i18n/mmc_over_gpio.pt-br.xml @@ -0,0 +1,9 @@ + + + + +Configuração do driver MMC/SD +Configuração do driver MMC/SD +Configurações + + diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/model/cbi/mmc_over_gpio.lua b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/model/cbi/mmc_over_gpio.lua new file mode 100644 index 0000000..591e7da --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/luasrc/model/cbi/mmc_over_gpio.lua @@ -0,0 +1,41 @@ +--[[ + +LuCI mmc_over_gpio +(c) 2008 Yanira + +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: mmc_over_gpio.lua 3635 2008-10-27 23:07:46Z jow $ + +]]-- + +m = Map("mmc_over_gpio", translate("mmc_over_gpio"), + translate("mmc_over_gpio_desc")) + +s = m:section(TypedSection, "mmc_over_gpio", translate("settings")) +s.addremove = true +s.anonymous = true + +s:option(Flag, "enabled", translate("enabled", "Enable")) + +s:option(Value, "name", translate("name")) + +pin = s:option(Value, "DI_pin", translate("DI_pin")) +for i = 0,7 do pin:value(i) end + +pin = s:option(Value, "DO_pin", translate("DO_pin")) +for i = 0,7 do pin:value(i) end + +pin = s:option(Value, "CLK_pin", translate("CLK_pin")) +for i = 0,7 do pin:value(i) end + +pin = s:option(Value, "CS_pin", translate("CS_pin")) +for i = 0,7 do pin:value(i) end + +s:option(Value, "mode", translate("mode")) + +return m diff --git a/openwrt/packages/luci/applications/luci-mmc_over_gpio/root/etc/uci-defaults/luci-mmc_over_gpio b/openwrt/packages/luci/applications/luci-mmc_over_gpio/root/etc/uci-defaults/luci-mmc_over_gpio new file mode 100644 index 0000000..3dd22ec --- /dev/null +++ b/openwrt/packages/luci/applications/luci-mmc_over_gpio/root/etc/uci-defaults/luci-mmc_over_gpio @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack mmc_over_gpio + set ucitrack.@mmc_over_gpio[-1].init=mmc_over_gpio + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-ntpc/Makefile b/openwrt/packages/luci/applications/luci-ntpc/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/controller/ntpc.lua b/openwrt/packages/luci/applications/luci-ntpc/luasrc/controller/ntpc.lua new file mode 100644 index 0000000..46595a7 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/controller/ntpc.lua @@ -0,0 +1,32 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ntpc.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.ntpc", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("ntpc") + if not luci.fs.access("/etc/config/ntpclient") then + return + end + + local page = entry({"admin", "system", "ntpc"}, cbi("ntpc/ntpc"), luci.i18n.translate("ntpc"), 50) + page.i18n = "ntpc" + page.dependent = true + + + local page = entry({"mini", "system", "ntpc"}, cbi("ntpc/ntpcmini", {autoapply=true}), luci.i18n.translate("ntpc"), 50) + page.i18n = "ntpc" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.lua b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.lua new file mode 100644 index 0000000..42ca434 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.lua @@ -0,0 +1,9 @@ +ntpc = 'Zeitsynchronisation' +ntpc_desc = 'Synchronisiert die Systemzeit' +ntpc_timeserver = 'Zeitserver' +ntpc_interval = 'Aktualisierungsintervall (in s)' +ntpc_count = 'Anzahl der Zeitmessungen' +ntpc_count_desc = 'leer = unendlich' +ntpc_drift = 'Zeitgeberjustierung' +ntpc_drift_freq = 'Frequenzabweichung' +ntpc_current = 'Aktuelle Systemzeit' diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.xml b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.xml new file mode 100644 index 0000000..e34484d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.de.xml @@ -0,0 +1,14 @@ + + + + +Zeitsynchronisation +Synchronisiert die Systemzeit +Zeitserver +Aktualisierungsintervall (in s) +Anzahl der Zeitmessungen +leer = unendlich +Zeitgeberjustierung +Frequenzabweichung +Aktuelle Systemzeit + diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.lua b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.lua new file mode 100644 index 0000000..35e3904 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.lua @@ -0,0 +1,9 @@ +ntpc = 'Time Synchronisation' +ntpc_desc = 'Synchronizes the system time' +ntpc_timeserver = 'Time Server' +ntpc_interval = 'Update Interval (in s)' +ntpc_count = 'Count of Time Measurements' +ntpc_count_desc = 'empty = infinite' +ntpc_drift = 'Clock Adjustment' +ntpc_drift_freq = 'Offset Frequency' +ntpc_current = 'Current system time' diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.xml b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.xml new file mode 100644 index 0000000..94c4092 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.en.xml @@ -0,0 +1,14 @@ + + + + +Time Synchronisation +Synchronizes the system time +Time Server +Update Interval (in s) +Count of Time Measurements +empty = infinite +Clock Adjustment +Offset Frequency +Current system time + diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.lua b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.lua new file mode 100644 index 0000000..be3ce5b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.lua @@ -0,0 +1,9 @@ +ntpc = 'Sincronização de Horário' +ntpc_desc = 'Sincroniza a hora do sistema' +ntpc_timeserver = 'Servidor de Hora' +ntpc_interval = 'Intervalo de Atualização (em s)' +ntpc_count = 'Quantas vezes irá atualizar' +ntpc_count_desc = 'vazio = infinito' +ntpc_drift = 'Ajuste do Relógio' +ntpc_drift_freq = 'Frequência do Offset' +ntpc_current = 'Hora atual do sistema' diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.xml b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.xml new file mode 100644 index 0000000..ed5e719 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/i18n/ntpc.pt-br.xml @@ -0,0 +1,14 @@ + + + + +Sincronização de Horário +Sincroniza a hora do sistema +Servidor de Hora +Intervalo de Atualização (em s) +Quantas vezes irá atualizar +vazio = infinito +Ajuste do Relógio +Frequência do Offset +Hora atual do sistema + diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpc.lua b/openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpc.lua new file mode 100644 index 0000000..50a62fc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpc.lua @@ -0,0 +1,39 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ntpc.lua 3240 2008-09-11 17:25:44Z Cyrus $ +]]-- +m = Map("ntpclient", translate("ntpc"), translate("ntpc_desc")) + +s = m:section(TypedSection, "ntpclient", translate("general")) +s.anonymous = true + +s:option(DummyValue, "_time", translate("ntpc_current")).value = os.date("%c") + +s:option(Value, "interval", translate("ntpc_interval")).rmempty = true +s:option(Value, "count", translate("ntpc_count"), translate("ntpc_count_desc")).rmempty = true + + +s2 = m:section(TypedSection, "ntpdrift", translate("ntpc_drift")) +s2.anonymous = true +s2:option(Value, "freq", translate("ntpc_drift_freq")).rmempty = true + + +s3 = m:section(TypedSection, "ntpserver", translate("ntpc_timeserver")) +s3.anonymous = true +s3.addremove = true +s3.template = "cbi/tblsection" + +s3:option(Value, "hostname", translate("hostname")) +s3:option(Value, "port", translate("port")).rmempty = true + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpcmini.lua b/openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpcmini.lua new file mode 100644 index 0000000..21241f1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/luasrc/model/cbi/ntpc/ntpcmini.lua @@ -0,0 +1,34 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ntpcmini.lua 3240 2008-09-11 17:25:44Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("ntpclient", translate("ntpc"), translate("ntpc_desc")) + +s = m:section(TypedSection, "ntpclient", translate("general")) +s.anonymous = true + +s:option(DummyValue, "_time", translate("ntpc_current")).value = os.date("%c") + +s:option(Value, "interval", translate("ntpc_interval")).rmempty = true + + +s3 = m:section(TypedSection, "ntpserver", translate("ntpc_timeserver")) +s3.anonymous = true +s3.addremove = true +s3.template = "cbi/tblsection" + +s3:option(Value, "hostname", translate("hostname")) +s3:option(Value, "port", translate("port")).rmempty = true + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-ntpc/root/lib/uci/schema/default/ntpclient b/openwrt/packages/luci/applications/luci-ntpc/root/lib/uci/schema/default/ntpclient new file mode 100644 index 0000000..0b7b5a5 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ntpc/root/lib/uci/schema/default/ntpclient @@ -0,0 +1,53 @@ +package ntpclient + +config package + option title 'Time Synchronisation' + +config section + option name 'ntpclient' + option package 'ntpclient' + option title 'General' + option unique true + option required true + +config variable + option name 'interval' + option section 'ntpclient.ntpclient' + option title 'Update Interval (in s)' + option datatype uint + +config variable + option name 'count' + option section 'ntpclient.ntpclient' + option title 'Count of Time Measurements' + option datatype uint + +config section + option name 'ntpdrift' + option package 'ntpclient' + option title 'Clock Adjustment' + option unique true + +config variable + option name 'freq' + option section 'ntpclient.ntpdrift' + option title 'Offset Frequency' + option datatype float + +config section + option name 'ntpserver' + option package 'ntpclient' + option title 'Time Server' + +config variable + option name 'hostname' + option section 'ntpclient.ntpserver' + option title 'Hostname' + option required true + option datatype host + +config variable + option name 'port' + option section 'ntpclient.ntpserver' + option title 'Port' + option datatype port diff --git a/openwrt/packages/luci/applications/luci-olsr/Makefile b/openwrt/packages/luci/applications/luci-olsr/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-olsr/ipkg/postinst b/openwrt/packages/luci/applications/luci-olsr/ipkg/postinst new file mode 100755 index 0000000..d2a7774 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-olsr ) && rm -f /etc/uci-defaults/luci-olsr +} diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/controller/olsr.lua b/openwrt/packages/luci/applications/luci-olsr/luasrc/controller/olsr.lua new file mode 100644 index 0000000..652f6b9 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/controller/olsr.lua @@ -0,0 +1,225 @@ +module("luci.controller.olsr", package.seeall) + +function index() + if not luci.fs.access("/etc/config/olsrd") then + return + end + + require("luci.i18n").loadc("olsr") + local i18n = luci.i18n.translate + + local page = node("admin", "status", "olsr") + page.target = call("action_index") + page.title = "OLSR" + page.i18n = "olsr" + page.subindex = true + + local page = node("admin", "status", "olsr", "routes") + page.target = call("action_routes") + page.title = i18n("olsr_routes", "Routen") + page.order = 10 + + local page = node("admin", "status", "olsr", "topology") + page.target = call("action_topology") + page.title = i18n("olsr_topology", "Topologie") + page.order = 20 + + local page = node("admin", "status", "olsr", "hna") + page.target = call("action_hna") + page.title = "HNA" + page.order = 30 + + local page = node("admin", "status", "olsr", "mid") + page.target = call("action_mid") + page.title = "MID" + page.order = 50 + + local ol = entry( + {"admin", "services", "olsrd"}, + cbi("olsr/olsrd"), "OLSR" + ) + ol.i18n = "olsr" + ol.subindex = true + + entry( + {"admin", "services", "olsrd", "hna"}, + cbi("olsr/olsrdhna"), "HNA Announcements" + ) + + oplg = entry( + {"admin", "services", "olsrd", "plugins"}, + cbi("olsr/olsrdplugins"), "Plugins" + ) + oplg.i18n = "olsr" + oplg.leaf = true + oplg.subindex = true + + local uci = require("luci.model.uci").cursor() + uci:foreach("olsrd", "LoadPlugin", + function (section) + local lib = section.library + entry( + {"admin", "services", "olsrd", "plugins", lib }, + cbi("olsr/olsrdplugins"), + nil --'Plugin "%s"' % lib:gsub("^olsrd_",""):gsub("%.so.+$","") + ) + end + ) +end + +function action_index() + local data = fetch_txtinfo("links") + + if not data or not data.Links then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + local c = tonumber(a.Cost) + local d = tonumber(b.Cost) + + if not c or c == 0 then + return false + end + + if not d or d == 0 then + return true + end + + return c < d + end + + table.sort(data.Links, compare) + + luci.template.render("status-olsr/index", {links=data.Links}) +end + +function action_routes() + local data = fetch_txtinfo("routes") + + if not data or not data.Routes then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + local c = tonumber(a.ETX) + local d = tonumber(b.ETX) + + if not c or c == 0 then + return false + end + + if not d or d == 0 then + return true + end + + return c < d + end + + table.sort(data.Routes, compare) + + luci.template.render("status-olsr/routes", {routes=data.Routes}) +end + +function action_topology() + local data = fetch_txtinfo("topology") + + if not data or not data.Topology then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + return a["Dest. IP"] < b["Dest. IP"] + end + + table.sort(data.Topology, compare) + + luci.template.render("status-olsr/topology", {routes=data.Topology}) +end + +function action_hna() + local data = fetch_txtinfo("hna") + + if not data or not data.HNA then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + return a.Destination < b.Destination + end + + table.sort(data.HNA, compare) + + luci.template.render("status-olsr/hna", {routes=data.HNA}) +end + +function action_mid() + local data = fetch_txtinfo("mid") + + if not data or not data.MID then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + return a["IP address"] < b["IP address"] + end + + table.sort(data.MID, compare) + + luci.template.render("status-olsr/mid", {mids=data.MID}) +end + + +-- Internal +function fetch_txtinfo(otable) + require("luci.sys") + otable = otable or "" + local rawdata = luci.sys.httpget("http://127.0.0.1:2006/"..otable) + + if #rawdata == 0 then + if luci.fs.access("/proc/net/ipv6_route", "r") then + rawdata = luci.sys.httpget("http://[::1]:2006/"..otable) + if #rawdata == 0 then + return nil + end + else + return nil + end + end + + local data = {} + + local tables = luci.util.split(luci.util.trim(rawdata), "\r?\n\r?\n", nil, true) + + + for i, tbl in ipairs(tables) do + local lines = luci.util.split(tbl, "\r?\n", nil, true) + local name = table.remove(lines, 1):sub(8) + local keys = luci.util.split(table.remove(lines, 1), "\t") + local split = #keys - 1 + + data[name] = {} + + for j, line in ipairs(lines) do + local fields = luci.util.split(line, "\t", split) + data[name][j] = {} + for k, key in pairs(keys) do + data[name][j][key] = fields[k] + end + + if data[name][j].Linkcost then + data[name][j].LinkQuality, + data[name][j].NLQ, + data[name][j].ETX = + data[name][j].Linkcost:match("([%w.]+)/([%w.]+)[%s]+([%w.]+)") + end + end + end + + return data +end diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.lua b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.lua new file mode 100644 index 0000000..4e652c8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.lua @@ -0,0 +1,127 @@ +olsrd = 'OLSR Daemon' +olsrd_neighbour_ip = 'Nachbar-IP' +olsrd_local_ip = 'Lokale Interface-IP' +olsrd_network = 'Angekündigtes Netzwerk' +olsrd_gateway = 'OLSR-Gateway' +olsrd_node = 'OLSR-Knoten' +olsrd_error = 'Es konnte keine Verbindung zum OLSR-Daemon hergestellt werden!' +olsrd_error_desc = 'Stellen Sie sicher das OLSRd läuft und das "txtinfo" Plugin auf Port 2006 geladen und "127.0.0.1" als Accept-Host gesetzt ist.' +olsrd_hna = 'OLSR - HNA-Ankündigungen' +olsrd_plugins = 'OLSR - Plugins' +olsrd_links = 'OLSR-Verbindungen' +olsrd_links_desc = 'Ãœbersicht über aktuell bestehende OLSR-Verbindungen' +olsrd_links_etx_desc = 'Zu erwartende Sendeversuche pro Paket' +olsrd_links_lq_desc = 'Erfolgsquote gesendeter Pakete' +olsrd_links_nlq_desc = 'Erfolgsquote empfangener Pakete' +olsrd_routes = 'Bekannte OLSR-Routen' +olsrd_routes_desc = 'Ãœbersicht über zur Zeit bekannte Routen zu anderen OLSR-Knoten' +olsrd_topology = 'Aktive OLSR-Knoten' +olsrd_topology_desc = 'Ãœbersicht über zur Zeit bekannte andere OLSR-Knoten' +olsrd_topology_lasthop = 'letzter Hop' +olsrd_hna2 = 'Aktive HNA-Ankündigungen' +olsrd_hna_desc = 'Ãœbersicht über zur Zeit aktive OLSR-Netzwerk-Ankündigungen' +olsrd_mid = 'Aktive MID-Ankündigungen' +olsrd_mid_desc = 'Ãœbersicht über bekannte Mehrfachschnittstellenmeldungen' +olsrd_mid_aliases = 'Sekundäre OLSR Schnittstellen' +olsrd_etx_ff = 'Freifunk' +olsrd_etx_float = 'Gleitkomma' +olsrd_etx_fpm = 'Festkomma' +olsrd_olsrd = 'Allgemeine Einstellungen' +olsrd_olsrd_allownoint = 'Start ohne Netzwerk' +olsrd_olsrd_clearscreen = 'Ansicht zurücksetzen' +olsrd_olsrd_debuglevel = 'Debugmodus' +olsrd_olsrd_fibmetric = 'FIB-Metrik' +olsrd_olsrd_ipversion = 'Internet Protokoll' +olsrd_olsrd_linkqualityaging = 'VQ-Alterung' +olsrd_olsrd_linkqualityalgorithm = 'VQ-Algorithmus' +olsrd_olsrd_linkqualitydijkstralimit = 'VQ-Dijkstralimit' +olsrd_olsrd_linkqualityfisheye = 'VQ-Fisheye' +olsrd_olsrd_linkqualitylevel = 'VQ-Level' +olsrd_olsrd_linkqualitylevel_1 = 'MPR-Auswahl' +olsrd_olsrd_linkqualitylevel_2 = 'MPR-Auswahl und Routing' +olsrd_olsrd_linkqualitywinsize = 'VQ-Fenstergröße' +olsrd_olsrd_mprcoverage = 'MPR-Erfassung' +olsrd_olsrd_pollrate = 'Abfragerate' +olsrd_olsrd_tcredundancy = 'TC-Redundanz' +olsrd_olsrd_tcredundancy_0 = 'MPR-Selektoren' +olsrd_olsrd_tcredundancy_1 = 'MPR-Selektoren und MPR' +olsrd_olsrd_tcredundancy_2 = 'Alle Nachbarn' +olsrd_olsrd_usehysteresis = 'Hysterese aktivieren' +olsrd_olsrd_willingness = 'Bereitschaft' +olsrd_interface_hellointerval = 'Hello-Intervall' +olsrd_interface_hellovaliditytime = 'Hello-Gültigkeit' +olsrd_interface_hnainterval = 'HNA-Intervall' +olsrd_interface_hnavaliditytime = 'HNA-Gültigkeit' +olsrd_interface_ip4broadcast = 'IPv4 Broadcast' +olsrd_interface_midinterval = 'MID-Intervall' +olsrd_interface_midvaliditytime = 'MID-Gültigkeit' +olsrd_interface_tcinterval = 'TC-Intervall' +olsrd_interface_tcvaliditytime = 'TC-Gültigkeit' +olsrd_interface_ip6addrtype = 'IPv6 Adresstyp' +olsrd_ipcconnect = 'IPC-Einstellungen' +olsrd_ipcconnect_desc = 'IPC-Verbindungen ermöglichen die Fernsteuerung des lokalen OLSR-Prozesses durch externe Programme' +olsrd_ipcconnect_host = 'Erlaubte Hostadressen' +olsrd_ipcconnect_host_desc = 'Mehrere mit Leerzeichen trennen' +olsrd_ipcconnect_maxconnections = 'Maximale Anzahl von Verbindungen' +olsrd_ipcconnect_maxconnections_desc = '0 deaktiviert IPC' +olsrd_ipcconnect_net = 'Erlaubte Netzbereiche' +olsrd_ipcconnect_net_desc = 'Adresse Maske; mehrere mit Leerzeichen' +olsrd_hna4 = 'IPv4 HNA-Ankündigungen' +olsrd_hna4_desc = 'Hna4-Entries ermöglichen die Ankündigung von lokalen IPv4 Host- und Netz-Routen im Mesh-Netzwerk' +olsrd_hna4_netaddr = 'Netzwerk-Adresse' +olsrd_hna4_netaddr_desc = 'IPv4 Adresse' +olsrd_hna4_netmask = 'Netzmaske' +olsrd_hna4_netmask_desc = 'IPv4 Adresse' +olsrd_hna6 = 'IPv6 HNA-Ankündigungen' +olsrd_hna6_desc = 'Hna6-Entries ermöglichen die Ankündigung von lokalen IPv6 Host- und Netz-Routen im Mesh-Netzwerk' +olsrd_hna6_netaddr = 'Netzwerk-Adresse' +olsrd_hna6_netaddr_desc = 'IPv6 Adresse' +olsrd_hna6_prefix = 'Prefix' +olsrd_hna6_prefix_desc = 'IPv6 Prefix' +olsrd_loadplugin = 'Pluginkonfiguration' +olsrd_loadplugin_ignore = 'Plugin aktivieren' +olsrd_loadplugin_library = 'Bibliothek' +olsrd_loadplugin_accept = 'Verbindungsaufbau von Addressen zulassen' +olsrd_loadplugin_ping = 'Pingtest Adressen' +olsrd_loadplugin_interval = 'Intervall' +olsrd_loadplugin_hna = 'HNA Ankündigungen' +olsrd_loadplugin_hna_desc = 'Format: IP-Adresse Netzmaske / OLSR kündigt dieses Netzwerk an sobald das Gateway erreichbar ist' +olsrd_loadplugin_addhosts = 'Alternative \"hosts\" Datei' +olsrd_loadplugin_addhosts_desc = 'Der Inhalt dieser Datei wird mit in die autogenerierte \"hosts\" Datei übernommen' +olsrd_loadplugin_dnsserver = 'DNS-Server' +olsrd_loadplugin_hosts = 'Alternative Hostnamen' +olsrd_loadplugin_hosts_desc = 'Format: Interface-IP Hostname' +olsrd_loadplugin_hostsfile = 'Pfad zur \"hosts\" Datei' +olsrd_loadplugin_lat = 'Latitude' +olsrd_loadplugin_latlonfile = 'Ausgabedatei für Koordinaten' +olsrd_loadplugin_latlonfile_desc = 'OLSR schreibt alle empfangenen Koordinaten anderer Knoten in diese Datei' +olsrd_loadplugin_latloninfile = 'Eingabedatei für Koordinaten' +olsrd_loadplugin_latloninfile_desc = 'OLSR prüft diese Datei periodisch auf neue Koordinaten und propagiert diese' +olsrd_loadplugin_lon = 'Longitude' +olsrd_loadplugin_name = 'Hostnamen' +olsrd_loadplugin_namechangescript = 'Kommando bei Namensänderungen' +olsrd_loadplugin_namechangescript_desc = 'OLSR ruft dieses Kommando auf sobald sich Einträge in der \"hosts\" Datei ändern' +olsrd_loadplugin_resolvfile = 'Pfad zur \"resolv\" Datei' +olsrd_loadplugin_serviceschangescript = 'Kommando bei Serviceänderungen' +olsrd_loadplugin_serviceschangescript_desc = 'OLSR ruft dieses Kommando auf sobald neue Service-Ankündigungen empfangen werden' +olsrd_loadplugin_sighuppidfile = 'PID-Datei für SIGHUP Signale' +olsrd_loadplugin_sighuppidfile_desc = 'OLSR sendet ein HUP Signal an den in der PID Datei angegebenen Prozess sobald sich die \"hosts\" oder \"resolv\" Datei ändert' +olsrd_loadplugin_suffix = 'Domain-Suffix' +olsrd_loadplugin_timeout = 'Timeout' +olsrd_loadplugin_bmfinterface = 'Name für die BMF-Schnittstelle' +olsrd_loadplugin_bmfinterfaceid = 'IP-Adresse für die BMF-Schnittstelle' +olsrd_loadplugin_dolocalbroadcast = 'Lokale Broadcasts weiterleiten' +olsrd_loadplugin_capturepacketsonolsrinterfaces = 'Broadcasts von OLSR-Schnittstellen weiterleiten' +olsrd_loadplugin_bmfmechanism = 'Verteilungsmechanismus' +olsrd_loadplugin_broadcastretransmitcount = 'Anzahl der Neuversendungen pro Paket' +olsrd_loadplugin_fanoutlimit = 'Mindestanzahl der Nachbarn für Broadcastweiterleitung' +olsrd_loadplugin_nonolsrif = 'Nicht-OLSR-Interfaces' +olsrd_loadplugin_port = 'Verwendeter Port' +olsrd_loadplugin_host = 'Verbindungsaufbau von Hosts zulassen' +olsrd_loadplugin_net = 'Verbindungsaufbau von Subnetzen zulassen' +olsrd_loadplugin_net_desc = 'Format: IP-Adresse Netzmaske' +olsrd_loadplugin_redistribute = 'Verwendete Protokolle' +olsrd_loadplugin_exportroutes = 'Routen nur an Quagga oder auch an Kernel exportieren' +olsrd_loadplugin_localpref = 'Lokale Routen immer bevorzugen' +olsrd_loadplugin_distance = 'Distanz für exportierte Routen' +olsrd_loadplugin_keyfile = 'Schlüsseldatei' diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.xml b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.xml new file mode 100644 index 0000000..6b003aa --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.de.xml @@ -0,0 +1,184 @@ + + + + + + +OLSR Daemon +Nachbar-IP +Lokale Interface-IP +Angekündigtes Netzwerk +OLSR-Gateway +OLSR-Knoten +Es konnte keine Verbindung zum OLSR-Daemon hergestellt werden! +Stellen Sie sicher das OLSRd läuft und das "txtinfo" Plugin auf Port 2006 geladen und "127.0.0.1" als Accept-Host gesetzt ist. +OLSR - HNA-Ankündigungen +OLSR - Plugins + + + + +OLSR-Verbindungen +Ãœbersicht über aktuell bestehende OLSR-Verbindungen +Zu erwartende Sendeversuche pro Paket +Erfolgsquote gesendeter Pakete +Erfolgsquote empfangener Pakete + + +Bekannte OLSR-Routen +Ãœbersicht über zur Zeit bekannte Routen zu anderen OLSR-Knoten + + +Aktive OLSR-Knoten +Ãœbersicht über zur Zeit bekannte andere OLSR-Knoten +letzter Hop + + +Aktive HNA-Ankündigungen +Ãœbersicht über zur Zeit aktive OLSR-Netzwerk-Ankündigungen + + +Aktive MID-Ankündigungen +Ãœbersicht über bekannte Mehrfachschnittstellenmeldungen +Sekundäre OLSR Schnittstellen + + + + +Freifunk +Gleitkomma +Festkomma +Allgemeine Einstellungen +Start ohne Netzwerk +Ansicht zurücksetzen +Debugmodus +FIB-Metrik +Internet Protokoll +VQ-Alterung +VQ-Algorithmus +VQ-Dijkstralimit +VQ-Fisheye +VQ-Level +MPR-Auswahl +MPR-Auswahl und Routing +VQ-Fenstergröße +MPR-Erfassung +Abfragerate +TC-Redundanz +MPR-Selektoren +MPR-Selektoren und MPR +Alle Nachbarn +Hysterese aktivieren +Bereitschaft + + + + +Hello-Intervall +Hello-Gültigkeit +HNA-Intervall +HNA-Gültigkeit +IPv4 Broadcast +MID-Intervall +MID-Gültigkeit +TC-Intervall +TC-Gültigkeit +IPv6 Adresstyp + + + + +IPC-Einstellungen +IPC-Verbindungen ermöglichen die Fernsteuerung des lokalen OLSR-Prozesses durch externe Programme +Erlaubte Hostadressen +Mehrere mit Leerzeichen trennen +Maximale Anzahl von Verbindungen +0 deaktiviert IPC +Erlaubte Netzbereiche +Adresse Maske; mehrere mit Leerzeichen + + + + + +IPv4 HNA-Ankündigungen +Hna4-Entries ermöglichen die Ankündigung von lokalen IPv4 Host- und Netz-Routen im Mesh-Netzwerk +Netzwerk-Adresse +IPv4 Adresse +Netzmaske +IPv4 Adresse + + +IPv6 HNA-Ankündigungen +Hna6-Entries ermöglichen die Ankündigung von lokalen IPv6 Host- und Netz-Routen im Mesh-Netzwerk +Netzwerk-Adresse +IPv6 Adresse +Prefix +IPv6 Prefix + + + + +Pluginkonfiguration +Plugin aktivieren +Bibliothek + + +Verbindungsaufbau von Addressen zulassen + + +Pingtest Adressen +Intervall +HNA Ankündigungen +Format: IP-Adresse Netzmaske / OLSR kündigt dieses Netzwerk an sobald das Gateway erreichbar ist + + +Alternative "hosts" Datei +Der Inhalt dieser Datei wird mit in die autogenerierte "hosts" Datei übernommen +DNS-Server +Alternative Hostnamen +Format: Interface-IP Hostname +Pfad zur "hosts" Datei +Latitude +Ausgabedatei für Koordinaten +OLSR schreibt alle empfangenen Koordinaten anderer Knoten in diese Datei +Eingabedatei für Koordinaten +OLSR prüft diese Datei periodisch auf neue Koordinaten und propagiert diese +Longitude +Hostnamen +Kommando bei Namensänderungen +OLSR ruft dieses Kommando auf sobald sich Einträge in der "hosts" Datei ändern +Pfad zur "resolv" Datei +Kommando bei Serviceänderungen +OLSR ruft dieses Kommando auf sobald neue Service-Ankündigungen empfangen werden +PID-Datei für SIGHUP Signale +OLSR sendet ein HUP Signal an den in der PID Datei angegebenen Prozess sobald sich die "hosts" oder "resolv" Datei ändert +Domain-Suffix +Timeout + + +Name für die BMF-Schnittstelle +IP-Adresse für die BMF-Schnittstelle +Lokale Broadcasts weiterleiten +Broadcasts von OLSR-Schnittstellen weiterleiten +Verteilungsmechanismus +Anzahl der Neuversendungen pro Paket +Mindestanzahl der Nachbarn für Broadcastweiterleitung +Nicht-OLSR-Interfaces + + +Verwendeter Port +Verbindungsaufbau von Hosts zulassen +Verbindungsaufbau von Subnetzen zulassen +Format: IP-Adresse Netzmaske + + +Verwendete Protokolle +Routen nur an Quagga oder auch an Kernel exportieren +Lokale Routen immer bevorzugen +Distanz für exportierte Routen + + +Schlüsseldatei + + diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.lua b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.lua new file mode 100644 index 0000000..dc1e442 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.lua @@ -0,0 +1,127 @@ +olsrd = 'OLSR Daemon' +olsrd_neighbour_ip = 'Neighbour IP' +olsrd_local_ip = 'Local interface IP' +olsrd_network = 'Announced network' +olsrd_gateway = 'OLSR gateway' +olsrd_node = 'OLSR node' +olsrd_error = 'Unable to connect to the OLSR daemon!' +olsrd_error_desc = 'Make sure that OLSRd is running, the "txtinfo" plugin is loaded, configured on port 2006 and accepts connections from "127.0.0.1".' +olsrd_hna = 'OLSR - HNA-Announcements' +olsrd_plugins = 'OLSR - Plugins' +olsrd_links = 'OLSR connections' +olsrd_links_desc = 'Overview of currently established OLSR connections' +olsrd_links_etx_desc = 'Expected retransmission count' +olsrd_links_lq_desc = 'Success rate of sent packages' +olsrd_links_nlq_desc = 'Success rate of received packages' +olsrd_routes = 'Known OLSR routes' +olsrd_routes_desc = 'Overview of currently known routes to other OLSR nodes' +olsrd_topology = 'Active OLSR nodes' +olsrd_topology_desc = 'Overview of currently known OLSR nodes' +olsrd_topology_lasthop = 'Last hop' +olsrd_hna2 = 'Active host net announcements' +olsrd_hna_desc = 'Overview of currently active OLSR host net announcements' +olsrd_mid = 'Active MID announcements' +olsrd_mid_desc = 'Overview of known multiple interface announcements' +olsrd_mid_aliases = 'Secondary OLSR interfaces' +olsrd_etx_ff = 'Freifunk' +olsrd_etx_float = 'floating point' +olsrd_etx_fpm = 'fixed point math' +olsrd_olsrd = 'General settings' +olsrd_olsrd_allownoint = 'Start without network' +olsrd_olsrd_clearscreen = 'Clear screen' +olsrd_olsrd_debuglevel = 'Debugmode' +olsrd_olsrd_fibmetric = 'FIB metric' +olsrd_olsrd_ipversion = 'Internet protocol' +olsrd_olsrd_linkqualityaging = 'LQ aging' +olsrd_olsrd_linkqualityalgorithm = 'LQ algorithm' +olsrd_olsrd_linkqualitydijkstralimit = 'LQ Dijkstra limit' +olsrd_olsrd_linkqualityfisheye = 'LQ fisheye' +olsrd_olsrd_linkqualitylevel = 'LQ level' +olsrd_olsrd_linkqualitylevel_1 = 'MPR selection' +olsrd_olsrd_linkqualitylevel_2 = 'MPR selection and routing' +olsrd_olsrd_linkqualitywinsize = 'LQ window size' +olsrd_olsrd_mprcoverage = 'MPR coverage' +olsrd_olsrd_pollrate = 'Pollrate' +olsrd_olsrd_tcredundancy = 'TC redundancy' +olsrd_olsrd_tcredundancy_0 = 'MPR selectors' +olsrd_olsrd_tcredundancy_1 = 'MPR selectors and MPR' +olsrd_olsrd_tcredundancy_2 = 'all neighbours' +olsrd_olsrd_usehysteresis = 'Use hysteresis' +olsrd_olsrd_willingness = 'Willingness' +olsrd_interface_hellointerval = 'Hello interval' +olsrd_interface_hellovaliditytime = 'Hello validity time' +olsrd_interface_hnainterval = 'HNA interval' +olsrd_interface_hnavaliditytime = 'HNA validity time' +olsrd_interface_ip4broadcast = 'IPv4 broadcast' +olsrd_interface_midinterval = 'MID interval' +olsrd_interface_midvaliditytime = 'MID validity time' +olsrd_interface_tcinterval = 'TC interval' +olsrd_interface_tcvaliditytime = 'TC validity time' +olsrd_interface_ip6addrtype = 'IPv6 address type' +olsrd_ipcconnect = 'IPC settings' +olsrd_ipcconnect_desc = 'IPC connections enable you to remote-control the local OLSRd instance using external programs' +olsrd_ipcconnect_host = 'Allowed host addresses' +olsrd_ipcconnect_host_desc = 'Multiple separated by spaces' +olsrd_ipcconnect_maxconnections = 'Maxmimum connection count' +olsrd_ipcconnect_maxconnections_desc = 'Set to 0 to disable IPC' +olsrd_ipcconnect_net = 'Allowed subnets' +olsrd_ipcconnect_net_desc = 'Address Mask; multiple separated by space' +olsrd_hna4 = 'IPv4 HNA announcements' +olsrd_hna4_desc = 'Hna4 entries allow you to propagate local IPv4 host- and network-routes into the mesh network' +olsrd_hna4_netaddr = 'Network address' +olsrd_hna4_netaddr_desc = 'IPv4 address' +olsrd_hna4_netmask = 'Netmask' +olsrd_hna4_netmask_desc = 'IPv4 address' +olsrd_hna6 = 'IPv6 HNA announcements' +olsrd_hna6_desc = 'Hna6 entries allow you to propagate local IPv6 host- and network-routes into the mesh network' +olsrd_hna6_netaddr = 'Network address' +olsrd_hna6_netaddr_desc = 'IPv6 address' +olsrd_hna6_prefix = 'Prefix' +olsrd_hna6_prefix_desc = 'IPv6 prefix' +olsrd_loadplugin = 'Plugin configuration' +olsrd_loadplugin_ignore = 'Enable plugin' +olsrd_loadplugin_library = 'Library' +olsrd_loadplugin_accept = 'Allow connections from this hosts' +olsrd_loadplugin_ping = 'Ping test addresses' +olsrd_loadplugin_interval = 'Interval' +olsrd_loadplugin_hna = 'HNA announcements' +olsrd_loadplugin_hna_desc = 'Format: IP-Address Netmask / OLSR will announce this network once it is reachable' +olsrd_loadplugin_addhosts = 'Alternative \"hosts\" file' +olsrd_loadplugin_addhosts_desc = 'The contents of this file will be appended to the autogenerated \"hosts\" file' +olsrd_loadplugin_dnsserver = 'DNS server' +olsrd_loadplugin_hosts = 'Alternative hostnames' +olsrd_loadplugin_hosts_desc = 'Format: Interface-IP Hostname' +olsrd_loadplugin_hostsfile = 'Path to the \"hosts\" file' +olsrd_loadplugin_lat = 'Latitude' +olsrd_loadplugin_latlonfile = 'Output file for coordinates' +olsrd_loadplugin_latlonfile_desc = 'OLSR will write received coordinates of other nodes to this file' +olsrd_loadplugin_latloninfile = 'Input file for coordinates' +olsrd_loadplugin_latloninfile_desc = 'OLSR periodically checks this file for new coordinates and propagates them' +olsrd_loadplugin_lon = 'Longitude' +olsrd_loadplugin_name = 'Hostnames' +olsrd_loadplugin_namechangescript = 'Command for name changes' +olsrd_loadplugin_namechangescript_desc = 'OLSR executes this command once entries in the \"hosts\" are changed' +olsrd_loadplugin_resolvfile = 'Path to the \"resolv\" file' +olsrd_loadplugin_serviceschangescript = 'Command for service changes' +olsrd_loadplugin_serviceschangescript_desc = 'OLSR excutes this command once new service announcements are received' +olsrd_loadplugin_sighuppidfile = 'PID file for SIGHUP signals' +olsrd_loadplugin_sighuppidfile_desc = 'OLSR sends a HUP signal to this PID once the \"hosts\" oder \"resolv\" file is changed' +olsrd_loadplugin_suffix = 'Domain suffix' +olsrd_loadplugin_timeout = 'Timeout' +olsrd_loadplugin_bmfinterface = 'Name of the BMF interface' +olsrd_loadplugin_bmfinterfaceid = 'IP address of the BMF interface' +olsrd_loadplugin_dolocalbroadcast = 'Redirect local broadcasts' +olsrd_loadplugin_capturepacketsonolsrinterfaces = 'Also redirect broadcasts from OLSR interfaces' +olsrd_loadplugin_bmfmechanism = 'Propagation mechanism' +olsrd_loadplugin_broadcastretransmitcount = 'Number of retransmissions per package' +olsrd_loadplugin_fanoutlimit = 'Minimum number of neighbours for broadcast redirection' +olsrd_loadplugin_nonolsrif = 'Non-OLSR interfaces' +olsrd_loadplugin_port = 'Used port' +olsrd_loadplugin_host = 'Allow connections from hosts' +olsrd_loadplugin_net = 'Allow connections from subnets' +olsrd_loadplugin_net_desc = 'Format: IP-AddresseNetmask' +olsrd_loadplugin_redistribute = 'Used protocols' +olsrd_loadplugin_exportroutes = 'Only export routes to Quagga or to kernel too' +olsrd_loadplugin_localpref = 'Always prefer local routes' +olsrd_loadplugin_distance = 'Distance of exported routes' +olsrd_loadplugin_keyfile = 'Key file' diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.xml b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.xml new file mode 100644 index 0000000..a8da243 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/i18n/olsr.en.xml @@ -0,0 +1,184 @@ + + + + + + +OLSR Daemon +Neighbour IP +Local interface IP +Announced network +OLSR gateway +OLSR node +Unable to connect to the OLSR daemon! +Make sure that OLSRd is running, the "txtinfo" plugin is loaded, configured on port 2006 and accepts connections from "127.0.0.1". +OLSR - HNA-Announcements +OLSR - Plugins + + + + +OLSR connections +Overview of currently established OLSR connections +Expected retransmission count +Success rate of sent packages +Success rate of received packages + + +Known OLSR routes +Overview of currently known routes to other OLSR nodes + + +Active OLSR nodes +Overview of currently known OLSR nodes +Last hop + + +Active host net announcements +Overview of currently active OLSR host net announcements + + +Active MID announcements +Overview of known multiple interface announcements +Secondary OLSR interfaces + + + + +Freifunk +floating point +fixed point math +General settings +Start without network +Clear screen +Debugmode +FIB metric +Internet protocol +LQ aging +LQ algorithm +LQ Dijkstra limit +LQ fisheye +LQ level +MPR selection +MPR selection and routing +LQ window size +MPR coverage +Pollrate +TC redundancy +MPR selectors +MPR selectors and MPR +all neighbours +Use hysteresis +Willingness + + + + +Hello interval +Hello validity time +HNA interval +HNA validity time +IPv4 broadcast +MID interval +MID validity time +TC interval +TC validity time +IPv6 address type + + + + +IPC settings +IPC connections enable you to remote-control the local OLSRd instance using external programs +Allowed host addresses +Multiple separated by spaces +Maxmimum connection count +Set to 0 to disable IPC +Allowed subnets +Address Mask; multiple separated by space + + + + + +IPv4 HNA announcements +Hna4 entries allow you to propagate local IPv4 host- and network-routes into the mesh network +Network address +IPv4 address +Netmask +IPv4 address + + +IPv6 HNA announcements +Hna6 entries allow you to propagate local IPv6 host- and network-routes into the mesh network +Network address +IPv6 address +Prefix +IPv6 prefix + + + + +Plugin configuration +Enable plugin +Library + + +Allow connections from this hosts + + +Ping test addresses +Interval +HNA announcements +Format: IP-Address Netmask / OLSR will announce this network once it is reachable + + +Alternative "hosts" file +The contents of this file will be appended to the autogenerated "hosts" file +DNS server +Alternative hostnames +Format: Interface-IP Hostname +Path to the "hosts" file +Latitude +Output file for coordinates +OLSR will write received coordinates of other nodes to this file +Input file for coordinates +OLSR periodically checks this file for new coordinates and propagates them +Longitude +Hostnames +Command for name changes +OLSR executes this command once entries in the "hosts" are changed +Path to the "resolv" file +Command for service changes +OLSR excutes this command once new service announcements are received +PID file for SIGHUP signals +OLSR sends a HUP signal to this PID once the "hosts" oder "resolv" file is changed +Domain suffix +Timeout + + +Name of the BMF interface +IP address of the BMF interface +Redirect local broadcasts +Also redirect broadcasts from OLSR interfaces +Propagation mechanism +Number of retransmissions per package +Minimum number of neighbours for broadcast redirection +Non-OLSR interfaces + + +Used port +Allow connections from hosts +Allow connections from subnets +Format: IP-AddresseNetmask + + +Used protocols +Only export routes to Quagga or to kernel too +Always prefer local routes +Distance of exported routes + + +Key file + + diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrd.lua b/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrd.lua new file mode 100644 index 0000000..bf4c7b6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrd.lua @@ -0,0 +1,145 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: olsrd.lua 4204 2009-01-31 03:02:57Z jow $ +]]-- + +require("luci.tools.webadmin") + +m = Map("olsrd", translate("olsrd", "OLSR Daemon")) + +s = m:section(TypedSection, "olsrd", translate("olsrd_general")) +s.dynamic = true +s.anonymous = true + +debug = s:option(ListValue, "DebugLevel") +for i=0, 9 do + debug:value(i) +end +debug.optional = true + +ipv = s:option(ListValue, "IpVersion") +ipv:value("4", "IPv4") +ipv:value("6", "IPv6") + +noint = s:option(Flag, "AllowNoInt") +noint.enabled = "yes" +noint.disabled = "no" +noint.optional = true + +s:option(Value, "Pollrate").optional = true + +tcr = s:option(ListValue, "TcRedundancy") +tcr:value("0", translate("olsrd_olsrd_tcredundancy_0")) +tcr:value("1", translate("olsrd_olsrd_tcredundancy_1")) +tcr:value("2", translate("olsrd_olsrd_tcredundancy_2")) +tcr.optional = true + +s:option(Value, "MprCoverage").optional = true + +lql = s:option(ListValue, "LinkQualityLevel") +lql:value("0", translate("disable")) +lql:value("1", translate("olsrd_olsrd_linkqualitylevel_1")) +lql:value("2", translate("olsrd_olsrd_linkqualitylevel_2")) +lql.optional = true + +s:option(Value, "LinkQualityAging").optional = true + +lqa = s:option(ListValue, "LinkQualityAlgorithm") +lqa.optional = true +lqa:value("etx_fpm", translate("olsrd_etx_fpm")) +lqa:value("etx_float", translate("olsrd_etx_float")) +lqa:value("etx_ff", translate("olsrd_etx_ff")) +lqa.optional = true + +lqfish = s:option(Flag, "LinkQualityFishEye") +lqfish.optional = true + +s:option(Value, "LinkQualityWinSize").optional = true + +s:option(Value, "LinkQualityDijkstraLimit").optional = true + +hyst = s:option(Flag, "UseHysteresis") +hyst.enabled = "yes" +hyst.disabled = "no" +hyst.optional = true + +fib = s:option(ListValue, "FIBMetric") +fib.optional = true +fib:value("flat") +fib:value("correct") +fib:value("approx") +fib.optional = true + +clrscr = s:option(Flag, "ClearScreen") +clrscr.enabled = "yes" +clrscr.disabled = "no" +clrscr.optional = true + +willingness = s:option(ListValue, "Willingness") +for i=0,7 do + willingness:value(i) +end +willingness.optional = true + + + +i = m:section(TypedSection, "Interface", translate("interfaces")) +i.anonymous = true +i.addremove = true +i.dynamic = true + +ign = i:option(Flag, "ignore", "Enable") +ign.enabled = "0" +ign.disabled = "1" + +network = i:option(ListValue, "interface", translate("network")) +luci.tools.webadmin.cbi_add_networks(network) + +i:option(Value, "Ip4Broadcast").optional = true + +ip6t = i:option(ListValue, "Ip6AddrType") +ip6t:value("", translate("cbi_select")) +ip6t:value("auto") +ip6t:value("site-local") +ip6t:value("unique-local") +ip6t:value("global") +ip6t.optional = true + +i:option(Value, "HelloInterval").optional = true +i:option(Value, "HelloValidityTime").optional = true +i:option(Value, "TcInterval").optional = true +i:option(Value, "TcValidityTime").optional = true +i:option(Value, "MidInterval").optional = true +i:option(Value, "MidValidityTime").optional = true +i:option(Value, "HnaInterval").optional = true +i:option(Value, "HnaValidityTime").optional = true + +adc = i:option(Flag, "AutoDetectChanges") +adc.enabled = "yes" +adc.disabled = "no" +adc.optional = true + +--[[ +ipc = m:section(TypedSection, "IpcConnect") +ipc.anonymous = true + +conns = ipc:option(Value, "MaxConnections") +conns.isInteger = true + +nets = ipc:option(Value, "Net") +nets.optional = true + +hosts = ipc:option(Value, "Host") +hosts.optional = true +]] + +return m diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdhna.lua b/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdhna.lua new file mode 100644 index 0000000..cbf02a4 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdhna.lua @@ -0,0 +1,36 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: olsrdhna.lua 3823 2008-11-27 14:26:37Z jow $ +]]-- + +mh = Map("olsrd", translate("olsrd_hna", "OLSR - HNA-Ankündigungen")) + + +hna4 = mh:section(TypedSection, "Hna4") +hna4.addremove = true +hna4.anonymous = true +hna4.template = "cbi/tblsection" + +net4 = hna4:option(Value, "netaddr") +msk4 = hna4:option(Value, "netmask") + + +hna6 = mh:section(TypedSection, "Hna6") +hna6.addremove = true +hna6.anonymous = true +hna6.template = "cbi/tblsection" + +net6 = hna6:option(Value, "netaddr") +msk6 = hna6:option(Value, "prefix") + + +return mh diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdplugins.lua b/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdplugins.lua new file mode 100644 index 0000000..5be4662 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/model/cbi/olsr/olsrdplugins.lua @@ -0,0 +1,244 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: olsrdplugins.lua 3976 2009-01-01 14:33:36Z jow $ +]]-- + +require("luci.fs") +require("luci.ip") + + +if arg[1] then + mp = Map("olsrd", translate("olsrd_plugins", "OLSR - Plugins")) + + p = mp:section(TypedSection, "LoadPlugin") + p:depends("library", arg[1]) + p.anonymous = true + + ign = p:option(Flag, "ignore", "Enable") + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + lib = p:option(DummyValue, "library", translate("library")) + lib.default = arg[1] + + local function Range(x,y) + local t = {} + for i = x, y do t[#t+1] = i end + return t + end + + local function Cidr2IpMask(val) + if val then + for i = 1, #val do + local cidr = luci.ip.IPv4(val[i]) or luci.ip.IPv6(val[i]) + if cidr then + val[i] = cidr:network():string() .. " " .. cidr:mask():string() + end + end + return val + end + end + + local function IpMask2Cidr(val) + if val then + for i = 1, #val do + local ip, mask = val[i]:gmatch("([^%s+])%s+([^%s+])")() + local cidr + if ip and mask and ip:match(":") then + cidr = luci.ip.IPv6(ip, mask) + elseif ip and mask then + cidr = luci.ip.IPv4(ip, mask) + end + + if cidr then + val[i] = cidr:string() + end + end + return val + end + end + + + local knownPlParams = { + ["olsrd_bmf.so.1.5.3"] = { + { Value, "BmfInterface", "bmf0" }, + { Value, "BmfInterfaceIp", "10.10.10.234/24" }, + { Flag, "DoLocalBroadcast", "no" }, + { Flag, "CapturePacketsOnOlsrInterfaces", "yes" }, + { ListValue, "BmfMechanism", { "UnicastPromiscuous", "Broadcast" } }, + { Value, "BroadcastRetransmitCount", "2" }, + { Value, "FanOutLimit", "4" }, + { DynamicList, "NonOlsrIf", "eth1" } + }, + + ["olsrd_dyn_gw.so.0.4"] = { + { Value, "Interval", "40" }, + { DynamicList, "Ping", "141.1.1.1" }, + { DynamicList, "HNA", "192.168.80.0/24", IpMask2Cidr, Cidr2IpMask } + }, + + ["olsrd_httpinfo.so.0.1"] = { + { Value, "port", "80" }, + { DynamicList, "Host", "163.24.87.3" }, + { DynamicList, "Net", "0.0.0.0/0", IpMask2Cidr, Cidr2IpMask } + }, + + ["olsrd_nameservice.so.0.3"] = { + { DynamicList, "name", "my-name.mesh" }, + { DynamicList, "hosts", "1.2.3.4 name-for-other-interface.mesh" }, + { Value, "suffix", ".olsr" }, + { Value, "hosts_file", "/path/to/hosts_file" }, + { Value, "add_hosts", "/path/to/file" }, + { Value, "dns_server", "141.1.1.1" }, + { Value, "resolv_file", "/path/to/resolv.conf" }, + { Value, "interval", "120" }, + { Value, "timeout", "240" }, + { Value, "lat", "12.123" }, + { Value, "lon", "12.123" }, + { Value, "latlon_file", "/var/run/latlon.js" }, + { Value, "latlon_infile", "/var/run/gps.txt" }, + { Value, "sighup_pid_file", "/var/run/dnsmasq.pid" }, + { Value, "name_change_script", "/usr/local/bin/announce_new_hosts.sh" }, + { Value, "services_change_script", "/usr/local/bin/announce_new_services.sh" } + }, + + ["olsrd_quagga.so.0.2.2"] = { + { StaticList, "redistribute", { + "system", "kernel", "connect", "static", "rip", "ripng", "ospf", + "ospf6", "isis", "bgp", "hsls" + } }, + { ListValue, "ExportRoutes", { "only", "both" } }, + { Flag, "LocalPref", "true" }, + { Value, "Distance", Range(0,255) } + }, + + ["olsrd_secure.so.0.5"] = { + { Value, "Keyfile", "/etc/private-olsr.key" } + }, + + ["olsrd_txtinfo.so.0.1"] = { + { Value, "accept", "10.247.200.4" } + }, + + ["olsrd_arprefresh.so.0.1"] = {}, + ["olsrd_dot_draw.so.0.3"] = {}, + ["olsrd_dyn_gw_plain.so.0.4"] = {}, + ["olsrd_pgraph.so.1.1"] = {}, + ["olsrd_tas.so.0.1"] = {} + } + + + -- build plugin options with dependencies + if knownPlParams[arg[1]] then + for _, option in ipairs(knownPlParams[arg[1]]) do + local otype, name, default, uci2cbi, cbi2uci = unpack(option) + local values + + if type(default) == "table" then + values = default + default = default[1] + end + + if otype == Flag then + local bool = p:option( Flag, name ) + if default == "yes" or default == "no" then + bool.enabled = "yes" + bool.disabled = "no" + elseif default == "on" or default == "off" then + bool.enabled = "on" + bool.disabled = "off" + elseif default == "1" or default == "0" then + bool.enabled = "1" + bool.disabled = "0" + else + bool.enabled = "true" + bool.disabled = "false" + end + bool.optional = true + bool.default = default + bool:depends({ library = plugin }) + else + local field = p:option( otype, name ) + if values then + for _, value in ipairs(values) do + field:value( value ) + end + end + if type(uci2cbi) == "function" then + function field.cfgvalue(self, section) + return uci2cbi(otype.cfgvalue(self, section)) + end + end + if type(cbi2uci) == "function" then + function field.formvalue(self, section) + return cbi2uci(otype.formvalue(self, section)) + end + end + field.optional = true + field.default = default + --field:depends({ library = arg[1] }) + end + end + end + + return mp + +else + + mpi = Map("olsrd", "OLSR - Plugins") + + local plugins = {} + mpi.uci:foreach("olsrd", "LoadPlugin", + function(section) + if section.library and not plugins[section.library] then + plugins[section.library] = true + end + end + ) + + -- create a loadplugin section for each found plugin + for k, v in pairs(luci.fs.dir("/usr/lib")) do + if v:sub(1, 6) == "olsrd_" then + if not plugins[v] then + mpi.uci:section( + "olsrd", "LoadPlugin", nil, + { library = v, ignore = 1 } + ) + end + end + end + + t = mpi:section( TypedSection, "LoadPlugin", "Plugins" ) + t.anonymous = true + t.template = "cbi/tblsection" + t.override_scheme = true + function t.extedit(self, section) + local lib = self.map:get(section, "library") or "" + return luci.dispatcher.build_url("admin", "services", "olsrd", "plugins") .. "/" .. lib + end + + ign = t:option( Flag, "ignore", "Enabled" ) + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + t:option( DummyValue, "library", "Library" ) + + return mpi +end diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/error_olsr.htm b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/error_olsr.htm new file mode 100644 index 0000000..fbb0f11 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/error_olsr.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: error_olsr.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd%>

+

<%:olsrd_error%>

+

<%:olsrd_error_desc%>

+<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/hna.htm b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/hna.htm new file mode 100644 index 0000000..5108fe1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/hna.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: hna.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_hna2%>

+

<%:olsrd_hna_desc%>

+
+ + + + + +<% for k, route in ipairs(routes) do %> + + + + +<% end %> +
<%:olsrd_network%><%:olsrd_gateway%>
<%=route.Destination%><%=route.Gateway%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/index.htm b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/index.htm new file mode 100644 index 0000000..e1fa009 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/index.htm @@ -0,0 +1,57 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_links%>

+

<%:olsrd_links_desc%>

+
+ + + + + + + + +<% for k, link in ipairs(links) do + local color = "#bb3333" + + link.Cost = tonumber(link.Cost) or 0 + if link.Cost == 0 then + color = "#bb3333" + elseif link.Cost < 4 then + color = "#00cc00" + elseif link.Cost < 10 then + color = "#ffcb05" + elseif link.Cost < 100 then + color = "#ff6600" + end +%> + + + + + + + +<% end %> +
<%:olsrd_neighbour_ip%><%:olsrd_local_ip%>LQNLQETX
"><%=link["Remote IP"]%><%=link["Local IP"]%><%=link.LQ%><%=link.NLQ%><%=string.format("%.3f", link.Cost)%>
+
+

<%:legend%>:

+
    +
  • LQ: <%:olsrd_links_lq_desc%>
  • +
  • NLQ: <%:olsrd_links_nlq_desc%>
  • +
  • ETX: <%:olsrd_links_etx_desc%>
  • +
+<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/mid.htm b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/mid.htm new file mode 100644 index 0000000..9a3cf5f --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/mid.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: mid.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_mid%>

+

<%:olsrd_mid_desc%>

+
+ + + + + +<% for k, mid in ipairs(mids) do %> + + + + +<% end %> +
<%:olsrd_node%><%:olsrd_mid_aliases%>
"><%=mid["IP address"]%><%=mid.Aliases%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/routes.htm b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/routes.htm new file mode 100644 index 0000000..ae176ae --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/routes.htm @@ -0,0 +1,51 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: routes.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_routes%>

+

<%:olsrd_routes_desc%>

+
+ + + + + + + + +<% for k, route in ipairs(routes) do + local color = "#bb3333" + + route.ETX = tonumber(route.ETX) + if route.ETX == 0 then + color = "#bb3333" + elseif route.ETX < 4 then + color = "#00cc00" + elseif route.ETX < 10 then + color = "#ffcb05" + elseif route.ETX < 100 then + color = "#ff6600" + end +%> + + + + + + + +<% end %> +
<%:olsrd_network%><%:olsrd_gateway%><%:interface%><%:metric%>ETX
<%=route.Destination%><%=route["Gateway IP"]%><%=route.Interface%><%=route.Metric%><%=string.format("%.3f", tonumber(route.ETX) or 0)%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/topology.htm b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/topology.htm new file mode 100644 index 0000000..f827ceb --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/luasrc/view/status-olsr/topology.htm @@ -0,0 +1,39 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: topology.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_topology%>

+

<%:olsrd_topology_desc%>

+
+ + + + + + + + +<% for k, route in ipairs(routes) do +%> + + + + + + + +<% end %> +
<%:olsrd_node%><%:olsrd_topology_lasthop%>LQILQETX
"><%=route["Dest. IP"]%>"><%=route["Last hop IP"]%><%=route.LQ%><%=route.NLQ%><%=string.format("%.3f", tonumber(route.Cost) or 0)%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-olsr/root/etc/uci-defaults/luci-olsr b/openwrt/packages/luci/applications/luci-olsr/root/etc/uci-defaults/luci-olsr new file mode 100644 index 0000000..2c38098 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-olsr/root/etc/uci-defaults/luci-olsr @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack olsrd + set ucitrack.@olsrd[-1].init=olsrd + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-p910nd/Makefile b/openwrt/packages/luci/applications/luci-p910nd/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/applications/luci-p910nd/ipkg/postinst b/openwrt/packages/luci/applications/luci-p910nd/ipkg/postinst new file mode 100644 index 0000000..d16d5cc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-p910nd ) && rm -f /etc/uci-defaults/luci-p910nd +} diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/controller/p910nd.lua b/openwrt/packages/luci/applications/luci-p910nd/luasrc/controller/p910nd.lua new file mode 100644 index 0000000..9dec110 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/controller/p910nd.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI UVC Streamer +(c) 2008 Yanira + +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: p910nd.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.p910nd", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("p910nd") + if not luci.fs.access("/etc/config/p910nd") then + return + end + + local page = entry({"admin", "services", "p910nd"}, cbi("p910nd"), luci.i18n.translate("p910nd", "Printer server"), 60) + page.i18n = "p910nd" + page.dependent = true +end diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.lua b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.lua new file mode 100644 index 0000000..b8cf6e6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.lua @@ -0,0 +1,4 @@ +p910nd = 'p910nd - Drucker server' +p910nd_desc = 'Bevor p910nd verwendet werden kann muessen Pakete fuer USB (kmod-usb-printer) und Parallelport (kmod-lp) Support installiert werden.' +bidirectional = 'Bidirektionaler Modus' +port_help = 'p910nd hoert auf Port 910+N. Z.B. 9100 fuer ersten Drucker' diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.xml b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.xml new file mode 100644 index 0000000..8ac06ff --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.de.xml @@ -0,0 +1,10 @@ + + + + +p910nd - Drucker server +Bevor p910nd verwendet werden kann muessen Pakete fuer USB (kmod-usb-printer) und Parallelport (kmod-lp) Support installiert werden. +Bidirektionaler Modus +p910nd hoert auf Port 910+N. Z.B. 9100 fuer ersten Drucker + + diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.lua b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.lua new file mode 100644 index 0000000..c9b3c8f --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.lua @@ -0,0 +1,4 @@ +p910nd = 'p910nd - Printer server' +p910nd_desc = 'First you have to install the packages to get support for USB (kmod-usb-printer) or parallel port (kmod-lp).' +bidirectional = 'Bidirectional mode' +port_help = 'p910nd listens on port 910+N. E.g. 9100 for the first printer.' diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.xml b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.xml new file mode 100644 index 0000000..3267305 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.en.xml @@ -0,0 +1,10 @@ + + + + +p910nd - Printer server +First you have to install the packages to get support for USB (kmod-usb-printer) or parallel port (kmod-lp). +Bidirectional mode +p910nd listens on port 910+N. E.g. 9100 for the first printer. + + diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.lua b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.lua new file mode 100644 index 0000000..71e4acb --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.lua @@ -0,0 +1,4 @@ +p910nd = 'P910nd - Servidor de impressão' +p910nd_desc = 'Primeiro você deve instalar os pacotes para obter suporte USB (kmod-usb-printer) ou porta paralela (kmod-lp).' +bidirectional = 'Modo bidirecional' +port_help = 'p910nd escuta na porta 910+N. Ex. 9100 para a primeira impressora.' diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.xml b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.xml new file mode 100644 index 0000000..2936115 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/i18n/p910nd.pt-br.xml @@ -0,0 +1,10 @@ + + + + +P910nd - Servidor de impressão +Primeiro você deve instalar os pacotes para obter suporte USB (kmod-usb-printer) ou porta paralela (kmod-lp). +Modo bidirecional +p910nd escuta na porta 910+N. Ex. 9100 para a primeira impressora. + + diff --git a/openwrt/packages/luci/applications/luci-p910nd/luasrc/model/cbi/p910nd.lua b/openwrt/packages/luci/applications/luci-p910nd/luasrc/model/cbi/p910nd.lua new file mode 100644 index 0000000..af55e05 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/luasrc/model/cbi/p910nd.lua @@ -0,0 +1,33 @@ +--[[ + +LuCI p910nd +(c) 2008 Yanira + +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: p910nd.lua 3467 2008-09-29 19:21:47Z jow $ + +]]-- + +local uci = luci.model.uci.cursor_state() + +m = Map("p910nd", translate("p910nd", "p910nd"), + translatef("p910nd_desc")) + +s = m:section(TypedSection, "p910nd", translate("settings", "settings")) +s.addremove = true +s.anonymous = true + +s:option(Flag, "enabled", translate("enable")) + +s:option(Value, "device", translate("device", "Device")).rmempty = true + +s:option(Value, "port", translate("port"), translate("port_help")).rmempty = true + +s:option(Flag, "bidirectional", translate("bidirectional")) + +return m diff --git a/openwrt/packages/luci/applications/luci-p910nd/root/etc/uci-defaults/luci-p910nd b/openwrt/packages/luci/applications/luci-p910nd/root/etc/uci-defaults/luci-p910nd new file mode 100644 index 0000000..b37952e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-p910nd/root/etc/uci-defaults/luci-p910nd @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack p910nd + set ucitrack.@p910nd[-1].init=p910nd + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-polipo/Makefile b/openwrt/packages/luci/applications/luci-polipo/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/applications/luci-polipo/ipkg/postinst b/openwrt/packages/luci/applications/luci-polipo/ipkg/postinst new file mode 100755 index 0000000..1640887 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-polipo ) && rm -f /etc/uci-defaults/luci-polipo +} diff --git a/openwrt/packages/luci/applications/luci-polipo/luasrc/controller/polipo.lua b/openwrt/packages/luci/applications/luci-polipo/luasrc/controller/polipo.lua new file mode 100644 index 0000000..f521984 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/luasrc/controller/polipo.lua @@ -0,0 +1,28 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Aleksandar Krsteski + +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: polipo.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.polipo", package.seeall) + +function index() + if not luci.fs.access("/etc/config/polipo") then + return + end + + require("luci.i18n") + luci.i18n.loadc("polipo") + local i18n = luci.i18n.translate + + local p = entry({"admin", "services", "polipo"}, cbi("polipo"), i18n("polipo", "Polipo")) + p.dependent = true + p.i18n = "polipo" +end diff --git a/openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.lua b/openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.lua new file mode 100644 index 0000000..23b1836 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.lua @@ -0,0 +1,43 @@ +polipo = 'Polipo' +polipo_cache = 'On-Disk Cache' +polipo_cache_cacheisshared = 'Shared cache' +polipo_cache_cacheisshared_desc = 'Enable if cache (proxy) is shared by multiple users.' +polipo_cache_desc = 'To enable polipo on-disk cache cleaning (highly recommended), you should add a cron job in Scheduled Tasks services that will execute /usr/sbin/polipo_purge script. For example to perform disk cache cleanup every day at 6:00 in the morning you should add the following line in Scheduled Tasks "0 6 * * * /usr/sbin/polipo_purge" (without quotes).' +polipo_cache_diskcacheroot = 'Disk cache location' +polipo_cache_diskcacheroot_desc = 'Location where polipo will cache files permanently. Use of external storage devices is recommended, because the cache can grow considerably. Leave it empty to disable on-disk cache.' +polipo_cache_diskcachetruncatesize = 'Truncate cache files size (in bytes)' +polipo_cache_diskcachetruncatesize_desc = 'Size to which cached files should be truncated. (default value: 1048576)' +polipo_cache_diskcachetruncatetime = 'Truncate cache files time' +polipo_cache_diskcachetruncatetime_desc = 'Time after which cached files will be truncated. (default value: 4d12h)' +polipo_cache_diskcacheunlinktime = 'Delete cache files time' +polipo_cache_diskcacheunlinktime_desc = 'Time after which cached files will be deleted. (default value: 32d)' +polipo_desc = 'Polipo is a small and fast caching web proxy.' +polipo_general = 'General' +polipo_general_allowedclients = 'Allowed clients' +polipo_general_allowedclients_desc = 'When listen address is set to 0.0.0.0 or :: (IPv6), you must list clients that are allowed to connect. The format is IP address or network address (192.168.1.123, 192.168.1.0/24, 2001:660:116::/48 (IPv6)).' +polipo_general_chunkhighmark = 'In RAM cache size (in bytes)' +polipo_general_chunkhighmark_desc = 'How much RAM should Polipo use for its cache.' +polipo_general_dnsnameserver = 'DNS server address' +polipo_general_dnsnameserver_desc = 'Set the DNS server address to use, if you want Polipo to use different DNS server than the host system.' +polipo_general_dnsqueryipv6 = 'Query DNS for IPv6' +polipo_general_dnsqueryipv6_desc = 'false = Do not query IPv6; reluctantly = Query both, prefer IPv4; happily = Query both, prefer IPv6; true = Query only IPv6' +polipo_general_dnsusegethostbyname = 'Query DNS by hostname' +polipo_general_dnsusegethostbyname_desc = 'false = Never use system DNS resolver; reluctantly = Query DNS directly, if DNS server is unavailable fail to system DNS resolver; happily = Query DNS directly, if host could not be found fallback to system DNS resolver; true = Always use system DNS resolver' +polipo_general_logfacility = 'Syslog facility' +polipo_general_logfile = 'Log file location' +polipo_general_logfile_desc = 'Use of external storage device is recommended, because the log file is written frequently and can grow considerably.' +polipo_general_logsyslog = 'Log to syslog' +polipo_general_parentauthcredentials = 'Parent proxy authentication' +polipo_general_parentauthcredentials_desc = 'Basic HTTP authentication supported. Provide username and password in username:password format.' +polipo_general_parentproxy = 'Parent proxy address' +polipo_general_parentproxy_desc = 'Parent proxy address (in host:port format), to which Polipo will forward the requests.' +polipo_general_proxyaddress = 'Listen address' +polipo_general_proxyaddress_desc = 'The interface on which Polipo will listen. To listen on all interfaces use 0.0.0.0 or :: (IPv6).' +polipo_general_proxyport = 'Listen port' +polipo_general_proxyport_desc = 'Port on which Polipo will listen. (default value: 8123)' +polipo_pmm = 'Poor Man's Multiplexing' +polipo_pmm_desc = 'Poor Man's Multiplexing (PMM) is a technique that simulates multiplexing by requesting an instance in multiple segments. It tries to lower the latency caused by the weakness of HTTP protocol. NOTE: some sites may not work with PMM enabled.' +polipo_pmm_pmmfirstsize = 'First PMM segment size (in bytes)' +polipo_pmm_pmmfirstsize_desc = 'Size of the first PMM segment. If not defined, it defaults to twice the PMM segment size.' +polipo_pmm_pmmsize = 'PMM segments size (in bytes)' +polipo_pmm_pmmsize_desc = 'To enable PMM, PMM segment size must be set to some positive value.' diff --git a/openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.xml b/openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.xml new file mode 100644 index 0000000..b4e8df8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/luasrc/i18n/polipo.en.xml @@ -0,0 +1,49 @@ + + + + +Polipo +On-Disk Cache +Shared cache +Enable if cache (proxy) is shared by multiple users. +To enable polipo on-disk cache cleaning (highly recommended), you should add a cron job in Scheduled Tasks services that will execute /usr/sbin/polipo_purge script. For example to perform disk cache cleanup every day at 6:00 in the morning you should add the following line in Scheduled Tasks "0 6 * * * /usr/sbin/polipo_purge" (without quotes). +Disk cache location +Location where polipo will cache files permanently. Use of external storage devices is recommended, because the cache can grow considerably. Leave it empty to disable on-disk cache. +Truncate cache files size (in bytes) +Size to which cached files should be truncated. (default value: 1048576) +Truncate cache files time +Time after which cached files will be truncated. (default value: 4d12h) +Delete cache files time +Time after which cached files will be deleted. (default value: 32d) +Polipo is a small and fast caching web proxy. +General +Allowed clients +When listen address is set to 0.0.0.0 or :: (IPv6), you must list clients that are allowed to connect. The format is IP address or network address (192.168.1.123, 192.168.1.0/24, 2001:660:116::/48 (IPv6)). +In RAM cache size (in bytes) +How much RAM should Polipo use for its cache. +DNS server address +Set the DNS server address to use, if you want Polipo to use different DNS server than the host system. +Query DNS for IPv6 +false = Do not query IPv6; reluctantly = Query both, prefer IPv4; happily = Query both, prefer IPv6; true = Query only IPv6 +Query DNS by hostname +false = Never use system DNS resolver; reluctantly = Query DNS directly, if DNS server is unavailable fail to system DNS resolver; happily = Query DNS directly, if host could not be found fallback to system DNS resolver; true = Always use system DNS resolver +Syslog facility +Log file location +Use of external storage device is recommended, because the log file is written frequently and can grow considerably. +Log to syslog +Parent proxy authentication +Basic HTTP authentication supported. Provide username and password in username:password format. +Parent proxy address +Parent proxy address (in host:port format), to which Polipo will forward the requests. +Listen address +The interface on which Polipo will listen. To listen on all interfaces use 0.0.0.0 or :: (IPv6). +Listen port +Port on which Polipo will listen. (default value: 8123) +Poor Man's Multiplexing +Poor Man's Multiplexing (PMM) is a technique that simulates multiplexing by requesting an instance in multiple segments. It tries to lower the latency caused by the weakness of HTTP protocol. NOTE: some sites may not work with PMM enabled. +First PMM segment size (in bytes) +Size of the first PMM segment. If not defined, it defaults to twice the PMM segment size. +PMM segments size (in bytes) +To enable PMM, PMM segment size must be set to some positive value. + + diff --git a/openwrt/packages/luci/applications/luci-polipo/luasrc/model/cbi/polipo.lua b/openwrt/packages/luci/applications/luci-polipo/luasrc/model/cbi/polipo.lua new file mode 100644 index 0000000..4ccaf79 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/luasrc/model/cbi/polipo.lua @@ -0,0 +1,67 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Aleksandar Krsteski + +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: polipo.lua 3720 2008-11-05 23:05:09Z jow $ +]]-- +m = Map("polipo") + +-- General section +s = m:section(NamedSection, "general", "polipo") + +-- General settings +s:option(Flag, "enabled", translate("enable")) +s:option(Value, "proxyAddress") +s:option(Value, "proxyPort").optional = true +s:option(DynamicList, "allowedClients") +s:option(Flag, "logSyslog") +s:option(Value, "logFacility"):depends("logSyslog", "1") +v = s:option(Value, "logFile") +v:depends("logSyslog", "") +v.rmempty = true +s:option(Value, "chunkHighMark") + +-- DNS and proxy settings +s:option(Value, "dnsNameServer").optional = true +s:option(Value, "parentProxy").optional = true +s:option(Value, "parentAuthCredentials").optional = true +l = s:option(ListValue, "dnsQueryIPv6") +l.optional = true +l.default = "happily" +l:value("") +l:value("true") +l:value("reluctantly") +l:value("happily") +l:value("false") +l = s:option(ListValue, "dnsUseGethostbyname") +l.optional = true +l.default = "reluctantly" +l:value("") +l:value("true") +l:value("reluctantly") +l:value("happily") +l:value("false") + +-- Dsik cache section +s = m:section(NamedSection, "cache", "polipo") + +-- Dsik cache settings +s:option(Value, "diskCacheRoot").rmempty = true +s:option(Flag, "cacheIsShared") +s:option(Value, "diskCacheTruncateSize").optional = true +s:option(Value, "diskCacheTruncateTime").optional = true +s:option(Value, "diskCacheUnlinkTime").optional = true + +-- Poor man's multiplexing section +s = m:section(NamedSection, "pmm", "polipo") +s:option(Value, "pmmSize").rmempty = true +s:option(Value, "pmmFirstSize").optional = true + +return m diff --git a/openwrt/packages/luci/applications/luci-polipo/root/etc/uci-defaults/luci-polipo b/openwrt/packages/luci/applications/luci-polipo/root/etc/uci-defaults/luci-polipo new file mode 100644 index 0000000..8a033f8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/root/etc/uci-defaults/luci-polipo @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack polipo + set ucitrack.@polipo[-1].init=polipo + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-polipo/root/usr/sbin/polipo_purge b/openwrt/packages/luci/applications/luci-polipo/root/usr/sbin/polipo_purge new file mode 100755 index 0000000..ce7c885 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-polipo/root/usr/sbin/polipo_purge @@ -0,0 +1,18 @@ +#!/bin/sh + +DAEMON=/usr/sbin/polipo +PIDFILE=`uci get polipo.daemon.pidFile` +CFGFILE=/var/etc/polipo.conf + +[ -e "$PIDFILE" ] && { + PID=`cat $PID_FILE` + + # send Polipo USR1 signal to write its in-memory cache to disk + kill -USR1 $PID + sleep 2 + # start polipo with -x flag to purge the on-disk cache + polipo -c $CFGFILE -x + # send Polipo USR2 signal to discard its in-memory cache + kill -USR2 $PID +} + diff --git a/openwrt/packages/luci/applications/luci-qos/Makefile b/openwrt/packages/luci/applications/luci-qos/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/controller/qos.lua b/openwrt/packages/luci/applications/luci-qos/luasrc/controller/qos.lua new file mode 100644 index 0000000..7299dfa --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/controller/qos.lua @@ -0,0 +1,29 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: qos.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.qos", package.seeall) + +function index() + if not luci.fs.access("/etc/config/qos") then + return + end + + local page = entry({"admin", "network", "qos"}, cbi("qos/qos"), "QoS") + page.i18n = "qos" + page.dependent = true + + + local page = entry({"mini", "network", "qos"}, cbi("qos/qosmini", {autoapply=true}), "QoS") + page.i18n = "qos" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.lua b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.lua new file mode 100644 index 0000000..1ef5499 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.lua @@ -0,0 +1,17 @@ +qos = 'Quality of Service' +qos_interface_classgroup = 'Klassifizierung' +qos_interface_overhead = 'Overheadberechnung' +qos_interface_download = 'Downlink' +qos_interface_upload = 'Uplink' +qos_classify = 'Priorisierung' +qos_classify_target = 'Priorität' +qos_classify_srchost = 'Quelladresse' +qos_classify_srchost_dest = 'Quellnetz / Quellhost' +qos_classify_dsthost = 'Zieladresse' +qos_classify_dsthost_dest = 'Zielnetz / Zielhost' +qos_classify_portrange = 'Portbereich' +qos_bulk = 'niedrig' +qos_normal = 'normal' +qos_express = 'express' +qos_priority = 'priorisiert' +qos_connbytes = 'Bytes gesendet' diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.xml b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.xml new file mode 100644 index 0000000..c64d0f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.de.xml @@ -0,0 +1,22 @@ + + + + +Quality of Service +Klassifizierung +Overheadberechnung +Downlink +Uplink +Priorisierung +Priorität +Quelladresse +Quellnetz / Quellhost +Zieladresse +Zielnetz / Zielhost +Portbereich +niedrig +normal +express +priorisiert +Bytes gesendet + diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.lua b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.lua new file mode 100644 index 0000000..67494e7 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.lua @@ -0,0 +1,18 @@ +qos = 'Quality of Service' +qos_desc = 'With QoS you can priorize network traffic selected by adresses, ports or services.' +qos_interface_classgroup = 'Classification' +qos_interface_overhead = 'Calculate Overhead' +qos_interface_download = 'Downlink' +qos_interface_upload = 'Uplink' +qos_classify = 'Prioritization' +qos_classify_target = 'Priority' +qos_classify_srchost = 'Source address' +qos_classify_srchost_dest = 'source network / source host' +qos_classify_dsthost = 'Target address' +qos_classify_dsthost_dest = 'target network / target host' +qos_classify_portrange = 'portrange' +qos_bulk = 'low' +qos_normal = 'normal' +qos_express = 'express' +qos_priority = 'priority' +qos_connbytes = 'Bytes sent' diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.xml b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.xml new file mode 100644 index 0000000..8a5eeca --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.en.xml @@ -0,0 +1,23 @@ + + + + +Quality of Service +With QoS you can priorize network traffic selected by adresses, ports or services. +Classification +Calculate Overhead +Downlink +Uplink +Prioritization +Priority +Source address +source network / source host +Target address +target network / target host +portrange +low +normal +express +priority +Bytes sent + diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.lua b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.lua new file mode 100644 index 0000000..73c54dc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.lua @@ -0,0 +1,17 @@ +qos = 'Qualité de service' +qos_bulk = 'lent' +qos_classify = 'Priorité' +qos_classify_dsthost = 'Adresse de destination' +qos_classify_dsthost_dest = 'Réseau de destination / Hôte de destination' +qos_classify_portrange = 'ports' +qos_classify_srchost = 'Adresse source' +qos_classify_srchost_dest = 'Réseau source / Hôte source' +qos_classify_target = 'Priorité' +qos_desc = 'Avec la QOS, vous pouvez donner des priorités au trafic de votre réseau en fonction des adresses, des ports ou des services présents.' +qos_express = 'express' +qos_interface_classgroup = 'Classification' +qos_interface_download = 'Liaison descendante' +qos_interface_overhead = 'calcul de la surcharge' +qos_interface_upload = 'Liaison montante' +qos_normal = 'normal' +qos_priority = 'prioritaire' diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.xml b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.xml new file mode 100644 index 0000000..b2703a0 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.fr.xml @@ -0,0 +1,23 @@ + + + + +Qualité de service +lent +Priorité +Adresse de destination +Réseau de destination / Hôte de destination +ports +Adresse source +Réseau source / Hôte source +Priorité +Avec la QOS, vous pouvez donner des priorités au trafic de votre réseau en fonction des adresses, des ports ou des services présents. +express +Classification +Liaison descendante +calcul de la surcharge +Liaison montante +normal +prioritaire + + diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.lua b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.lua new file mode 100644 index 0000000..582e7aa --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.lua @@ -0,0 +1,17 @@ +qos = 'Qualidade de Serviço' +qos_desc = 'Com QoS você pode priozirar o tráfego da rede selecionada por endereços, portas ou serviços.' +qos_interface_classgroup = 'Classificação' +qos_interface_overhead = 'Calcular Overhead' +qos_interface_download = 'Link para download' +qos_interface_upload = 'Link para upload' +qos_classify = 'Priorização' +qos_classify_target = 'Prioridade' +qos_classify_srchost = 'Endereço de origem' +qos_classify_srchost_dest = 'rede de origem / host de origem' +qos_classify_dsthost = 'Endereço de destino' +qos_classify_dsthost_dest = 'rede de destino / host de destino' +qos_classify_portrange = 'faixa de portas' +qos_bulk = 'baixa' +qos_normal = 'normal' +qos_express = 'expressa' +qos_priority = 'alta' diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.xml b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.xml new file mode 100644 index 0000000..ff32e22 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/i18n/qos.pt-br.xml @@ -0,0 +1,22 @@ + + + + +Qualidade de Serviço +Com QoS você pode priozirar o tráfego da rede selecionada por endereços, portas ou serviços. +Classificação +Calcular Overhead +Link para download +Link para upload +Priorização +Prioridade +Endereço de origem +rede de origem / host de origem +Endereço de destino +rede de destino / host de destino +faixa de portas +baixa +normal +expressa +alta + diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qos.lua b/openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qos.lua new file mode 100644 index 0000000..07ad127 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qos.lua @@ -0,0 +1,89 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: qos.lua 4075 2009-01-17 16:20:20Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("qos") + +s = m:section(TypedSection, "interface", translate("interfaces")) +s.addremove = true + +s:option(Flag, "enabled", translate("enable")) + +c = s:option(ListValue, "classgroup") +c:value("Default", "standard") +c.default = "Default" + +s:option(Flag, "overhead") + +s:option(Value, "download", nil, "kb/s") + +s:option(Value, "upload", nil, "kb/s") + +s = m:section(TypedSection, "classify") +s.template = "cbi/tblsection" +s.anonymous = true +s.addremove = true + +t = s:option(ListValue, "target") +t:value("Priority", translate("qos_priority")) +t:value("Express", translate("qos_express")) +t:value("Normal", translate("qos_normal")) +t:value("Bulk", translate("qos_bulk")) +t.default = "Normal" + +srch = s:option(Value, "srchost") +srch.rmempty = true +srch:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(srch) + +dsth = s:option(Value, "dsthost") +dsth.rmempty = true +dsth:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(dsth) + +l7 = s:option(ListValue, "layer7", translate("service")) +l7.rmempty = true +l7:value("", translate("all")) +local pats = luci.fs.dir("/etc/l7-protocols") +if pats then + for i,f in ipairs(pats) do + if f:sub(-4) == ".pat" then + l7:value(f:sub(1, #f-4)) + end + end +end + +p2p = s:option(ListValue, "ipp2p", "P2P") +p2p:value("", "-") +p2p:value("all", translate("all")) +p2p:value("bit", "BIT") +p2p:value("dc", "DC") +p2p:value("edk", "EDK") +p2p:value("gnu", "GNU") +p2p:value("kazaa", "KAZ") +p2p.rmempty = true + +p = s:option(Value, "proto", translate("protocol")) +p:value("", translate("all")) +p:value("tcp", "TCP") +p:value("udp", "UDP") +p:value("icmp", "ICMP") +p.rmempty = true + +ports = s:option(Value, "ports", translate("ports")) +ports.rmempty = true +ports:value("", translate("allf", translate("all"))) + +bytes = s:option(Value, "connbytes", translate("qos_connbytes")) + +return m diff --git a/openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qosmini.lua b/openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qosmini.lua new file mode 100644 index 0000000..c8dcfe8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/luasrc/model/cbi/qos/qosmini.lua @@ -0,0 +1,82 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: qosmini.lua 4075 2009-01-17 16:20:20Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("qos") + +s = m:section(NamedSection, "wan", "interface", translate("m_n_inet")) + +s:option(Flag, "enabled", translate("qos")) +s:option(Value, "download", translate("qos_interface_download"), "kb/s") +s:option(Value, "upload", translate("qos_interface_upload"), "kb/s") + +s = m:section(TypedSection, "classify") +s.template = "cbi/tblsection" + +s.anonymous = true +s.addremove = true + +t = s:option(ListValue, "target") +t:value("Priority", translate("qos_priority")) +t:value("Express", translate("qos_express")) +t:value("Normal", translate("qos_normal")) +t:value("Bulk", translate("qos_bulk")) +t.default = "Normal" + +srch = s:option(Value, "srchost") +srch.rmempty = true +srch:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(srch) + +dsth = s:option(Value, "dsthost") +dsth.rmempty = true +dsth:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(dsth) + +l7 = s:option(ListValue, "layer7", translate("service")) +l7.rmempty = true +l7:value("", translate("all")) +local pats = luci.fs.dir("/etc/l7-protocols") +if pats then + for i,f in ipairs(pats) do + if f:sub(-4) == ".pat" then + l7:value(f:sub(1, #f-4)) + end + end +end + +p2p = s:option(ListValue, "ipp2p", "P2P") +p2p:value("", "-") +p2p:value("all", translate("all")) +p2p:value("bit", "BIT") +p2p:value("dc", "DC") +p2p:value("edk", "EDK") +p2p:value("gnu", "GNU") +p2p:value("kazaa", "KAZ") +p2p.rmempty = true + +p = s:option(ListValue, "proto", translate("protocol")) +p:value("", translate("all")) +p:value("tcp", "TCP") +p:value("udp", "UDP") +p:value("icmp", "ICMP") +p.rmempty = true + +ports = s:option(Value, "ports", translate("ports")) +ports.rmempty = true +ports:value("", translate("allf", translate("all"))) + +bytes = s:option(Value, "connbytes", translate("qos_connbytes")) + +return m diff --git a/openwrt/packages/luci/applications/luci-qos/root/lib/uci/schema/default/qos b/openwrt/packages/luci/applications/luci-qos/root/lib/uci/schema/default/qos new file mode 100644 index 0000000..24f8e0d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-qos/root/lib/uci/schema/default/qos @@ -0,0 +1,200 @@ +package qos + +config package + option title 'Network quality of service' + +config section + option name 'interface' + option title 'QoS interface section' + option package 'qos' + option named true + option required true + +config variable + option name 'enabled' + option title 'Enable QoS on this interface' + option section 'qos.interface' + +config variable + option name 'overhead' + option title 'Calculate overhead bandwidth' + option section 'qos.interface' + option datatype 'boolean' + +config variable + option name 'classgroup' + option title 'QoS classification' + option section 'qos.interface' + option valueof 'qos.classgroup' + +config variable + option name 'download' + option title 'Maximum download speed in kBits/s' + option section 'qos.interface' + option datatype 'integer' + +config variable + option name 'upload' + option title 'Maximum upload speed in kBits/s' + option section 'qos.interface' + option datatype 'integer' + + +config section + option name 'class' + option title 'QoS traffic class definition' + option package 'qos' + option named true + option required true + +config variable + option name 'avgrate' + option title 'Average rate' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'maxsize' + option title 'Maximum size' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'packetdelay' + option title 'Packet delay' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'packetsize' + option title 'Packet size' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'priority' + option title 'QoS priority' + option section 'qos.class' + option datatype 'integer' + + +config section + option name 'classgroup' + option title 'QoS classification group' + option package 'qos' + option named true + +config variable + option name 'classes' + option title 'Defined QoS classes in group' + option section 'qos.classgroup' + +config variable + option name 'default' + option title 'Default QoS class in group' + option section 'qos.classgroup' + option valueof 'qos.class' + + +config section + option name 'default' + option title 'QoS default classification' + option package 'qos' + list depends 'target, pktsize' + list depends 'target, portrange' + list depends 'target, proto' + +config variable + option name 'pktsize' + option title 'Match by packet size' + option section 'qos.default' + option datatype 'integer' + +config variable + option name 'portrange' + option title 'Match by port range' + option section 'qos.default' + +config variable + option name 'proto' + option title 'Match by layer 3 protocol' + option section 'qos.default' + +config variable + option name 'target' + option title 'Option target' + option section 'qos.default' + option valueof 'qos.class' + option required true + + +config section + option name 'classify' + option title 'QoS classification rule' + option package 'qos' + +config variable + option name 'ipp2p' + option title 'Match by ipp2p' + option section 'qos.classify' + +config variable + option name 'layer7' + option title 'Match by layer 7 protocol' + option section 'qos.classify' + +config variable + option name 'ports' + option title 'Match by ports' + option section 'qos.classify' + +config variable + option name 'proto' + option title 'Match by layer 3 protocol' + option section 'qos.classify' + +config variable + option name 'tcpflags' + option title 'Match by TCP flags' + option section 'qos.classify' + +config variable + option name 'target' + option title 'QoS target class' + option section 'qos.classify' + option valueof 'qos.class' + option required true + + +config section + option name 'reclassify' + option title 'QoS reclassification rule' + option package 'qos' + +config variable + option name 'mark' + option title 'Match by classification mark' + option section 'qos.reclassify' + +config variable + option name 'pktsize' + option title 'Match by packet size' + option section 'qos.reclassify' + option datatype 'integer' + +config variable + option name 'proto' + option title 'Match by layer 3 protocol' + option section 'qos.reclassify' + +config variable + option name 'tcpflags' + option title 'Match by TCP flags' + option section 'qos.reclassify' + +config variable + option name 'target' + option title 'QoS classification target' + option section 'qos.reclassify' + option valueof 'qos.class' + option required true diff --git a/openwrt/packages/luci/applications/luci-samba/Makefile b/openwrt/packages/luci/applications/luci-samba/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/controller/samba.lua b/openwrt/packages/luci/applications/luci-samba/luasrc/controller/samba.lua new file mode 100644 index 0000000..c5f5834 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/controller/samba.lua @@ -0,0 +1,27 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: samba.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.samba", package.seeall) + +function index() + if not luci.fs.access("/etc/config/samba") then + return + end + require("luci.i18n") + luci.i18n.loadc("samba") + + local page = entry({"admin", "services", "samba"}, cbi("samba"), luci.i18n.translate("samba")) + page.i18n = "samba" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.lua b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.lua new file mode 100644 index 0000000..8273895 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.lua @@ -0,0 +1,17 @@ +samba = 'Netzwerkfreigaben' +samba_samba_name = 'Hostname' +samba_samba_description = 'Beschreibung' +samba_samba_workgroup = 'Arbeitsgruppe' +samba_samba_homes = 'Heimatverzeichnisse freigeben' +samba_samba_homes_desc = 'Systembenutzer können ihre Heimatverzeichnis über Netzwerkfreigaben erreichen.' +samba_sambashare = 'Dateifreigaben' +samba_sambashare_path = 'Freigabepfad' +samba_sambashare_path_desc = 'Physischer Pfad' +samba_sambashare_users = 'Erlaubte Benutzer' +samba_sambashare_users_desc = 'optional' +samba_sambashare_readonly = 'Nur Lesen' +samba_sambashare_guestok = 'Gäste erlauben' +samba_sambashare_createmask = 'Anlegemaske' +samba_sambashare_createmask_desc = 'Maske für neue Dateien' +samba_sambashare_dirmask = 'Verzeichnismaske' +samba_sambashare_dirmask_desc = 'Maske für neue Verzeichnisse' diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.xml b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.xml new file mode 100644 index 0000000..10c594d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.de.xml @@ -0,0 +1,24 @@ + + + + +Netzwerkfreigaben +Hostname +Beschreibung +Arbeitsgruppe +Heimatverzeichnisse freigeben +Systembenutzer können ihre Heimatverzeichnis über Netzwerkfreigaben erreichen. + +Dateifreigaben +Freigabepfad +Physischer Pfad +Erlaubte Benutzer +optional +Nur Lesen +Gäste erlauben +Anlegemaske +Maske für neue Dateien +Verzeichnismaske +Maske für neue Verzeichnisse + + diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.lua b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.lua new file mode 100644 index 0000000..30e9339 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.lua @@ -0,0 +1,17 @@ +samba = 'Network Shares' +samba_samba_name = 'Hostname' +samba_samba_description = 'Description' +samba_samba_workgroup = 'Workgroup' +samba_samba_homes = 'Share home-directories' +samba_samba_homes_desc = 'System users can reach their home directories via network shares.' +samba_sambashare = 'Shared Directories' +samba_sambashare_path = 'Shared Directory' +samba_sambashare_path_desc = 'Physical Path' +samba_sambashare_users = 'Allowed Users' +samba_sambashare_users_desc = 'optional' +samba_sambashare_readonly = 'Read Only' +samba_sambashare_guestok = 'Allow Guests' +samba_sambashare_createmask = 'Create Mask' +samba_sambashare_createmask_desc = 'Mask for new files' +samba_sambashare_dirmask = 'Directory Mask' +samba_sambashare_dirmask_desc = 'Mask for new directories' diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.xml b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.xml new file mode 100644 index 0000000..f6c03bd --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.en.xml @@ -0,0 +1,24 @@ + + + + +Network Shares +Hostname +Description +Workgroup +Share home-directories +System users can reach their home directories via network shares. + +Shared Directories +Shared Directory +Physical Path +Allowed Users +optional +Read Only +Allow Guests +Create Mask +Mask for new files +Directory Mask +Mask for new directories + + diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.lua b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.lua new file mode 100644 index 0000000..9129ef6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.lua @@ -0,0 +1,17 @@ +samba = 'Compartilhamentos de Rede' +samba_samba_name = 'Hostname' +samba_samba_description = 'Descrição' +samba_samba_workgroup = 'Grupo de Trabalho' +samba_samba_homes = 'Compartilhar diretórios home' +samba_samba_homes_desc = 'Usuários do sistema poderão acessar seu diretório home através dos compartilhamentos de rede.' +samba_sambashare = 'Diretórios Compartilhados' +samba_sambashare_path = 'Diretório Compartilhado' +samba_sambashare_path_desc = 'Caminho Físico' +samba_sambashare_users = 'Usuários Permitidos' +samba_sambashare_users_desc = 'opcional' +samba_sambashare_readonly = 'Somente Leitura' +samba_sambashare_guestok = 'Permitir Convidados' +samba_sambashare_createmask = 'Criar Máscara' +samba_sambashare_createmask_desc = 'Máscara para novos arquivos' +samba_sambashare_dirmask = 'Máscara do Diretório' +samba_sambashare_dirmask_desc = 'Máscara para novos diretórios' diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.xml b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.xml new file mode 100644 index 0000000..288a50d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/i18n/samba.pt-br.xml @@ -0,0 +1,24 @@ + + + + +Compartilhamentos de Rede +Hostname +Descrição +Grupo de Trabalho +Compartilhar diretórios home +Usuários do sistema poderão acessar seu diretório home através dos compartilhamentos de rede. + +Diretórios Compartilhados +Diretório Compartilhado +Caminho Físico +Usuários Permitidos +opcional +Somente Leitura +Permitir Convidados +Criar Máscara +Máscara para novos arquivos +Máscara do Diretório +Máscara para novos diretórios + + diff --git a/openwrt/packages/luci/applications/luci-samba/luasrc/model/cbi/samba.lua b/openwrt/packages/luci/applications/luci-samba/luasrc/model/cbi/samba.lua new file mode 100644 index 0000000..a33c069 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/luasrc/model/cbi/samba.lua @@ -0,0 +1,56 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: samba.lua 3973 2009-01-01 13:33:45Z Cyrus $ +]]-- + +m = Map("samba") + +s = m:section(TypedSection, "samba", "Samba") +s.anonymous = true + +s:option(Value, "name") +s:option(Value, "description") +s:option(Value, "workgroup") +s:option(Flag, "homes") + + +s = m:section(TypedSection, "sambashare") +s.anonymous = true +s.addremove = true +s.template = "cbi/tblsection" + +s:option(Value, "name", translate("name")) +s:option(Value, "path").titleref = luci.dispatcher.build_url("admin", "system", "fstab") + +s:option(Value, "users").rmempty = true + +ro = s:option(Flag, "read_only") +ro.rmempty = false +ro.enabled = "yes" +ro.disabled = "no" + +go = s:option(Flag, "guest_ok") +go.rmempty = false +go.enabled = "yes" +go.disabled = "no" + +cm = s:option(Value, "create_mask") +cm.rmempty = true +cm.size = 4 + +dm = s:option(Value, "dir_mask") +dm.rmempty = true +dm.size = 4 + + +return m diff --git a/openwrt/packages/luci/applications/luci-samba/root/lib/uci/schema/default/samba b/openwrt/packages/luci/applications/luci-samba/root/lib/uci/schema/default/samba new file mode 100644 index 0000000..d4c7d8c --- /dev/null +++ b/openwrt/packages/luci/applications/luci-samba/root/lib/uci/schema/default/samba @@ -0,0 +1,76 @@ +package samba + +config package + option title 'Samba CIFS/SMB Daemon' + +config section + option name 'samba' + option package 'samba' + option title 'General Settings' + option unique true + option required true + +config variable + option name 'name' + option section 'samba.samba' + option title 'Hostname' + option datatype host + option required true + +config variable + option name 'description' + option section 'samba.samba' + option title 'Description' + +config variable + option name 'workgroup' + option section 'samba.samba' + option title 'Workgroup' + option required true + +config variable + option name 'homes' + option section 'samba.samba' + option title 'Share home-directories' + option description 'System users can reach their home directories via network shares.' + option datatype boolean + +config section + option name 'sambashare' + option package 'samba' + option title 'Shared Directories' + +config variable + option name 'name' + option section 'samba.sambashare' + option title 'Name' + option required true + +config variable + option name 'users' + option section 'samba.sambashare' + option title 'Allowed Users' + +config variable + option name 'read_only' + option section 'samba.sambashare' + option title 'Read Only' + option datatype boolean + +config variable + option name 'guest_ok' + option section 'samba.sambashare' + option title 'Allow Guests' + option datatype boolean + +config variable + option name 'create_mask' + option section 'samba.sambashare' + option title 'Create Mask' + option description 'Mask for new files' + +config variable + option name 'dir_mask' + option section 'samba.sambashare' + option title 'Directory Mask' + option description 'Mask for new directories' diff --git a/openwrt/packages/luci/applications/luci-siitwizard/Makefile b/openwrt/packages/luci/applications/luci-siitwizard/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-siitwizard/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-siitwizard/luasrc/controller/siitwizard.lua b/openwrt/packages/luci/applications/luci-siitwizard/luasrc/controller/siitwizard.lua new file mode 100644 index 0000000..64c9b98 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-siitwizard/luasrc/controller/siitwizard.lua @@ -0,0 +1,21 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: siitwizard.lua 3934 2008-12-23 05:18:08Z jow $ + +]]-- + +module "luci.controller.siitwizard" + +function index() + entry({"admin", "network", "siitwizard"}, form("siitwizard"), "SIIT 4over6 assistent", 99) +end diff --git a/openwrt/packages/luci/applications/luci-siitwizard/luasrc/model/cbi/siitwizard.lua b/openwrt/packages/luci/applications/luci-siitwizard/luasrc/model/cbi/siitwizard.lua new file mode 100644 index 0000000..048c0f4 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-siitwizard/luasrc/model/cbi/siitwizard.lua @@ -0,0 +1,338 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: siitwizard.lua 3940 2008-12-23 16:49:48Z jow $ + +]]-- + +local uci = require "luci.model.uci".cursor() + +-------------------- View -------------------- +f = SimpleForm("siitwizward", "4over6-Assistent", + "Dieser Assistent unterstüzt bei der Einrichtung von IPv4-over-IPv6 Translation.") + +mode = f:field(ListValue, "mode", "Betriebsmodus") +mode:value("client", "Client") +mode:value("gateway", "Gateway") + +dev = f:field(ListValue, "device", "WLAN-Gerät") +uci:foreach("wireless", "wifi-device", + function(section) + dev:value(section[".name"]) + end) + +lanip = f:field(Value, "ipaddr", "LAN IP Adresse") +lanip.value = "172.23.1.1" + +lanmsk = f:field(Value, "lanmask", "Lokale LAN Netzmaske") +lanmsk.value = "255.255.255.0" + +gv4msk = f:field(Value, "gv4mask", "Globale LAN Netzmaske") +gv4msk.value = "255.255.0.0" + + +-------------------- Control -------------------- +LL_PREFIX = luci.ip.IPv6("fe80::/64") + +-- +-- find link-local address +-- +function find_ll() + for _, r in ipairs(luci.sys.net.routes6()) do + if LL_PREFIX:contains(r.dest) and r.dest:higher(LL_PREFIX) then + return r.dest:sub(LL_PREFIX) + end + end + return luci.ip.IPv6("::") +end + + + +function f.handle(self, state, data) + if state == FORM_VALID then + luci.http.redirect(luci.dispatcher.build_url("admin", "uci", "changes")) + return false + elseif state == FORM_INVALID then + self.errmessage = "Ungültige Eingabe: Bitte die Formularfelder auf Fehler prüfen." + end + return true +end + +function mode.write(self, section, value) + + -- lan interface + local lan_net = luci.ip.IPv4( + lanip:formvalue(section) or "192.168.1.1", + lanmsk:formvalue(section) or "255.255.255.0" + ) + + local gv4_net = luci.ip.IPv4( + lanip:formvalue(section) or "192.168.1.1", + gv4msk:formvalue(section) or "255.255.0.0" + ) + + -- + -- Configure wifi device + -- + local wifi_device = dev:formvalue(section) + local wifi_essid = uci:get("siit", "wifi", "essid") or "6mesh.freifunk.net" + local wifi_bssid = uci:get("siit", "wifi", "bssid") or "02:ca:ff:ee:ba:be" + local wifi_channel = uci:get("siit", "wifi", "channel") or "1" + + -- nuke old device definition + uci:delete_all("wireless", "wifi-iface", + function(s) return s.device == wifi_device end ) + + uci:delete_all("network", "interface", + function(s) return s['.name'] == wifi_device end ) + + -- create wifi device definition + uci:tset("wireless", wifi_device, { + disabled = 0, + channel = wifi_channel, +-- txantenna = 1, +-- rxantenna = 1, +-- diversity = 0 + }) + + uci:section("wireless", "wifi-iface", nil, { + encryption = "none", + mode = "adhoc", + network = wifi_device, + device = wifi_device, + ssid = wifi_essid, + bssid = wifi_bssid, + }) + + + -- + -- Determine defaults + -- + local ula_prefix = uci:get("siit", "ipv6", "ula_prefix") or "fd00::" + local ula_global = uci:get("siit", "ipv6", "ula_global") or "00ca:ffee:babe::" -- = Freifunk + local ula_subnet = uci:get("siit", "ipv6", "ula_subnet") or "0000:0000:0000:4223::" -- = Berlin + local siit_prefix = uci:get("siit", "ipv6", "siit_prefix") or "::ffff:0000:0000" + + -- Find wifi interface + local device = dev:formvalue(section) + + -- + -- Generate ULA + -- + local ula = luci.ip.IPv6("::/64") + + for _, prefix in ipairs({ ula_prefix, ula_global, ula_subnet }) do + ula = ula:add(luci.ip.IPv6(prefix)) + end + + ula = ula:add(find_ll()) + + + -- + -- Gateway mode + -- + -- * wan port is dhcp, lan port is 172.23.1.1/24 + -- * siit0 gets a dummy address: 169.254.42.42 + -- * wl0 gets an ipv6 address, in this case the fdca:ffee:babe::1:1/64 + -- * we do a ::ffff:ffff:0/96 route into siit0, so everything from 6mesh goes into translation. + -- * an HNA6 of ::ffff:ffff:0:0/96 announces the mapped 0.0.0.0/0 ipv4 space. + -- * MTU on WAN, LAN down to 1400, ipv6 headers are slighly larger. + + if value == "gateway" then + + + -- wan mtu + uci:set("network", "wan", "mtu", 1400) + + -- lan settings + uci:tset("network", "lan", { + mtu = 1400, + ipaddr = lan_net:host():string(), + netmask = lan_net:mask():string() + }) + + -- use full siit subnet + siit_route = luci.ip.IPv6(siit_prefix .. "/96") + + -- v4 <-> siit route + uci:delete_all("network", "route", + function(s) return s.interface == "siit0" end) + + uci:section("network", "route", nil, { + interface = "siit0", + target = gv4_net:network():string(), + netmask = gv4_net:mask():string() + }) + + -- + -- Client mode + -- + -- * 172.23.2.1/24 on its lan, fdca:ffee:babe::1:2 on wl0 and the usual dummy address on siit0. + -- * we do a ::ffff:ffff:172.13.2.0/120 to siit0, because in this case, only traffic directed to clients needs to go into translation. + -- * same route as HNA6 announcement to catch the traffic out of the mesh. + -- * Also, MTU on LAN reduced to 1400. + + else + + -- lan settings + uci:tset("network", "lan", { + mtu = 1400, + ipaddr = lan_net:host():string(), + netmask = lan_net:mask():string() + }) + + -- derive siit subnet from lan config + siit_route = luci.ip.IPv6( + siit_prefix .. "/" .. (96 + lan_net:prefix()) + ):add(lan_net[2]) + + -- ipv4 <-> siit route + uci:delete_all("network", "route", + function(s) return s.interface == "siit0" end) + + -- XXX: kind of a catch all, gv4_net would be better + -- but does not cover non-local v4 space + uci:section("network", "route", nil, { + interface = "siit0", + target = "0.0.0.0", + netmask = "0.0.0.0" + }) + end + + -- setup the firewall + uci:delete_all("firewall", "zone", + function(s) return ( + s['.name'] == "siit0" or s.name == "siit0" or + s.network == "siit0" or s['.name'] == wifi_device or + s.name == wifi_device or s.network == wifi_device + ) end) + + uci:delete_all("firewall", "forwarding", + function(s) return ( + s.src == wifi_device and s.dest == "siit0" or + s.dest == wifi_device and s.src == "siit0" or + s.src == "lan" and s.dest == "siit0" or + s.dest == "lan" and s.src == "siit0" + ) end) + + uci:section("firewall", "zone", "siit0", { + name = "siit0", + network = "siit0", + input = "ACCEPT", + output = "ACCEPT", + forward = "ACCEPT" + }) + + uci:section("firewall", "zone", wifi_device, { + name = wifi_device, + network = wifi_device, + input = "ACCEPT", + output = "ACCEPT", + forward = "ACCEPT" + }) + + uci:section("firewall", "forwarding", nil, { + src = wifi_device, + dest = "siit0" + }) + + uci:section("firewall", "forwarding", nil, { + src = "siit0", + dest = wifi_device + }) + + uci:section("firewall", "forwarding", nil, { + src = "lan", + dest = "siit0" + }) + + uci:section("firewall", "forwarding", nil, { + src = "siit0", + dest = "lan" + }) + + -- firewall include + uci:delete_all("firewall", "include", + function(s) return s.path == "/etc/firewall.user" end) + + uci:section("firewall", "include", nil, { + path = "/etc/firewall.user" + }) + + + -- siit0 interface + uci:delete_all("network", "interface", + function(s) return ( s.ifname == "siit0" ) end) + + uci:section("network", "interface", "siit0", { + ifname = "siit0", + proto = "none" + }) + + -- siit0 route + uci:delete_all("network", "route6", + function(s) return siit_route:contains(luci.ip.IPv6(s.target)) end) + + uci:section("network", "route6", nil, { + interface = "siit0", + target = siit_route:string() + }) + + -- create wifi network interface + uci:section("network", "interface", wifi_device, { + proto = "static", + mtu = 1400, + ip6addr = ula:string() + }) + + -- nuke old olsrd interfaces + uci:delete_all("olsrd", "Interface", + function(s) return s.interface == wifi_device end) + + -- configure olsrd interface + uci:foreach("olsrd", "olsrd", + function(s) uci:set("olsrd", s['.name'], "IpVersion", 6) end) + + uci:section("olsrd", "Interface", nil, { + ignore = 0, + interface = wifi_device, + Ip6AddrType = "global" + }) + + -- hna6 + uci:delete_all("olsrd", "Hna6", + function(s) + if s.netaddr and s.prefix then + return siit_route:contains(luci.ip.IPv6(s.netaddr.."/"..s.prefix)) + end + end) + + uci:section("olsrd", "Hna6", nil, { + netaddr = siit_route:host():string(), + prefix = siit_route:prefix() + }) + + -- txtinfo v6 + uci:foreach("olsrd", "LoadPlugin", + function(s) + if s.library == "olsrd_txtinfo.so.0.1" then + uci:set("olsrd", s['.name'], "accept", "::1") + end + end) + + uci:save("wireless") + uci:save("firewall") + uci:save("network") + uci:save("olsrd") +end + +return f diff --git a/openwrt/packages/luci/applications/luci-siitwizard/root/etc/config/siit b/openwrt/packages/luci/applications/luci-siitwizard/root/etc/config/siit new file mode 100644 index 0000000..0fce1ea --- /dev/null +++ b/openwrt/packages/luci/applications/luci-siitwizard/root/etc/config/siit @@ -0,0 +1,10 @@ +config siit ipv6 + option ula_prefix "fd00::" + option ula_global "00ca:ffee:babe::" + option ula_subnet "0000:0000:0000:dada::" + option siit_prefix "::ffff:0000:0000" + +config siit wifi + option essid "6mesh.freifunk.net" + option bssid "02:ca:ff:ee:ba:be" + option channel "1" diff --git a/openwrt/packages/luci/applications/luci-splash/Makefile b/openwrt/packages/luci/applications/luci-splash/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-splash/htdocs/luci/splash/index.html b/openwrt/packages/luci/applications/luci-splash/htdocs/luci/splash/index.html new file mode 100644 index 0000000..5257312 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/htdocs/luci/splash/index.html @@ -0,0 +1,10 @@ + + + + + + + +Flukso Configuration Interface + + diff --git a/openwrt/packages/luci/applications/luci-splash/ipkg/postinst b/openwrt/packages/luci/applications/luci-splash/ipkg/postinst new file mode 100755 index 0000000..f898ad1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/ipkg/postinst @@ -0,0 +1,5 @@ +#!/bin/sh + +[ -n "${IPKG_INSTROOT}" ] || { + /etc/init.d/luci_splash enabled || /etc/init.d/luci_splash enable +} diff --git a/openwrt/packages/luci/applications/luci-splash/luasrc/controller/splash/splash.lua b/openwrt/packages/luci/applications/luci-splash/luasrc/controller/splash/splash.lua new file mode 100644 index 0000000..b046ff4 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/luasrc/controller/splash/splash.lua @@ -0,0 +1,29 @@ +module("luci.controller.splash.splash", package.seeall) + +function index() + entry({"admin", "services", "splash"}, cbi("splash/splash"), "Client-Splash") + + node("splash").target = call("action_dispatch") + node("splash", "splash", "activate").target = call("action_activate") + node("splash", "splash", "splash").target = template("splash_splash/splash") +end + +function action_dispatch() + local mac = luci.sys.net.ip4mac(luci.http.getenv("REMOTE_ADDR")) or "" + local status = luci.util.execl("luci-splash status "..mac)[1] + if #mac > 0 and ( status == "whitelisted" or status == "lease" ) then + luci.http.redirect(luci.dispatcher.build_url()) + else + luci.http.redirect(luci.dispatcher.build_url("splash", "splash", "splash")) + end +end + +function action_activate() + local mac = luci.sys.net.ip4mac(luci.http.getenv("REMOTE_ADDR")) + if mac and luci.http.formvalue("accept") then + os.execute("luci-splash add "..mac.." >/dev/null 2>&1") + luci.http.redirect(luci.model.uci.cursor():get("freifunk", "community", "homepage")) + else + luci.http.redirect(luci.dispatcher.build_url()) + end +end diff --git a/openwrt/packages/luci/applications/luci-splash/luasrc/model/cbi/splash/splash.lua b/openwrt/packages/luci/applications/luci-splash/luasrc/model/cbi/splash/splash.lua new file mode 100644 index 0000000..29bc6d9 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/luasrc/model/cbi/splash/splash.lua @@ -0,0 +1,47 @@ +-- ToDo: Translate, Add descriptions and help texts +require("luci.model.uci") + +m = Map("luci_splash", "Client-Splash", [[Client-Splash ist das Freifunk Hotspot-Authentifizierungs-System.]]) + +s = m:section(NamedSection, "general", "core", "Allgemein") +s:option(Value, "leasetime", "Freigabezeit", "h") + +s = m:section(TypedSection, "iface", "Schnittstellen") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true + +local uci = luci.model.uci.cursor() + +zone = s:option(ListValue, "zone", "Firewallzone") +uci:foreach("firewall", "zone", + function (section) + zone:value(section.name) + end) + +iface = s:option(ListValue, "network", "Netzwerk") +uci:foreach("network", "interface", + function (section) + if section[".name"] ~= "loopback" then + iface:value(section[".name"]) + end + end) + +uci:foreach("network", "alias", + function (section) + iface:value(section[".name"]) + end) + +s = m:section(TypedSection, "whitelist", "Automatische Freigabe") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true +s:option(Value, "mac", "MAC-Adresse") + +s = m:section(TypedSection, "blacklist", "Automatische Sperrung") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true +s:option(Value, "mac", "MAC-Adresse") + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash/splash.htm b/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash/splash.htm new file mode 100644 index 0000000..b906ec2 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash/splash.htm @@ -0,0 +1,47 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: splash.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<% local c = luci.model.uci.cursor():get_all("freifunk", "community") %> + +

Willkommen!

+

+Du bist jetzt mit dem freien Funknetz +<%=c.name%> verbunden.
+Wir sind ein experimentelles Gemeinschaftsnetzwerk, aber kein Internetanbieter. +

+ +

+Ein Zugang ins Internet ist trotzdem möglich, +da einige Freifunker ihre privaten Internetzugänge zur Verfügung stellen. +Diese Zugänge müssen sich hier alle teilen. +Bitte sei Dir dessen bewusst und verhalte Dich dementsprechend: +

    +
  • bitte keine Filesharing-Programme betreiben!
  • +
  • bitte keine unnötigen Downloads oder Streams starten!
  • +
  • bitte keine illegalen Aktivitäten!
  • +
+

+ +

+Wenn Du unsere Idee gut findest, kannst Du uns unterstützen: +

+

+ +

+Mit einem Klick auf <%:accept%> kannst du für <%=c.leasetime%> Stunden +über unser Netz das Internet verwenden. Dann wirst du erneut aufgefordet, diese Bedingungen zu akzeptieren. +

\ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/index.htm b/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/index.htm new file mode 100644 index 0000000..e2ed857 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/index.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 2539 2008-07-07 22:08:34Z jow $ + +-%> +<%+header%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/splash.htm b/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/splash.htm new file mode 100644 index 0000000..7a873cf --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/luasrc/view/splash_splash/splash.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: splash.htm 2539 2008-07-07 22:08:34Z jow $ + +-%> +<%+header%> +<%+splash/splash%> +
+ + +
+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-splash/root/etc/config/luci_splash b/openwrt/packages/luci/applications/luci-splash/root/etc/config/luci_splash new file mode 100644 index 0000000..c4cfef5 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/root/etc/config/luci_splash @@ -0,0 +1,2 @@ +config core general + option leasetime 1 \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-splash/root/etc/cron.minutely/luci_splash b/openwrt/packages/luci/applications/luci-splash/root/etc/cron.minutely/luci_splash new file mode 100755 index 0000000..eae4294 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/root/etc/cron.minutely/luci_splash @@ -0,0 +1,2 @@ +#!/bin/sh +[ "$(date +%M | cut -c2)" == "5" ] && luci-splash sync \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-splash/root/etc/init.d/luci_splash b/openwrt/packages/luci/applications/luci-splash/root/etc/init.d/luci_splash new file mode 100755 index 0000000..85ea8ec --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/root/etc/init.d/luci_splash @@ -0,0 +1,87 @@ +#!/bin/sh /etc/rc.common +START=70 + +iface_add() { + local cfg="$1" + + config_get zone "$cfg" zone + [ -n "$zone" ] || return 0 + + config_get net "$cfg" network + [ -n "$net" ] || return 0 + + config_get ipaddr "$net" ipaddr + [ -n "$ipaddr" ] || return 0 + + config_get netmask "$net" netmask + [ -n "$netmask" ] || return 0 + + eval "$(ipcalc.sh $ipaddr $netmask)" + + iptables -t nat -A zone_${zone}_prerouting -s "$NETWORK/$PREFIX" -p ! tcp -j luci_splash_portal + iptables -t nat -A zone_${zone}_prerouting -s "$NETWORK/$PREFIX" -d ! "$ipaddr" -j luci_splash_portal + iptables -t nat -A zone_${zone}_prerouting -s "$NETWORK/$PREFIX" -d "$ipaddr" -p tcp -m multiport ! --dport 22,80,443 -j luci_splash_portal +} + +blacklist_add() { + local cfg="$1" + + config_get mac "$cfg" mac + [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j DROP +} + +whitelist_add() { + local cfg="$1" + + config_get mac "$cfg" mac + [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j RETURN +} + +start() { + ### Read chains from config + include /lib/network + scan_interfaces + config_load luci_splash + + ### Create subchains + iptables -t nat -N luci_splash + iptables -t nat -N luci_splash_portal + iptables -t nat -N luci_splash_leases + + ### Build the main and portal rule + config_foreach blacklist_add blacklist + config_foreach whitelist_add whitelist + config_foreach iface_add iface + + ### Build the portal rule + iptables -t nat -A luci_splash_portal -p udp --dport 53 -j RETURN + iptables -t nat -A luci_splash_portal -j luci_splash_leases + + ### Build the leases rule + iptables -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082 + iptables -t nat -A luci_splash_leases -j DROP + + ### Add crontab entry + grep luci-splash /var/spool/cron/crontabs/root >/dev/null 2>&1 || { + echo '*/5 * * * * /usr/sbin/luci-splash sync' >> /var/spool/cron/crontabs/root + } + + ### Start the splash httpd + start-stop-daemon -S -b -q -x /usr/bin/luci-splashd +} + +stop() { + ### Clear subchains + iptables -t nat -F luci_splash_leases + iptables -t nat -F luci_splash_portal + iptables -t nat -F luci_splash + + ### Delete subchains + iptables -t nat -X luci_splash_leases + iptables -t nat -X luci_splash_portal + iptables -t nat -X luci_splash + + ### Stop the splash httpd + start-stop-daemon -K -q -x /usr/bin/luci-splashd +} + diff --git a/openwrt/packages/luci/applications/luci-splash/root/lib/uci/schema/default/luci_splash b/openwrt/packages/luci/applications/luci-splash/root/lib/uci/schema/default/luci_splash new file mode 100644 index 0000000..f320141 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/root/lib/uci/schema/default/luci_splash @@ -0,0 +1,14 @@ +package luci_splash + +config section + option name 'core' + option title 'Common DHCP splash settings' + option package 'luci_splash' + option unique true + option required true + +config variable + option name 'leasetime' + option title 'Lease time in hours' + option section 'luci_splash.core' + option datatype 'float' diff --git a/openwrt/packages/luci/applications/luci-splash/root/usr/bin/luci-splashd b/openwrt/packages/luci/applications/luci-splash/root/usr/bin/luci-splashd new file mode 100755 index 0000000..267fbdf --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/root/usr/bin/luci-splashd @@ -0,0 +1,38 @@ +#!/usr/bin/lua + +require("socket") +require("luci.ip") +require("luci.model.uci") + +local uci = luci.model.uci.cursor_state() +uci:load("network") + +local server = socket.bind("0.0.0.0", arg[1] or 8082) +server:settimeout(0, "t") + +while true do + local client = server:accept() + + if client then + client:settimeout(1) + local srv + local ip = luci.ip.IPv4(client:getpeername()) + uci:foreach("network", "interface", + function (section) + if section.ipaddr then + local net = luci.ip.IPv4(section.ipaddr, section.netmask) + if ip and net and net:contains(ip) then + srv = section.ipaddr + return + end + end + end) + + client:receive() + client:send("HTTP/1.0 302 Found\r\nLocation: http://" .. srv .. + (arg[2] or "/luci/splash") .. "\r\n\r\n") + client:close() + else + socket.sleep(0.1) + end +end diff --git a/openwrt/packages/luci/applications/luci-splash/root/usr/sbin/luci-splash b/openwrt/packages/luci/applications/luci-splash/root/usr/sbin/luci-splash new file mode 100755 index 0000000..82662c8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-splash/root/usr/sbin/luci-splash @@ -0,0 +1,190 @@ +#!/usr/bin/lua + +require("luci.http") +require("luci.util") +require("luci.model.uci") + +-- Init state session +local uci = luci.model.uci.cursor_state() + + +function main(argv) + local cmd = argv[1] + local arg = argv[2] + + if cmd == "status" then + if not arg then + os.exit(1) + end + + if iswhitelisted(arg) then + print("whitelisted") + os.exit(0) + end + + if haslease(arg) then + print("lease") + os.exit(0) + end + + print("unknown") + os.exit(0) + elseif cmd == "add" then + if not arg then + os.exit(1) + end + + if not haslease(arg) then + add_lease(arg) + else + print("already leased!") + os.exit(2) + end + os.exit(0) + elseif cmd == "remove" then + if not arg then + os.exit(1) + end + + remove_lease(arg) + os.exit(0) + elseif cmd == "sync" then + sync() + os.exit(0) + else + print("Usage: " .. argv[0] .. " [MAC]") + os.exit(1) + end +end + +-- Add a lease to state and invoke add_rule +function add_lease(mac) + uci:section("luci_splash", "lease", nil, { + mac = mac, + start = os.time() + }) + add_rule(mac) + + uci:save("luci_splash") +end + + +-- Remove a lease from state and invoke remove_rule +function remove_lease(mac) + mac = mac:lower() + local del = {} + + uci:foreach("luci_splash", "lease", + function (section) + if section.mac:lower() == mac then + table.insert(del, section[".name"]) + end + end) + + for i,j in ipairs(del) do + remove_rule(j) + uci:delete("luci_splash", j) + end + + uci:save("luci_splash") +end + + +-- Add an iptables rule +function add_rule(mac) + return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN") +end + + +-- Remove an iptables rule +function remove_rule(mac) + return os.execute("iptables -t nat -D luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN") +end + + +-- Check whether a MAC-Address is listed in the lease state list +function haslease(mac) + mac = mac:lower() + local stat = false + + uci:foreach("luci_splash", "lease", + function (section) + if section.mac:lower() == mac then + stat = true + return + end + end) + + return stat +end + + +-- Check whether a MAC-Address is whitelisted +function iswhitelisted(mac) + mac = mac:lower() + + uci:foreach("luci_splash", "whitelist", + function (section) + if section.mac:lower() == mac then + stat = true + return + end + end) + + return false +end + + +-- Returns a list of MAC-Addresses for which a rule is existing +function listrules() + local cmd = "iptables -t nat -L luci_splash_leases | grep RETURN |" + cmd = cmd .. "egrep -io [0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+" + return luci.util.split(luci.util.exec(cmd)) +end + + +-- Synchronise leases, remove abandoned rules +function sync() + local written = {} + local time = os.time() + + -- Current leases in state files + local leases = uci:get_all("luci_splash") + + -- Convert leasetime to seconds + local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600 + + -- Clean state file + uci:load("luci_splash") + uci:revert("luci_splash") + + + -- For all leases + for k, v in pairs(leases) do + if v[".type"] == "lease" then + if os.difftime(time, tonumber(v.start)) > leasetime then + -- Remove expired + remove_rule(v.mac) + else + -- Rewrite state + uci:section("luci_splash", "lease", nil, { + mac = v.mac, + start = v.start + }) + written[v.mac:lower()] = 1 + end + end + end + + + -- Delete rules without state + for i, r in ipairs(listrules()) do + if #r > 0 and not written[r:lower()] then + remove_rule(r) + end + end + + uci:save("luci_splash") +end + +main(arg) \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-statistics/Makefile b/openwrt/packages/luci/applications/luci-statistics/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-statistics/ipkg/postinst b/openwrt/packages/luci/applications/luci-statistics/ipkg/postinst new file mode 100755 index 0000000..8d52ec2 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/ipkg/postinst @@ -0,0 +1,7 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-statistics ) && rm -f /etc/uci-defaults/luci-statistics + + /etc/init.d/luci_statistics enabled || /etc/init.d/luci_statistics enable + /etc/init.d/collectd enabled || /etc/init.d/collectd enable +} diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua new file mode 100644 index 0000000..f9fd60a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua @@ -0,0 +1,198 @@ +--[[ + +Luci statistics - statistics controller module +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: luci_statistics.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.luci_statistics.luci_statistics", package.seeall) + +function index() + + require("luci.fs") + require("luci.util") + require("luci.i18n") + require("luci.statistics.datatree") + + -- load language files + luci.i18n.loadc("rrdtool") + luci.i18n.loadc("statistics") + + -- get rrd data tree + local tree = luci.statistics.datatree.Instance() + + -- override entry(): check for existance .so where is derived from the called path + function _entry( path, ... ) + local file = path[5] or path[4] + if luci.fs.access( "/usr/lib/collectd/" .. file .. ".so" ) then + entry( path, ... ) + end + end + + -- override i18n(): try to translate stat_ or fall back to + function _i18n( str ) + return luci.i18n.translate( "stat_" .. str, str ) + end + + -- our collectd menu + local collectd_menu = { + output = { "rrdtool", "network", "unixsock", "csv" }, + system = { "exec", "email", "cpu", "df", "disk", "irq", "processes", "load" }, + network = { "interface", "netlink", "iptables", "tcpconns", "ping", "dns", "wireless" } + } + + -- create toplevel menu nodes + local st = entry({"admin", "statistics"}, call("statistics_index"), _i18n("statistics"), 80) + st.i18n = "statistics" + st.index = true + + entry({"admin", "statistics", "collectd"}, cbi("luci_statistics/collectd"), _i18n("collectd"), 10).subindex = true + + + -- populate collectd plugin menu + local index = 1 + for section, plugins in luci.util.kspairs( collectd_menu ) do + entry( + { "admin", "statistics", "collectd", section }, + call( "statistics_" .. section .. "plugins" ), + _i18n( section .. "plugins" ), + index * 10 + ).index = true + + for j, plugin in luci.util.vspairs( plugins ) do + _entry( + { "admin", "statistics", "collectd", section, plugin }, + cbi("luci_statistics/" .. plugin ), + _i18n( plugin ), + j * 10 + ) + end + + index = index + 1 + end + + -- output views + local page = entry( { "admin", "statistics", "graph" }, call("statistics_index"), _i18n("graphs"), 80) + page.i18n = "statistics" + page.setuser = "nobody" + page.setgroup = "nogroup" + + local vars = luci.http.formvalue(nil, true) + local span = vars.timespan or nil + + for i, plugin in luci.util.vspairs( tree:plugins() ) do + + -- get plugin instances + local instances = tree:plugin_instances( plugin ) + + -- plugin menu entry + entry( + { "admin", "statistics", "graph", plugin }, + call("statistics_render"), _i18n( plugin ), i + ).query = { timespan = span } + + -- if more then one instance is found then generate submenu + if #instances > 1 then + for j, inst in luci.util.vspairs(instances) do + -- instance menu entry + entry( + { "admin", "statistics", "graph", plugin, inst }, + call("statistics_render"), inst, j + ).query = { timespan = span } + end + end + end +end + +function statistics_index() + luci.template.render("admin_statistics/index") +end + +function statistics_outputplugins() + local plugins = { } + + for i, p in ipairs({ "rrdtool", "network", "unixsock", "csv" }) do + plugins[p] = luci.i18n.translate( "stat_" .. p, p ) + end + + luci.template.render("admin_statistics/outputplugins", {plugins=plugins}) +end + +function statistics_systemplugins() + local plugins = { } + + for i, p in ipairs({ "exec", "email", "df", "disk", "irq", "processes", "cpu" }) do + plugins[p] = luci.i18n.translate( "stat_" .. p, p ) + end + + luci.template.render("admin_statistics/systemplugins", {plugins=plugins}) +end + +function statistics_networkplugins() + local plugins = { } + + for i, p in ipairs({ "interface", "netlink", "iptables", "tcpconns", "ping", "dns", "wireless" }) do + plugins[p] = luci.i18n.translate( "stat_" .. p, p ) + end + + luci.template.render("admin_statistics/networkplugins", {plugins=plugins}) +end + + +function statistics_render() + + require("luci.statistics.rrdtool") + require("luci.template") + require("luci.model.uci") + + local vars = luci.http.formvalue() + local req = luci.dispatcher.context.request + local path = luci.dispatcher.context.path + local uci = luci.model.uci.cursor() + local spans = luci.util.split( uci:get( "luci_statistics", "collectd_rrdtool", "RRATimespans" ), "%s+", nil, true ) + local span = vars.timespan or uci:get( "luci_statistics", "rrdtool", "default_timespan" ) or spans[1] + local graph = luci.statistics.rrdtool.Graph( luci.util.parse_units( span ) ) + + local plugin, instances + local images = { } + + -- find requested plugin and instance + for i, p in ipairs( luci.dispatcher.context.path ) do + if luci.dispatcher.context.path[i] == "graph" then + plugin = luci.dispatcher.context.path[i+1] + instances = { luci.dispatcher.context.path[i+2] } + end + end + + -- no instance requested, find all instances + if #instances == 0 then + instances = { graph.tree:plugin_instances( plugin )[1] } + + -- index instance requested + elseif instances[1] == "-" then + instances[1] = "" + end + + + -- render graphs + for i, inst in ipairs( instances ) do + for i, img in ipairs( graph:render( plugin, inst ) ) do + table.insert( images, graph:strippngpath( img ) ) + end + end + + luci.template.render( "public_statistics/graph", { + images = images, + plugin = plugin, + timespans = spans, + current_timespan = span + } ) +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.lua new file mode 100644 index 0000000..afd97f0 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.lua @@ -0,0 +1,70 @@ +stat_dg_title_wireless__signal_noise = [[%H: Drahtlos - Signal-Noise-Verhältnis]] +stat_dg_label_wireless__signal_noise = [[dBm]] +stat_ds_signal_noise = [[Noise-Level]] +stat_ds_signal_power = [[Signalstärke]] +stat_dg_title_wireless__signal_quality = [[%H: Drahtlos - Signalqualität]] +stat_dg_label_wireless__signal_quality = [[n]] +stat_ds_signal_quality = [[Signalqualität]] +stat_dg_title_ping = [[%H: ICMP Antwortzeiten]] +stat_dg_label_ping = [[ms]] +stat_ds_ping = [[%di]] +stat_dg_title_iptables__ipt_packets = [[%H: Firewall - Verarbeitete Pakete]] +stat_dg_label_iptables__ipt_packets = [[Pakete/s]] +stat_ds_ipt_packets = [[Kette "%di"]] +stat_dg_title_netlink__if_octets = [[%H: Netlink - Transfer auf %pi]] +stat_dg_label_netlink__if_octets = [[Bytes/s]] +stat_ds_if_octets = [[Bytes (%ds)]] +stat_dg_title_netlink__if_packets = [[%H: Netlink - Pakete auf %pi]] +stat_dg_label_netlink__if_packets = [[Pakete/s]] +stat_ds_if_packets = [[Verarbeitet (%ds)]] +stat_ds_if_dropped = [[Verworfen (%ds)]] +stat_ds_if_errors = [[Fehler (%ds)]] +stat_dg_title_netlink__if_multicast = [[%H: Netlink - Multicast auf %pi]] +stat_dg_label_netlink__if_multicast = [[Pakete/s]] +stat_ds_if_multicast = [[Pakete]] +stat_dg_title_netlink__if_collisions = [[%H: Netlink - Kollisionen auf %pi]] +stat_dg_label_netlink__if_collisions = [[Kollisionen/s]] +stat_ds_if_collisions = [[Kollisionen]] +stat_dg_title_netlink__if_tx_errors = [[%H: Netlink - Fehler auf %pi]] +stat_dg_label_netlink__if_tx_errors = [[Fehler/s]] +stat_ds_if_tx_errors = [[%di]] +stat_ds_if_rx_errors = [[%di]] +stat_dg_title_processes = [[%H: Prozesse]] +stat_dg_label_processes = [[Prozesse/s]] +stat_ds_ps_state = [[%di]] +stat_dg_title_processes__ps_cputime = [[%H: Prozess %pi - Verbrauchte CPU Zeit]] +stat_dg_label_processes__ps_cputime = [[Jiffies]] +stat_ds_ps_cputime__syst = [[System]] +stat_ds_ps_cputime__user = [[User]] +stat_dg_title_processes__ps_count = [[%H: Prozess %pi - Threads und Prozesse]] +stat_dg_label_processes__ps_count = [[Anzahl]] +stat_ds_ps_count__threads = [[Threads]] +stat_ds_ps_count__processes = [[Prozesse]] +stat_dg_title_processes__ps_pagefaults = [[%H: Prozess %pi - Speicherzugriffsfehler]] +stat_dg_label_processes__ps_pagefaults = [[Zugriffsfehler]] +stat_ds_ps_pagefaults = [[Zugriffsfehler]] +stat_dg_title_processes__ps_rss = [[%H: Process %pi - Virtueller Speicher]] +stat_dg_label_processes__ps_rss = [[Bytes]] +stat_ds_ps_rss = [[virtueller Speicher]] +stat_dg_title_cpu = [[%H: Auslastung auf Prozessor #%pi]] +stat_dg_label_cpu = [[%]] +stat_ds_cpu = [[%di]] +stat_dg_title_interface__if_octets = [[%H: Transfer auf %di]] +stat_dg_label_interface__if_octets = [[Bytes/s]] +stat_dg_title_interface__if_packets = [[%H: Pakete auf %di]] +stat_dg_label_interface__if_packets = [[Pakete/s]] +stat_dg_title_tcpconns = [[%H: TCP-Verbindungen auf Port %pi]] +stat_dg_label_tcpconns = [[Verbindungen/s]] +stat_ds_tcp_connections = [[%di]] +stat_dg_title_df = [[%H: Speicherverbrauch auf %di]] +stat_dg_label_df = [[Bytes]] +stat_ds_df__free = [[verfügbar]] +stat_ds_df__used = [[belegt ]] +stat_dg_title_irq = [[%H: Interrupts]] +stat_dg_label_irq = [[Aufrufe/s]] +stat_ds_irq = [[IRQ %di]] +stat_dg_title_load = [[%H: Systemlast]] +stat_dg_label_load = [[Last]] +stat_ds_load__shortterm = [[1 Minute]] +stat_ds_load__midterm = [[5 Minuten]] +stat_ds_load__longterm = [[15 Minuten]] diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.xml.hide b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.xml.hide new file mode 100644 index 0000000..1432321 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.de.xml.hide @@ -0,0 +1,96 @@ + + + + +%H: Drahtlos - Signal-Noise-Verhältnis +dBm +Noise-Level +Signalstärke + +%H: Drahtlos - Signalqualität +n +Signalqualität + +%H: ICMP Antwortzeiten +ms +%di + +%H: Firewall - Verarbeitete Pakete +Pakete/s +Kette "%di" + +%H: Netlink - Transfer auf %pi +Bytes/s +Bytes (%ds) + +%H: Netlink - Pakete auf %pi +Pakete/s +Verarbeitet (%ds) +Verworfen (%ds) +Fehler (%ds) + +%H: Netlink - Multicast auf %pi +Pakete/s +Pakete + +%H: Netlink - Kollisionen auf %pi +Kollisionen/s +Kollisionen + +%H: Netlink - Fehler auf %pi +Fehler/s +%di +%di + +%H: Prozesse +Prozesse/s +%di + +%H: Prozess %pi - Verbrauchte CPU Zeit +Jiffies +System +User + +%H: Prozess %pi - Threads und Prozesse +Anzahl +Threads +Prozesse + +%H: Prozess %pi - Speicherzugriffsfehler +Zugriffsfehler +Zugriffsfehler + +%H: Process %pi - Virtueller Speicher +Bytes +virtueller Speicher + +%H: Auslastung auf Prozessor #%pi +% +%di + +%H: Transfer auf %di +Bytes/s + +%H: Pakete auf %di +Pakete/s + +%H: TCP-Verbindungen auf Port %pi +Verbindungen/s +%di + +%H: Speicherverbrauch auf %di +Bytes +verfügbar +belegt + +%H: Interrupts +Aufrufe/s +IRQ %di + +%H: Systemlast +Last +1 Minute +5 Minuten +15 Minuten + + diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.lua new file mode 100644 index 0000000..2da4be8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.lua @@ -0,0 +1,69 @@ +stat_dg_title_wireless__signal_noise = [[%H: Wireless - Signal Noise Ratio]] +stat_dg_label_wireless__signal_noise = [[dBm]] +stat_ds_signal_noise = [[Noise Level]] +stat_ds_signal_power = [[Signal Strength]] +stat_dg_title_wireless__signal_quality = [[%H: Wireless - Signal Quality]] +stat_dg_label_wireless__signal_quality = [[n]] +stat_ds_signal_quality = [[Signal Quality]] +stat_dg_title_ping = [[%H: ICMP Roundtrip Times]] +stat_dg_label_ping = [[ms]] +stat_ds_ping = [[%di]] +stat_dg_title_iptables__ipt_packets = [[%H: Firewall - Processed Packets]] +stat_dg_label_iptables__ipt_packets = [[Packets/s]] +stat_ds_ipt_packets = [[Chain "%di"]] +stat_dg_title_netlink__if_octets = [[%H: Netlink - Transfer on %pi]] +stat_dg_label_netlink__if_octets = [[Bytes/s]] +stat_ds_if_octets = [[Bytes (%ds)]] +stat_dg_title_netlink__if_packets = [[%H: Netlink - Packets on %pi]] +stat_dg_label_netlink__if_packets = [[Packets/s]] +stat_ds_if_packets = [[Processed (%ds)]] +stat_ds_if_dropped = [[Dropped (%ds)]] +stat_ds_if_errors = [[Errors (%ds)]] +stat_dg_title_netlink__if_multicast = [[%H: Netlink - Multicast on %pi]] +stat_dg_label_netlink__if_multicast = [[Packets/s]] +stat_ds_if_multicast = [[Packets]] +stat_dg_title_netlink__if_collisions = [[%H: Netlink - Collisions on %pi]] +stat_dg_label_netlink__if_collisions = [[Collisions/s]] +stat_ds_if_collisions = [[Collisions]] +stat_dg_title_netlink__if_tx_errors = [[%H: Netlink - Errors on %pi]] +stat_dg_label_netlink__if_tx_errors = [[Errors/s]] +stat_ds_if_tx_errors = [[%di]] +stat_ds_if_rx_errors = [[%di]] +stat_dg_title_processes = [[%H: Processes]] +stat_dg_label_processes = [[Processes/s]] +stat_ds_ps_state = [[%di]] +stat_dg_title_processes__ps_cputime = [[%H: Process %pi - used cpu time]] +stat_dg_label_processes__ps_cputime = [[Jiffies]] +stat_ds_ps_cputime__syst = [[system]] +stat_ds_ps_cputime__user = [[user]] +stat_dg_title_processes__ps_count = [[%H: Process %pi - threads and processes]] +stat_dg_label_processes__ps_count = [[Count]] +stat_ds_ps_count = [[%ds]] +stat_dg_title_processes__ps_pagefaults = [[%H: Process %pi - page faults]] +stat_dg_label_processes__ps_pagefaults = [[Pagefaults]] +stat_ds_ps_pagefaults = [[page faults]] +stat_dg_title_processes__ps_rss = [[%H: Process %pi - virtual memory size]] +stat_dg_label_processes__ps_rss = [[Bytes]] +stat_ds_ps_rss = [[virtual memory]] +stat_dg_title_cpu = [[%H: Usage on Processor #%pi]] +stat_dg_label_cpu = [[%]] +stat_ds_cpu = [[%di]] +stat_dg_title_interface__if_octets = [[%H: Transfer on %di]] +stat_dg_label_interface__if_octets = [[Bytes/s]] +stat_dg_title_interface__if_packets = [[%H: Packets on %di]] +stat_dg_label_interface__if_packets = [[Packets/s]] +stat_dg_title_tcpconns = [[%H: TCP-Connections to Port %pi]] +stat_dg_label_tcpconns = [[Connections/s]] +stat_ds_tcp_connections = [[%di]] +stat_dg_title_df = [[%H: Disk Space Usage on %di]] +stat_dg_label_df = [[Bytes]] +stat_ds_df__free = [[%ds]] +stat_ds_df__used = [[%ds]] +stat_dg_title_irq = [[%H: Interrupts]] +stat_dg_label_irq = [[Issues/s]] +stat_ds_irq = [[IRQ %di]] +stat_dg_title_load = [[%H: System Load]] +stat_dg_label_load = [[Load]] +stat_ds_load__shortterm = [[1 min]] +stat_ds_load__midterm = [[5 min]] +stat_ds_load__longterm = [[15 min]] diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.xml.hide b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.xml.hide new file mode 100644 index 0000000..8e3de05 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.en.xml.hide @@ -0,0 +1,95 @@ + + + + +%H: Wireless - Signal Noise Ratio +dBm +Noise Level +Signal Strength + +%H: Wireless - Signal Quality +n +Signal Quality + +%H: ICMP Roundtrip Times +ms +%di + +%H: Firewall - Processed Packets +Packets/s +Chain "%di" + +%H: Netlink - Transfer on %pi +Bytes/s +Bytes (%ds) + +%H: Netlink - Packets on %pi +Packets/s +Processed (%ds) +Dropped (%ds) +Errors (%ds) + +%H: Netlink - Multicast on %pi +Packets/s +Packets + +%H: Netlink - Collisions on %pi +Collisions/s +Collisions + +%H: Netlink - Errors on %pi +Errors/s +%di +%di + +%H: Processes +Processes/s +%di + +%H: Process %pi - used cpu time +Jiffies +system +user + +%H: Process %pi - threads and processes +Count +%ds + +%H: Process %pi - page faults +Pagefaults +page faults + +%H: Process %pi - virtual memory size +Bytes +virtual memory + +%H: Usage on Processor #%pi +% +%di + +%H: Transfer on %di +Bytes/s + +%H: Packets on %di +Packets/s + +%H: TCP-Connections to Port %pi +Connections/s +%di + +%H: Disk Space Usage on %di +Bytes +%ds +%ds + +%H: Interrupts +Issues/s +IRQ %di + +%H: System Load +Load +1 min +5 min +15 min + + diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.lua new file mode 100644 index 0000000..708f34c --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.lua @@ -0,0 +1,69 @@ +stat_dg_title_wireless__signal_noise = '%H: Wireless - Relação Sinal/Ruido' +stat_dg_label_wireless__signal_noise = 'dBm' +stat_ds_signal_noise = 'Nivel de Ruido' +stat_ds_signal_power = 'Forca do Sinal' +stat_dg_title_wireless__signal_quality = '%H: Wireless - Qualidade do Sinal' +stat_dg_label_wireless__signal_quality = 'n' +stat_ds_signal_quality = 'Qualidade do Sinal' +stat_dg_title_ping = '%H: Tempo de resposta ICMP' +stat_dg_label_ping = 'ms' +stat_ds_ping = '%di' +stat_dg_title_iptables__ipt_packets = '%H: Firewall - Pacotes Processados' +stat_dg_label_iptables__ipt_packets = 'Pacote/s' +stat_ds_ipt_packets = 'Cadeia "%di"' +stat_dg_title_netlink__if_octets = '%H: Netlink - Transferencia na %pi' +stat_dg_label_netlink__if_octets = 'Bytes/s' +stat_ds_if_octets = 'Bytes (%ds)' +stat_dg_title_netlink__if_packets = '%H: Netlink - Pacotes na %pi' +stat_dg_label_netlink__if_packets = 'Packets/s' +stat_ds_if_packets = 'Processado (%ds)' +stat_ds_if_dropped = 'Dropado (%ds)' +stat_ds_if_errors = 'Erros (%ds)' +stat_dg_title_netlink__if_multicast = '%H: Netlink - Multicast na %pi' +stat_dg_label_netlink__if_multicast = 'Pacote/s' +stat_ds_if_multicast = 'Pacotes' +stat_dg_title_netlink__if_collisions = '%H: Netlink - Colisoes na %pi' +stat_dg_label_netlink__if_collisions = 'Colisao(es)' +stat_ds_if_collisions = 'Colisoes' +stat_dg_title_netlink__if_tx_errors = '%H: Netlink - Erros na %pi' +stat_dg_label_netlink__if_tx_errors = 'Erro/s' +stat_ds_if_tx_errors = '%di' +stat_ds_if_rx_errors = '%di' +stat_dg_title_processes = '%H: Processos' +stat_dg_label_processes = 'Processo/s' +stat_ds_ps_state = '%di' +stat_dg_title_processes__ps_cputime = '%H: Processo %pi - tempo usado da cpu' +stat_dg_label_processes__ps_cputime = 'Jiffies' +stat_ds_ps_cputime__syst = 'sistema' +stat_ds_ps_cputime__user = 'usuario' +stat_dg_title_processes__ps_count = '%H: Processo %pi - threads e processos' +stat_dg_label_processes__ps_count = 'Contagem' +stat_ds_ps_count = '%ds' +stat_dg_title_processes__ps_pagefaults = '%H: Prcesso %pi - pagina de erros' +stat_dg_label_processes__ps_pagefaults = 'Pagina de erros' +stat_ds_ps_pagefaults = 'pagina de erros' +stat_dg_title_processes__ps_rss = '%H: Processo %pi - tamanho da memoria virtual' +stat_dg_label_processes__ps_rss = 'Bytes' +stat_ds_ps_rss = 'memoria virtual' +stat_dg_title_cpu = '%H: Usado no Processado #%pi' +stat_dg_label_cpu = '%' +stat_ds_cpu = '%di' +stat_dg_title_interface__if_octets = '%H: Transferencia na %di' +stat_dg_label_interface__if_octets = 'Bytes/s' +stat_dg_title_interface__if_packets = '%H: Pacotes na %di' +stat_dg_label_interface__if_packets = 'Pacote/s' +stat_dg_title_tcpconns = '%H: Conexoes TCP na Porta %pi' +stat_dg_label_tcpconns = 'Conexao(oes)' +stat_ds_tcp_connections = '%di' +stat_dg_title_df = '%H: Utilizacao de Espaco em Disco em %di' +stat_dg_label_df = 'Bytes' +stat_ds_df__free = '%ds' +stat_ds_df__used = '%ds' +stat_dg_title_irq = '%H: Interrupcoes' +stat_dg_label_irq = 'Erro/s' +stat_ds_irq = 'IRQ %di' +stat_dg_title_load = '%H: Carga do Sistema' +stat_dg_label_load = 'Carga' +stat_ds_load__shortterm = '1 min' +stat_ds_load__midterm = '5 min' +stat_ds_load__longterm = '15 min' diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.xml.hide b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.xml.hide new file mode 100644 index 0000000..7f369c1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/rrdtool.pt-br.xml.hide @@ -0,0 +1,95 @@ + + + + +%H: Wireless - Relação Sinal/Ruido +dBm +Nivel de Ruido +Forca do Sinal + +%H: Wireless - Qualidade do Sinal +n +Qualidade do Sinal + +%H: Tempo de resposta ICMP +ms +%di + +%H: Firewall - Pacotes Processados +Pacote/s +Cadeia "%di" + +%H: Netlink - Transferencia na %pi +Bytes/s +Bytes (%ds) + +%H: Netlink - Pacotes na %pi +Packets/s +Processado (%ds) +Dropado (%ds) +Erros (%ds) + +%H: Netlink - Multicast na %pi +Pacote/s +Pacotes + +%H: Netlink - Colisoes na %pi +Colisao(es) +Colisoes + +%H: Netlink - Erros na %pi +Erro/s +%di +%di + +%H: Processos +Processo/s +%di + +%H: Processo %pi - tempo usado da cpu +Jiffies +sistema +usuario + +%H: Processo %pi - threads e processos +Contagem +%ds + +%H: Prcesso %pi - pagina de erros +Pagina de erros +pagina de erros + +%H: Processo %pi - tamanho da memoria virtual +Bytes +memoria virtual + +%H: Usado no Processador #%pi +% +%di + +%H: Transferencia na %di +Bytes/s + +%H: Pacotes na %di +Pacote/s + +%H: Conexoes TCP na Porta %pi +Conexao(oes) +%di + +%H: Utilizacao de Espaco em Disco em %di +Bytes +%ds +%ds + +%H: Interrupcoes +Erro/s +IRQ %di + +%H: Carga do Sistema +Carga +1 min +5 min +15 min + + diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.lua new file mode 100644 index 0000000..1e2e1f1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.lua @@ -0,0 +1,212 @@ +stat_statistics = 'Statistiken' +stat_desc = 'Das Statistik-Paket basiert auf Collectd und nutzt RRD Tool um die gesammelten Daten in Diagramme zu rendern.' +stat_systemplugins = 'Systemplugins' +stat_networkplugins = 'Netzwerkplugins' +stat_outputplugins = 'Ausgabeplugins' +stat_showtimespan = 'Zeitspanne zeigen »' +stat_graphs = 'Diagramme' +stat_collectd = 'Collectd' +stat_cpu = 'Prozessor' +stat_ping = 'Ping' +stat_iptables = 'Firewall' +stat_netlink = 'Netlink' +stat_processes = 'Prozesse' +stat_wireless = 'Drahtlos' +stat_tcpconns = 'TCP-Verbindungen' +stat_interface = 'Schnittstellen' +stat_df = 'Plattenspeicher' +stat_irq = 'Interrupts' +stat_disk = 'Plattenauslastung' +stat_exec = 'Exec' +stat_rrdtool = 'RRDTool' +stat_network = 'Netzwerk' +stat_csv = 'CSV Ausgabe' +stat_load = 'Systemlast' +stat_dns = 'DNS' +stat_email = 'Email' +stat_unixsock = 'UnixSock' +lucistatistics = 'Statistiken' +lucistatistics_collectd = 'Collectd Einstellungen' +lucistatistics_collectd_desc = 'Collectd ist ein schlankes Dienstprogramm zum Sammeln von Systemdaten aus verschiedenen Quellen mittels diverser Plugins. Auf dieser Seite können generelle Einstellungen für den Collectd-Daemon vorgenommen werden.' +lucistatistics_collectd_hostname = 'Hostname' +lucistatistics_collectd_basedir = 'Basisverzeichnis' +lucistatistics_collectd_include = 'Verzeichnis für Unterkonfigurationen' +lucistatistics_collectd_plugindir = 'Verzeichnis für Collectd-Plugins' +lucistatistics_collectd_pidfile = 'Pfad zu PID-Datei' +lucistatistics_collectd_typesdb = 'Dataset-Definitionen' +lucistatistics_collectd_interval = 'Daten-Sammelintervall' +lucistatistics_collectd_interval_desc = 'Sekunden' +lucistatistics_collectd_readthreads = 'Anzahl paralleler Sammelprozesse' +lucistatistics_collectd_fqdnlookup = 'automatisch vollen Hostnamen herausfinden' +lucistatistics_collectdcpu = 'CPU Plugin Konfiguration' +lucistatistics_collectdcpu_desc = 'Das CPU-Plugin sammelt grundlegende Statistiken über die Prozessorauslastung.' +lucistatistics_collectdcpu_enable = 'Plugin aktivieren' +lucistatistics_collectdcsv = 'CSV Plugin Konfiguration' +lucistatistics_collectdcsv_desc = 'Das CSV-Plugin speichert die gesammelten Daten im CSV-Format, geeignet für die Weiterverarbeitung durch externe Programme.' +lucistatistics_collectdcsv_enable = 'Plugin aktivieren' +lucistatistics_collectdcsv_datadir = 'Speicherverzeichnis für die CSV-Dateien' +lucistatistics_collectdcsv_storerates = 'Werte nicht absolut sondern als Raten speichern' +lucistatistics_collectddf = 'DF Plugin Konfiguration' +lucistatistics_collectddf_desc = 'Das DF-Plugin sammelt Statistiken über den Speicherverbrauch auf verschiedenen Geräten, Mount-Punkten oder Dateisystemtypen.' +lucistatistics_collectddf_enable = 'Plugin aktivieren' +lucistatistics_collectddf_devices = 'Geräte überwachen' +lucistatistics_collectddf_devices_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddf_mountpoints = 'Mount-Punkte überwachen' +lucistatistics_collectddf_mountpoints_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddf_fstypes = 'Datesystemtypen überwachen' +lucistatistics_collectddf_fstypes_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddf_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectddisk = 'Disk Plugin Konfiguration' +lucistatistics_collectddisk_desc = 'Das Disk-Plugin sammelt detaillierte Statistiken über die Auslastung auf ausgewählten Festplatten und Partitionen.' +lucistatistics_collectddisk_enable = 'Plugin aktivieren' +lucistatistics_collectddisk_disks = 'Geräte und Partitionen überwachen' +lucistatistics_collectddisk_disks_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddisk_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectddns = 'DNS Plugin Konfiguration' +lucistatistics_collectddns_desc = 'Das DNS-Plugin sammelt detaillierte Statistiken über DNS-bezogenen Verkehr auf ausgewählten Schnittstellen.' +lucistatistics_collectddns_enable = 'Plugin aktivieren' +lucistatistics_collectddns_interfaces = 'Schnittstellen überwachen' +lucistatistics_collectddns_interfaces_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddns_ignoresources = 'Quelladressen ignorieren' +lucistatistics_collectddns_ignoresources_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdemail = 'E-Mail Plugin Konfiguration' +lucistatistics_collectdemail_desc = 'Das E-Mail Plugin erstellt einen Unix-Socket welcher benutzt werden kann um E-Mail-Statistiken an den laufenden Collectd-Daemon zu übermitteln. Dieses Plugin ist primär für die Verwendung zusammen mit Mail::SpamAssasin::Plugin::Collectd gedacht, kann aber auch anderweitig verwendet werden.' +lucistatistics_collectdemail_enable = 'Plugin aktivieren' +lucistatistics_collectdemail_socketfile = 'Dateipfad des Unix-Sockets' +lucistatistics_collectdemail_socketgroup = 'Gruppenbesitzer festlegen' +lucistatistics_collectdemail_socketgroup_desc = 'Gruppenname' +lucistatistics_collectdemail_socketperms = 'Dateiberechtigungen des Unix-Sockets' +lucistatistics_collectdemail_socketperms_desc = 'oktal' +lucistatistics_collectdemail_maxconns = 'Maximale Anzahl erlaubter Verbindungen' +lucistatistics_collectdexec = 'Exec Plugin Konfiguration' +lucistatistics_collectdexec_desc = 'Das Exec-Plugin startet externe Kommandos um Werte einzulesen oder um Benachrichtigungen auszulösen falls bestimmte Grenzwerte erreicht werden.' +lucistatistics_collectdexec_enable = 'Plugin aktivieren' +lucistatistics_collectdexecinput = 'Kommando zum Werte einlesen hinzufügen' +lucistatistics_collectdexecinput_desc = 'Hier können externe Kommandos definiert werden, welche durch Collectd gestartet werden um Statistik-Werte einzulesen. Die Werte werden dabei vom STDOUT des aufgerufenen Programmes gelesen.' +lucistatistics_collectdexecinput_cmdline = 'Kommandozeile' +lucistatistics_collectdexecinput_cmduser = 'Als Benutzer ausführen' +lucistatistics_collectdexecinput_cmdgroup = 'Als Gruppe ausführen' +lucistatistics_collectdexecnotify = 'Benachrichtigungskommando hinzufügen' +lucistatistics_collectdexecnotify_desc = 'Hier können externe Kommandos definiert werden, welche durch Collectd gestartet werden sobald konfigurierte Grenzwerte erreicht werden. Die Werte welche die Benachrichtigung ausgelöst haben werden dabei an den STDIN des aufgerufenen Programmes übergeben.' +lucistatistics_collectdexecnotify_cmdline = 'Kommandozeile' +lucistatistics_collectdexecnotify_cmduser = 'Als Benutzer ausführen' +lucistatistics_collectdexecnotify_cmdgroup = 'Als Gruppe ausführen' +lucistatistics_collectdinterface = 'Interface Plugin Konfiguration' +lucistatistics_collectdinterface_desc = 'Das Interface-Plugin sammelt allgemeine Verkehrsstatistiken auf ausgewählten Schnittstellen.' +lucistatistics_collectdinterface_enable = 'Plugin aktivieren' +lucistatistics_collectdinterface_interfaces = 'Schnittstellen überwachen' +lucistatistics_collectdinterface_interfaces_desc = 'Strg gedrückt halten um mehrere Schnittstellen zu wählen' +lucistatistics_collectdinterface_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectdiptables = 'Iptables Plugin Konfiguration' +lucistatistics_collectdiptables_desc = 'Das Iptables-Plugin überwacht ausgewählte Firewall-Regeln und sammelt Werte über die Anzahl der verarbeiteten Pakete und Bytes.' +lucistatistics_collectdiptables_enable = 'Plugin aktivieren' +lucistatistics_collectdiptablesmatch = 'Auswahlregel hinzufügen' +lucistatistics_collectdiptablesmatch_desc = 'Hier werden die Kriterien festgelegt nach welchen die zu überwachenden Firewall-Regeln ausgewählt werden.' +lucistatistics_collectdiptablesmatch_name = 'Name der Regel' +lucistatistics_collectdiptablesmatch_name_desc = 'max. 16 Buchstaben' +lucistatistics_collectdiptablesmatch_table = 'Tabelle' +lucistatistics_collectdiptablesmatch_chain = 'Kette (Chain)' +lucistatistics_collectdiptablesmatch_target = 'Aktion (Target)' +lucistatistics_collectdiptablesmatch_protocol = 'Netzwerkprotokoll' +lucistatistics_collectdiptablesmatch_source = 'Quell-IP-Bereich' +lucistatistics_collectdiptablesmatch_source_desc = 'CIDR-Notation' +lucistatistics_collectdiptablesmatch_destination = 'Ziel-IP-Bereich' +lucistatistics_collectdiptablesmatch_destination_desc = 'CIDR-Notation' +lucistatistics_collectdiptablesmatch_inputif = 'eingehende Schnittstelle' +lucistatistics_collectdiptablesmatch_inputif_desc = 'z.B. br-lan' +lucistatistics_collectdiptablesmatch_outputif = 'ausgehende Schnittstelle' +lucistatistics_collectdiptablesmatch_outputif_desc = 'z.B. br-ff' +lucistatistics_collectdiptablesmatch_options = 'Optionen' +lucistatistics_collectdiptablesmatch_options_desc = 'z.B. reject-with tcp-reset' +lucistatistics_collectdirq = 'IRQ Plugin Konfiguration' +lucistatistics_collectdirq_desc = 'Das IRQ-Plugin überwacht die Anzahl der Aufrufe pro Sekunde für jeden ausgewählten Interrupt. Wird kein Interrupt ausgewählt überwacht das Plugin alle im System vorhandenen Interrupts.' +lucistatistics_collectdirq_enable = 'Plugin aktivieren' +lucistatistics_collectdirq_irqs = 'Interrups überwachen' +lucistatistics_collectdirq_irqs_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdirq_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectdload = 'Load Plugin Konfiguration' +lucistatistics_collectdload_desc = 'Das Load-Plugin sammelt Informationen über die allgemeine Systemlast.' +lucistatistics_collectdload_enable = 'Plugin aktivieren' +lucistatistics_collectdnetlink = 'Netlink Plugin Konfiguration' +lucistatistics_collectdnetlink_desc = 'Das Netlink-Plugin sammelt erweiterte QoS-Informationen wie QDisc-, Class- und Filter-Statistiken auf ausgewählten Schnittstellen.' +lucistatistics_collectdnetlink_enable = 'Plugin aktivieren' +lucistatistics_collectdnetlink_interfaces = 'Schnittstellen einfach überwachen' +lucistatistics_collectdnetlink_interfaces_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_verboseinterfaces = 'Schnittstellen detailliert überwachen' +lucistatistics_collectdnetlink_verboseinterfaces_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_qdiscs = 'Queue Discipline überwachen' +lucistatistics_collectdnetlink_qdiscs_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_classes = 'Shapingklassen überwachen' +lucistatistics_collectdnetlink_classes_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_filters = 'Filterklassen überwachen' +lucistatistics_collectdnetlink_filters_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectdnetwork = 'Network Plugin Konfiguration' +lucistatistics_collectdnetwork_desc = 'Das Network-Plugin ermöglicht die netzwerkgestützte Kommunikation zwischen verschiedenen Collectd-Instanzen. Collectd kann gleichzeitig im Server- und Client-Modus betrieben werden. Im Client-Modus werden lokal gesammelte Daten an einen Collectd-Server übermittelt, im Server-Modus empfängt die lokale Instanz Daten von anderen Installationen.' +lucistatistics_collectdnetwork_enable = 'Plugin aktivieren' +lucistatistics_collectdnetworklisten = 'Listen-Schnittstelle' +lucistatistics_collectdnetworklisten_desc = 'Diese Sektion legt fest auf welchen Schnittstellen Collectd auf eingehende Verbindungen wartet.' +lucistatistics_collectdnetworklisten_host = 'Listen-Host' +lucistatistics_collectdnetworklisten_host_desc = 'Host-, IP- oder IPv6-Adresse' +lucistatistics_collectdnetworklisten_port = 'Listen-Port' +lucistatistics_collectdnetworklisten_port_desc = '0 - 65535' +lucistatistics_collectdnetworkserver = 'Server-Schnittstellen' +lucistatistics_collectdnetworkserver_desc = 'Diese Sektion legt fest zu welchen Collectd-Servern die lokal gesammelten Daten gesendet werden.' +lucistatistics_collectdnetworkserver_host = 'Server-Host' +lucistatistics_collectdnetworkserver_host_desc = 'Host-, IP- oder IPv6-Adresse' +lucistatistics_collectdnetworkserver_port = 'Server-Port' +lucistatistics_collectdnetworkserver_port_desc = '0 - 65535' +lucistatistics_collectdnetwork_timetolive = 'TTL für Netzwerkpakete' +lucistatistics_collectdnetwork_timetolive_desc = '0 - 255' +lucistatistics_collectdnetwork_forward = 'Weiterleitung zwischen Listen- und Server-Adressen' +lucistatistics_collectdnetwork_cacheflush = 'Cache-Leerungsintervall' +lucistatistics_collectdnetwork_cacheflush_desc = 'Sekunden' +lucistatistics_collectdping = 'Ping Plugin Konfiguration' +lucistatistics_collectdping_desc = 'Das Ping-Plugin sendet ICMP-Echo-Requests an ausgewählte Hosts und misst die Antwortzeiten für jede Adresse.' +lucistatistics_collectdping_enable = 'Plugin aktivieren' +lucistatistics_collectdping_hosts = 'Hosts überwachen' +lucistatistics_collectdping_hosts_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdping_ttl = 'TTL für Ping Pakete' +lucistatistics_collectdping_ttl_desc = '0 - 255' +lucistatistics_collectdProzesse = 'Prozesse Plugin Konfiguration' +lucistatistics_collectdProzesse_desc = 'Das Prozess-Plugin sammelt Informationen wie CPU-Zeit, Speicherzugriffsfehler und Speicherverbrauch ausgewählter Prozesse.' +lucistatistics_collectdProzesse_enable = 'Plugin aktivieren' +lucistatistics_collectdProzesse_processes = 'Prozesse überwachen' +lucistatistics_collectdProzesse_processes_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdrrdtool = 'RRDTool Plugin Konfiguration' +lucistatistics_collectdrrdtool_desc = 'Das RRDTool-Plugin speichert die gesammelten Daten in sogenannten RRD-Datenbanken, der Grundlage für die Diagramm-Bilder.

Warnung: Falsche Werte resultieren in einem sehr hohen Speicherverbrauch im temporären Verzeichnis. Das kann das Gerät unbrauchbar machen, da Systemspeicher für den regulären Betrieb fehlt!' +lucistatistics_collectdrrdtool_enable = 'Plugin aktivieren' +lucistatistics_collectdrrdtool_datadir = 'Speicherverzeichnis' +lucistatistics_collectdrrdtool_stepsize = 'RRD Schrittintervall' +lucistatistics_collectdrrdtool_stepsize_desc = 'Sekunden' +lucistatistics_collectdrrdtool_heartbeat = 'RRD Heartbeatintervall' +lucistatistics_collectdrrdtool_heartbeat_desc = 'Sekunden' +lucistatistics_collectdrrdtool_rrasingle = 'Nur 'average' RRAs erzeugen' +lucistatistics_collectdrrdtool_rrasingle_desc = 'reduziert die RRD Größe' +lucistatistics_collectdrrdtool_rratimespans = 'gespeicherte Zeitspannen' +lucistatistics_collectdrrdtool_rratimespans_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdrrdtool_rrarows = 'Spalten pro RRA' +lucistatistics_collectdrrdtool_xff = 'RRD XFiles Faktor' +lucistatistics_collectdrrdtool_cachetimeout = 'Zwischenspeicherzeit für gesammelte Daten' +lucistatistics_collectdrrdtool_cachetimeout_desc = 'Sekunden' +lucistatistics_collectdrrdtool_cacheflush = 'Leerungsintervall für Zwischenspeicher' +lucistatistics_collectdrrdtool_cacheflush_desc = 'Sekunden' +lucistatistics_collectdtcpconns = 'TCPConns Plugin Konfiguration' +lucistatistics_collectdtcpconns_desc = 'Das TCPConns-Plugin sammelt Informationen über offene TCP-Verbindungen auf ausgewählten Ports.' +lucistatistics_collectdtcpconns_enable = 'Plugin aktivieren' +lucistatistics_collectdtcpconns_listeningports = 'Alle durch lokale Dienste genutzten Ports überwachen' +lucistatistics_collectdtcpconns_localports = 'lokale Ports überwachen' +lucistatistics_collectdtcpconns_localports_desc = '0 - 65535; mehrere mit Leerzeichen trennen' +lucistatistics_collectdtcpconns_remoteports = 'entfernte Ports überwachen' +lucistatistics_collectdtcpconns_remoteports_desc = '0 - 65535; mehrere mit Leerzeichen trennen' +lucistatistics_collectdunixsock = 'Unixsock Plugin Konfiguration' +lucistatistics_collectdunixsock_desc = 'Das Unixsock-Plugin erstellt einen Unix-Socket über welchen gesammelte Werte aus der laufenden Collectd-Instanz ausgelesen werden können.' +lucistatistics_collectdunixsock_enable = 'Plugin aktivieren' +lucistatistics_collectdunixsock_socketfile = 'Dateipfad des Unix-Sockets' +lucistatistics_collectdunixsock_socketgroup = 'Gruppenbesitzer festlegen' +lucistatistics_collectdunixsock_socketgroup_desc = 'Gruppenname' +lucistatistics_collectdunixsock_socketperms = 'Dateiberechtigungen des Unix-Sockets' +lucistatistics_collectdunixsock_socketperms_desc = 'oktal' +lucistatistics_collectdwireless = 'Wireless Plugin Konfiguration' +lucistatistics_collectdwireless_desc = 'Das Wireless-Plugin sammelt Statistiken über die drahtlose Signalstärke, den Störpegel und die Signalqualität.' +lucistatistics_collectdwireless_enable = 'Plugin aktivieren' diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.xml b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.xml new file mode 100644 index 0000000..060bbc8 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.de.xml @@ -0,0 +1,259 @@ + + + + +Statistiken +Das Statistik-Paket basiert auf Collectd und nutzt RRD Tool um die gesammelten Daten in Diagramme zu rendern. +Systemplugins +Netzwerkplugins +Ausgabeplugins +Zeitspanne zeigen » +Diagramme + +Collectd +Prozessor +Ping +Firewall +Netlink +Prozesse +Drahtlos +TCP-Verbindungen +Schnittstellen +Plattenspeicher +Interrupts +Plattenauslastung +Exec +RRDTool +Netzwerk +CSV Ausgabe +Systemlast +DNS +Email +UnixSock + +Statistiken + +Collectd Einstellungen +Collectd ist ein schlankes Dienstprogramm zum Sammeln von Systemdaten aus verschiedenen Quellen mittels diverser Plugins. Auf dieser Seite können generelle Einstellungen für den Collectd-Daemon vorgenommen werden. + +Hostname +Basisverzeichnis +Verzeichnis für Unterkonfigurationen +Verzeichnis für Collectd-Plugins +Pfad zu PID-Datei +Dataset-Definitionen +Daten-Sammelintervall +Sekunden +Anzahl paralleler Sammelprozesse +automatisch vollen Hostnamen herausfinden + +CPU Plugin Konfiguration +Das CPU-Plugin sammelt grundlegende Statistiken über die Prozessorauslastung. +Plugin aktivieren + +CSV Plugin Konfiguration +Das CSV-Plugin speichert die gesammelten Daten im CSV-Format, geeignet für die Weiterverarbeitung durch externe Programme. + +Plugin aktivieren +Speicherverzeichnis für die CSV-Dateien +Werte nicht absolut sondern als Raten speichern + +DF Plugin Konfiguration +Das DF-Plugin sammelt Statistiken über den Speicherverbrauch auf verschiedenen Geräten, Mount-Punkten oder Dateisystemtypen. +Plugin aktivieren +Geräte überwachen +mehrere mit Leerzeichen trennen +Mount-Punkte überwachen +mehrere mit Leerzeichen trennen +Datesystemtypen überwachen +mehrere mit Leerzeichen trennen +Alle außer Ausgewählte überwachen + +Disk Plugin Konfiguration +Das Disk-Plugin sammelt detaillierte Statistiken über die Auslastung auf ausgewählten Festplatten und Partitionen. +Plugin aktivieren +Geräte und Partitionen überwachen +mehrere mit Leerzeichen trennen +Alle außer Ausgewählte überwachen + +DNS Plugin Konfiguration +Das DNS-Plugin sammelt detaillierte Statistiken über DNS-bezogenen Verkehr auf ausgewählten Schnittstellen. +Plugin aktivieren +Schnittstellen überwachen +mehrere mit Leerzeichen trennen +Quelladressen ignorieren +mehrere mit Leerzeichen trennen + +E-Mail Plugin Konfiguration +Das E-Mail Plugin erstellt einen Unix-Socket welcher benutzt werden kann um E-Mail-Statistiken an den laufenden Collectd-Daemon zu übermitteln. Dieses Plugin ist primär für die Verwendung zusammen mit Mail::SpamAssasin::Plugin::Collectd gedacht, kann aber auch anderweitig verwendet werden. + +Plugin aktivieren +Dateipfad des Unix-Sockets +Gruppenbesitzer festlegen +Gruppenname +Dateiberechtigungen des Unix-Sockets +oktal +Maximale Anzahl erlaubter Verbindungen + +Exec Plugin Konfiguration +Das Exec-Plugin startet externe Kommandos um Werte einzulesen oder um Benachrichtigungen auszulösen falls bestimmte Grenzwerte erreicht werden. + +Plugin aktivieren +Kommando zum Werte einlesen hinzufügen +Hier können externe Kommandos definiert werden, welche durch Collectd gestartet werden um Statistik-Werte einzulesen. Die Werte werden dabei vom STDOUT des aufgerufenen Programmes gelesen. + +Kommandozeile +Als Benutzer ausführen +Als Gruppe ausführen +Benachrichtigungskommando hinzufügen +Hier können externe Kommandos definiert werden, welche durch Collectd gestartet werden sobald konfigurierte Grenzwerte erreicht werden. Die Werte welche die Benachrichtigung ausgelöst haben werden dabei an den STDIN des aufgerufenen Programmes übergeben. + +Kommandozeile +Als Benutzer ausführen +Als Gruppe ausführen + +Interface Plugin Konfiguration +Das Interface-Plugin sammelt allgemeine Verkehrsstatistiken auf ausgewählten Schnittstellen. +Plugin aktivieren +Schnittstellen überwachen +Strg gedrückt halten um mehrere Schnittstellen zu wählen +Alle außer Ausgewählte überwachen + +Iptables Plugin Konfiguration +Das Iptables-Plugin überwacht ausgewählte Firewall-Regeln und sammelt Werte über die Anzahl der verarbeiteten Pakete und Bytes. + +Plugin aktivieren + +Auswahlregel hinzufügen +Hier werden die Kriterien festgelegt nach welchen die zu überwachenden Firewall-Regeln ausgewählt werden. + +Name der Regel +max. 16 Buchstaben +Tabelle +Kette (Chain) +Aktion (Target) +Netzwerkprotokoll +Quell-IP-Bereich +CIDR-Notation +Ziel-IP-Bereich +CIDR-Notation +eingehende Schnittstelle +z.B. br-lan +ausgehende Schnittstelle +z.B. br-ff +Optionen +z.B. reject-with tcp-reset + +IRQ Plugin Konfiguration +Das IRQ-Plugin überwacht die Anzahl der Aufrufe pro Sekunde für jeden ausgewählten Interrupt. Wird kein Interrupt ausgewählt überwacht das Plugin alle im System vorhandenen Interrupts. + +Plugin aktivieren +Interrups überwachen +mehrere mit Leerzeichen trennen +Alle außer Ausgewählte überwachen + +Load Plugin Konfiguration +Das Load-Plugin sammelt Informationen über die allgemeine Systemlast. + +Plugin aktivieren + +Netlink Plugin Konfiguration +Das Netlink-Plugin sammelt erweiterte QoS-Informationen wie QDisc-, Class- und Filter-Statistiken auf ausgewählten Schnittstellen. + +Plugin aktivieren +Schnittstellen einfach überwachen +Strg gedrückt halten um mehrere zu wählen +Schnittstellen detailliert überwachen +Strg gedrückt halten um mehrere zu wählen +Queue Discipline überwachen +Strg gedrückt halten um mehrere zu wählen +Shapingklassen überwachen +Strg gedrückt halten um mehrere zu wählen +Filterklassen überwachen +Strg gedrückt halten um mehrere zu wählen +Alle außer Ausgewählte überwachen + +Network Plugin Konfiguration +Das Network-Plugin ermöglicht die netzwerkgestützte Kommunikation zwischen verschiedenen Collectd-Instanzen. Collectd kann gleichzeitig im Server- und Client-Modus betrieben werden. Im Client-Modus werden lokal gesammelte Daten an einen Collectd-Server übermittelt, im Server-Modus empfängt die lokale Instanz Daten von anderen Installationen. + +Plugin aktivieren +Listen-Schnittstelle +Diese Sektion legt fest auf welchen Schnittstellen Collectd auf eingehende Verbindungen wartet. +Listen-Host +Host-, IP- oder IPv6-Adresse +Listen-Port +0 - 65535 +Server-Schnittstellen +Diese Sektion legt fest zu welchen Collectd-Servern die lokal gesammelten Daten gesendet werden. +Server-Host +Host-, IP- oder IPv6-Adresse +Server-Port +0 - 65535 +TTL für Netzwerkpakete +0 - 255 +Weiterleitung zwischen Listen- und Server-Adressen +Cache-Leerungsintervall +Sekunden + +Ping Plugin Konfiguration +Das Ping-Plugin sendet ICMP-Echo-Requests an ausgewählte Hosts und misst die Antwortzeiten für jede Adresse. + +Plugin aktivieren +Hosts überwachen +mehrere mit Leerzeichen trennen +TTL für Ping Pakete +0 - 255 + +Prozesse Plugin Konfiguration +Das Prozess-Plugin sammelt Informationen wie CPU-Zeit, Speicherzugriffsfehler und Speicherverbrauch ausgewählter Prozesse. + +Plugin aktivieren +Prozesse überwachen +mehrere mit Leerzeichen trennen + +RRDTool Plugin Konfiguration +Das RRDTool-Plugin speichert die gesammelten Daten in sogenannten RRD-Datenbanken, der Grundlage für die Diagramm-Bilder.

Warnung: Falsche Werte resultieren in einem sehr hohen Speicherverbrauch im temporären Verzeichnis. Das kann das Gerät unbrauchbar machen, da Systemspeicher für den regulären Betrieb fehlt!
+ +Plugin aktivieren +Speicherverzeichnis +RRD Schrittintervall +Sekunden +RRD Heartbeatintervall +Sekunden +Nur 'average' RRAs erzeugen +reduziert die RRD Größe +gespeicherte Zeitspannen +mehrere mit Leerzeichen trennen +Spalten pro RRA +RRD XFiles Faktor +Zwischenspeicherzeit für gesammelte Daten +Sekunden +Leerungsintervall für Zwischenspeicher +Sekunden + +TCPConns Plugin Konfiguration +Das TCPConns-Plugin sammelt Informationen über offene TCP-Verbindungen auf ausgewählten Ports. + +Plugin aktivieren +Alle durch lokale Dienste genutzten Ports überwachen +lokale Ports überwachen +0 - 65535; mehrere mit Leerzeichen trennen +entfernte Ports überwachen +0 - 65535; mehrere mit Leerzeichen trennen + +Unixsock Plugin Konfiguration +Das Unixsock-Plugin erstellt einen Unix-Socket über welchen gesammelte Werte aus der laufenden Collectd-Instanz ausgelesen werden können. + +Plugin aktivieren +Dateipfad des Unix-Sockets +Gruppenbesitzer festlegen +Gruppenname +Dateiberechtigungen des Unix-Sockets +oktal + +Wireless Plugin Konfiguration +Das Wireless-Plugin sammelt Statistiken über die drahtlose Signalstärke, den Störpegel und die Signalqualität. + +Plugin aktivieren + +
diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.lua new file mode 100644 index 0000000..c12b420 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.lua @@ -0,0 +1,212 @@ +stat_statistics = 'Statistics' +stat_desc = 'The statistics package is based on Collectd and uses RRD Tool to render diagram images from collected data.' +stat_systemplugins = 'System plugins' +stat_networkplugins = 'Network plugins' +stat_outputplugins = 'Output plugins' +stat_showtimespan = 'Display timespan »' +stat_graphs = 'Graphs' +stat_collectd = 'Collectd' +stat_cpu = 'Processor' +stat_ping = 'Ping' +stat_iptables = 'Firewall' +stat_netlink = 'Netlink' +stat_processes = 'Processes' +stat_wireless = 'Wireless' +stat_tcpconns = 'TCP Connections' +stat_interface = 'Interfaces' +stat_df = 'Disk Space Usage' +stat_irq = 'Interrupts' +stat_disk = 'Disk Usage' +stat_exec = 'Exec' +stat_rrdtool = 'RRDTool' +stat_network = 'Network' +stat_csv = 'CSV Output' +stat_load = 'System Load' +stat_dns = 'DNS' +stat_email = 'Email' +stat_unixsock = 'UnixSock' +lucistatistics = 'Statistics' +lucistatistics_collectd = 'Collectd Settings' +lucistatistics_collectd_desc = 'Collectd is a small daeomon for collecting data from various sources through different plugins. On this page you can change general settings for the collectd daemon.' +lucistatistics_collectd_hostname = 'Hostname' +lucistatistics_collectd_basedir = 'Base Directory' +lucistatistics_collectd_include = 'Directory for sub-configurations' +lucistatistics_collectd_plugindir = 'Directory for collectd plugins' +lucistatistics_collectd_pidfile = 'Used PID file' +lucistatistics_collectd_typesdb = 'Datasets definition file' +lucistatistics_collectd_interval = 'Data collection interval' +lucistatistics_collectd_interval_desc = 'Seconds' +lucistatistics_collectd_readthreads = 'Number of threads for data collection' +lucistatistics_collectd_fqdnlookup = 'Try to lookup fully qualified hostname' +lucistatistics_collectdcpu = 'CPU Plugin Configuration' +lucistatistics_collectdcpu_desc = 'The cpu plugin collects basic statistics about the processor usage.' +lucistatistics_collectdcpu_enable = 'Enable this plugin' +lucistatistics_collectdcsv = 'CSV Plugin Configuration' +lucistatistics_collectdcsv_desc = 'The csv plugin stores collected data in csv file format for further processing by external programs.' +lucistatistics_collectdcsv_enable = 'Enable this plugin' +lucistatistics_collectdcsv_datadir = 'Storage directory for the csv files' +lucistatistics_collectdcsv_storerates = 'Store data values as rates instead of absolute values' +lucistatistics_collectddf = 'DF Plugin Configuration' +lucistatistics_collectddf_desc = 'The df plugin collects statistics about the disk space usage on different devices, mount points or filesystem types.' +lucistatistics_collectddf_enable = 'Enable this plugin' +lucistatistics_collectddf_devices = 'Monitor devices' +lucistatistics_collectddf_devices_desc = 'multiple separated by space' +lucistatistics_collectddf_mountpoints = 'Monitor mount points' +lucistatistics_collectddf_mountpoints_desc = 'multiple separated by space' +lucistatistics_collectddf_fstypes = 'Monitor filesystem types' +lucistatistics_collectddf_fstypes_desc = 'multiple separated by space' +lucistatistics_collectddf_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectddisk = 'Disk Plugin Configuration' +lucistatistics_collectddisk_desc = 'The disk plugin collects detailled usage statistics for selected partitions or whole disks.' +lucistatistics_collectddisk_enable = 'Enable this plugin' +lucistatistics_collectddisk_disks = 'Monitor disks and partitions' +lucistatistics_collectddisk_disks_desc = 'multiple separated by space' +lucistatistics_collectddisk_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectddns = 'DNS Plugin Configuration' +lucistatistics_collectddns_desc = 'The dns plugin collects detailled statistics about dns related traffic on selected interfaces.' +lucistatistics_collectddns_enable = 'Enable this plugin' +lucistatistics_collectddns_interfaces = 'Monitor interfaces' +lucistatistics_collectddns_interfaces_desc = 'multiple separated by space' +lucistatistics_collectddns_ignoresources = 'Ignore source addresses' +lucistatistics_collectddns_ignoresources_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdemail = 'E-Mail Plugin Configuration' +lucistatistics_collectdemail_desc = 'The email plugin creates a unix socket which can be used to transmit email-statistics to a running collectd daemon. This plugin is primarily intended to be used in conjunction with Mail::SpamAssasin::Plugin::Collectd but can be used in other ways as well.' +lucistatistics_collectdemail_enable = 'Enable this plugin' +lucistatistics_collectdemail_socketfile = 'Filepath of the unix socket' +lucistatistics_collectdemail_socketgroup = 'Group ownership of the unix socket' +lucistatistics_collectdemail_socketgroup_desc = 'group name' +lucistatistics_collectdemail_socketperms = 'File permissions of the unix socket' +lucistatistics_collectdemail_socketperms_desc = 'octal' +lucistatistics_collectdemail_maxconns = 'Maximum allowed connections' +lucistatistics_collectdexec = 'Exec Plugin Configuration' +lucistatistics_collectdexec_desc = 'The exec plugin starts external commands to read values from or to notify external processes when certain threshold values have been reached.' +lucistatistics_collectdexec_enable = 'Enable this plugin' +lucistatistics_collectdexecinput = 'Add command for reading values' +lucistatistics_collectdexecinput_desc = 'Here you can define external commands which will be started by collectd in order to read certain values. The values will be read from stdout.' +lucistatistics_collectdexecinput_cmdline = 'Commandline' +lucistatistics_collectdexecinput_cmduser = 'Run as user' +lucistatistics_collectdexecinput_cmdgroup = 'Run as group' +lucistatistics_collectdexecnotify = 'Add notification command' +lucistatistics_collectdexecnotify_desc = 'Here you can define external commands which will be started by collectd when certain threshold values have been reached. The values leading to invokation will be feeded to the the called programs stdin.' +lucistatistics_collectdexecnotify_cmdline = 'Commandline' +lucistatistics_collectdexecnotify_cmduser = 'Run as user' +lucistatistics_collectdexecnotify_cmdgroup = 'Run as group' +lucistatistics_collectdinterface = 'Interface Plugin Configuration' +lucistatistics_collectdinterface_desc = 'The interface plugin collects traffic statistics on selected interfaces.' +lucistatistics_collectdinterface_enable = 'Enable this plugin' +lucistatistics_collectdinterface_interfaces = 'Monitor interfaces' +lucistatistics_collectdinterface_interfaces_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdinterface_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectdiptables = 'Iptables Plugin Configuration' +lucistatistics_collectdiptables_desc = 'The iptables plugin will monitor selected firewall rules and collect informations about processed bytes and packets per rule.' +lucistatistics_collectdiptables_enable = 'Enable this plugin' +lucistatistics_collectdiptablesmatch = 'Add matching rule' +lucistatistics_collectdiptablesmatch_desc = 'Here you can define various criteria by which the monitored iptables rules are selected.' +lucistatistics_collectdiptablesmatch_name = 'Name of the rule' +lucistatistics_collectdiptablesmatch_name_desc = 'max. 16 chars' +lucistatistics_collectdiptablesmatch_table = 'Table' +lucistatistics_collectdiptablesmatch_chain = 'Chain' +lucistatistics_collectdiptablesmatch_target = 'Action (target)' +lucistatistics_collectdiptablesmatch_protocol = 'Network protocol' +lucistatistics_collectdiptablesmatch_source = 'Source ip range' +lucistatistics_collectdiptablesmatch_source_desc = 'CIDR notation' +lucistatistics_collectdiptablesmatch_destination = 'Destination ip range' +lucistatistics_collectdiptablesmatch_destination_desc = 'CIDR notation' +lucistatistics_collectdiptablesmatch_inputif = 'Incoming interface' +lucistatistics_collectdiptablesmatch_inputif_desc = 'e.g. br-lan' +lucistatistics_collectdiptablesmatch_outputif = 'Outgoing interface' +lucistatistics_collectdiptablesmatch_outputif_desc = 'e.g. br-ff' +lucistatistics_collectdiptablesmatch_options = 'Options' +lucistatistics_collectdiptablesmatch_options_desc = 'e.g. reject-with tcp-reset' +lucistatistics_collectdirq = 'IRQ Plugin Configuration' +lucistatistics_collectdirq_desc = 'The irq plugin will monitor the rate of issues per second for each selected interrupt. If no interrupt is selected then all interrupts are monitored.' +lucistatistics_collectdirq_enable = 'Enable this plugin' +lucistatistics_collectdirq_irqs = 'Monitor interrupts' +lucistatistics_collectdirq_irqs_desc = 'multiple separated by space' +lucistatistics_collectdirq_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectdload = 'Load Plugin Configuration' +lucistatistics_collectdload_desc = 'The load plugin collects statistics about the general system load.' +lucistatistics_collectdload_enable = 'Enable this plugin' +lucistatistics_collectdnetlink = 'Netlink Plugin Configuration' +lucistatistics_collectdnetlink_desc = 'The netlink plugin collects extended informations like qdisc-, class- and filter-statistics for selected interfaces.' +lucistatistics_collectdnetlink_enable = 'Enable this plugin' +lucistatistics_collectdnetlink_interfaces = 'Basic monitoring' +lucistatistics_collectdnetlink_interfaces_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_verboseinterfaces = 'Verbose monitoring' +lucistatistics_collectdnetlink_verboseinterfaces_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_qdiscs = 'Qdisc monitoring' +lucistatistics_collectdnetlink_qdiscs_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_classes = 'Shaping class monitoring' +lucistatistics_collectdnetlink_classes_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_filters = 'Filter class monitoring' +lucistatistics_collectdnetlink_filters_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectdnetwork = 'Network Plugin Configuration' +lucistatistics_collectdnetwork_desc = 'The network plugin provides network based communication between different collectd instances. Collectd can operate both in client and server mode. In client mode locally collected date is transferred to a collectd server instance, in server mode the local instance receives data from other hosts.' +lucistatistics_collectdnetwork_enable = 'Enable this plugin' +lucistatistics_collectdnetworklisten = 'Listener interfaces' +lucistatistics_collectdnetworklisten_desc = 'This section defines on which interfaces collectd will wait for incoming connections.' +lucistatistics_collectdnetworklisten_host = 'Listen host' +lucistatistics_collectdnetworklisten_host_desc = 'host-, ip- or ip6 address' +lucistatistics_collectdnetworklisten_port = 'Listen port' +lucistatistics_collectdnetworklisten_port_desc = '0 - 65535' +lucistatistics_collectdnetworkserver = 'server interfaces' +lucistatistics_collectdnetworkserver_desc = 'This section defines to which servers the locally collected data is sent to.' +lucistatistics_collectdnetworkserver_host = 'Server host' +lucistatistics_collectdnetworkserver_host_desc = 'host-, ip- or ip6 address' +lucistatistics_collectdnetworkserver_port = 'Server port' +lucistatistics_collectdnetworkserver_port_desc = '0 - 65535' +lucistatistics_collectdnetwork_timetolive = 'TTL for network packets' +lucistatistics_collectdnetwork_timetolive_desc = '0 - 255' +lucistatistics_collectdnetwork_forward = 'Forwarding between listen and server addresses' +lucistatistics_collectdnetwork_cacheflush = 'Cache flush interval' +lucistatistics_collectdnetwork_cacheflush_desc = 'seconds' +lucistatistics_collectdping = 'Ping Plugin Configuration' +lucistatistics_collectdping_desc = 'The ping plugin will send icmp echo replies to selected hosts and measure the roundtrip time for each host.' +lucistatistics_collectdping_enable = 'Enable this plugin' +lucistatistics_collectdping_hosts = 'Monitor hosts' +lucistatistics_collectdping_hosts_desc = 'multiple separated by space' +lucistatistics_collectdping_ttl = 'TTL for ping packets' +lucistatistics_collectdping_ttl_desc = '0 - 255' +lucistatistics_collectdprocesses = 'Processes Plugin Configuration' +lucistatistics_collectdprocesses_desc = 'The processes plugin collects informations like cpu time, page faults and memory usage of selected processes.' +lucistatistics_collectdprocesses_enable = 'Enable this plugin' +lucistatistics_collectdprocesses_processes = 'Monitor processes' +lucistatistics_collectdprocesses_processes_desc = 'multiple separated by space' +lucistatistics_collectdrrdtool = 'RRDTool Plugin Configuration' +lucistatistics_collectdrrdtool_desc = 'The rrdtool plugin stores the collected data in rrd database files, the foundation of the diagrams.

Warning: Setting the wrong values will result in a very high memory consumption in the temporary directory. This can render the device unusable!' +lucistatistics_collectdrrdtool_enable = 'Enable this plugin' +lucistatistics_collectdrrdtool_datadir = 'Storage directory' +lucistatistics_collectdrrdtool_stepsize = 'RRD step interval' +lucistatistics_collectdrrdtool_stepsize_desc = 'seconds' +lucistatistics_collectdrrdtool_heartbeat = 'RRD heart beat interval' +lucistatistics_collectdrrdtool_heartbeat_desc = 'seconds' +lucistatistics_collectdrrdtool_rrasingle = 'Only create average RRAs' +lucistatistics_collectdrrdtool_rrasingle_desc = 'reduces rrd size' +lucistatistics_collectdrrdtool_rratimespans = 'Stored timespans' +lucistatistics_collectdrrdtool_rratimespans_desc = 'seconds; multiple separated by space' +lucistatistics_collectdrrdtool_rrarows = 'Rows per RRA' +lucistatistics_collectdrrdtool_xff = 'RRD XFiles Factor' +lucistatistics_collectdrrdtool_cachetimeout = 'Cache collected data for' +lucistatistics_collectdrrdtool_cachetimeout_desc = 'seconds' +lucistatistics_collectdrrdtool_cacheflush = 'Flush cache after' +lucistatistics_collectdrrdtool_cacheflush_desc = 'seconds' +lucistatistics_collectdtcpconns = 'TCPConns Plugin Configuration' +lucistatistics_collectdtcpconns_desc = 'The tcpconns plugin collects informations about open tcp connections on selected ports.' +lucistatistics_collectdtcpconns_enable = 'Enable this plugin' +lucistatistics_collectdtcpconns_listeningports = 'Monitor all local listen ports' +lucistatistics_collectdtcpconns_localports = 'Monitor local ports' +lucistatistics_collectdtcpconns_localports_desc = '0 - 65535; multiple separated by space' +lucistatistics_collectdtcpconns_remoteports = 'Monitor remote ports' +lucistatistics_collectdtcpconns_remoteports_desc = '0 - 65535; multiple separated by space' +lucistatistics_collectdunixsock = 'Unixsock Plugin Configuration' +lucistatistics_collectdunixsock_desc = 'The unixsock plugin creates a unix socket which can be used to read collected data from a running collectd instance.' +lucistatistics_collectdunixsock_enable = 'Enable this plugin' +lucistatistics_collectdunixsock_socketfile = 'Filepath of the unix socket' +lucistatistics_collectdunixsock_socketgroup = 'Group ownership of the unix socket' +lucistatistics_collectdunixsock_socketgroup_desc = 'group name' +lucistatistics_collectdunixsock_socketperms = 'File permissions of the unix socket' +lucistatistics_collectdunixsock_socketperms_desc = 'octal' +lucistatistics_collectdwireless = 'Wireless Plugin Configuration' +lucistatistics_collectdwireless_desc = 'The wireless plugin collects statistics about wireless signal strength, noise and quality.' +lucistatistics_collectdwireless_enable = 'Enable this plugin' diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.xml b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.xml new file mode 100644 index 0000000..016e042 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.en.xml @@ -0,0 +1,258 @@ + + + + +Statistics +The statistics package is based on Collectd and uses RRD Tool to render diagram images from collected data. +System plugins +Network plugins +Output plugins +Display timespan » +Graphs + +Collectd +Processor +Ping +Firewall +Netlink +Processes +Wireless +TCP Connections +Interfaces +Disk Space Usage +Interrupts +Disk Usage +Exec +RRDTool +Network +CSV Output +System Load +DNS +Email +UnixSock + +Statistics + +Collectd Settings +Collectd is a small daeomon for collecting data from various sources through different plugins. On this page you can change general settings for the collectd daemon. + +Hostname +Base Directory +Directory for sub-configurations +Directory for collectd plugins +Used PID file +Datasets definition file +Data collection interval +Seconds +Number of threads for data collection +Try to lookup fully qualified hostname + +CPU Plugin Configuration +The cpu plugin collects basic statistics about the processor usage. +Enable this plugin + +CSV Plugin Configuration +The csv plugin stores collected data in csv file format for further processing by external programs. +Enable this plugin +Storage directory for the csv files +Store data values as rates instead of absolute values + +DF Plugin Configuration +The df plugin collects statistics about the disk space usage on different devices, mount points or filesystem types. +Enable this plugin +Monitor devices +multiple separated by space +Monitor mount points +multiple separated by space +Monitor filesystem types +multiple separated by space +Monitor all except selected ones + +Disk Plugin Configuration +The disk plugin collects detailled usage statistics for selected partitions or whole disks. +Enable this plugin +Monitor disks and partitions +multiple separated by space +Monitor all except selected ones + +DNS Plugin Configuration +The dns plugin collects detailled statistics about dns related traffic on selected interfaces. +Enable this plugin +Monitor interfaces +multiple separated by space +Ignore source addresses +hold Ctrl while clicking to select multiple interfaces + +E-Mail Plugin Configuration +The email plugin creates a unix socket which can be used to transmit email-statistics to a running collectd daemon. This plugin is primarily intended to be used in conjunction with Mail::SpamAssasin::Plugin::Collectd but can be used in other ways as well. + +Enable this plugin +Filepath of the unix socket +Group ownership of the unix socket +group name +File permissions of the unix socket +octal +Maximum allowed connections + +Exec Plugin Configuration +The exec plugin starts external commands to read values from or to notify external processes when certain threshold values have been reached. + +Enable this plugin +Add command for reading values +Here you can define external commands which will be started by collectd in order to read certain values. The values will be read from stdout. + +Commandline +Run as user +Run as group +Add notification command +Here you can define external commands which will be started by collectd when certain threshold values have been reached. The values leading to invokation will be feeded to the the called programs stdin. + +Commandline +Run as user +Run as group + +Interface Plugin Configuration +The interface plugin collects traffic statistics on selected interfaces. +Enable this plugin +Monitor interfaces +hold Ctrl while clicking to select multiple interfaces +Monitor all except selected ones + +Iptables Plugin Configuration +The iptables plugin will monitor selected firewall rules and collect informations about processed bytes and packets per rule. + +Enable this plugin + +Add matching rule +Here you can define various criteria by which the monitored iptables rules are selected. + +Name of the rule +max. 16 chars +Table +Chain +Action (target) +Network protocol +Source ip range +CIDR notation +Destination ip range +CIDR notation +Incoming interface +e.g. br-lan +Outgoing interface +e.g. br-ff +Options +e.g. reject-with tcp-reset + +IRQ Plugin Configuration +The irq plugin will monitor the rate of issues per second for each selected interrupt. If no interrupt is selected then all interrupts are monitored. + +Enable this plugin +Monitor interrupts +multiple separated by space +Monitor all except selected ones + +Load Plugin Configuration +The load plugin collects statistics about the general system load. + +Enable this plugin + +Netlink Plugin Configuration +The netlink plugin collects extended informations like qdisc-, class- and filter-statistics for selected interfaces. + +Enable this plugin +Basic monitoring +hold Ctrl while clicking to select multiple interfaces +Verbose monitoring +hold Ctrl while clicking to select multiple interfaces +Qdisc monitoring +hold Ctrl while clicking to select multiple interfaces +Shaping class monitoring +hold Ctrl while clicking to select multiple interfaces +Filter class monitoring +hold Ctrl while clicking to select multiple interfaces +Monitor all except selected ones + +Network Plugin Configuration +The network plugin provides network based communication between different collectd instances. Collectd can operate both in client and server mode. In client mode locally collected date is transferred to a collectd server instance, in server mode the local instance receives data from other hosts. + +Enable this plugin +Listener interfaces +This section defines on which interfaces collectd will wait for incoming connections. +Listen host +host-, ip- or ip6 address +Listen port +0 - 65535 +server interfaces +This section defines to which servers the locally collected data is sent to. +Server host +host-, ip- or ip6 address +Server port +0 - 65535 +TTL for network packets +0 - 255 +Forwarding between listen and server addresses +Cache flush interval +seconds + +Ping Plugin Configuration +The ping plugin will send icmp echo replies to selected hosts and measure the roundtrip time for each host. + +Enable this plugin +Monitor hosts +multiple separated by space +TTL for ping packets +0 - 255 + +Processes Plugin Configuration +The processes plugin collects informations like cpu time, page faults and memory usage of selected processes. + +Enable this plugin +Monitor processes +multiple separated by space + +RRDTool Plugin Configuration +The rrdtool plugin stores the collected data in rrd database files, the foundation of the diagrams.

Warning: Setting the wrong values will result in a very high memory consumption in the temporary directory. This can render the device unusable!
+ +Enable this plugin +Storage directory +RRD step interval +seconds +RRD heart beat interval +seconds +Only create average RRAs +reduces rrd size +Stored timespans +seconds; multiple separated by space +Rows per RRA +RRD XFiles Factor +Cache collected data for +seconds +Flush cache after +seconds + +TCPConns Plugin Configuration +The tcpconns plugin collects informations about open tcp connections on selected ports. + +Enable this plugin +Monitor all local listen ports +Monitor local ports +0 - 65535; multiple separated by space +Monitor remote ports +0 - 65535; multiple separated by space + +Unixsock Plugin Configuration +The unixsock plugin creates a unix socket which can be used to read collected data from a running collectd instance. + +Enable this plugin +Filepath of the unix socket +Group ownership of the unix socket +group name +File permissions of the unix socket +octal + +Wireless Plugin Configuration +The wireless plugin collects statistics about wireless signal strength, noise and quality. + +Enable this plugin + +
diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.lua new file mode 100644 index 0000000..e2b5cac --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.lua @@ -0,0 +1,212 @@ +stat_statistics = 'Estatísticas' +stat_desc = 'As estatísticas são baseadas no Collectd e é utilizado o RRD Tool para renderização das imagens à partir dos dados coletados.' +stat_systemplugins = 'Plugis de Sistema' +stat_networkplugins = 'Plugins de rede' +stat_outputplugins = 'Plugins de saída' +stat_showtimespan = 'Mostrar intervalo »' +stat_graphs = 'Gráficos' +stat_collectd = 'Collectd' +stat_cpu = 'Processador' +stat_ping = 'Ping' +stat_iptables = 'Firewall' +stat_netlink = 'Netlink' +stat_processes = 'Processos' +stat_wireless = 'Wireless' +stat_tcpconns = 'Conexões TCP' +stat_interface = 'Interfaces' +stat_df = 'Utilização de espaço em disco' +stat_irq = 'Interrupções' +stat_disk = 'Utilização do Disco' +stat_exec = 'Exec' +stat_rrdtool = 'RRDTool' +stat_network = 'Rede' +stat_csv = 'Formato CSV' +stat_load = 'Carga do Sistema' +stat_dns = 'DNS' +stat_email = 'Email' +stat_unixsock = 'UnixSock' +lucistatistics = 'Estatísticas' +lucistatistics_collectd = 'Configurações do Collectd' +lucistatistics_collectd_desc = 'Collectd é um pequeno daemon que coleta dados de várias fontes através de diferentes plugins. Nesta página você pode alterar as configurações gerais do daemon collectd.' +lucistatistics_collectd_hostname = 'Hostname' +lucistatistics_collectd_basedir = 'Diretório Base' +lucistatistics_collectd_include = 'Diretório para sub-configurações' +lucistatistics_collectd_plugindir = 'Diretório para os plugins do collectd' +lucistatistics_collectd_pidfile = 'Arquivo PID usado' +lucistatistics_collectd_typesdb = 'Arquivo com a definição de dados' +lucistatistics_collectd_interval = 'Intervalo da coleta de dados' +lucistatistics_collectd_interval_desc = 'Segundos' +lucistatistics_collectd_readthreads = 'Número de threads para o coletor de dados' +lucistatistics_collectd_fqdnlookup = 'Tentar encontrar o nome do host completo (FQDN)' +lucistatistics_collectdcpu = 'Configuração do plugin CPU' +lucistatistics_collectdcpu_desc = 'O plugin cpu coleta as estatísticas básicas sobre o uso do processador.' +lucistatistics_collectdcpu_enable = 'Habilitar este plugin' +lucistatistics_collectdcsv = 'Configuração do plugin CSV' +lucistatistics_collectdcsv_desc = 'O plugin csv armazena os dados coletados em um arquivo no formato csv para um futuro processamento por outros programas.' +lucistatistics_collectdcsv_enable = 'Habilitar este plugin' +lucistatistics_collectdcsv_datadir = 'Diretório para armazenamento dos arquivos csv' +lucistatistics_collectdcsv_storerates = 'Armazenar os valores dos dados como taxas em vez de valores absolutos' +lucistatistics_collectddf = 'Configuração do plugin DF' +lucistatistics_collectddf_desc = 'O plugin df coleta estatísticas sobre a utilização de espaço em disco em diferentes dispositivos, pontos de montagem ou tipos de sistemas de arquivos.' +lucistatistics_collectddf_enable = 'Habilitar este plugin' +lucistatistics_collectddf_devices = 'Monitorar dispositivos' +lucistatistics_collectddf_devices_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddf_mountpoints = 'Monitorar pontos de montagem' +lucistatistics_collectddf_mountpoints_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddf_fstypes = 'Monitorar tipos de sistemas de arquivos' +lucistatistics_collectddf_fstypes_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddf_ignoreselected = 'Monitorar tudo exceto os selecionados' +lucistatistics_collectddisk = 'Configuração do plugin Disco' +lucistatistics_collectddisk_desc = 'O plugin disco coleta estatísticas de uso detalhadas das partições selecionadas ou discos inteiros.' +lucistatistics_collectddisk_enable = 'Habilitar este plugin' +lucistatistics_collectddisk_disks = 'Monitoras discos e partições' +lucistatistics_collectddisk_disks_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddisk_ignoreselected = 'Monitorar tudo exceto os selecionados' +lucistatistics_collectddns = 'Configuração do plugin DNS' +lucistatistics_collectddns_desc = 'O plugin dns coleta estatísticas detalhadas sobre o tráfego do dns nas interfaces selecionadas.' +lucistatistics_collectddns_enable = 'Habilitar este plugin' +lucistatistics_collectddns_interfaces = 'Monitorar interfaces' +lucistatistics_collectddns_interfaces_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddns_ignoresources = 'Ignorar endereços de origem' +lucistatistics_collectddns_ignoresources_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdemail = 'Configuração do plugin E-Mail' +lucistatistics_collectdemail_desc = 'O plugin de email cria um socket unix que pode ser usado para transmitir estatísticas de email o daemon collectd. Este plugin é essencialmente destinado a ser utilizado em conjunto com o plugin Mail::SpamAssasin::Plugin::Collectd mas pode ser utilizado de outras maneiras também.' +lucistatistics_collectdemail_enable = 'Habilitar este plugin' +lucistatistics_collectdemail_socketfile = 'Caminho do arquivo do socket unix' +lucistatistics_collectdemail_socketgroup = 'Grupo dono do socket unix' +lucistatistics_collectdemail_socketgroup_desc = 'nome do grupo' +lucistatistics_collectdemail_socketperms = 'Permissões de arquivo do socket unix' +lucistatistics_collectdemail_socketperms_desc = 'octal' +lucistatistics_collectdemail_maxconns = 'Máximo de conexões permitidas' +lucistatistics_collectdexec = 'Configuração do plugin Exec' +lucistatistics_collectdexec_desc = 'O plugin exec inicia comandos externos para leitura de valores ou notificar processos externos quando um determinado valor limite for atingido.' +lucistatistics_collectdexec_enable = 'Habilitar este plugin' +lucistatistics_collectdexecinput = 'Adicionar comando para leitura de valores' +lucistatistics_collectdexecinput_desc = 'Aqui você pode definir comandos externos que serão iniciados pelo collectd a fim de ler determinados valores. Os valores serão lidos a partir do stdout.' +lucistatistics_collectdexecinput_cmdline = 'Linha de comando' +lucistatistics_collectdexecinput_cmduser = 'Executar como usuário' +lucistatistics_collectdexecinput_cmdgroup = 'Executar como grupo' +lucistatistics_collectdexecnotify = 'Adicionar o comando de notificação' +lucistatistics_collectdexecnotify_desc = 'Aqui você pode definir os comandos externos que serão iniciados pelo collectd quando determinados valores limite forem atingidos. Os valores passados ao comando serão enviados para o stdin.' +lucistatistics_collectdexecnotify_cmdline = 'Linha de comando' +lucistatistics_collectdexecnotify_cmduser = 'Executar como usuário' +lucistatistics_collectdexecnotify_cmdgroup = 'Executar como grupo' +lucistatistics_collectdinterface = 'Configuração do plugin Interface' +lucistatistics_collectdinterface_desc = 'O plugin interface plugin coleta estatísticas sobre o tráfego das interfaces selecionadas.' +lucistatistics_collectdinterface_enable = 'Habilitar este plugin' +lucistatistics_collectdinterface_interfaces = 'Monitorar interfaces' +lucistatistics_collectdinterface_interfaces_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdinterface_ignoreselected = 'Monitorar todas exceto as selecionadas' +lucistatistics_collectdiptables = 'Configuração do plugin Iptables' +lucistatistics_collectdiptables_desc = 'O plugin iptables irá monitorar as regras de firewall selecionadas e coletar informações sobre pacotes e bytes processados pela regra.' +lucistatistics_collectdiptables_enable = 'Habilitar este plugin' +lucistatistics_collectdiptablesmatch = 'Adicionar regra' +lucistatistics_collectdiptablesmatch_desc = 'Aqui você pode definir diversos critérios para as regras iptables selecionadas serem monitoradas.' +lucistatistics_collectdiptablesmatch_name = 'Nome da regra' +lucistatistics_collectdiptablesmatch_name_desc = 'max. 16 caract.' +lucistatistics_collectdiptablesmatch_table = 'Tabela' +lucistatistics_collectdiptablesmatch_chain = 'Cadeia' +lucistatistics_collectdiptablesmatch_target = 'Ação (destino)' +lucistatistics_collectdiptablesmatch_protocol = 'Protocolo de rede' +lucistatistics_collectdiptablesmatch_source = 'IP de origem' +lucistatistics_collectdiptablesmatch_source_desc = 'Notação CIDR' +lucistatistics_collectdiptablesmatch_destination = 'IP de destino' +lucistatistics_collectdiptablesmatch_destination_desc = 'Notação CIDR' +lucistatistics_collectdiptablesmatch_inputif = 'Interface de entrada' +lucistatistics_collectdiptablesmatch_inputif_desc = 'ex. br-lan' +lucistatistics_collectdiptablesmatch_outputif = 'Interface de saída' +lucistatistics_collectdiptablesmatch_outputif_desc = 'ex. br-ff' +lucistatistics_collectdiptablesmatch_options = 'Opções' +lucistatistics_collectdiptablesmatch_options_desc = 'ex. rejeitar-com tcp-reset' +lucistatistics_collectdirq = 'Configuração do plugin IRQ' +lucistatistics_collectdirq_desc = 'O plugin irq irá monitorar a taxa de erros por segundo de cada interrupção selecionada. Se nenhuma interrupção for selecionada então todas as interrupções serão monitoradas.' +lucistatistics_collectdirq_enable = 'Habilitar este plugin' +lucistatistics_collectdirq_irqs = 'Monitorar interrupções' +lucistatistics_collectdirq_irqs_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectdirq_ignoreselected = 'Monitorar todas exceto as selecionadas' +lucistatistics_collectdload = 'Configuração do plugin carga' +lucistatistics_collectdload_desc = 'O plugin carga coleta estatísticas gerais sobre a carga do sistema.' +lucistatistics_collectdload_enable = 'Habilitar este plugin' +lucistatistics_collectdnetlink = 'Configuração do plugin Netlink' +lucistatistics_collectdnetlink_desc = 'O plugin Netlink coleta informações detalhadas como qdisc-, classe- e filtro de estatísticas das interfaces selecionadas.' +lucistatistics_collectdnetlink_enable = 'Habilitar este plugin' +lucistatistics_collectdnetlink_interfaces = 'Monitoramento básico' +lucistatistics_collectdnetlink_interfaces_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_verboseinterfaces = 'Monitoramento no modo verbose' +lucistatistics_collectdnetlink_verboseinterfaces_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_qdiscs = 'Monitoramento do Qdisc' +lucistatistics_collectdnetlink_qdiscs_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_classes = 'Monitoramento das Classes de Shaping' +lucistatistics_collectdnetlink_classes_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_filters = 'Monitoramento das Classes de Filtros' +lucistatistics_collectdnetlink_filters_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_ignoreselected = 'Monitorar todas exceto as selecionadas' +lucistatistics_collectdnetwork = 'Configuração do plugin Rede' +lucistatistics_collectdnetwork_desc = 'O plugin rede fornece informações de rede baseadas na comunicação entre as diferentes instâncias do collectd. O Collectd pode operar tanto no modo cliente quanto no modo servidor. No modo cliente os dados coletados localmente são transferidos para um servidor collectd, no modo de servidor a instância local recebe dados de outros hosts.' +lucistatistics_collectdnetwork_enable = 'Habilitar este plugin' +lucistatistics_collectdnetworklisten = 'Escutar na(s) interface(s)' +lucistatistics_collectdnetworklisten_desc = 'Esta seção define em quais interfaces o collectd irá aguardar para receber conexões.' +lucistatistics_collectdnetworklisten_host = 'Endereço de escuta do Host' +lucistatistics_collectdnetworklisten_host_desc = 'hostname, ip ou ip6' +lucistatistics_collectdnetworklisten_port = 'Porta de escuta' +lucistatistics_collectdnetworklisten_port_desc = '0 - 65535' +lucistatistics_collectdnetworkserver = 'Interfaces do servidor' +lucistatistics_collectdnetworkserver_desc = 'Esta seção define para qual servidor os dados coletados localmente serão enviados.' +lucistatistics_collectdnetworkserver_host = 'IP/Hostname do servidor' +lucistatistics_collectdnetworkserver_host_desc = 'hostname, ip ou ip6' +lucistatistics_collectdnetworkserver_port = 'Porta do servidor' +lucistatistics_collectdnetworkserver_port_desc = '0 - 65535' +lucistatistics_collectdnetwork_timetolive = 'TTL para os pacotes de rede' +lucistatistics_collectdnetwork_timetolive_desc = '0 - 255' +lucistatistics_collectdnetwork_forward = 'Transmissão entre o endereço de escuta e dos servidores' +lucistatistics_collectdnetwork_cacheflush = 'Intervalo de limpeza do cache' +lucistatistics_collectdnetwork_cacheflush_desc = 'segundos' +lucistatistics_collectdping = 'Configuração do plugin Ping' +lucistatistics_collectdping_desc = 'O plugin ping irá enviar pacotes ICMP to tipo echo aos hosts selecionados e medir o tempo de resposta para cada host.' +lucistatistics_collectdping_enable = 'Habilitar este plugin' +lucistatistics_collectdping_hosts = 'Monitorar os hosts' +lucistatistics_collectdping_hosts_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectdping_ttl = 'TTL para os pacotes do ping' +lucistatistics_collectdping_ttl_desc = '0 - 255' +lucistatistics_collectdprocesses = 'Configuração do plugin Processos' +lucistatistics_collectdprocesses_desc = 'O plugin processo coleta informações como o tempo da cpu, página falhas e uso de memória dos processos selecionados.' +lucistatistics_collectdprocesses_enable = 'Habilitar este plugin' +lucistatistics_collectdprocesses_processes = 'Monitorar processos' +lucistatistics_collectdprocesses_processes_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectdrrdtool = 'Configuração do plugin RRDTool' +lucistatistics_collectdrrdtool_desc = 'O plugin rrdtool armazena os dados coletados no arquivo de banco de dados rrd.

Aviso: A má configuração desses valores, resultará em um valor muito elevado no consumo de memória no diretório temporário. Isso pode tornar o equipamento inutilizável!' +lucistatistics_collectdrrdtool_enable = 'Habilitar este plugin' +lucistatistics_collectdrrdtool_datadir = 'Diretório de armazenamento' +lucistatistics_collectdrrdtool_stepsize = 'Intervalo de atualização' +lucistatistics_collectdrrdtool_stepsize_desc = 'segundos' +lucistatistics_collectdrrdtool_heartbeat = 'Intervalo entre duas atualizações' +lucistatistics_collectdrrdtool_heartbeat_desc = 'segundos' +lucistatistics_collectdrrdtool_rrasingle = 'Somente criar RRAs de média' +lucistatistics_collectdrrdtool_rrasingle_desc = 'reduzir o tamanho do rrd' +lucistatistics_collectdrrdtool_rratimespans = 'Intervalos armazenados' +lucistatistics_collectdrrdtool_rratimespans_desc = 'segundos; vários valores, separar com espaço' +lucistatistics_collectdrrdtool_rrarows = 'Linhas por RRA' +lucistatistics_collectdrrdtool_xff = 'Arquivos RRD XFiles Factor' +lucistatistics_collectdrrdtool_cachetimeout = 'Cache dos dados coletados' +lucistatistics_collectdrrdtool_cachetimeout_desc = 'segundos' +lucistatistics_collectdrrdtool_cacheflush = 'Limpar cache após' +lucistatistics_collectdrrdtool_cacheflush_desc = 'segundos' +lucistatistics_collectdtcpconns = 'Configuração do plugin TCPConns' +lucistatistics_collectdtcpconns_desc = 'O plugin tcpconns coleta informações sobre as conexões TCP abertas das portas selecionadas.' +lucistatistics_collectdtcpconns_enable = 'Habilitar este plugin' +lucistatistics_collectdtcpconns_listeningports = 'Monitorar todas as portas locais' +lucistatistics_collectdtcpconns_localports = 'Monitorar as portas locais' +lucistatistics_collectdtcpconns_localports_desc = '0 - 65535; vários valores, separar com espaço' +lucistatistics_collectdtcpconns_remoteports = 'Monitorar portas remotas' +lucistatistics_collectdtcpconns_remoteports_desc = '0 - 65535; vários valores, separar com espaço' +lucistatistics_collectdunixsock = 'Configuração do plugin Unixsock' +lucistatistics_collectdunixsock_desc = 'O plugin unixsock cria um socket unix, que pode ser usado para ler os dados coletados a partir de uma instância do collectd.' +lucistatistics_collectdunixsock_enable = 'Habilitar este plugin' +lucistatistics_collectdunixsock_socketfile = 'Caminho do arquivo socket unix' +lucistatistics_collectdunixsock_socketgroup = 'Grupo dono do socket unix' +lucistatistics_collectdunixsock_socketgroup_desc = 'nome do grupo' +lucistatistics_collectdunixsock_socketperms = 'Permissões de arquivo do socket unix' +lucistatistics_collectdunixsock_socketperms_desc = 'octal' +lucistatistics_collectdwireless = 'Configuração do plugin Wireless' +lucistatistics_collectdwireless_desc = 'O plugin wireless coleta estatísticas sobre o nível de sinal wireless, o ruído e qualidade.' +lucistatistics_collectdwireless_enable = 'Habilitar este plugin' diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.xml b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.xml new file mode 100644 index 0000000..d619f83 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/i18n/statistics.pt-br.xml @@ -0,0 +1,258 @@ + + + + +Estatísticas +As estatísticas são baseadas no Collectd e é utilizado o RRD Tool para renderização das imagens à partir dos dados coletados. +Plugis de Sistema +Plugins de rede +Plugins de saída +Mostrar intervalo » +Gráficos + +Collectd +Processador +Ping +Firewall +Netlink +Processos +Wireless +Conexões TCP +Interfaces +Utilização de espaço em disco +Interrupções +Utilização do Disco +Exec +RRDTool +Rede +Formato CSV +Carga do Sistema +DNS +Email +UnixSock + +Estatísticas + +Configurações do Collectd +Collectd é um pequeno daemon que coleta dados de várias fontes através de diferentes plugins. Nesta página você pode alterar as configurações gerais do daemon collectd. + +Hostname +Diretório Base +Diretório para sub-configurações +Diretório para os plugins do collectd +Arquivo PID usado +Arquivo com a definição de dados +Intervalo da coleta de dados +Segundos +Número de threads para o coletor de dados +Tentar encontrar o nome do host completo (FQDN) + +Configuração do plugin CPU +O plugin cpu coleta as estatísticas básicas sobre o uso do processador. +Habilitar este plugin + +Configuração do plugin CSV +O plugin csv armazena os dados coletados em um arquivo no formato csv para um futuro processamento por outros programas. +Habilitar este plugin +Diretório para armazenamento dos arquivos csv +Armazenar os valores dos dados como taxas em vez de valores absolutos + +Configuração do plugin DF +O plugin df coleta estatísticas sobre a utilização de espaço em disco em diferentes dispositivos, pontos de montagem ou tipos de sistemas de arquivos. +Habilitar este plugin +Monitorar dispositivos +múltiplos valores, separados por espaço +Monitorar pontos de montagem +múltiplos valores, separados por espaço +Monitorar tipos de sistemas de arquivos +múltiplos valores, separados por espaço +Monitorar tudo exceto os selecionados + +Configuração do plugin Disco +O plugin disco coleta estatísticas de uso detalhadas das partições selecionadas ou discos inteiros. +Habilitar este plugin +Monitoras discos e partições +múltiplos valores, separados por espaço +Monitorar tudo exceto os selecionados + +Configuração do plugin DNS +O plugin dns coleta estatísticas detalhadas sobre o tráfego do dns nas interfaces selecionadas. +Habilitar este plugin +Monitorar interfaces +múltiplos valores, separados por espaço +Ignorar endereços de origem +pressione Ctrl enquanto clica para selecionar várias interfaces + +Configuração do plugin E-Mail +O plugin de email cria um socket unix que pode ser usado para transmitir estatísticas de email o daemon collectd. Este plugin é essencialmente destinado a ser utilizado em conjunto com o plugin Mail::SpamAssasin::Plugin::Collectd mas pode ser utilizado de outras maneiras também. + +Habilitar este plugin +Caminho do arquivo do socket unix +Grupo dono do socket unix +nome do grupo +Permissões de arquivo do socket unix +octal +Máximo de conexões permitidas + +Configuração do plugin Exec +O plugin exec inicia comandos externos para leitura de valores ou notificar processos externos quando um determinado valor limite for atingido. + +Habilitar este plugin +Adicionar comando para leitura de valores +Aqui você pode definir comandos externos que serão iniciados pelo collectd a fim de ler determinados valores. Os valores serão lidos a partir do stdout. + +Linha de comando +Executar como usuário +Executar como grupo +Adicionar o comando de notificação +Aqui você pode definir os comandos externos que serão iniciados pelo collectd quando determinados valores limite forem atingidos. Os valores passados ao comando serão enviados para o stdin. + +Linha de comando +Executar como usuário +Executar como grupo + +Configuração do plugin Interface +O plugin interface plugin coleta estatísticas sobre o tráfego das interfaces selecionadas. +Habilitar este plugin +Monitorar interfaces +pressione Ctrl enquanto clica para selecionar várias interfaces +Monitorar todas exceto as selecionadas + +Configuração do plugin Iptables +O plugin iptables irá monitorar as regras de firewall selecionadas e coletar informações sobre pacotes e bytes processados pela regra. + +Habilitar este plugin + +Adicionar regra +Aqui você pode definir diversos critérios para as regras iptables selecionadas serem monitoradas. + +Nome da regra +max. 16 caract. +Tabela +Cadeia +Ação (destino) +Protocolo de rede +IP de origem +Notação CIDR +IP de destino +Notação CIDR +Interface de entrada +ex. br-lan +Interface de saída +ex. br-ff +Opções +ex. rejeitar-com tcp-reset + +Configuração do plugin IRQ +O plugin irq irá monitorar a taxa de erros por segundo de cada interrupção selecionada. Se nenhuma interrupção for selecionada então todas as interrupções serão monitoradas. + +Habilitar este plugin +Monitorar interrupções +múltiplos valores, separados por espaço +Monitorar todas exceto as selecionadas + +Configuração do plugin carga +O plugin carga coleta estatísticas gerais sobre a carga do sistema. + +Habilitar este plugin + +Configuração do plugin Netlink +O plugin Netlink coleta informações detalhadas como qdisc-, classe- e filtro de estatísticas das interfaces selecionadas. + +Habilitar este plugin +Monitoramento básico +pressione Ctrl enquanto clica para selecionar várias interfaces +Monitoramento no modo verbose +pressione Ctrl enquanto clica para selecionar várias interfaces +Monitoramento do Qdisc +pressione Ctrl enquanto clica para selecionar várias interfaces +Monitoramento das Classes de Shaping +pressione Ctrl enquanto clica para selecionar várias interfaces +Monitoramento das Classes de Filtros +pressione Ctrl enquanto clica para selecionar várias interfaces +Monitorar todas exceto as selecionadas + +Configuração do plugin Rede +O plugin rede fornece informações de rede baseadas na comunicação entre as diferentes instâncias do collectd. O Collectd pode operar tanto no modo cliente quanto no modo servidor. No modo cliente os dados coletados localmente são transferidos para um servidor collectd, no modo de servidor a instância local recebe dados de outros hosts. + +Habilitar este plugin +Escutar na(s) interface(s) +Esta seção define em quais interfaces o collectd irá aguardar para receber conexões. +Endereço de escuta do Host +hostname, ip ou ip6 +Porta de escuta +0 - 65535 +Interfaces do servidor +Esta seção define para qual servidor os dados coletados localmente serão enviados. +IP/Hostname do servidor +hostname, ip ou ip6 +Porta do servidor +0 - 65535 +TTL para os pacotes de rede +0 - 255 +Transmissão entre o endereço de escuta e dos servidores +Intervalo de limpeza do cache +segundos + +Configuração do plugin Ping +O plugin ping irá enviar pacotes ICMP to tipo echo aos hosts selecionados e medir o tempo de resposta para cada host. + +Habilitar este plugin +Monitorar os hosts +múltiplos valores, separados por espaço +TTL para os pacotes do ping +0 - 255 + +Configuração do plugin Processos +O plugin processo coleta informações como o tempo da cpu, página falhas e uso de memória dos processos selecionados. + +Habilitar este plugin +Monitorar processos +múltiplos valores, separados por espaço + +Configuração do plugin RRDTool +O plugin rrdtool armazena os dados coletados no arquivo de banco de dados rrd.

Aviso: A má configuração desses valores, resultará em um valor muito elevado no consumo de memória no diretório temporário. Isso pode tornar o equipamento inutilizável!
+ +Habilitar este plugin +Diretório de armazenamento +Intervalo de atualização +segundos +Intervalo entre duas atualizações +segundos +Somente criar RRAs de média +reduzir o tamanho do rrd +Intervalos armazenados +segundos; vários valores, separar com espaço +Linhas por RRA +Arquivos RRD XFiles Factor +Cache dos dados coletados +segundos +Limpar cache após +segundos + +Configuração do plugin TCPConns +O plugin tcpconns coleta informações sobre as conexões TCP abertas das portas selecionadas. + +Habilitar este plugin +Monitorar todas as portas locais +Monitorar as portas locais +0 - 65535; vários valores, separar com espaço +Monitorar portas remotas +0 - 65535; vários valores, separar com espaço + +Configuração do plugin Unixsock +O plugin unixsock cria um socket unix, que pode ser usado para ler os dados coletados a partir de uma instância do collectd. + +Habilitar este plugin +Caminho do arquivo socket unix +Grupo dono do socket unix +nome do grupo +Permissões de arquivo do socket unix +octal + +Configuração do plugin Wireless +O plugin wireless coleta estatísticas sobre o nível de sinal wireless, o ruído e qualidade. + +Habilitar este plugin + +
diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/collectd.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/collectd.lua new file mode 100644 index 0000000..2b03eaa --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/collectd.lua @@ -0,0 +1,74 @@ +--[[ + +Luci configuration model for statistics - general collectd configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: collectd.lua 2317 2008-06-08 14:19:26Z jow $ + +]]-- + +require("luci.sys") + + +--[[ +m = Map("luci_statistics", "Collector Daemon", +Collectd ist ein kleiner und flexibler Dienst zum Sammeln und Abfragen von Daten +aus verschieden Quellen. Zur weiteren Verarbeitung werden die Daten in RRD Datenbanken +gespeichert oder per Multicast Relaying über das Netzwerk versendet.) +]]-- +m = Map("luci_statistics") + +-- general config section +s = m:section( NamedSection, "collectd", "luci_statistics" ) + +-- general.hostname (Hostname) +hostname = s:option( Value, "Hostname" ) +hostname.default = luci.sys.hostname() +hostname.optional = true + +-- general.basedir (BaseDir) +basedir = s:option( Value, "BaseDir" ) +basedir.default = "/var/run/collectd" + +-- general.include (Include) +include = s:option( Value, "Include" ) +include.default = "/etc/collectd/conf.d/*.conf" + +-- general.plugindir (PluginDir) +plugindir = s:option( Value, "PluginDir" ) +plugindir.default = "/usr/lib/collectd/" + +-- general.pidfile (PIDFile) +pidfile = s:option( Value, "PIDFile" ) +pidfile.default = "/var/run/collectd.pid" + +-- general.typesdb (TypesDB) +typesdb = s:option( Value, "TypesDB" ) +typesdb.default = "/etc/collectd/types.db" + +-- general.interval (Interval) +interval = s:option( Value, "Interval" ) +interval.default = 60 +interval.isnumber = true + +-- general.readthreads (ReadThreads) +readthreads = s:option( Value, "ReadThreads" ) +readthreads.default = 5 +readthreads.isnumber = true + +-- general.fqdnlookup (FQDNLookup) +fqdnlookup = s:option( Flag, "FQDNLookup" ) +fqdnlookup.enabled = "true" +fqdnlookup.disabled = "false" +fqdnlookup.default = "false" +fqdnlookup.optional = true +fqdnlookup:depends( "Hostname", "" ) + + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/cpu.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/cpu.lua new file mode 100644 index 0000000..5744411 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/cpu.lua @@ -0,0 +1,25 @@ +--[[ + +Luci configuration model for statistics - collectd cpu plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: cpu.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_cpu config section +s = m:section( NamedSection, "collectd_cpu", "luci_statistics" ) + +-- collectd_cpu.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/csv.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/csv.lua new file mode 100644 index 0000000..d3d00b2 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/csv.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd csv plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: csv.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_csv config section +s = m:section( NamedSection, "collectd_csv", "luci_statistics" ) + +-- collectd_csv.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_csv.datadir (DataDir) +datadir = s:option( Value, "DataDir" ) +datadir.default = "127.0.0.1" +datadir:depends( "enable", 1 ) + +-- collectd_csv.storerates (StoreRates) +storerates = s:option( Flag, "StoreRates" ) +storerates.default = 0 +storerates:depends( "enable", 1 ) + +return m + diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/df.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/df.lua new file mode 100644 index 0000000..7cc4860 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/df.lua @@ -0,0 +1,48 @@ +--[[ + +Luci configuration model for statistics - collectd df plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: df.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_df config section +s = m:section( NamedSection, "collectd_df", "luci_statistics" ) + +-- collectd_df.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_df.devices (Device) +devices = s:option( Value, "Devices" ) +devices.default = "/dev/mtdblock/4" +devices.optional = true +devices:depends( "enable", 1 ) + +-- collectd_df.mountpoints (MountPoint) +mountpoints = s:option( Value, "MountPoints" ) +mountpoints.default = "/jffs" +mountpoints.optional = true +mountpoints:depends( "enable", 1 ) + +-- collectd_df.fstypes (FSType) +fstypes = s:option( Value, "FSTypes" ) +fstypes.default = "tmpfs" +fstypes.optional = true +fstypes:depends( "enable", 1 ) + +-- collectd_df.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/disk.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/disk.lua new file mode 100644 index 0000000..8ca6de2 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/disk.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd disk plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: disk.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_disk config section +s = m:section( NamedSection, "collectd_disk", "luci_statistics" ) + +-- collectd_disk.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_disk.disks (Disk) +devices = s:option( Value, "Disks" ) +devices.default = "hda1 hdb" +devices.rmempty = true +devices:depends( "enable", 1 ) + +-- collectd_disk.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/dns.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/dns.lua new file mode 100644 index 0000000..bd65e0b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/dns.lua @@ -0,0 +1,43 @@ +--[[ + +Luci configuration model for statistics - collectd dns plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: dns.lua 3648 2008-10-29 19:11:54Z jow $ + +]]-- + +require("luci.sys") + + +m = Map("luci_statistics") + +-- collectd_dns config section +s = m:section( NamedSection, "collectd_dns", "luci_statistics" ) + +-- collectd_dns.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_dns.interfaces (Interface) +interfaces = s:option( MultiValue, "Interfaces" ) +interfaces.widget = "select" +interfaces.size = 5 +interfaces:depends( "enable", 1 ) +interfaces:value("any") +for k, v in pairs(luci.sys.net.devices()) do + interfaces:value(v) +end + +-- collectd_dns.ignoresources (IgnoreSource) +ignoresources = s:option( Value, "IgnoreSources" ) +ignoresources.default = "127.0.0.1" +ignoresources:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/email.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/email.lua new file mode 100644 index 0000000..46c7863 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/email.lua @@ -0,0 +1,52 @@ +--[[ + +Luci configuration model for statistics - collectd email plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: email.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_email config section +s = m:section( NamedSection, "collectd_email", "luci_statistics" ) + +-- collectd_email.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_email.socketfile (SocketFile) +socketfile = s:option( Value, "SocketFile" ) +socketfile.default = "/var/run/collect-email.sock" +socketfile:depends( "enable", 1 ) + +-- collectd_email.socketgroup (SocketGroup) +socketgroup = s:option( Value, "SocketGroup" ) +socketgroup.default = "nobody" +socketgroup.rmempty = true +socketgroup.optional = true +socketgroup:depends( "enable", 1 ) + +-- collectd_email.socketperms (SocketPerms) +socketperms = s:option( Value, "SocketPerms" ) +socketperms.default = "0770" +socketperms.rmempty = true +socketperms.optional = true +socketperms:depends( "enable", 1 ) + +-- collectd_email.maxconns (MaxConns) +maxconns = s:option( Value, "MaxConns" ) +maxconns.default = 5 +maxconns.isinteger = true +maxconns.rmempty = true +maxconns.optional = true +maxconns:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/exec.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/exec.lua new file mode 100644 index 0000000..4e47712 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/exec.lua @@ -0,0 +1,70 @@ +--[[ + +Luci configuration model for statistics - collectd exec plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: exec.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_exec config section +s = m:section( NamedSection, "collectd_exec", "luci_statistics" ) + +-- collectd_exec.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + + +-- collectd_exec_input config section (Exec directives) +exec = m:section( TypedSection, "collectd_exec_input" ) +exec.addremove = true +exec.anonymous = true + +-- collectd_exec_input.cmdline +exec_cmdline = exec:option( Value, "cmdline" ) +exec_cmdline.default = "/usr/bin/stat-dhcpusers" + +-- collectd_exec_input.cmdline +exec_cmduser = exec:option( Value, "cmduser" ) +exec_cmduser.default = "nobody" +exec_cmduser.rmempty = true +exec_cmduser.optional = true + +-- collectd_exec_input.cmdline +exec_cmdgroup = exec:option( Value, "cmdgroup" ) +exec_cmdgroup.default = "nogroup" +exec_cmdgroup.rmempty = true +exec_cmdgroup.optional = true + + +-- collectd_exec_notify config section (NotifyExec directives) +notify = m:section( TypedSection, "collectd_exec_notify" ) +notify.addremove = true +notify.anonymous = true + +-- collectd_notify_input.cmdline +notify_cmdline = notify:option( Value, "cmdline" ) +notify_cmdline.default = "/usr/bin/stat-dhcpusers" + +-- collectd_notify_input.cmdline +notify_cmduser = notify:option( Value, "cmduser" ) +notify_cmduser.default = "nobody" +notify_cmduser.rmempty = true +notify_cmduser.optional = true + +-- collectd_notify_input.cmdline +notify_cmdgroup = notify:option( Value, "cmdgroup" ) +notify_cmdgroup.default = "nogroup" +notify_cmdgroup.rmempty = true +notify_cmdgroup.optional = true + + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/interface.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/interface.lua new file mode 100644 index 0000000..40b843d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/interface.lua @@ -0,0 +1,42 @@ +--[[ + +Luci configuration model for statistics - collectd interface plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: interface.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +require("luci.sys") + + +m = Map("luci_statistics") + +-- collectd_interface config section +s = m:section( NamedSection, "collectd_interface", "luci_statistics" ) + +-- collectd_interface.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_interface.interfaces (Interface) +interfaces = s:option( MultiValue, "Interfaces" ) +interfaces.widget = "select" +interfaces.size = 5 +interfaces:depends( "enable", 1 ) +for k, v in pairs(luci.sys.net.devices()) do + interfaces:value(v) +end + +-- collectd_interface.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/iptables.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/iptables.lua new file mode 100644 index 0000000..865b32d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/iptables.lua @@ -0,0 +1,116 @@ +--[[ + +Luci configuration model for statistics - collectd iptables plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: iptables.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +require("luci.sys.iptparser") + +ip = luci.sys.iptparser.IptParser() +chains = { } +targets = { } + +for i, rule in ipairs( ip:find() ) do + chains[rule.chain] = true + targets[rule.target] = true +end + + +m = Map("luci_statistics") + +-- collectd_iptables config section +s = m:section( NamedSection, "collectd_iptables", "luci_statistics" ) + +-- collectd_iptables.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + + +-- collectd_iptables_match config section (Chain directives) +rule = m:section( TypedSection, "collectd_iptables_match" ) +rule.addremove = true +rule.anonymous = true + + +-- collectd_iptables_match.name +rule_table = rule:option( Value, "name" ) + +-- collectd_iptables_match.table +rule_table = rule:option( ListValue, "table" ) +rule_table.default = "filter" +rule_table.rmempty = true +rule_table.optional = true +rule_table:value("") +rule_table:value("filter") +rule_table:value("nat") +rule_table:value("mangle") + + +-- collectd_iptables_match.chain +rule_chain = rule:option( ListValue, "chain" ) +rule_chain.rmempty = true +rule_chain.optional = true +rule_chain:value("") + +for chain, void in pairs( chains ) do + rule_chain:value( chain ) +end + + +-- collectd_iptables_match.target +rule_target = rule:option( ListValue, "target" ) +rule_target.rmempty = true +rule_target.optional = true +rule_target:value("") + +for target, void in pairs( targets ) do + rule_target:value( target ) +end + + +-- collectd_iptables_match.protocol +rule_protocol = rule:option( ListValue, "protocol" ) +rule_protocol.rmempty = true +rule_protocol.optional = true +rule_protocol:value("") +rule_protocol:value("tcp") +rule_protocol:value("udp") +rule_protocol:value("icmp") + +-- collectd_iptables_match.source +rule_source = rule:option( Value, "source" ) +rule_source.default = "0.0.0.0/0" +rule_source.rmempty = true +rule_source.optional = true + +-- collectd_iptables_match.destination +rule_destination = rule:option( Value, "destination" ) +rule_destination.default = "0.0.0.0/0" +rule_destination.rmempty = true +rule_destination.optional = true + +-- collectd_iptables_match.inputif +rule_inputif = rule:option( Value, "inputif" ) +rule_inputif.rmempty = true +rule_inputif.optional = true + +-- collectd_iptables_match.outputif +rule_outputif = rule:option( Value, "outputif" ) +rule_outputif.rmempty = true +rule_outputif.optional = true + +-- collectd_iptables_match.options +rule_options = rule:option( Value, "options" ) +rule_options.rmempty = true +rule_options.optional = true + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/irq.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/irq.lua new file mode 100644 index 0000000..41f09a7 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/irq.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd irq plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: irq.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_irq config section +s = m:section( NamedSection, "collectd_irq", "luci_statistics" ) + +-- collectd_irq.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_irq.irqs (Irq) +irqs = s:option( Value, "Irqs" ) +irqs.optional = true +irqs:depends( "enable", 1 ) + +-- collectd_irq.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected.optional = "true" +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/load.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/load.lua new file mode 100644 index 0000000..ae97d7f --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/load.lua @@ -0,0 +1,25 @@ +--[[ + +Luci configuration model for statistics - collectd load plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: load.lua 2329 2008-06-08 21:51:55Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_wireless config section +s = m:section( NamedSection, "collectd_load", "luci_statistics" ) + +-- collectd_wireless.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/netlink.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/netlink.lua new file mode 100644 index 0000000..b7e8d34 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/netlink.lua @@ -0,0 +1,90 @@ +--[[ + +Luci configuration model for statistics - collectd netlink plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: netlink.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +require("luci.sys") + +local devices = luci.sys.net.devices() + + +m = Map("luci_statistics") + +-- collectd_netlink config section +s = m:section( NamedSection, "collectd_netlink", "luci_statistics" ) + +-- collectd_netlink.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_netlink.interfaces (Interface) +interfaces = s:option( MultiValue, "Interfaces" ) +interfaces.widget = "select" +interfaces.optional = true +interfaces.size = #devices + 1 +interfaces:depends( "enable", 1 ) +interfaces:value("") +for i, v in ipairs(devices) do + interfaces:value(v) +end + +-- collectd_netlink.verboseinterfaces (VerboseInterface) +verboseinterfaces = s:option( MultiValue, "VerboseInterfaces" ) +verboseinterfaces.widget = "select" +verboseinterfaces.optional = true +verboseinterfaces.size = #devices + 1 +verboseinterfaces:depends( "enable", 1 ) +verboseinterfaces:value("") +for i, v in ipairs(devices) do + verboseinterfaces:value(v) +end + +-- collectd_netlink.qdiscs (QDisc) +qdiscs = s:option( MultiValue, "QDiscs" ) +qdiscs.widget = "select" +qdiscs.optional = true +qdiscs.size = #devices + 1 +qdiscs:depends( "enable", 1 ) +qdiscs:value("") +for i, v in ipairs(devices) do + qdiscs:value(v) +end + +-- collectd_netlink.classes (Class) +classes = s:option( MultiValue, "Classes" ) +classes.widget = "select" +classes.optional = true +classes.size = #devices + 1 +classes:depends( "enable", 1 ) +classes:value("") +for i, v in ipairs(devices) do + classes:value(v) +end + +-- collectd_netlink.filters (Filter) +filters = s:option( MultiValue, "Filters" ) +filters.widget = "select" +filters.optional = true +filters.size = #devices + 1 +filters:depends( "enable", 1 ) +filters:value("") +for i, v in ipairs(devices) do + filters:value(v) +end + +-- collectd_netlink.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/network.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/network.lua new file mode 100644 index 0000000..7364e89 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/network.lua @@ -0,0 +1,79 @@ +--[[ + +Luci configuration model for statistics - collectd network plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: network.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + + +m = Map("luci_statistics") + +-- collectd_network config section +s = m:section( NamedSection, "collectd_network", "luci_statistics" ) + +-- collectd_network.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + + +-- collectd_network_listen config section (Listen) +listen = m:section( TypedSection, "collectd_network_listen" ) +listen.addremove = true +listen.anonymous = true + +-- collectd_network_listen.host +listen_host = listen:option( Value, "host" ) +listen_host.default = "0.0.0.0" + +-- collectd_network_listen.port +listen_port = listen:option( Value, "port" ) +listen_port.default = 25826 +listen_port.isinteger = true +listen_port.optional = true + + +-- collectd_network_server config section (Server) +server = m:section( TypedSection, "collectd_network_server" ) +server.addremove = true +server.anonymous = true + +-- collectd_network_server.host +server_host = server:option( Value, "host" ) +server_host.default = "0.0.0.0" + +-- collectd_network_server.port +server_port = server:option( Value, "port" ) +server_port.default = 25826 +server_port.isinteger = true +server_port.optional = true + +-- collectd_network.timetolive (TimeToLive) +ttl = s:option( Value, "TimeToLive" ) +ttl.default = 128 +ttl.isinteger = true +ttl.optional = true +ttl:depends( "enable", 1 ) + +-- collectd_network.forward (Forward) +forward = s:option( Flag, "Forward" ) +forward.default = 0 +forward.optional = true +forward:depends( "enable", 1 ) + +-- collectd_network.cacheflush (CacheFlush) +cacheflush = s:option( Value, "CacheFlush" ) +cacheflush.default = 86400 +cacheflush.isinteger = true +cacheflush.optional = true +cacheflush:depends( "enable", 1 ) + + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/ping.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/ping.lua new file mode 100644 index 0000000..0bcb264 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/ping.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd ping plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ping.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_ping config section +s = m:section( NamedSection, "collectd_ping", "luci_statistics" ) + +-- collectd_ping.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_ping.hosts (Host) +hosts = s:option( Value, "Hosts" ) +hosts.default = "127.0.0.1" +hosts:depends( "enable", 1 ) + +-- collectd_ping.ttl (TTL) +ttl = s:option( Value, "TTL" ) +ttl.isinteger = true +ttl.default = 128 +ttl:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/processes.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/processes.lua new file mode 100644 index 0000000..08386c5 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/processes.lua @@ -0,0 +1,30 @@ +--[[ + +Luci configuration model for statistics - collectd processes plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: processes.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_processes config section +s = m:section( NamedSection, "collectd_processes", "luci_statistics" ) + +-- collectd_processes.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_processes.processes (Process) +processes = s:option( Value, "Processes" ) +processes.default = "olsrd bmxd httpd dnsmasq dropbear tinc" +processes:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/rrdtool.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/rrdtool.lua new file mode 100644 index 0000000..9f51794 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/rrdtool.lua @@ -0,0 +1,94 @@ +--[[ + +Luci configuration model for statistics - collectd rrdtool plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: rrdtool.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_rrdtool config section +s = m:section( NamedSection, "collectd_rrdtool", "luci_statistics" ) + +-- collectd_rrdtool.enable +enable = s:option( Flag, "enable" ) +enable.default = 1 + +-- collectd_rrdtool.datadir (DataDir) +datadir = s:option( Value, "DataDir" ) +datadir.default = "/tmp" +datadir.rmempty = true +datadir.optional = true +datadir:depends( "enable", 1 ) + +-- collectd_rrdtool.stepsize (StepSize) +stepsize = s:option( Value, "StepSize" ) +stepsize.default = 30 +stepsize.isinteger = true +stepsize.rmempty = true +stepsize.optional = true +stepsize:depends( "enable", 1 ) + +-- collectd_rrdtool.heartbeat (HeartBeat) +heartbeat = s:option( Value, "HeartBeat" ) +heartbeat.default = 60 +heartbeat.isinteger = true +heartbeat.rmempty = true +heartbeat.optional = true +heartbeat:depends( "enable", 1 ) + +-- collectd_rrdtool.rrasingle (RRASingle) +rrasingle = s:option( Flag, "RRASingle" ) +rrasingle.default = true +rrasingle.rmempty = true +rrasingle.optional = true +rrasingle:depends( "enable", 1 ) + +-- collectd_rrdtool.rratimespans (RRATimespan) +rratimespans = s:option( Value, "RRATimespans" ) +rratimespans.default = "600 86400 604800 2678400 31622400" +rratimespans.rmempty = true +rratimespans.optional = true +rratimespans:depends( "enable", 1 ) + +-- collectd_rrdtool.rrarows (RRARows) +rrarows = s:option( Value, "RRARows" ) +rrarows.isinteger = true +rrarows.default = 100 +rrarows.rmempty = true +rrarows.optional = true +rrarows:depends( "enable", 1 ) + +-- collectd_rrdtool.xff (XFF) +xff = s:option( Value, "XFF" ) +xff.default = 0.1 +xff.isnumber = true +xff.rmempty = true +xff.optional = true +xff:depends( "enable", 1 ) + +-- collectd_rrdtool.cachetimeout (CacheTimeout) +cachetimeout = s:option( Value, "CacheTimeout" ) +cachetimeout.isinteger = true +cachetimeout.default = 100 +cachetimeout.rmempty = true +cachetimeout.optional = true +cachetimeout:depends( "enable", 1 ) + +-- collectd_rrdtool.cacheflush (CacheFlush) +cacheflush = s:option( Value, "CacheFlush" ) +cacheflush.isinteger = true +cacheflush.default = 100 +cacheflush.rmempty = true +cacheflush.optional = true +cacheflush:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/tcpconns.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/tcpconns.lua new file mode 100644 index 0000000..281e581 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/tcpconns.lua @@ -0,0 +1,40 @@ +--[[ + +Luci configuration model for statistics - collectd tcpconns plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: tcpconns.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_tcpconns config section +s = m:section( NamedSection, "collectd_tcpconns", "luci_statistics" ) + +-- collectd_tcpconns.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_tcpconns.listeningports (ListeningPorts) +listeningports = s:option( Flag, "ListeningPorts" ) +listeningports.default = 1 +listeningports:depends( "enable", 1 ) + +-- collectd_tcpconns.localports (LocalPort) +localports = s:option( Value, "LocalPorts" ) +localports.optional = true +localports:depends( "enable", 1 ) + +-- collectd_tcpconns.remoteports (RemotePort) +remoteports = s:option( Value, "RemotePorts" ) +remoteports.optional = true +remoteports:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/unixsock.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/unixsock.lua new file mode 100644 index 0000000..f812200 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/unixsock.lua @@ -0,0 +1,44 @@ +--[[ + +Luci configuration model for statistics - collectd unixsock plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: unixsock.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_unixsock config section +s = m:section( NamedSection, "collectd_unixsock", "luci_statistics" ) + +-- collectd_unixsock.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_unixsock.socketfile (SocketFile) +socketfile = s:option( Value, "SocketFile" ) +socketfile.default = "/var/run/collect-query.socket" +socketfile:depends( "enable", 1 ) + +-- collectd_unixsock.socketgroup (SocketGroup) +socketgroup = s:option( Value, "SocketGroup" ) +socketgroup.default = "nobody" +socketgroup.rmempty = true +socketgroup.optional = true +socketgroup:depends( "enable", 1 ) + +-- collectd_unixsock.socketperms (SocketPerms) +socketperms = s:option( Value, "SocketPerms" ) +socketperms.default = "0770" +socketperms.rmempty = true +socketperms.optional = true +socketperms:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/wireless.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/wireless.lua new file mode 100644 index 0000000..7590dcd --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/model/cbi/luci_statistics/wireless.lua @@ -0,0 +1,25 @@ +--[[ + +Luci configuration model for statistics - collectd wireless plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: wireless.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_wireless config section +s = m:section( NamedSection, "collectd_wireless", "luci_statistics" ) + +-- collectd_wireless.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +return m diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/datatree.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/datatree.lua new file mode 100644 index 0000000..3411702 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/datatree.lua @@ -0,0 +1,181 @@ +--[[ + +Luci statistics - rrd data tree builder +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: datatree.lua 3642 2008-10-29 05:08:03Z jow $ + +]]-- + +module("luci.statistics.datatree", package.seeall) + +local util = require("luci.util") +local sys = require("luci.sys") +local fs = require("luci.fs") +local uci = require("luci.model.uci").cursor() +local sections = uci:get_all("luci_statistics") + + +Instance = util.class() + +function Instance.__init__( self, host ) + self._host = host or sections.collectd.Hostname or sys.hostname() + self._libdir = sections.collectd.PluginDir or "/usr/lib/collectd" + self._rrddir = sections.collectd_rrdtool.DataDir or "/tmp/rrd" + + self._libdir = self._libdir:gsub("/$","") + self._rrddir = self._rrddir:gsub("/$","") + self._plugins = { } + + self:_scan() +end + +function Instance._mkpath( self, plugin, pinstance ) + local dir = self._rrddir .. "/" .. self._host + + if type(plugin) == "string" and plugin:len() > 0 then + dir = dir .. "/" .. plugin + + if type(pinstance) == "string" and pinstance:len() > 0 then + dir = dir .. "-" .. pinstance + end + end + + return dir +end + +function Instance._notzero( self, table ) + for k in pairs(table) do + return true + end + + return false +end + +function Instance._scan( self ) + local dirs = fs.dir( self:_mkpath() ) + if not dirs then + return + end + +-- for i, plugin in ipairs( dirs ) do +-- if plugin:match("%w+.so") then +-- self._plugins[ plugin:gsub("%.so$", "") ] = { } +-- end +-- end + + for _, dir in ipairs(dirs) do + if dir ~= "." and dir ~= ".." and + fs.stat(self:_mkpath(dir)).type == "directory" + then + local plugin = dir:gsub("%-.+$", "") + if not self._plugins[plugin] then + self._plugins[plugin] = { } + end + end + end + + for plugin, instances in pairs( self._plugins ) do + + local dirs = fs.dir( self:_mkpath() ) + + if type(dirs) == "table" then + for i, dir in ipairs(dirs) do + if dir:find( plugin .. "%-" ) or dir == plugin then + local instance = "" + + if dir ~= plugin then + instance = dir:gsub( plugin .. "%-", "", 1 ) + end + + instances[instance] = { } + end + end + end + + for instance, data_instances in pairs( instances ) do + + dirs = fs.dir( self:_mkpath( plugin, instance ) ) + + if type(dirs) == "table" then + for i, file in ipairs(dirs) do + if file:find("%.rrd") then + file = file:gsub("%.rrd","") + + local data_type + local data_instance + + if file:find("%-") then + data_type = file:gsub( "%-.+","" ) + data_instance = file:gsub( "[^%-]-%-", "", 1 ) + else + data_type = file + data_instance = "" + end + + if not data_instances[data_type] then + data_instances[data_type] = { data_instance } + else + table.insert( data_instances[data_type], data_instance ) + end + end + end + end + end + end +end + + +function Instance.plugins( self ) + local rv = { } + + for plugin, val in pairs( self._plugins ) do + if self:_notzero( val ) then + table.insert( rv, plugin ) + end + end + + return rv +end + +function Instance.plugin_instances( self, plugin ) + local rv = { } + + for instance, val in pairs( self._plugins[plugin] ) do + table.insert( rv, instance ) + end + + return rv +end + +function Instance.data_types( self, plugin, instance ) + local rv = { } + local p = self._plugins[plugin] + + if type(p) == "table" and type(p[instance]) == "table" then + for type, val in pairs(p[instance]) do + table.insert( rv, type ) + end + end + + return rv +end + +function Instance.data_instances( self, plugin, instance, dtype ) + local rv = { } + local p = self._plugins[plugin] + + if type(p) == "table" and type(p[instance]) == "table" and type(p[instance][dtype]) == "table" then + for i, instance in ipairs(p[instance][dtype]) do + table.insert( rv, instance ) + end + end + + return rv +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/i18n.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/i18n.lua new file mode 100644 index 0000000..b54e30b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/i18n.lua @@ -0,0 +1,115 @@ +--[[ + +Luci statistics - diagram i18n helper +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: i18n.lua 3033 2008-08-31 14:38:28Z jow $ + +]]-- + +module("luci.statistics.i18n", package.seeall) + +require("luci.util") +require("luci.i18n") + + +Instance = luci.util.class() + + +function Instance.__init__( self, graph ) + self.i18n = luci.i18n + self.graph = graph + + self.i18n.loadc("rrdtool") + self.i18n.loadc("statistics") +end + +function Instance._subst( self, str, val ) + str = str:gsub( "%%H", self.graph.opts.host or "" ) + str = str:gsub( "%%pn", val.plugin or "" ) + str = str:gsub( "%%pi", val.pinst or "" ) + str = str:gsub( "%%dt", val.dtype or "" ) + str = str:gsub( "%%di", val.dinst or "" ) + str = str:gsub( "%%ds", val.dsrc or "" ) + + return str +end + +function Instance.title( self, plugin, pinst, dtype, dinst ) + + local title = self.i18n.translate( + string.format( "stat_dg_title_%s_%s_%s", plugin, pinst, dtype ), + self.i18n.translate( + string.format( "stat_dg_title_%s_%s", plugin, pinst ), + self.i18n.translate( + string.format( "stat_dg_title_%s__%s", plugin, dtype ), + self.i18n.translate( + string.format( "stat_dg_title_%s", plugin ), + self.graph:_mkpath( plugin, pinst, dtype ) + ) + ) + ) + ) + + return self:_subst( title, { + plugin = plugin, + pinst = pinst, + dtype = dtype, + dinst = dinst + } ) + +end + +function Instance.label( self, plugin, pinst, dtype, dinst ) + + local label = self.i18n.translate( + string.format( "stat_dg_label_%s_%s_%s", plugin, pinst, dtype ), + self.i18n.translate( + string.format( "stat_dg_label_%s_%s", plugin, pinst ), + self.i18n.translate( + string.format( "stat_dg_label_%s__%s", plugin, dtype ), + self.i18n.translate( + string.format( "stat_dg_label_%s", plugin ), + self.graph:_mkpath( plugin, pinst, dtype ) + ) + ) + ) + ) + + return self:_subst( label, { + plugin = plugin, + pinst = pinst, + dtype = dtype, + dinst = dinst + } ) + +end + +function Instance.ds( self, source ) + + local label = self.i18n.translate( + string.format( "stat_ds_%s_%s_%s", source.type, source.instance, source.ds ), + self.i18n.translate( + string.format( "stat_ds_%s_%s", source.type, source.instance ), + self.i18n.translate( + string.format( "stat_ds_label_%s__%s", source.type, source.ds ), + self.i18n.translate( + string.format( "stat_ds_%s", source.type ), + source.type .. "_" .. source.instance:gsub("[^%w]","_") .. "_" .. source.ds + ) + ) + ) + ) + + return self:_subst( label, { + dtype = source.type, + dinst = source.instance, + dsrc = source.ds + } ) +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool.lua new file mode 100644 index 0000000..ca00e42 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool.lua @@ -0,0 +1,607 @@ +--[[ + +Luci statistics - rrdtool interface library / diagram model interpreter +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: rrdtool.lua 3873 2008-12-07 23:44:22Z jow $ + +]]-- + +module("luci.statistics.rrdtool", package.seeall) + +require("luci.statistics.datatree") +require("luci.statistics.rrdtool.colors") +require("luci.statistics.rrdtool.definitions") +require("luci.statistics.i18n") +require("luci.model.uci") +require("luci.util") +require("luci.sys") +require("luci.fs") + + +Graph = luci.util.class() + +function Graph.__init__( self, timespan, opts ) + + opts = opts or { } + + local uci = luci.model.uci.cursor() + local sections = uci:get_all( "luci_statistics" ) + + -- helper classes + self.colors = luci.statistics.rrdtool.colors.Instance() + self.defs = luci.statistics.rrdtool.definitions.Instance() + self.tree = luci.statistics.datatree.Instance() + self.i18n = luci.statistics.i18n.Instance( self ) + + -- options + opts.timespan = timespan or sections.rrdtool.default_timespan or 900 + opts.rrasingle = opts.rrasingle or ( sections.collectd_rrdtool.RRASingle == "1" ) + opts.host = opts.host or sections.collectd.Hostname or luci.sys.hostname() + opts.width = opts.width or sections.rrdtool.image_width or 400 + opts.rrdpath = opts.rrdpath or sections.collectd_rrdtool.DataDir or "/tmp/rrd" + opts.imgpath = opts.imgpath or sections.rrdtool.image_path or "/tmp/rrdimg" + opts.rrdpath = opts.rrdpath:gsub("/$","") + opts.imgpath = opts.imgpath:gsub("/$","") + + -- rrdtool default args + self.args = { + "-a", "PNG", + "-s", "NOW-" .. opts.timespan, + "-w", opts.width + } + + -- store options + self.opts = opts +end + +function Graph._mkpath( self, plugin, plugin_instance, dtype, dtype_instance ) + local t = self.opts.host .. "/" .. plugin + if type(plugin_instance) == "string" and plugin_instance:len() > 0 then + t = t .. "-" .. plugin_instance + end + t = t .. "/" .. dtype + if type(dtype_instance) == "string" and dtype_instance:len() > 0 then + t = t .. "-" .. dtype_instance + end + return t +end + +function Graph.mkrrdpath( self, ... ) + return string.format( "%s/%s.rrd", self.opts.rrdpath, self:_mkpath( ... ) ) +end + +function Graph.mkpngpath( self, ... ) + return string.format( "%s/%s.%i.png", self.opts.imgpath, self:_mkpath( ... ), self.opts.timespan ) +end + +function Graph.strippngpath( self, path ) + return path:sub( self.opts.imgpath:len() + 2 ) +end + +function Graph._forcelol( self, list ) + if type(list[1]) ~= "table" then + return( { list } ) + end + return( list ) +end + +function Graph._rrdtool( self, def, rrd ) + + -- prepare directory + local dir = def[1]:gsub("/[^/]+$","") + luci.fs.mkdir( dir, true ) + + -- construct commandline + local cmdline = "rrdtool graph" + + -- copy default arguments to def stack + for i, opt in ipairs(self.args) do + table.insert( def, 1 + i, opt ) + end + + -- construct commandline from def stack + for i, opt in ipairs(def) do + opt = opt .. "" -- force string + + if rrd then + opt = opt:gsub( "{file}", rrd ) + end + + if opt:match("[^%w]") then + cmdline = cmdline .. " '" .. opt .. "'" + else + cmdline = cmdline .. " " .. opt + end + end + + -- execute rrdtool + local rrdtool = io.popen( cmdline ) + rrdtool:close() +end + +function Graph._generic( self, opts, plugin, plugin_instance, dtype, index ) + + -- generated graph defs + local defs = { } + + -- internal state variables + local _args = { } + local _sources = { } + local _stack_neg = { } + local _stack_pos = { } + local _longest_name = 0 + local _has_totals = false + + -- some convenient aliases + local _ti = table.insert + local _sf = string.format + + -- local helper: append a string.format() formatted string to given table + function _tif( list, fmt, ... ) + table.insert( list, string.format( fmt, ... ) ) + end + + -- local helper: create definitions for min, max, avg and create *_nnl (not null) variable from avg + function __def(source) + + local inst = source.sname + local rrd = source.rrd + local ds = source.ds + + if not ds or ds:len() == 0 then ds = "value" end + + _tif( _args, "DEF:%s_avg=%s:%s:AVERAGE", inst, rrd, ds ) + + if not self.opts.rrasingle then + _tif( _args, "DEF:%s_min=%s:%s:MIN", inst, rrd, ds ) + _tif( _args, "DEF:%s_max=%s:%s:MAX", inst, rrd, ds ) + end + + _tif( _args, "CDEF:%s_nnl=%s_avg,UN,0,%s_avg,IF", inst, inst, inst ) + end + + -- local helper: create cdefs depending on source options like flip and overlay + function __cdef(source) + + local prev + + -- find previous source, choose stack depending on flip state + if source.flip then + prev = _stack_neg[#_stack_neg] + else + prev = _stack_pos[#_stack_pos] + end + + -- is first source in stack or overlay source: source_stk = source_nnl + if not prev or source.overlay then + -- create cdef statement + _tif( _args, "CDEF:%s_stk=%s_nnl", source.sname, source.sname ) + + -- is subsequent source without overlay: source_stk = source_nnl + previous_stk + else + -- create cdef statement + _tif( _args, "CDEF:%s_stk=%s_nnl,%s_stk,+", source.sname, source.sname, prev ) + end + + -- create multiply by minus one cdef if flip is enabled + if source.flip then + + -- create cdef statement: source_stk = source_stk * -1 + _tif( _args, "CDEF:%s_neg=%s_stk,-1,*", source.sname, source.sname ) + + -- push to negative stack if overlay is disabled + if not source.overlay then + _ti( _stack_neg, source.sname ) + end + + -- no flipping, push to positive stack if overlay is disabled + elseif not source.overlay then + + -- push to positive stack + _ti( _stack_pos, source.sname ) + end + + -- calculate total amount of data if requested + if source.total then + _tif( _args, + "CDEF:%s_avg_sample=%s_avg,UN,0,%s_avg,IF,sample_len,*", + source.sname, source.sname, source.sname + ) + + _tif( _args, + "CDEF:%s_avg_sum=PREV,UN,0,PREV,IF,%s_avg_sample,+", + source.sname, source.sname, source.sname + ) + end + end + + -- local helper: create cdefs required for calculating total values + function __cdef_totals() + if _has_totals then + _tif( _args, "CDEF:mytime=%s_avg,TIME,TIME,IF", _sources[1].sname ) + _ti( _args, "CDEF:sample_len_raw=mytime,PREV(mytime),-" ) + _ti( _args, "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF" ) + end + end + + -- local helper: create line and area statements + function __line(source) + + local line_color + local area_color + local legend + local var + + -- find colors: try source, then opts.colors; fall back to random color + if type(source.color) == "string" then + line_color = source.color + area_color = self.colors:from_string( line_color ) + elseif type(opts.colors[source.name:gsub("[^%w]","_")]) == "string" then + line_color = opts.colors[source.name:gsub("[^%w]","_")] + area_color = self.colors:from_string( line_color ) + else + area_color = self.colors:random() + line_color = self.colors:to_string( area_color ) + end + + -- derive area background color from line color + area_color = self.colors:to_string( self.colors:faded( area_color ) ) + + -- choose source_stk or source_neg variable depending on flip state + if source.flip then + var = "neg" + else + var = "stk" + end + + -- create legend + legend = _sf( "%-" .. _longest_name .. "s", source.title ) + + -- create area if not disabled + if not source.noarea then + _tif( _args, "AREA:%s_%s#%s", source.sname, var, area_color ) + end + + -- create line1 statement + _tif( _args, "LINE1:%s_%s#%s:%s", source.sname, var, line_color, legend ) + end + + -- local helper: create gprint statements + function __gprint(source) + + local numfmt = opts.number_format or "%6.1lf" + local totfmt = opts.totals_format or "%5.1lf%s" + + -- don't include MIN if rrasingle is enabled + if not self.opts.rrasingle then + _tif( _args, "GPRINT:%s_min:MIN:\tMin\\: %s", source.sname, numfmt ) + end + + -- always include AVERAGE + _tif( _args, "GPRINT:%s_avg:AVERAGE:\tAvg\\: %s", source.sname, numfmt ) + + -- don't include MAX if rrasingle is enabled + if not self.opts.rrasingle then + _tif( _args, "GPRINT:%s_max:MAX:\tMax\\: %s", source.sname, numfmt ) + end + + -- include total count if requested else include LAST + if source.total then + _tif( _args, "GPRINT:%s_avg_sum:LAST:(ca. %s Total)\\l", source.sname, totfmt ) + else + _tif( _args, "GPRINT:%s_avg:LAST:\tLast\\: %s\\l", source.sname, numfmt ) + end + end + + + -- + -- find all data sources + -- + + -- find data types + local data_types + + if dtype then + data_types = { dtype } + else + data_types = opts.data.types or { } + end + + if not ( dtype or opts.data.types ) then + if opts.data.instances then + for k, v in pairs(opts.data.instances) do + _ti( data_types, k ) + end + elseif opts.data.sources then + for k, v in pairs(opts.data.sources) do + _ti( data_types, k ) + end + end + end + + + -- iterate over data types + for i, dtype in ipairs(data_types) do + + -- find instances + + local data_instances + + if not opts.per_instance then + if type(opts.data.instances) == "table" and type(opts.data.instances[dtype]) == "table" then + data_instances = opts.data.instances[dtype] + else + data_instances = self.tree:data_instances( plugin, plugin_instance, dtype ) + end + end + + if type(data_instances) ~= "table" or #data_instances == 0 then data_instances = { "" } end + + + -- iterate over data instances + for i, dinst in ipairs(data_instances) do + + -- construct combined data type / instance name + local dname = dtype + + if dinst:len() > 0 then + dname = dname .. "_" .. dinst + end + + + -- find sources + local data_sources = { "value" } + + if type(opts.data.sources) == "table" then + if type(opts.data.sources[dname]) == "table" then + data_sources = opts.data.sources[dname] + elseif type(opts.data.sources[dtype]) == "table" then + data_sources = opts.data.sources[dtype] + end + end + + + -- iterate over data sources + for i, dsource in ipairs(data_sources) do + + local dsname = dtype .. "_" .. dinst:gsub("[^%w]","_") .. "_" .. dsource + local altname = dtype .. "__" .. dsource + + -- find datasource options + local dopts = { } + + if type(opts.data.options) == "table" then + if type(opts.data.options[dsname]) == "table" then + dopts = opts.data.options[dsname] + elseif type(opts.data.options[altname]) == "table" then + dopts = opts.data.options[altname] + elseif type(opts.data.options[dname]) == "table" then + dopts = opts.data.options[dname] + elseif type(opts.data.options[dtype]) == "table" then + dopts = opts.data.options[dtype] + end + end + + + -- store values + _ti( _sources, { + rrd = dopts.rrd or self:mkrrdpath( plugin, plugin_instance, dtype, dinst ), + color = dopts.color or self.colors:to_string( self.colors:random() ), + flip = dopts.flip or false, + total = dopts.total or false, + overlay = dopts.overlay or false, + noarea = dopts.noarea or false, + ds = dsource, + type = dtype, + instance = dinst, + index = #_sources + 1, + sname = ( #_sources + 1 ) .. dtype + } ) + + + -- generate datasource title + _sources[#_sources].title = self.i18n:ds( _sources[#_sources] ) + + + -- find longest name ... + if _sources[#_sources].title:len() > _longest_name then + _longest_name = _sources[#_sources].title:len() + end + + + -- has totals? + if _sources[#_sources].total then + _has_totals = true + end + end + end + end + + + -- + -- construct diagrams + -- + + -- if per_instance is enabled then find all instances from the first datasource in diagram + -- if per_instance is disabled then use an empty pseudo instance and use model provided values + local instances = { "" } + + if opts.per_instance then + instances = self.tree:data_instances( plugin, plugin_instance, _sources[1].type ) + end + + + -- iterate over instances + for i, instance in ipairs(instances) do + + -- store title and vlabel + _ti( _args, "-t" ) + _ti( _args, opts.title or self.i18n:title( plugin, plugin_instance, _sources[1].type, instance ) ) + _ti( _args, "-v" ) + _ti( _args, opts.vlabel or self.i18n:label( plugin, plugin_instance, _sources[1].type, instance ) ) + + -- store additional rrd options + if opts.rrdopts then + for i, o in ipairs(opts.rrdopts) do _ti( _args, o ) end + end + + + -- create DEF statements for each instance + for i, source in ipairs(_sources) do + -- fixup properties for per instance mode... + if opts.per_instance then + source.instance = instance + source.rrd = self:mkrrdpath( plugin, plugin_instance, source.type, instance ) + end + + __def( source ) + end + + -- create CDEF required for calculating totals + __cdef_totals() + + -- create CDEF statements for each instance in reversed order + for i, source in ipairs(_sources) do + __cdef( _sources[1 + #_sources - i] ) + end + + -- create LINE1, AREA and GPRINT statements for each instance + for i, source in ipairs(_sources) do + __line( source ) + __gprint( source ) + end + + -- prepend image path to arg stack + _ti( _args, 1, self:mkpngpath( plugin, plugin_instance, index .. instance ) ) + + -- push arg stack to definition list + _ti( defs, _args ) + + -- reset stacks + _args = { } + _stack_pos = { } + _stack_neg = { } + end + + return defs +end + +function Graph.render( self, plugin, plugin_instance ) + + dtype_instances = dtype_instances or { "" } + local pngs = { } + + -- check for a whole graph handler + local plugin_def = "luci.statistics.rrdtool.definitions." .. plugin + local stat, def = luci.util.copcall( require, plugin_def ) + + if stat and def and type(def.rrdargs) == "function" then + + -- temporary image matrix + local _images = { } + + -- get diagram definitions + for i, opts in ipairs( self:_forcelol( def.rrdargs( self, plugin, plugin_instance ) ) ) do + + _images[i] = { } + + -- get diagram definition instances + local diagrams = self:_generic( opts, plugin, plugin_instance, nil, i ) + + -- render all diagrams + for j, def in ipairs( diagrams ) do + + -- remember image + _images[i][j] = def[1] + + -- exec + self:_rrdtool( def ) + end + end + + -- remember images - XXX: fixme (will cause probs with asymmetric data) + for y = 1, #_images[1] do + for x = 1, #_images do + table.insert( pngs, _images[x][y] ) + end + end + else + + -- no graph handler, iterate over data types + for i, dtype in ipairs( self.tree:data_types( plugin, plugin_instance ) ) do + + -- check for data type handler + local dtype_def = plugin_def .. "." .. dtype + local stat, def = luci.util.copcall( require, dtype_def ) + + if stat and def and type(def.rrdargs) == "function" then + + -- temporary image matrix + local _images = { } + + -- get diagram definitions + for i, opts in ipairs( self:_forcelol( def.rrdargs( self, plugin, plugin_instance, dtype ) ) ) do + + _images[i] = { } + + -- get diagram definition instances + local diagrams = self:_generic( opts, plugin, plugin_instance, dtype, i ) + + -- render all diagrams + for j, def in ipairs( diagrams ) do + + -- remember image + _images[i][j] = def[1] + + -- exec + self:_rrdtool( def ) + end + end + + -- remember images - XXX: fixme (will cause probs with asymmetric data) + for y = 1, #_images[1] do + for x = 1, #_images do + table.insert( pngs, _images[x][y] ) + end + end + else + + -- no data type handler, fall back to builtin definition + if type(self.defs.definitions[dtype]) == "table" then + + -- iterate over data type instances + for i, inst in ipairs( self.tree:data_instances( plugin, plugin_instance, dtype ) ) do + + local title = self.i18n:title( plugin, plugin_instance, dtype, inst ) + local label = self.i18n:label( plugin, plugin_instance, dtype, inst ) + local png = self:mkpngpath( plugin, plugin_instance, dtype, inst ) + local rrd = self:mkrrdpath( plugin, plugin_instance, dtype, inst ) + local args = { png, "-t", title, "-v", label } + + for i, o in ipairs(self.defs.definitions[dtype]) do + -- XXX: this is a somewhat ugly hack to exclude min/max RRAs when rrasingle is on + if not ( self.opts.rrasingle and ( o:match("_min") or o:match("_max") ) ) then + table.insert( args, o ) + end + end + + -- remember image + table.insert( pngs, png ) + + -- exec + self:_rrdtool( args, rrd ) + end + end + end + end + end + + return pngs +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/colors.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/colors.lua new file mode 100644 index 0000000..e5fef17 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/colors.lua @@ -0,0 +1,73 @@ +--[[ + +Luci statistics - diagram color helper class +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: colors.lua 2829 2008-08-14 22:51:12Z Cyrus $ + +]]-- + +module("luci.statistics.rrdtool.colors", package.seeall) + +require("luci.util") + + +Instance = luci.util.class() + +function Instance.from_string( self, s ) + return { + tonumber(s:sub(1,2), 16), + tonumber(s:sub(3,4), 16), + tonumber(s:sub(5,6), 16) + } +end + +function Instance.to_string( self, c ) + return string.format( + "%02x%02x%02x", + math.floor(c[1]), + math.floor(c[2]), + math.floor(c[3]) + ) +end + +function Instance.random( self ) + local r = math.random(255) + local g = math.random(255) + local min = 0 + local max = 255 + + if ( r + g ) < 255 then + min = 255 - r - g + else + max = 511 - r - g + end + + local b = min + math.floor( math.random() * ( max - min ) ) + + return { r, g, b } +end + +function Instance.faded( self, fg, opts ) + opts = opts or {} + opts.background = opts.background or { 255, 255, 255 } + opts.alpha = opts.alpha or 0.25 + + if type(opts.background) == "string" then + opts.background = _string_to_color(opts.background) + end + + local bg = opts.background + + return { + ( opts.alpha * fg[1] ) + ( ( 1.0 - opts.alpha ) * bg[1] ), + ( opts.alpha * fg[2] ) + ( ( 1.0 - opts.alpha ) * bg[2] ), + ( opts.alpha * fg[3] ) + ( ( 1.0 - opts.alpha ) * bg[3] ) + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions.lua new file mode 100644 index 0000000..159fa7e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions.lua @@ -0,0 +1,1123 @@ +--[[ + +Luci statistics - data definition database (obsolete) +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: definitions.lua 3540 2008-10-08 15:59:10Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions", package.seeall) + +require("luci.util") +require("luci.fs") + + +Instance = luci.util.class() + +function Instance.__init__( self, ... ) + + -- used color palette + self.palette = { + Canvas = "FFFFFF", + FullRed = "FF0000", + FullGreen = "00E000", + FullBlue = "0000FF", + FullYellow = "F0A000", + FullCyan = "00A0FF", + FullMagenta = "A000FF", + HalfRed = "F7B7B7", + HalfGreen = "B7EFB7", + HalfBlue = "B7B7F7", + HalfYellow = "F3DFB7", + HalfCyan = "B7DFF7", + HalfMagenta = "DFB7F7", + HalfBlueGreen = "89B3C9" + } + + -- plotting arguments for each defined datasource + self.definitions = { + apache_bytes = { + "DEF:min_raw={file}:count:MIN", + "DEF:avg_raw={file}:count:AVERAGE", + "DEF:max_raw={file}:count:MAX", + "CDEF:min=min_raw,8,*", + "CDEF:avg=avg_raw,8,*", + "CDEF:max=max_raw,8,*", + "CDEF:mytime=avg_raw,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*", + "CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+", + "AREA:avg#" .. self.palette.HalfBlue, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bit/s", + "GPRINT:min:MIN:%5.1lf%s Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:max:MAX:%5.1lf%s Max,", + "GPRINT:avg:LAST:%5.1lf%s Last\\l", + "GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)" + }, + + apache_requests = { + "DEF:min={file}:count:MIN", + "DEF:avg={file}:count:AVERAGE", + "DEF:max={file}:count:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Requests/s", + "GPRINT:min:MIN:%6.2lf Min,", + "GPRINT:avg:AVERAGE:%6.2lf Avg,", + "GPRINT:max:MAX:%6.2lf Max,", + "GPRINT:avg:LAST:%6.2lf Last\\l" + }, + + apache_scoreboard = { + "DEF:min={file}:count:MIN", + "DEF:avg={file}:count:AVERAGE", + "DEF:max={file}:count:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Processes", + "GPRINT:min:MIN:%6.2lf Min,", + "GPRINT:avg:AVERAGE:%6.2lf Avg,", + "GPRINT:max:MAX:%6.2lf Max,", + "GPRINT:avg:LAST:%6.2lf Last\\l" + }, + + bitrate = { + "-v", "Bits/s", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bits/s", + "GPRINT:min:MIN:%5.1lf%s Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s Average,", + "GPRINT:max:MAX:%5.1lf%s Max,", + "GPRINT:avg:LAST:%5.1lf%s Last\\l" + }, + + charge = { + "-v", "Ah", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Charge", + "GPRINT:min:MIN:%5.1lf%sAh Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sAh Avg,", + "GPRINT:max:MAX:%5.1lf%sAh Max,", + "GPRINT:avg:LAST:%5.1lf%sAh Last\\l" + }, + + current = { + "-v", "Ampere", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Current", + "GPRINT:min:MIN:%5.1lf%sA Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sA Avg,", + "GPRINT:max:MAX:%5.1lf%sA Max,", + "GPRINT:avg:LAST:%5.1lf%sA Last\\l" + }, + + disk = { + "DEF:rtime_avg={file}:rtime:AVERAGE", + "DEF:rtime_min={file}:rtime:MIN", + "DEF:rtime_max={file}:rtime:MAX", + "DEF:wtime_avg={file}:wtime:AVERAGE", + "DEF:wtime_min={file}:wtime:MIN", + "DEF:wtime_max={file}:wtime:MAX", + "CDEF:rtime_avg_ms=rtime_avg,1000,/", + "CDEF:rtime_min_ms=rtime_min,1000,/", + "CDEF:rtime_max_ms=rtime_max,1000,/", + "CDEF:wtime_avg_ms=wtime_avg,1000,/", + "CDEF:wtime_min_ms=wtime_min,1000,/", + "CDEF:wtime_max_ms=wtime_max,1000,/", + "CDEF:total_avg_ms=rtime_avg_ms,wtime_avg_ms,+", + "CDEF:total_min_ms=rtime_min_ms,wtime_min_ms,+", + "CDEF:total_max_ms=rtime_max_ms,wtime_max_ms,+", + "AREA:total_max_ms#" .. self.palette.HalfRed, + "AREA:total_min_ms#" .. self.palette.Canvas, + "LINE1:wtime_avg_ms#" .. self.palette.FullGreen .. ":Write", + "GPRINT:wtime_min_ms:MIN:%5.1lf%s Min,", + "GPRINT:wtime_avg_ms:AVERAGE:%5.1lf%s Avg,", + "GPRINT:wtime_max_ms:MAX:%5.1lf%s Max,", + "GPRINT:wtime_avg_ms:LAST:%5.1lf%s Last\n", + "LINE1:rtime_avg_ms#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:rtime_min_ms:MIN:%5.1lf%s Min,", + "GPRINT:rtime_avg_ms:AVERAGE:%5.1lf%s Avg,", + "GPRINT:rtime_max_ms:MAX:%5.1lf%s Max,", + "GPRINT:rtime_avg_ms:LAST:%5.1lf%s Last\n", + "LINE1:total_avg_ms#" .. self.palette.FullRed .. ":Total", + "GPRINT:total_min_ms:MIN:%5.1lf%s Min,", + "GPRINT:total_avg_ms:AVERAGE:%5.1lf%s Avg,", + "GPRINT:total_max_ms:MAX:%5.1lf%s Max,", + "GPRINT:total_avg_ms:LAST:%5.1lf%s Last\\l" + }, + + disk_octets = { + "-v", "Bytes/s", + "DEF:out_min={file}:write:MIN", + "DEF:out_avg={file}:write:AVERAGE", + "DEF:out_max={file}:write:MAX", + "DEF:inc_min={file}:read:MIN", + "DEF:inc_avg={file}:read:AVERAGE", + "DEF:inc_max={file}:read:MAX", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "CDEF:mytime=out_avg,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*", + "CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+", + "CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*", + "CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:out_max:MAX:%5.1lf%s Max,", + "GPRINT:out_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:inc_max:MAX:%5.1lf%s Max,", + "GPRINT:inc_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)" + }, + + disk_merged = { + "-v", "Merged Ops/s", + "DEF:out_min={file}:write:MIN", + "DEF:out_avg={file}:write:AVERAGE", + "DEF:out_max={file}:write:MAX", + "DEF:inc_min={file}:read:MIN", + "DEF:inc_avg={file}:read:AVERAGE", + "DEF:inc_max={file}:read:MAX", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:out_max:MAX:%6.2lf Max,", + "GPRINT:out_avg:LAST:%6.2lf Last\\l", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:inc_max:MAX:%6.2lf Max,", + "GPRINT:inc_avg:LAST:%6.2lf Last\\l" + }, + + disk_ops = { + "-v", "Ops/s", + "DEF:out_min={file}:write:MIN", + "DEF:out_avg={file}:write:AVERAGE", + "DEF:out_max={file}:write:MAX", + "DEF:inc_min={file}:read:MIN", + "DEF:inc_avg={file}:read:AVERAGE", + "DEF:inc_max={file}:read:MAX", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:out_max:MAX:%6.2lf Max,", + "GPRINT:out_avg:LAST:%6.2lf Last\\l", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:inc_max:MAX:%6.2lf Max,", + "GPRINT:inc_avg:LAST:%6.2lf Last\\l" + }, + + disk_time = { + "-v", "Seconds/s", + "DEF:out_min_raw={file}:write:MIN", + "DEF:out_avg_raw={file}:write:AVERAGE", + "DEF:out_max_raw={file}:write:MAX", + "DEF:inc_min_raw={file}:read:MIN", + "DEF:inc_avg_raw={file}:read:AVERAGE", + "DEF:inc_max_raw={file}:read:MAX", + "CDEF:out_min=out_min_raw,1000,/", + "CDEF:out_avg=out_avg_raw,1000,/", + "CDEF:out_max=out_max_raw,1000,/", + "CDEF:inc_min=inc_min_raw,1000,/", + "CDEF:inc_avg=inc_avg_raw,1000,/", + "CDEF:inc_max=inc_max_raw,1000,/", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%5.1lf%ss Avg,", + "GPRINT:out_max:MAX:%5.1lf%ss Max,", + "GPRINT:out_avg:LAST:%5.1lf%ss Last\\l", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%5.1lf%ss Avg,", + "GPRINT:inc_max:MAX:%5.1lf%ss Max,", + "GPRINT:inc_avg:LAST:%5.1lf%ss Last\\l" + }, + + dns_octets = { + "DEF:rsp_min_raw={file}:responses:MIN", + "DEF:rsp_avg_raw={file}:responses:AVERAGE", + "DEF:rsp_max_raw={file}:responses:MAX", + "DEF:qry_min_raw={file}:queries:MIN", + "DEF:qry_avg_raw={file}:queries:AVERAGE", + "DEF:qry_max_raw={file}:queries:MAX", + "CDEF:rsp_min=rsp_min_raw,8,*", + "CDEF:rsp_avg=rsp_avg_raw,8,*", + "CDEF:rsp_max=rsp_max_raw,8,*", + "CDEF:qry_min=qry_min_raw,8,*", + "CDEF:qry_avg=qry_avg_raw,8,*", + "CDEF:qry_max=qry_max_raw,8,*", + "CDEF:overlap=rsp_avg,qry_avg,GT,qry_avg,rsp_avg,IF", + "CDEF:mytime=rsp_avg_raw,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:rsp_avg_sample=rsp_avg_raw,UN,0,rsp_avg_raw,IF,sample_len,*", + "CDEF:rsp_avg_sum=PREV,UN,0,PREV,IF,rsp_avg_sample,+", + "CDEF:qry_avg_sample=qry_avg_raw,UN,0,qry_avg_raw,IF,sample_len,*", + "CDEF:qry_avg_sum=PREV,UN,0,PREV,IF,qry_avg_sample,+", + "AREA:rsp_avg#" .. self.palette.HalfGreen, + "AREA:qry_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:rsp_avg#" .. self.palette.FullGreen .. ":Responses", + "GPRINT:rsp_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:rsp_max:MAX:%5.1lf%s Max,", + "GPRINT:rsp_avg:LAST:%5.1lf%s Last", + "GPRINT:rsp_avg_sum:LAST:(ca. %5.1lf%sB Total)\\l", + "LINE1:qry_avg#" .. self.palette.FullBlue .. ":Queries ", + "GPRINT:qry_min:MIN:%5.1lf %s Min,", + "GPRINT:qry_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:qry_max:MAX:%5.1lf%s Max,", + "GPRINT:qry_avg:LAST:%5.1lf%s Last", + "GPRINT:qry_avg_sum:LAST:(ca. %5.1lf%sB Total)\\l" + }, + + dns_opcode = { + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Queries/s", + "GPRINT:min:MIN:%9.3lf Min,", + "GPRINT:avg:AVERAGE:%9.3lf Average,", + "GPRINT:max:MAX:%9.3lf Max,", + "GPRINT:avg:LAST:%9.3lf Last\\l" + }, + + email_count = { + "-v", "Mails", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":Count ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + email_size = { + "-v", "Bytes", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":Count ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + spam_score = { + "-v", "Score", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Score ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + spam_check = { + "DEF:avg={file}:hits:AVERAGE", + "DEF:min={file}:hits:MIN", + "DEF:max={file}:hits:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":Count ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + entropy = { + "-v", "Bits", + "DEF:avg={file}:entropy:AVERAGE", + "DEF:min={file}:entropy:MIN", + "DEF:max={file}:entropy:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bits", + "GPRINT:min:MIN:%4.0lfbit Min,", + "GPRINT:avg:AVERAGE:%4.0lfbit Avg,", + "GPRINT:max:MAX:%4.0lfbit Max,", + "GPRINT:avg:LAST:%4.0lfbit Last\\l" + }, + + fanspeed = { + "-v", "RPM", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":RPM", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + frequency = { + "-v", "Hertz", + "DEF:avg={file}:frequency:AVERAGE", + "DEF:min={file}:frequency:MIN", + "DEF:max={file}:frequency:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Frequency [Hz]", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + frequency_offset = { + "DEF:ppm_avg={file}:ppm:AVERAGE", + "DEF:ppm_min={file}:ppm:MIN", + "DEF:ppm_max={file}:ppm:MAX", + "AREA:ppm_max#" .. self.palette.HalfBlue, + "AREA:ppm_min#" .. self.palette.Canvas, + "LINE1:ppm_avg#" .. self.palette.FullBlue .. ":{inst}", + "GPRINT:ppm_min:MIN:%5.2lf Min,", + "GPRINT:ppm_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:ppm_max:MAX:%5.2lf Max,", + "GPRINT:ppm_avg:LAST:%5.2lf Last\\l" + }, + + gauge = { + "-v", "Exec value", + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "AREA:temp_max#" .. self.palette.HalfBlue, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullBlue .. ":Exec value", + "GPRINT:temp_min:MIN:%6.2lf Min,", + "GPRINT:temp_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:temp_max:MAX:%6.2lf Max,", + "GPRINT:temp_avg:LAST:%6.2lf Last\\l" + }, + + hddtemp = { + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "AREA:temp_max#" .. self.palette.HalfRed, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullRed .. ":Temperature", + "GPRINT:temp_min:MIN:%4.1lf Min,", + "GPRINT:temp_avg:AVERAGE:%4.1lf Avg,", + "GPRINT:temp_max:MAX:%4.1lf Max,", + "GPRINT:temp_avg:LAST:%4.1lf Last\\l" + }, + + humidity = { + "-v", "Percent", + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "AREA:temp_max#" .. self.palette.HalfGreen, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullGreen .. ":Temperature", + "GPRINT:temp_min:MIN:%4.1lf%% Min,", + "GPRINT:temp_avg:AVERAGE:%4.1lf%% Avg,", + "GPRINT:temp_max:MAX:%4.1lf%% Max,", + "GPRINT:temp_avg:LAST:%4.1lf%% Last\\l" + }, + + load = { + "-v", "System load", + "DEF:s_avg={file}:shortterm:AVERAGE", + "DEF:s_min={file}:shortterm:MIN", + "DEF:s_max={file}:shortterm:MAX", + "DEF:m_avg={file}:midterm:AVERAGE", + "DEF:m_min={file}:midterm:MIN", + "DEF:m_max={file}:midterm:MAX", + "DEF:l_avg={file}:longterm:AVERAGE", + "DEF:l_min={file}:longterm:MIN", + "DEF:l_max={file}:longterm:MAX", + "AREA:s_max#" .. self.palette.HalfGreen, + "AREA:s_min#" .. self.palette.Canvas, + "LINE1:s_avg#" .. self.palette.FullGreen .. ": 1m average", + "GPRINT:s_min:MIN:%4.2lf Min,", + "GPRINT:s_avg:AVERAGE:%4.2lf Avg,", + "GPRINT:s_max:MAX:%4.2lf Max,", + "GPRINT:s_avg:LAST:%4.2lf Last\n", + "LINE1:m_avg#" .. self.palette.FullBlue .. ": 5m average", + "GPRINT:m_min:MIN:%4.2lf Min,", + "GPRINT:m_avg:AVERAGE:%4.2lf Avg,", + "GPRINT:m_max:MAX:%4.2lf Max,", + "GPRINT:m_avg:LAST:%4.2lf Last\n", + "LINE1:l_avg#" .. self.palette.FullRed .. ":15m average", + "GPRINT:l_min:MIN:%4.2lf Min,", + "GPRINT:l_avg:AVERAGE:%4.2lf Avg,", + "GPRINT:l_max:MAX:%4.2lf Max,", + "GPRINT:l_avg:LAST:%4.2lf Last\\l" + }, + + load_percent = { + "DEF:avg={file}:percent:AVERAGE", + "DEF:min={file}:percent:MIN", + "DEF:max={file}:percent:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Load", + "GPRINT:min:MIN:%5.1lf%s%% Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,", + "GPRINT:max:MAX:%5.1lf%s%% Max,", + "GPRINT:avg:LAST:%5.1lf%s%% Last\\l" + }, + + mails = { + "DEF:rawgood={file}:good:AVERAGE", + "DEF:rawspam={file}:spam:AVERAGE", + "CDEF:good=rawgood,UN,0,rawgood,IF", + "CDEF:spam=rawspam,UN,0,rawspam,IF", + "CDEF:negspam=spam,-1,*", + "AREA:good#" .. self.palette.HalfGreen, + "LINE1:good#" .. self.palette.FullGreen .. ":Good mails", + "GPRINT:good:AVERAGE:%4.1lf Avg,", + "GPRINT:good:MAX:%4.1lf Max,", + "GPRINT:good:LAST:%4.1lf Last\n", + "AREA:negspam#" .. self.palette.HalfRed, + "LINE1:negspam#" .. self.palette.FullRed .. ":Spam mails", + "GPRINT:spam:AVERAGE:%4.1lf Avg,", + "GPRINT:spam:MAX:%4.1lf Max,", + "GPRINT:spam:LAST:%4.1lf Last\\l", + "HRULE:0#000000" + }, + + memory = { + "-b", "1024", "-v", "Bytes", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Memory", + "GPRINT:min:MIN:%5.1lf%sbyte Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sbyte Avg,", + "GPRINT:max:MAX:%5.1lf%sbyte Max,", + "GPRINT:avg:LAST:%5.1lf%sbyte Last\\l" + }, + + old_memory = { + "DEF:used_avg={file}:used:AVERAGE", + "DEF:free_avg={file}:free:AVERAGE", + "DEF:buffers_avg={file}:buffers:AVERAGE", + "DEF:cached_avg={file}:cached:AVERAGE", + "DEF:used_min={file}:used:MIN", + "DEF:free_min={file}:free:MIN", + "DEF:buffers_min={file}:buffers:MIN", + "DEF:cached_min={file}:cached:MIN", + "DEF:used_max={file}:used:MAX", + "DEF:free_max={file}:free:MAX", + "DEF:buffers_max={file}:buffers:MAX", + "DEF:cached_max={file}:cached:MAX", + "CDEF:cached_avg_nn=cached_avg,UN,0,cached_avg,IF", + "CDEF:buffers_avg_nn=buffers_avg,UN,0,buffers_avg,IF", + "CDEF:free_cached_buffers_used=free_avg,cached_avg_nn,+,buffers_avg_nn,+,used_avg,+", + "CDEF:cached_buffers_used=cached_avg,buffers_avg_nn,+,used_avg,+", + "CDEF:buffers_used=buffers_avg,used_avg,+", + "AREA:free_cached_buffers_used#" .. self.palette.HalfGreen, + "AREA:cached_buffers_used#" .. self.palette.HalfBlue, + "AREA:buffers_used#" .. self.palette.HalfYellow, + "AREA:used_avg#" .. self.palette.HalfRed, + "LINE1:free_cached_buffers_used#" .. self.palette.FullGreen .. ":Free ", + "GPRINT:free_min:MIN:%5.1lf%s Min,", + "GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:free_max:MAX:%5.1lf%s Max,", + "GPRINT:free_avg:LAST:%5.1lf%s Last\n", + "LINE1:cached_buffers_used#" .. self.palette.FullBlue .. ":Page cache ", + "GPRINT:cached_min:MIN:%5.1lf%s Min,", + "GPRINT:cached_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:cached_max:MAX:%5.1lf%s Max,", + "GPRINT:cached_avg:LAST:%5.1lf%s Last\n", + "LINE1:buffers_used#" .. self.palette.FullYellow .. ":Buffer cache", + "GPRINT:buffers_min:MIN:%5.1lf%s Min,", + "GPRINT:buffers_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:buffers_max:MAX:%5.1lf%s Max,", + "GPRINT:buffers_avg:LAST:%5.1lf%s Last\n", + "LINE1:used_avg#" .. self.palette.FullRed .. ":Used ", + "GPRINT:used_min:MIN:%5.1lf%s Min,", + "GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:used_max:MAX:%5.1lf%s Max,", + "GPRINT:used_avg:LAST:%5.1lf%s Last\\l" + }, + + mysql_commands = { + "-v", "Issues/s", + "DEF:val_avg={file}:value:AVERAGE", + "DEF:val_min={file}:value:MIN", + "DEF:val_max={file}:value:MAX", + "AREA:val_max#" .. self.palette.HalfBlue, + "AREA:val_min#" .. self.palette.Canvas, + "LINE1:val_avg#" .. self.palette.FullBlue .. ":Issues/s", + "GPRINT:val_min:MIN:%5.2lf Min,", + "GPRINT:val_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:val_max:MAX:%5.2lf Max,", + "GPRINT:val_avg:LAST:%5.2lf Last\\l" + }, + + mysql_handler = { + "-v", "Issues/s", + "DEF:val_avg={file}:value:AVERAGE", + "DEF:val_min={file}:value:MIN", + "DEF:val_max={file}:value:MAX", + "AREA:val_max#" .. self.palette.HalfBlue, + "AREA:val_min#" .. self.palette.Canvas, + "LINE1:val_avg#" .. self.palette.FullBlue .. ":Issues/s", + "GPRINT:val_min:MIN:%5.2lf Min,", + "GPRINT:val_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:val_max:MAX:%5.2lf Max,", + "GPRINT:val_avg:LAST:%5.2lf Last\\l" + }, + + mysql_octets = { + "-v", "Bits/s", + "DEF:out_min={file}:tx:MIN", + "DEF:out_avg={file}:tx:AVERAGE", + "DEF:out_max={file}:tx:MAX", + "DEF:inc_min={file}:rx:MIN", + "DEF:inc_avg={file}:rx:AVERAGE", + "DEF:inc_max={file}:rx:MAX", + "CDEF:mytime=out_avg,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*", + "CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+", + "CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*", + "CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+", + "CDEF:out_bit_min=out_min,8,*", + "CDEF:out_bit_avg=out_avg,8,*", + "CDEF:out_bit_max=out_max,8,*", + "CDEF:inc_bit_min=inc_min,8,*", + "CDEF:inc_bit_avg=inc_avg,8,*", + "CDEF:inc_bit_max=inc_max,8,*", + "CDEF:overlap=out_bit_avg,inc_bit_avg,GT,inc_bit_avg,out_bit_avg,IF", + "AREA:out_bit_avg#" .. self.palette.HalfGreen, + "AREA:inc_bit_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_bit_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_bit_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:out_bit_max:MAX:%5.1lf%s Max,", + "GPRINT:out_bit_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)", + "LINE1:inc_bit_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_bit_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:inc_bit_max:MAX:%5.1lf%s Max,", + "GPRINT:inc_bit_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)" + }, + + mysql_qcache = { + "-v", "Queries/s", + "DEF:hits_min={file}:hits:MIN", + "DEF:hits_avg={file}:hits:AVERAGE", + "DEF:hits_max={file}:hits:MAX", + "DEF:inserts_min={file}:inserts:MIN", + "DEF:inserts_avg={file}:inserts:AVERAGE", + "DEF:inserts_max={file}:inserts:MAX", + "DEF:not_cached_min={file}:not_cached:MIN", + "DEF:not_cached_avg={file}:not_cached:AVERAGE", + "DEF:not_cached_max={file}:not_cached:MAX", + "DEF:lowmem_prunes_min={file}:lowmem_prunes:MIN", + "DEF:lowmem_prunes_avg={file}:lowmem_prunes:AVERAGE", + "DEF:lowmem_prunes_max={file}:lowmem_prunes:MAX", + "DEF:queries_min={file}:queries_in_cache:MIN", + "DEF:queries_avg={file}:queries_in_cache:AVERAGE", + "DEF:queries_max={file}:queries_in_cache:MAX", + "CDEF:unknown=queries_avg,UNKN,+", + "CDEF:not_cached_agg=hits_avg,inserts_avg,+,not_cached_avg,+", + "CDEF:inserts_agg=hits_avg,inserts_avg,+", + "CDEF:hits_agg=hits_avg", + "AREA:not_cached_agg#" .. self.palette.HalfYellow, + "AREA:inserts_agg#" .. self.palette.HalfBlue, + "AREA:hits_agg#" .. self.palette.HalfGreen, + "LINE1:not_cached_agg#" .. self.palette.FullYellow .. ":Not Cached ", + "GPRINT:not_cached_min:MIN:%5.2lf Min,", + "GPRINT:not_cached_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:not_cached_max:MAX:%5.2lf Max,", + "GPRINT:not_cached_avg:LAST:%5.2lf Last\\l", + "LINE1:inserts_agg#" .. self.palette.FullBlue .. ":Inserts ", + "GPRINT:inserts_min:MIN:%5.2lf Min,", + "GPRINT:inserts_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:inserts_max:MAX:%5.2lf Max,", + "GPRINT:inserts_avg:LAST:%5.2lf Last\\l", + "LINE1:hits_agg#" .. self.palette.FullGreen .. ":Hits ", + "GPRINT:hits_min:MIN:%5.2lf Min,", + "GPRINT:hits_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:hits_max:MAX:%5.2lf Max,", + "GPRINT:hits_avg:LAST:%5.2lf Last\\l", + "LINE1:lowmem_prunes_avg#" .. self.palette.FullRed .. ":Lowmem Prunes ", + "GPRINT:lowmem_prunes_min:MIN:%5.2lf Min,", + "GPRINT:lowmem_prunes_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:lowmem_prunes_max:MAX:%5.2lf Max,", + "GPRINT:lowmem_prunes_avg:LAST:%5.2lf Last\\l", + "LINE1:unknown#" .. self.palette.Canvas .. ":Queries in cache", + "GPRINT:queries_min:MIN:%5.0lf Min,", + "GPRINT:queries_avg:AVERAGE:%5.0lf Avg,", + "GPRINT:queries_max:MAX:%5.0lf Max,", + "GPRINT:queries_avg:LAST:%5.0lf Last\\l" + }, + + mysql_threads = { + "-v", "Threads", + "DEF:running_min={file}:running:MIN", + "DEF:running_avg={file}:running:AVERAGE", + "DEF:running_max={file}:running:MAX", + "DEF:connected_min={file}:connected:MIN", + "DEF:connected_avg={file}:connected:AVERAGE", + "DEF:connected_max={file}:connected:MAX", + "DEF:cached_min={file}:cached:MIN", + "DEF:cached_avg={file}:cached:AVERAGE", + "DEF:cached_max={file}:cached:MAX", + "DEF:created_min={file}:created:MIN", + "DEF:created_avg={file}:created:AVERAGE", + "DEF:created_max={file}:created:MAX", + "CDEF:unknown=created_avg,UNKN,+", + "CDEF:cached_agg=connected_avg,cached_avg,+", + "AREA:cached_agg#" .. self.palette.HalfGreen, + "AREA:connected_avg#" .. self.palette.HalfBlue, + "AREA:running_avg#" .. self.palette.HalfRed, + "LINE1:cached_agg#" .. self.palette.FullGreen .. ":Cached ", + "GPRINT:cached_min:MIN:%5.1lf Min,", + "GPRINT:cached_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:cached_max:MAX:%5.1lf Max,", + "GPRINT:cached_avg:LAST:%5.1lf Last\\l", + "LINE1:connected_avg#" .. self.palette.FullBlue .. ":Connected", + "GPRINT:connected_min:MIN:%5.1lf Min,", + "GPRINT:connected_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:connected_max:MAX:%5.1lf Max,", + "GPRINT:connected_avg:LAST:%5.1lf Last\\l", + "LINE1:running_avg#" .. self.palette.FullRed .. ":Running ", + "GPRINT:running_min:MIN:%5.1lf Min,", + "GPRINT:running_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:running_max:MAX:%5.1lf Max,", + "GPRINT:running_avg:LAST:%5.1lf Last\\l", + "LINE1:unknown#" .. self.palette.Canvas .. ":Created ", + "GPRINT:created_min:MIN:%5.0lf Min,", + "GPRINT:created_avg:AVERAGE:%5.0lf Avg,", + "GPRINT:created_max:MAX:%5.0lf Max,", + "GPRINT:created_avg:LAST:%5.0lf Last\\l" + }, + + nfs_procedure = { + "-v", "Issues/s", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Issues/s", + "GPRINT:min:MIN:%6.2lf Min,", + "GPRINT:avg:AVERAGE:%6.2lf Avg,", + "GPRINT:max:MAX:%6.2lf Max,", + "GPRINT:avg:LAST:%6.2lf Last\\l" + }, + + nfs3_procedures = { + "DEF:null_avg={file}:null:AVERAGE", + "DEF:getattr_avg={file}:getattr:AVERAGE", + "DEF:setattr_avg={file}:setattr:AVERAGE", + "DEF:lookup_avg={file}:lookup:AVERAGE", + "DEF:access_avg={file}:access:AVERAGE", + "DEF:readlink_avg={file}:readlink:AVERAGE", + "DEF:read_avg={file}:read:AVERAGE", + "DEF:write_avg={file}:write:AVERAGE", + "DEF:create_avg={file}:create:AVERAGE", + "DEF:mkdir_avg={file}:mkdir:AVERAGE", + "DEF:symlink_avg={file}:symlink:AVERAGE", + "DEF:mknod_avg={file}:mknod:AVERAGE", + "DEF:remove_avg={file}:remove:AVERAGE", + "DEF:rmdir_avg={file}:rmdir:AVERAGE", + "DEF:rename_avg={file}:rename:AVERAGE", + "DEF:link_avg={file}:link:AVERAGE", + "DEF:readdir_avg={file}:readdir:AVERAGE", + "DEF:readdirplus_avg={file}:readdirplus:AVERAGE", + "DEF:fsstat_avg={file}:fsstat:AVERAGE", + "DEF:fsinfo_avg={file}:fsinfo:AVERAGE", + "DEF:pathconf_avg={file}:pathconf:AVERAGE", + "DEF:commit_avg={file}:commit:AVERAGE", + "DEF:null_max={file}:null:MAX", + "DEF:getattr_max={file}:getattr:MAX", + "DEF:setattr_max={file}:setattr:MAX", + "DEF:lookup_max={file}:lookup:MAX", + "DEF:access_max={file}:access:MAX", + "DEF:readlink_max={file}:readlink:MAX", + "DEF:read_max={file}:read:MAX", + "DEF:write_max={file}:write:MAX", + "DEF:create_max={file}:create:MAX", + "DEF:mkdir_max={file}:mkdir:MAX", + "DEF:symlink_max={file}:symlink:MAX", + "DEF:mknod_max={file}:mknod:MAX", + "DEF:remove_max={file}:remove:MAX", + "DEF:rmdir_max={file}:rmdir:MAX", + "DEF:rename_max={file}:rename:MAX", + "DEF:link_max={file}:link:MAX", + "DEF:readdir_max={file}:readdir:MAX", + "DEF:readdirplus_max={file}:readdirplus:MAX", + "DEF:fsstat_max={file}:fsstat:MAX", + "DEF:fsinfo_max={file}:fsinfo:MAX", + "DEF:pathconf_max={file}:pathconf:MAX", + "DEF:commit_max={file}:commit:MAX", + "CDEF:other_avg=null_avg,readlink_avg,create_avg,mkdir_avg,symlink_avg,mknod_avg,remove_avg,rmdir_avg,rename_avg,link_avg,readdir_avg,readdirplus_avg,fsstat_avg,fsinfo_avg,pathconf_avg,+,+,+,+,+,+,+,+,+,+,+,+,+,+", + "CDEF:other_max=null_max,readlink_max,create_max,mkdir_max,symlink_max,mknod_max,remove_max,rmdir_max,rename_max,link_max,readdir_max,readdirplus_max,fsstat_max,fsinfo_max,pathconf_max,+,+,+,+,+,+,+,+,+,+,+,+,+,+", + "CDEF:stack_read=read_avg", + "CDEF:stack_getattr=stack_read,getattr_avg,+", + "CDEF:stack_access=stack_getattr,access_avg,+", + "CDEF:stack_lookup=stack_access,lookup_avg,+", + "CDEF:stack_write=stack_lookup,write_avg,+", + "CDEF:stack_commit=stack_write,commit_avg,+", + "CDEF:stack_setattr=stack_commit,setattr_avg,+", + "CDEF:stack_other=stack_setattr,other_avg,+", + "AREA:stack_other#" .. self.palette.HalfRed, + "AREA:stack_setattr#" .. self.palette.HalfGreen, + "AREA:stack_commit#" .. self.palette.HalfYellow, + "AREA:stack_write#" .. self.palette.HalfGreen, + "AREA:stack_lookup#" .. self.palette.HalfBlue, + "AREA:stack_access#" .. self.palette.HalfMagenta, + "AREA:stack_getattr#" .. self.palette.HalfCyan, + "AREA:stack_read#" .. self.palette.HalfBlue, + "LINE1:stack_other#" .. self.palette.FullRed .. ":Other ", + "GPRINT:other_max:MAX:%5.1lf Max,", + "GPRINT:other_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:other_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_setattr#" .. self.palette.FullGreen .. ":setattr", + "GPRINT:setattr_max:MAX:%5.1lf Max,", + "GPRINT:setattr_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:setattr_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_commit#" .. self.palette.FullYellow .. ":commit ", + "GPRINT:commit_max:MAX:%5.1lf Max,", + "GPRINT:commit_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:commit_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_write#" .. self.palette.FullGreen .. ":write ", + "GPRINT:write_max:MAX:%5.1lf Max,", + "GPRINT:write_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:write_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_lookup#" .. self.palette.FullBlue .. ":lookup ", + "GPRINT:lookup_max:MAX:%5.1lf Max,", + "GPRINT:lookup_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:lookup_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_access#" .. self.palette.FullMagenta .. ":access ", + "GPRINT:access_max:MAX:%5.1lf Max,", + "GPRINT:access_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:access_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_getattr#" .. self.palette.FullCyan .. ":getattr", + "GPRINT:getattr_max:MAX:%5.1lf Max,", + "GPRINT:getattr_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:getattr_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_read#" .. self.palette.FullBlue .. ":read ", + "GPRINT:read_max:MAX:%5.1lf Max,", + "GPRINT:read_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:read_avg:LAST:%5.1lf Last\\l" + }, + + partition = { + "DEF:rbyte_avg={file}:rbytes:AVERAGE", + "DEF:rbyte_min={file}:rbytes:MIN", + "DEF:rbyte_max={file}:rbytes:MAX", + "DEF:wbyte_avg={file}:wbytes:AVERAGE", + "DEF:wbyte_min={file}:wbytes:MIN", + "DEF:wbyte_max={file}:wbytes:MAX", + "CDEF:overlap=wbyte_avg,rbyte_avg,GT,rbyte_avg,wbyte_avg,IF", + "AREA:wbyte_avg#" .. self.palette.HalfGreen, + "AREA:rbyte_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:wbyte_avg#" .. self.palette.FullGreen .. ":Write", + "GPRINT:wbyte_min:MIN:%5.1lf%s Min,", + "GPRINT:wbyte_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:wbyte_max:MAX:%5.1lf%s Max,", + "GPRINT:wbyte_avg:LAST:%5.1lf%s Last\\l", + "LINE1:rbyte_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:rbyte_min:MIN:%5.1lf%s Min,", + "GPRINT:rbyte_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:rbyte_max:MAX:%5.1lf%s Max,", + "GPRINT:rbyte_avg:LAST:%5.1lf%s Last\\l" + }, + + percent = { + "-v", "Percent", + "DEF:avg={file}:percent:AVERAGE", + "DEF:min={file}:percent:MIN", + "DEF:max={file}:percent:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Percent", + "GPRINT:min:MIN:%5.1lf%% Min,", + "GPRINT:avg:AVERAGE:%5.1lf%% Avg,", + "GPRINT:max:MAX:%5.1lf%% Max,", + "GPRINT:avg:LAST:%5.1lf%% Last\\l" + }, + + power = { + "-v", "Watt", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Watt", + "GPRINT:min:MIN:%5.1lf%sW Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sW Avg,", + "GPRINT:max:MAX:%5.1lf%sW Max,", + "GPRINT:avg:LAST:%5.1lf%sW Last\\l" + }, + + swap = { + "-v", "Bytes", "-b", "1024", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bytes", + "GPRINT:min:MIN:%6.2lf%sByte Min,", + "GPRINT:avg:AVERAGE:%6.2lf%sByte Avg,", + "GPRINT:max:MAX:%6.2lf%sByte Max,", + "GPRINT:avg:LAST:%6.2lf%sByte Last\\l" + }, + + old_swap = { + "DEF:used_avg={file}:used:AVERAGE", + "DEF:used_min={file}:used:MIN", + "DEF:used_max={file}:used:MAX", + "DEF:free_avg={file}:free:AVERAGE", + "DEF:free_min={file}:free:MIN", + "DEF:free_max={file}:free:MAX", + "DEF:cach_avg={file}:cached:AVERAGE", + "DEF:cach_min={file}:cached:MIN", + "DEF:cach_max={file}:cached:MAX", + "DEF:resv_avg={file}:resv:AVERAGE", + "DEF:resv_min={file}:resv:MIN", + "DEF:resv_max={file}:resv:MAX", + "CDEF:cach_avg_notnull=cach_avg,UN,0,cach_avg,IF", + "CDEF:resv_avg_notnull=resv_avg,UN,0,resv_avg,IF", + "CDEF:used_acc=used_avg", + "CDEF:resv_acc=used_acc,resv_avg_notnull,+", + "CDEF:cach_acc=resv_acc,cach_avg_notnull,+", + "CDEF:free_acc=cach_acc,free_avg,+", + "AREA:free_acc#" .. self.palette.HalfGreen, + "AREA:cach_acc#" .. self.palette.HalfBlue, + "AREA:resv_acc#" .. self.palette.HalfYellow, + "AREA:used_acc#" .. self.palette.HalfRed, + "LINE1:free_acc#" .. self.palette.FullGreen .. ":Free ", + "GPRINT:free_min:MIN:%5.1lf%s Min,", + "GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:free_max:MAX:%5.1lf%s Max,", + "GPRINT:free_avg:LAST:%5.1lf%s Last\n", + "LINE1:cach_acc#" .. self.palette.FullBlue .. ":Cached ", + "GPRINT:cach_min:MIN:%5.1lf%s Min,", + "GPRINT:cach_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:cach_max:MAX:%5.1lf%s Max,", + "GPRINT:cach_avg:LAST:%5.1lf%s Last\\l", + "LINE1:resv_acc#" .. self.palette.FullYellow .. ":Reserved", + "GPRINT:resv_min:MIN:%5.1lf%s Min,", + "GPRINT:resv_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:resv_max:MAX:%5.1lf%s Max,", + "GPRINT:resv_avg:LAST:%5.1lf%s Last\n", + "LINE1:used_acc#" .. self.palette.FullRed .. ":Used ", + "GPRINT:used_min:MIN:%5.1lf%s Min,", + "GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:used_max:MAX:%5.1lf%s Max,", + "GPRINT:used_avg:LAST:%5.1lf%s Last\\l" + }, + + tcp_connections = { + "-v", "Connections", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Connections", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + temperature = { + "-v", "Celsius", + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "CDEF:average=temp_avg,0.2,*,PREV,UN,temp_avg,PREV,IF,0.8,*,+", + "AREA:temp_max#" .. self.palette.HalfRed, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullRed .. ":Temperature", + "GPRINT:temp_min:MIN:%4.1lf Min,", + "GPRINT:temp_avg:AVERAGE:%4.1lf Avg,", + "GPRINT:temp_max:MAX:%4.1lf Max,", + "GPRINT:temp_avg:LAST:%4.1lf Last\\l" + }, + + timeleft = { + "-v", "Minutes", + "DEF:avg={file}:timeleft:AVERAGE", + "DEF:min={file}:timeleft:MIN", + "DEF:max={file}:timeleft:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Time left [min]", + "GPRINT:min:MIN:%5.1lf%s Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:max:MAX:%5.1lf%s Max,", + "GPRINT:avg:LAST:%5.1lf%s Last\\l" + }, + + time_offset = { + "DEF:s_avg={file}:seconds:AVERAGE", + "DEF:s_min={file}:seconds:MIN", + "DEF:s_max={file}:seconds:MAX", + "AREA:s_max#" .. self.palette.HalfBlue, + "AREA:s_min#" .. self.palette.Canvas, + "LINE1:s_avg#" .. self.palette.FullBlue .. ":{inst}", + "GPRINT:s_min:MIN:%7.3lf%s Min,", + "GPRINT:s_avg:AVERAGE:%7.3lf%s Avg,", + "GPRINT:s_max:MAX:%7.3lf%s Max,", + "GPRINT:s_avg:LAST:%7.3lf%s Last\\l" + }, + + cpufreq = { + "DEF:cpufreq_avg={file}:value:AVERAGE", + "DEF:cpufreq_min={file}:value:MIN", + "DEF:cpufreq_max={file}:value:MAX", + "AREA:cpufreq_max#" .. self.palette.HalfBlue, + "AREA:cpufreq_min#" .. self.palette.Canvas, + "LINE1:cpufreq_avg#" .. self.palette.FullBlue .. ":Frequency", + "GPRINT:cpufreq_min:MIN:%5.1lf%s Min,", + "GPRINT:cpufreq_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:cpufreq_max:MAX:%5.1lf%s Max,", + "GPRINT:cpufreq_avg:LAST:%5.1lf%s Last\\l" + }, + + multimeter = { + "DEF:multimeter_avg={file}:value:AVERAGE", + "DEF:multimeter_min={file}:value:MIN", + "DEF:multimeter_max={file}:value:MAX", + "AREA:multimeter_max#" .. self.palette.HalfBlue, + "AREA:multimeter_min#" .. self.palette.Canvas, + "LINE1:multimeter_avg#" .. self.palette.FullBlue .. ":Multimeter", + "GPRINT:multimeter_min:MIN:%4.1lf Min,", + "GPRINT:multimeter_avg:AVERAGE:%4.1lf Average,", + "GPRINT:multimeter_max:MAX:%4.1lf Max,", + "GPRINT:multimeter_avg:LAST:%4.1lf Last\\l" + }, + + users = { + "-v", "Users", + "DEF:users_avg={file}:users:AVERAGE", + "DEF:users_min={file}:users:MIN", + "DEF:users_max={file}:users:MAX", + "AREA:users_max#" .. self.palette.HalfBlue, + "AREA:users_min#" .. self.palette.Canvas, + "LINE1:users_avg#" .. self.palette.FullBlue .. ":Users", + "GPRINT:users_min:MIN:%4.1lf Min,", + "GPRINT:users_avg:AVERAGE:%4.1lf Average,", + "GPRINT:users_max:MAX:%4.1lf Max,", + "GPRINT:users_avg:LAST:%4.1lf Last\\l" + }, + + voltage = { + "-v", "Voltage", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Voltage", + "GPRINT:min:MIN:%5.1lf%sV Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sV Avg,", + "GPRINT:max:MAX:%5.1lf%sV Max,", + "GPRINT:avg:LAST:%5.1lf%sV Last\\l" + }, + + vs_threads = { + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Threads", + "GPRINT:min:MIN:%5.1lf Min,", + "GPRINT:avg:AVERAGE:%5.1lf Avg.,", + "GPRINT:max:MAX:%5.1lf Max,", + "GPRINT:avg:LAST:%5.1lf Last\\l", + }, + + vs_memory = { + "-b", "1024", "-v", "Bytes", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":", + "GPRINT:min:MIN:%5.1lf%sbytes Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sbytes Avg.,", + "GPRINT:max:MAX:%5.1lf%sbytes Max,", + "GPRINT:avg:LAST:%5.1lf%sbytes Last\\l", + }, + + vs_processes = { + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Processes", + "GPRINT:min:MIN:%5.1lf Min,", + "GPRINT:avg:AVERAGE:%5.1lf Avg.,", + "GPRINT:max:MAX:%5.1lf Max,", + "GPRINT:avg:LAST:%5.1lf Last\\l", + }, + } +end + diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/cpu/cpu.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/cpu/cpu.lua new file mode 100644 index 0000000..aca3fb7 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/cpu/cpu.lua @@ -0,0 +1,38 @@ +--[[ + +Luci statistics - cpu plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: cpu.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.cpu.cpu",package.seeall) + +function rrdargs( graph, host, plugin, plugin_instance, dtype ) + + return { + data = { + instances = { + cpu = { "idle", "user", "system", "nice" } + }, + + options = { + cpu_idle = { color = "ffffff" }, + cpu_nice = { color = "00e000" }, + cpu_user = { color = "0000ff" }, + cpu_wait = { color = "ffb000" }, + cpu_system = { color = "ff0000" }, + cpu_softirq = { color = "ff00ff" }, + cpu_interrupt = { color = "a000a0" }, + cpu_steal = { color = "000000" } + } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/df/df.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/df/df.lua new file mode 100644 index 0000000..4fd630d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/df/df.lua @@ -0,0 +1,41 @@ +--[[ + +Luci statistics - df plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: df.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.df.df", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + per_instance = true, + number_format = "%5.1lf%s", + + data = { + sources = { + df = { "free", "used" } + }, + + options = { + df__free = { + color = "00ff00" + }, + + df__used = { + color = "ff0000", + flip = true + } + } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/interface.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/interface.lua new file mode 100644 index 0000000..fff8e81 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/interface.lua @@ -0,0 +1,107 @@ +--[[ + +Luci statistics - interface plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: interface.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.interface", package.seeall) + +function rrdargs( graph, host, plugin, plugin_instance ) + + -- + -- traffic diagram + -- + local traffic = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + -- defined sources for data types, if ommitted assume a single DS named "value" (optional) + sources = { + if_octets = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + if_octets__tx = { + total = true, -- report total amount of bytes + color = "00ff00" -- tx is green + }, + + if_octets__rx = { + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- rx is blue + } + } + } + } + + + -- + -- packet diagram + -- + local packets = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + -- data type order + types = { "if_packets", "if_errors" }, + + -- defined sources for data types + sources = { + if_packets = { "tx", "rx" }, + if_errors = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + -- processed packets (tx DS) + if_packets__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of bytes + color = "00ff00" -- processed tx is green + }, + + -- processed packets (rx DS) + if_packets__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- processed rx is blue + }, + + -- packet errors (tx DS) + if_errors__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of packets + color = "ff5500" -- tx errors are orange + }, + + -- packet errors (rx DS) + if_errors__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of packets + color = "ff0000" -- rx errors are red + } + } + } + } + + return { traffic, packets } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_bytes.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_bytes.lua new file mode 100644 index 0000000..c3c2bb9 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_bytes.lua @@ -0,0 +1,27 @@ +--[[ + +Luci statistics - iptables plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ipt_bytes.lua 2276 2008-06-03 23:18:37Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.iptables.ipt_bytes", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + options = { + ipt_bytes = { total = true } + } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_packets.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_packets.lua new file mode 100644 index 0000000..698464a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/iptables/ipt_packets.lua @@ -0,0 +1,27 @@ +--[[ + +Luci statistics - iptables plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ipt_packets.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.iptables.ipt_packets", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + options = { + ipt_packets = { total = true } + } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/irq/irq.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/irq/irq.lua new file mode 100644 index 0000000..65ed1e6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/irq/irq.lua @@ -0,0 +1,25 @@ +--[[ + +Luci statistics - irq plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: irq.lua 2276 2008-06-03 23:18:37Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.irq.irq", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + types = { "irq" } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/load/load.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/load/load.lua new file mode 100644 index 0000000..0c1eb2b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/load/load.lua @@ -0,0 +1,33 @@ +--[[ + +Luci statistics - load plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: load.lua 2329 2008-06-08 21:51:55Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.load.load", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + sources = { + load = { "shortterm", "midterm", "longterm" } + }, + + options = { + load__shortterm = { color = "ff0000" }, + load__midterm = { color = "ff6600" }, + load__longterm = { color = "ffaa00" } + } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/netlink.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/netlink.lua new file mode 100644 index 0000000..a46f7cc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/netlink.lua @@ -0,0 +1,193 @@ +--[[ + +Luci statistics - netlink plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: netlink.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.netlink", package.seeall) + +function rrdargs( graph, plugin, plugin_instance ) + + -- + -- traffic diagram + -- + local traffic = { + + -- diagram data description + data = { + -- defined sources for data types, if ommitted assume a single DS named "value" (optional) + sources = { + if_octets = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + if_octets__tx = { + total = true, -- report total amount of bytes + color = "00ff00" -- tx is green + }, + + if_octets__rx = { + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- rx is blue + } + } + } + } + + + -- + -- packet diagram + -- + local packets = { + + -- diagram data description + data = { + -- data type order + types = { "if_packets", "if_dropped", "if_errors" }, + + -- defined sources for data types + sources = { + if_packets = { "tx", "rx" }, + if_dropped = { "tx", "rx" }, + if_errors = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + -- processed packets (tx DS) + if_packets__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of bytes + color = "00ff00" -- processed tx is green + }, + + -- processed packets (rx DS) + if_packets__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- processed rx is blue + }, + + -- dropped packets (tx DS) + if_dropped__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of bytes + color = "660055" -- dropped tx is ... dunno ;) + }, + + -- dropped packets (rx DS) + if_dropped__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "440066" -- dropped rx is violett + }, + + -- packet errors (tx DS) + if_errors__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of packets + color = "ff5500" -- tx errors are orange + }, + + -- packet errors (rx DS) + if_errors__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of packets + color = "ff0000" -- rx errors are red + } + } + } + } + + + -- + -- multicast diagram + -- + local multicast = { + + -- diagram data description + data = { + -- data type order + types = { "if_multicast" }, + + -- special options for single data lines + options = { + -- multicast packets + if_multicast = { + total = true, -- report total amount of packets + color = "0000ff" -- multicast is blue + } + } + } + } + + + -- + -- collision diagram + -- + local collisions = { + + -- diagram data description + data = { + -- data type order + types = { "if_collisions" }, + + -- special options for single data lines + options = { + -- collision rate + if_collisions = { + total = true, -- report total amount of packets + color = "ff0000" -- collsions are red + } + } + } + } + + + -- + -- error diagram + -- + local errors = { + + -- diagram data description + data = { + -- data type order + types = { "if_tx_errors", "if_rx_errors" }, + + -- data type instances + instances = { + if_tx_errors = { "aborted", "carrier", "fifo", "heartbeat", "window" }, + if_rx_errors = { "length", "missed", "over", "crc", "fifo", "frame" } + }, + + -- special options for single data lines + options = { -- XXX: fixme (define colors...) + if_tx_errors = { + total = true + }, + + if_rx_errors = { + flip = true, + total = true + } + } + } + } + + + return { traffic, packets, multicast, collisions, errors } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/ping/ping.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/ping/ping.lua new file mode 100644 index 0000000..a094737 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/ping/ping.lua @@ -0,0 +1,27 @@ +--[[ + +Luci statistics - ping plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ping.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.ping.ping", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + sources = { + ping = { "ping" } + } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/processes.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/processes.lua new file mode 100644 index 0000000..fc01ca5 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/processes.lua @@ -0,0 +1,101 @@ +--[[ + +Luci statistics - processes plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: processes.lua 2276 2008-06-03 23:18:37Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.processes", package.seeall) + +function rrdargs( graph, plugin, plugin_instance ) + + if plugin_instance == "" then + return { + data = { + instances = { + ps_state = { + "sleeping", "running", "paging", "blocked", "stopped", "zombies" + } + }, + + options = { + ps_state_sleeping = { color = "0000ff" }, + ps_state_running = { color = "008000" }, + ps_state_paging = { color = "ffff00" }, + ps_state_blocked = { color = "ff5000" }, + ps_state_stopped = { color = "555555" }, + ps_state_zombies = { color = "ff0000" } + } + } + } + else + return { + + { + data = { + sources = { + ps_cputime = { "syst", "user" } + }, + + options = { + ps_cputime__user = { + color = "0000ff", + overlay = true + }, + + ps_cputime__syst = { + color = "ff0000", + overlay = true + } + } + } + }, + + { + data = { + sources = { + ps_count = { "threads", "processes" } + }, + + options = { + ps_count__threads = { color = "00ff00" }, + ps_count__processes = { color = "0000bb" } + } + } + }, + + { + data = { + sources = { + ps_pagefaults = { "minflt", "majflt" } + }, + + options = { + ps_pagefaults__minflt = { color = "ff0000" }, + ps_pagefaults__majflt = { color = "ff5500" } + } + } + }, + + { + number_format = "%5.1lf%s", + + data = { + types = { "ps_rss" }, + + options = { + ps_rss = { color = "0000ff" } + } + } + } + } + end +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua new file mode 100644 index 0000000..9d94dd7 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua @@ -0,0 +1,31 @@ +--[[ + +Luci statistics - tcpconns plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: tcp_connections.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.tcpconns.tcp_connections", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + instances = { + tcp_connections = { + "SYN_SENT", "SYN_RECV", "LISTEN", "ESTABLISHED", + "LAST_ACK", "TIME_WAIT", "CLOSING", "CLOSE_WAIT", + "CLOSED", "FIN_WAIT1", "FIN_WAIT2" + } + } + } + } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/wireless.lua b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/wireless.lua new file mode 100644 index 0000000..867eabd --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/statistics/rrdtool/definitions/wireless.lua @@ -0,0 +1,71 @@ +--[[ + +Luci statistics - wireless plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: wireless.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.wireless", package.seeall) + +function rrdargs( graph, host, plugin, plugin_instance ) + + -- + -- signal/noise diagram + -- + local snr = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + types = { "signal_noise", "signal_power" }, + + -- special options for single data lines + options = { + signal_power = { + overlay = true, -- don't summarize + color = "0000ff" -- power is blue + }, + + signal_noise = { + overlay = true, -- don't summarize + color = "ff0000" -- noise is red + } + } + } + } + + + -- + -- signal quality diagram + -- + local quality = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + types = { "signal_quality" }, + + -- special options for single data lines + options = { + signal_quality = { + noarea = true, -- don't draw area + color = "0000ff" -- quality is blue + } + } + } + } + + return { snr, quality } +end diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/index.htm b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/index.htm new file mode 100644 index 0000000..3225753 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/index.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> + +

<%:stat_statistics Statistics%>

+ +

<%:stat_desc The statistics package is based on Collectd +and uses RRD Tool to render diagram images from collected data.%>

+ +<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/networkplugins.htm b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/networkplugins.htm new file mode 100644 index 0000000..0c7b448 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/networkplugins.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: networkplugins.htm 3987 2009-01-02 21:35:25Z Cyrus $ + +-%> +<%+header%> + +

<%:stat_networkplugins Network plugins%>

+ +

<%:stat_networkplugins_desc Network plugins are used to collect information +about open tcp connections, interface traffic, iptables rules etc.%>

+ +

<%:stat_networkplugins_installed Installed network plugins:%> +

    + <% for plugin, desc in pairs(plugins) do %> + <% if luci.fs.access("/usr/lib/collectd/" .. plugin .. ".so") then %> +
  • <%=desc%>
  • + <% end %> + <% end %> +
+

+ +<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/outputplugins.htm b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/outputplugins.htm new file mode 100644 index 0000000..18f7103 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/outputplugins.htm @@ -0,0 +1,33 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: outputplugins.htm 3987 2009-01-02 21:35:25Z Cyrus $ + +-%> +<%+header%> + +

<%:stat_outputplugins Output plugins%>

+ +

<%:stat_outputplugins_desc Output plugins provide different possibilities to store collected data. +It is possible to enable multiple plugin at one, for example to store collected data in rrd databases +and to transmit the data over the network to other collectd instances.%>

+ +

<%:stat_outputplugins_installed Installed output plugins:%> +

    + <% for plugin, desc in pairs(plugins) do %> + <% if luci.fs.access("/usr/lib/collectd/" .. plugin .. ".so") then %> +
  • <%=desc%>
  • + <% end %> + <% end %> +
+

+ +<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/systemplugins.htm b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/systemplugins.htm new file mode 100644 index 0000000..547a9fc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/admin_statistics/systemplugins.htm @@ -0,0 +1,29 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: systemplugins.htm 3987 2009-01-02 21:35:25Z Cyrus $ + +-%> +<%+header%> + +

<%:stat_systemplugins System plugins%>

+ +

<%:stat_systemplugins_desc System plugins collecting values about system state and ressource usage on the device.:%> +

    + <% for plugin, desc in pairs(plugins) do %> + <% if luci.fs.access("/usr/lib/collectd/" .. plugin .. ".so") then %> +
  • <%=desc%>
  • + <% end %> + <% end %> +
+

+ +<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-statistics/luasrc/view/public_statistics/graph.htm b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/public_statistics/graph.htm new file mode 100644 index 0000000..83a8b61 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/luasrc/view/public_statistics/graph.htm @@ -0,0 +1,39 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: graph.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> + +

<%:stat_statistics Statistics%>

+ +
+ + +
+ +
+
+
+ +
+ <% for i, img in ipairs(images) do %> + +
+ <% end %> +
+ +<%+footer%> diff --git a/openwrt/packages/luci/applications/luci-statistics/root/etc/config/luci_statistics b/openwrt/packages/luci/applications/luci-statistics/root/etc/config/luci_statistics new file mode 100644 index 0000000..f6d870e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/root/etc/config/luci_statistics @@ -0,0 +1,132 @@ +config 'statistics' 'rrdtool' + option 'default_timespan' '1hour' + option 'image_width' '400' + option 'image_path' '/tmp/rrdimg' + +config 'statistics' 'collectd' + option 'BaseDir' '/var/run/collectd' + option 'Include' '/etc/collectd/conf.d' + option 'PIDFile' '/var/run/collectd.pid' + option 'PluginDir' '/usr/lib/collectd' + option 'TypesDB' '/usr/lib/collectd/types.db' + option 'Interval' '30' + option 'ReadThreads' '2' + +config 'statistics' 'collectd_ping' + option 'enable' '0' + option 'TTL' '127' + option 'Hosts' '127.0.0.1' + +config 'statistics' 'collectd_csv' + option 'enable' '0' + option 'StoreRates' '0' + option 'DataDir' '/tmp' + +config 'statistics' 'collectd_df' + option 'enable' '0' + option 'Devices' '/dev/mtdblock/4' + option 'MountPoints' '/jffs' + option 'FSTypes' 'tmpfs' + option 'IgnoreSelected' '0' + +config 'statistics' 'collectd_disk' + option 'enable' '0' + option 'Disks' 'hda1 hdb' + option 'IgnoreSelected' '0' + +config 'statistics' 'collectd_dns' + option 'enable' '0' + option 'Interfaces' 'ffdhcp ff br-lan' + option 'IgnoreSources' '127.0.0.1' + +config 'statistics' 'collectd_email' + option 'enable' '0' + option 'SocketFile' '/var/run/collectd/email.sock' + option 'SocketGroup' 'nogroup' + +config 'statistics' 'collectd_exec' + option 'enable' '1' + +config 'collectd_exec_input' + option 'cmdline' '/usr/bin/stat-input-olsr' + +config 'collectd_exec_notify' + option 'cmdline' '/usr/bin/stat-output-syslog' + +config 'statistics' 'collectd_interface' + option 'enable' '1' + option 'Interfaces' 'br-lan br-ff' + option 'IgnoreSelected' '0' + +config 'statistics' 'collectd_iptables' + option 'enable' '1' + +config 'collectd_iptables_match' + option 'table' 'nat' + option 'chain' 'luci_fw_postrouting' + option 'target' 'MASQUERADE' + option 'source' '192.168.1.0/24' + option 'outputif' 'br-ff' + option 'name' 'Verkehr LAN-Clients' + +config 'collectd_iptables_match' + option 'chain' 'luci_fw_postrouting' + option 'table' 'nat' + option 'target' 'MASQUERADE' + option 'source' '10.61.230.0/24' + option 'outputif' 'br-ff' + option 'name' 'Verkehr WLAN-Clients' + +config 'statistics' 'collectd_irq' + option 'enable' '0' + option 'Irqs' '2 3 4 7' + +config 'statistics' 'collectd_load' + option 'enable' '1' + +config 'statistics' 'collectd_logfile' + option 'enable' '0' + option 'LogLevel' 'notice' + option 'File' '/var/log/collectd.log' + option 'Timestamp' '1' + +config 'statistics' 'collectd_netlink' + option 'enable' '0' + option 'IgnoreSelected' '0' + option 'VerboseInterfaces' 'br-lan br-ff' + option 'QDiscs' 'br-lan br-ff' + +config 'statistics' 'collectd_network' + option 'enable' '0' + +config 'collectd_network_listen' + option 'host' '0.0.0.0' + +config 'collectd_network_server' + option 'host' '0.0.0.0' + +config 'statistics' 'collectd_processes' + option 'enable' '1' + +config 'statistics' 'collectd_tcpconns' + option 'enable' '1' + option 'ListeningPorts' '0' + option 'LocalPorts' '22 80' + +config 'statistics' 'collectd_unixsock' + option 'enable' '0' + option 'SocketFile' '/var/run/collectd/query.sock' + option 'SocketGroup' 'nogroup' + +config 'statistics' 'collectd_wireless' + option 'enable' '1' + +config 'statistics' 'collectd_cpu' + option 'enable' '1' + +config 'statistics' 'collectd_rrdtool' + option 'enable' '1' + option 'DataDir' '/tmp' + option 'RRARows' '100' + option 'RRASingle' '1' + option 'RRATimespans' '10min 1hour 1day 1week 1month 1year' diff --git a/openwrt/packages/luci/applications/luci-statistics/root/etc/init.d/luci_statistics b/openwrt/packages/luci/applications/luci-statistics/root/etc/init.d/luci_statistics new file mode 100755 index 0000000..e4da1d5 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/root/etc/init.d/luci_statistics @@ -0,0 +1,31 @@ +#!/bin/sh /etc/rc.common +START=79 + +start() { + ### replace shipped config with symlink + if [ ! -L /etc/collectd.conf ]; then + test -f /etc/collectd.conf && mv /etc/collectd.conf /etc/collectd.conf.bak + ln -s /var/etc/collectd.conf /etc/collectd.conf + fi + + ### create config + mkdir -p /var/etc + /usr/bin/stat-genconfig > /var/etc/collectd.conf + + ### prepare rrdimg directory + if [ ! -L /www/rrdimg ]; then + imagepath="$(uci get luci_statistics.rrdtool.image_path)" + ln -s ${imagepath:-/tmp/rrdimg}/ /www/rrdimg + fi + + ### flush LuCI index cache + test -f /var/luci-indexcache && rm /var/luci-indexcache +} + +restart() { + ### regenerate config / prepare environment + start + + ### restart collectd + /etc/init.d/collectd restart +} diff --git a/openwrt/packages/luci/applications/luci-statistics/root/etc/uci-defaults/luci-statistics b/openwrt/packages/luci/applications/luci-statistics/root/etc/uci-defaults/luci-statistics new file mode 100644 index 0000000..f89366f --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/root/etc/uci-defaults/luci-statistics @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack luci_statistics + set ucitrack.@luci_statistics[-1].init=luci_statistics + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-statistics/root/usr/bin/stat-genconfig b/openwrt/packages/luci/applications/luci-statistics/root/usr/bin/stat-genconfig new file mode 100755 index 0000000..5313869 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-statistics/root/usr/bin/stat-genconfig @@ -0,0 +1,381 @@ +#!/usr/bin/lua + +--[[ + +Luci statistics - collectd configuration generator +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: stat-genconfig 3642 2008-10-29 05:08:03Z jow $ + +]]-- + + +require("luci.model.uci") +require("luci.sys.iptparser") +require("luci.util") + +local ipt = luci.sys.iptparser.IptParser() +local uci = luci.model.uci.cursor() +local sections = uci:get_all( "luci_statistics" ) + + +function section( plugin ) + + local config = sections[ "collectd_" .. plugin ] or sections["collectd"] + + if type(config) == "table" and ( plugin == "collectd" or config.enable == "1" ) then + + local params = "" + + if type( plugins[plugin] ) == "function" then + params = plugins[plugin]( config ) + else + params = config_generic( config, plugins[plugin][1], plugins[plugin][2], plugins[plugin][3], plugin == "collectd" ) + end + + + if plugin ~= "collectd" then + print( "LoadPlugin " .. plugin ) + + if params:len() > 0 then + print( "\n" .. params .. "\n" ) + else + print( "" ) + end + else + print( params .. "\n" ) + end + end +end + +function config_generic( c, singles, bools, lists, nopad ) + local str = "" + + if type(c) == "table" then + + if type(singles) == "table" then + for i, key in ipairs( singles ) do + if preprocess[key] then + c[key] = preprocess[key](c[key]) + end + + str = str .. _string( c[key], key, nopad ) + end + end + + if type(bools) == "table" then + for i, key in ipairs( bools ) do + if preprocess[key] then + c[key] = preprocess[key](c[key]) + end + + str = str .. _bool( c[key], key, nopad ) + end + end + + if type(lists) == "table" then + str = str .. _list_expand( c, lists, nopad ) + end + end + + return str +end + +function config_exec( c ) + local str = "" + + for s in pairs(sections) do + for key, type in pairs({ Exec="collectd_exec_input", NotificationExec="collectd_exec_notify" }) do + if sections[s][".type"] == type then + + cmd = sections[s].cmdline + + if cmd then + cmd = cmd:gsub("^%s+", ""):gsub("%s+$", "") + user = sections[s].cmduser or "nobody" + group = sections[s].cmdgroup + + str = str .. "\t" .. key .. ' "' .. + user .. ( group and ":" .. group or "" ) .. '" "' .. + cmd:gsub('%s+', '" "') .. '"\n' + end + end + end + end + + return str +end + +function config_iptables( c ) + local str = "" + + for s in pairs(sections) do + if sections[s][".type"] == "collectd_iptables_match" then + + search = { } + + for i, k in ipairs( { + "table", "chain", "target", "protocol", "source", "destination", + "inputif", "outputif", "options" + } ) do + v = sections[s][k] + + if type(v) == "string" then + if k == "options" then v = luci.util.split( v, "%s+", nil, true ) end + search[k] = v + end + end + + for i, rule in ipairs( ipt:find( search ) ) do + + name = sections[s].name:gsub( "%s+", "_" ) + if i > 1 then name = name .. "_(" .. i .. ")" end + + str = str .. "\tChain " .. rule.table .. " " .. rule.chain .. " " .. rule.index .. ' "' .. name .. "\"\n" + end + end + end + + return str +end + +function config_network( c ) + local str = "" + + for s in pairs(sections) do + for key, type in pairs({ Listen="collectd_network_listen", Server="collectd_network_server" }) do + if sections[s][".type"] == type then + + host = sections[s].host + port = sections[s].port + + if host then + if port then + str = str .. "\t" .. key .. " " .. host .. " " .. port .. "\n" + else + str = str .. "\t" .. key .. " " .. host .. "\n" + end + end + end + end + end + + return str .. _string( c["TimeToLive"], "TimeToLive" ) + .. _string( c["CacheFlush"], "CacheFlush" ) + .. _bool( c["Forward"], "Forward" ) +end + + +function _list_expand( c, l, nopad ) + local str = "" + + for i, n in ipairs(l) do + if c[n] then + if preprocess[n] then + c[n] = preprocess[n](c[n]) + end + + if n:find("(%w+)ses") then + k = n:gsub("(%w+)ses", "%1s") + else + k = n:gsub("(%w+)s", "%1") + end + + str = str .. _expand( c[n], k, nopad ) + end + end + + return str +end + +function _expand( s, n, nopad ) + if type(s) == "string" then + local str = "" + + for i, v in ipairs( luci.util.split( s, "%s+", nil, true ) ) do + str = str .. _string( v, n, nopad ) + end + + return str + end +end + +function _bool( s, n, nopad ) + + local str = "" + local pad = "" + if not nopad then pad = "\t" end + + if s and s == "1" then + str = pad .. n .. " true" + else + str = pad .. n .. " false" + end + + return str .. "\n" +end + +function _string( s, n, nopad ) + + local str = "" + local pad = "" + if not nopad then pad = "\t" end + + if s then + if s:find("[^%d]") then + if not s:find("[^%w]") then + str = pad .. n .. " " .. luci.util.trim(s) + else + str = pad .. n .. ' "' .. luci.util.trim(s) .. '"' + end + else + str = pad .. n .. " " .. luci.util.trim(s) + end + + str = str .. "\n" + end + + return str +end + + +plugins = { + collectd = { + { "BaseDir", "Include", "PIDFile", "PluginDir", "TypesDB", "Interval", "ReadThreads", "Hostname" }, + { }, + { } + }, + + cpu = { + { }, + { }, + { } + }, + + csv = { + { "DataDir" }, + { "StoreRates" }, + { } + }, + + df = { + { }, + { "IgnoreSelected" }, + { "Devices", "MountPoints", "FSTypes" } + }, + + disk = { + { }, + { "IgnoreSelected" }, + { "Disks" } + }, + + dns = { + { }, + { }, + { "Interfaces", "IgnoreSources" } + }, + + email = { + { "SocketFile", "SocketGroup", "SocketPerms", "MaxConns" }, + { }, + { } + }, + + exec = config_exec, + + interface = { + { }, + { "IgnoreSelected" }, + { "Interfaces" } + }, + + iptables = config_iptables, + + irq = { + { }, + { "IgnoreSelected" }, + { "Irqs" } + }, + + load = { + { }, + { }, + { } + }, + + logfile = { + { "LogLevel", "File" }, + { "Timestamp" }, + { } + }, + + netlink = { + { }, + { "IgnoreSelected" }, + { "Interfaces", "VerboseInterfaces", "QDiscs", "Classes", "Filters" } + }, + + network = config_network, + + ping = { + { "TTL" }, + { }, + { "Hosts" } + }, + + processes = { + { }, + { }, + { "Processes" } + }, + + rrdtool = { + { "DataDir", "StepSize", "HeartBeat", "RRARows", "XFF", "CacheFlush", "CacheTimeout" }, + { "RRASingle" }, + { "RRATimespans" } + }, + + tcpconns = { + { }, + { "ListeningPorts" }, + { "LocalPorts", "RemotePorts" } + }, + + unixsock = { + { "SocketFile", "SocketGroup", "SocketPerms" }, + { }, + { } + }, + + wireless = { + { }, + { }, + { } + }, +} + +preprocess = { + RRATimespans = function(val) + local rv = { } + for time in val:gmatch("[^%s]+") do + table.insert( rv, luci.util.parse_units(time) ) + end + return table.concat(rv, " ") + end +} + + +section("collectd") + +for plugin in pairs(plugins) do + if plugin ~= "collectd" then + section( plugin ) + end +end diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/Makefile b/openwrt/packages/luci/applications/luci-tinyproxy/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/controller/tinyproxy.lua b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/controller/tinyproxy.lua new file mode 100644 index 0000000..4919c2a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/controller/tinyproxy.lua @@ -0,0 +1,25 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tinyproxy.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.tinyproxy", package.seeall) + +function index() + if not luci.fs.access("/etc/config/tinyproxy") then + return + end + + local page = entry({"admin", "services", "tinyproxy"}, cbi("tinyproxy"), "Tinyproxy") + page.dependent = true + page.i18n = "tinyproxy" +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.lua b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.lua new file mode 100644 index 0000000..5aaafe4 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.lua @@ -0,0 +1,32 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy ist ein schlanker HTTP(S)-Proxy ohne Zwischenspeicher' +tinyproxy_tinyproxy_allow = 'Proxyzugang erlauben von' +tinyproxy_tinyproxy_anonymous = 'Erlaube Header für anonymen Proxy' +tinyproxy_tinyproxy_bind = 'Ausgehendenden Verkehr an Adresse binden' +tinyproxy_tinyproxy_connectport = 'Ports für CONNECT-Methode' +tinyproxy_tinyproxy_connectport_desc = '0 = deaktiviert, leer = alle' +tinyproxy_tinyproxy_defaulterrorfile = 'Fehlerseite' +tinyproxy_tinyproxy_filter = 'Filterliste' +tinyproxy_tinyproxy_filtercasesensitive = 'Filter unterscheiden Groß-/Kleinschreibung' +tinyproxy_tinyproxy_filterdefaultdeny = 'Filterliste ist eine Whitelist' +tinyproxy_tinyproxy_filterextended = 'Erweiterte reguläre Ausdrücke für Filter' +tinyproxy_tinyproxy_filterurls = 'Filtere URLs statt Domains' +tinyproxy_tinyproxy_listen = 'An Adresse binden' +tinyproxy_tinyproxy_logfile = 'Protokolldatei' +tinyproxy_tinyproxy_loglevel = 'Protokolllevel' +tinyproxy_tinyproxy_maxclients = 'Maximale Anzahl an Clients' +tinyproxy_tinyproxy_maxrequestsperchild = 'Maximale Anfragen pro Prozess' +tinyproxy_tinyproxy_maxspareservers = 'Max. Prozesszahl' +tinyproxy_tinyproxy_minspareservers = 'Min. Prozesszahl' +tinyproxy_tinyproxy_startservers = 'Anfängliche Prozesszahl' +tinyproxy_tinyproxy_statfile = 'Statistikseite' +tinyproxy_tinyproxy_syslog = 'In Systemprotokoll schreiben' +tinyproxy_tinyproxy_timeout = 'Verbindungstimeout' +tinyproxy_tinyproxy_viaproxyname = 'Wert des Via-Headers' +tinyproxy_tinyproxy_xtinyproxy = 'Client-IP übertragen' +tinyproxy_type_proxy = 'Über Proxy' +tinyproxy_type_reject = 'Verbiete Zugriff' +tinyproxy_upstream = 'Zugangskontrolle' +tinyproxy_upstream_target = 'Zielhost' +tinyproxy_upstream_type = 'Methode' +tinyproxy_upstream_via = 'Zugangsproxy' diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.xml b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.xml new file mode 100644 index 0000000..7e4da0d --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.de.xml @@ -0,0 +1,38 @@ + + + + +Tinyproxy +Tinyproxy ist ein schlanker HTTP(S)-Proxy ohne Zwischenspeicher +Proxyzugang erlauben von +Erlaube Header für anonymen Proxy +Ausgehendenden Verkehr an Adresse binden +Ports für CONNECT-Methode +0 = deaktiviert, leer = alle +Fehlerseite +Filterliste +Filter unterscheiden Groß-/Kleinschreibung +Filterliste ist eine Whitelist +Erweiterte reguläre Ausdrücke für Filter +Filtere URLs statt Domains +An Adresse binden +Protokolldatei +Protokolllevel +Maximale Anzahl an Clients +Maximale Anfragen pro Prozess +Max. Prozesszahl +Min. Prozesszahl +Anfängliche Prozesszahl +Statistikseite +In Systemprotokoll schreiben +Verbindungstimeout +Wert des Via-Headers +Client-IP übertragen +Über Proxy +Verbiete Zugriff +Zugangskontrolle +Zielhost +Methode +Zugangsproxy + + diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.lua b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.lua new file mode 100644 index 0000000..2520e38 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.lua @@ -0,0 +1,32 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy is a small and fast non-caching HTTP(S)-Proxy' +tinyproxy_tinyproxy_allow = 'Allow access from' +tinyproxy_tinyproxy_anonymous = 'Allowed headers for anonymous proxy' +tinyproxy_tinyproxy_bind = 'Bind outgoing traffic to address' +tinyproxy_tinyproxy_connectport = 'Ports allowed for CONNECT method' +tinyproxy_tinyproxy_connectport_desc = '0 = disabled, empty = all' +tinyproxy_tinyproxy_defaulterrorfile = 'Error document' +tinyproxy_tinyproxy_filter = 'Filter list' +tinyproxy_tinyproxy_filtercasesensitive = 'Case sensitive filters' +tinyproxy_tinyproxy_filterdefaultdeny = 'Filter list is a whitelist' +tinyproxy_tinyproxy_filterextended = 'Extended regular expression filters' +tinyproxy_tinyproxy_filterurls = 'Filter URLs instead of domains' +tinyproxy_tinyproxy_listen = 'Listen on address' +tinyproxy_tinyproxy_logfile = 'Logfile' +tinyproxy_tinyproxy_loglevel = 'Log level' +tinyproxy_tinyproxy_maxclients = 'Maximum number of clients' +tinyproxy_tinyproxy_maxrequestsperchild = 'Maximum requests per thread' +tinyproxy_tinyproxy_maxspareservers = 'Max. spare servers' +tinyproxy_tinyproxy_minspareservers = 'Min. spare servers' +tinyproxy_tinyproxy_startservers = 'Spare servers to start with' +tinyproxy_tinyproxy_statfile = 'Statistic document' +tinyproxy_tinyproxy_syslog = 'Write to syslog' +tinyproxy_tinyproxy_timeout = 'Connection Timeout' +tinyproxy_tinyproxy_viaproxyname = 'Value of Via-Header' +tinyproxy_tinyproxy_xtinyproxy = 'Include client IP' +tinyproxy_type_proxy = 'Via proxy' +tinyproxy_type_reject = 'Reject access' +tinyproxy_upstream = 'Upstream Control' +tinyproxy_upstream_target = 'Target host' +tinyproxy_upstream_type = 'Type' +tinyproxy_upstream_via = 'Upstream Proxy' diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.xml b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.xml new file mode 100644 index 0000000..e97ca59 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.en.xml @@ -0,0 +1,38 @@ + + + + +Tinyproxy +Tinyproxy is a small and fast non-caching HTTP(S)-Proxy +Allow access from +Allowed headers for anonymous proxy +Bind outgoing traffic to address +Ports allowed for CONNECT method +0 = disabled, empty = all +Error document +Filter list +Case sensitive filters +Filter list is a whitelist +Extended regular expression filters +Filter URLs instead of domains +Listen on address +Logfile +Log level +Maximum number of clients +Maximum requests per thread +Max. spare servers +Min. spare servers +Spare servers to start with +Statistic document +Write to syslog +Connection Timeout +Value of Via-Header +Include client IP +Via proxy +Reject access +Upstream Control +Target host +Type +Upstream Proxy + + diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.lua b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.lua new file mode 100644 index 0000000..af7a134 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.lua @@ -0,0 +1,34 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy is a small and fast non-caching HTTP(S)-Proxy' +tinyproxy_tinyproxy_allow = 'Allow access from' +tinyproxy_tinyproxy_anonymous = 'Allowed headers for anonymous proxy' +tinyproxy_tinyproxy_bind = 'Lier le trafic sortant à l'adresse ip' +tinyproxy_tinyproxy_connectport = 'Ports allowed for CONNECT method' +tinyproxy_tinyproxy_connectport_desc = '0 = disabled, empty = all' +tinyproxy_tinyproxy_defaulterrorfile = 'Fichier d'erreur' +tinyproxy_tinyproxy_filter = 'Liste de filtres' +tinyproxy_tinyproxy_filtercasesensitive = 'Case sensitive filters' +tinyproxy_tinyproxy_filterdefaultdeny = 'Filter list is a whitelist' +tinyproxy_tinyproxy_filterextended = 'Extended regular expression filters' +tinyproxy_tinyproxy_filterurls = 'Filter URLs instead of domains' +tinyproxy_tinyproxy_group = 'Groupe' +tinyproxy_tinyproxy_listen = 'Listen on address' +tinyproxy_tinyproxy_logfile = 'Chemin du fichier de log' +tinyproxy_tinyproxy_loglevel = 'Niveau de log' +tinyproxy_tinyproxy_maxclients = 'Nombre maximum de clients' +tinyproxy_tinyproxy_maxrequestsperchild = 'Maximum de connexion par processus' +tinyproxy_tinyproxy_maxspareservers = 'Nombre Maximum de processus serveur' +tinyproxy_tinyproxy_minspareservers = 'Nombre Minimum de processus serveur' +tinyproxy_tinyproxy_startservers = 'Nombre de processus serveur lancés au demarrage' +tinyproxy_tinyproxy_statfile = 'Fichier de statistiques' +tinyproxy_tinyproxy_syslog = 'Écrire dans le journal système (Syslog)' +tinyproxy_tinyproxy_timeout = 'Délai de connexion' +tinyproxy_tinyproxy_user = 'Utilisateur' +tinyproxy_tinyproxy_viaproxyname = 'Valeur de l'entête "VIA" utilisée comme nom d'hôte' +tinyproxy_tinyproxy_xtinyproxy = 'Inclure l'ip du client' +tinyproxy_type_proxy = 'Via proxy' +tinyproxy_type_reject = 'Refuser l'accès' +tinyproxy_upstream = 'Upstream Control' +tinyproxy_upstream_target = 'Hôte de destination' +tinyproxy_upstream_type = 'Type' +tinyproxy_upstream_via = 'Proxy' diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.xml b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.xml new file mode 100644 index 0000000..77470ec --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.fr.xml @@ -0,0 +1,40 @@ + + + + +Tinyproxy +Tinyproxy is a small and fast non-caching HTTP(S)-Proxy +Allow access from +Allowed headers for anonymous proxy +Lier le trafic sortant à l'adresse ip +Ports allowed for CONNECT method +0 = disabled, empty = all +Fichier d'erreur +Liste de filtres +Case sensitive filters +Filter list is a whitelist +Extended regular expression filters +Filter URLs instead of domains +Groupe +Listen on address +Chemin du fichier de log +Niveau de log +Nombre maximum de clients +Maximum de connexion par processus +Nombre Maximum de processus serveur +Nombre Minimum de processus serveur +Nombre de processus serveur lancés au demarrage +Fichier de statistiques +Écrire dans le journal système (Syslog) +Délai de connexion +Utilisateur +Valeur de l'entête "VIA" utilisée comme nom d'hôte +Inclure l'ip du client +Via proxy +Refuser l'accès +Upstream Control +Hôte de destination +Type +Proxy + + diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.lua b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.lua new file mode 100644 index 0000000..33b664a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.lua @@ -0,0 +1,34 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy é um pequeno e rápido Proxy-HTTP(S) sem suporte à cache' +tinyproxy_tinyproxy_allow = 'Permitir acesso de' +tinyproxy_tinyproxy_anonymous = 'Cabeçalhos permitidos para proxy anônimo' +tinyproxy_tinyproxy_bind = 'Associar o tráfego de saída ao endereço' +tinyproxy_tinyproxy_connectport = 'Portas permitidas para o método CONNECT ' +tinyproxy_tinyproxy_connectport_desc = '0 = desativado, vazio = todas' +tinyproxy_tinyproxy_defaulterrorfile = 'Documento de erro' +tinyproxy_tinyproxy_filter = 'Lista de filtros' +tinyproxy_tinyproxy_filtercasesensitive = 'Filtros "case sensitive"' +tinyproxy_tinyproxy_filterdefaultdeny = 'A lista de filtros é uma lista branca' +tinyproxy_tinyproxy_filterextended = 'Filtros com suporte à expressões regulares' +tinyproxy_tinyproxy_filterurls = 'Filtrar URLs em vez de domínios' +tinyproxy_tinyproxy_listen = 'Escutar no endereço' +tinyproxy_tinyproxy_logfile = 'Arquivo de log' +tinyproxy_tinyproxy_loglevel = 'Nível do log' +tinyproxy_tinyproxy_maxclients = 'Número máximo de clientes' +tinyproxy_tinyproxy_maxrequestsperchild = 'Máximo de solicitações por thread' +tinyproxy_tinyproxy_maxspareservers = 'Max. servidores sobressalentes' +tinyproxy_tinyproxy_minspareservers = 'Min. servidores sobressalentes' +tinyproxy_tinyproxy_startservers = 'Servidores sobressalentes iniciar com' +tinyproxy_tinyproxy_statfile = 'Documento de estatísticas' +tinyproxy_tinyproxy_syslog = 'Escrever para syslog' +tinyproxy_tinyproxy_timeout = 'Timeout de conexão' +tinyproxy_tinyproxy_group = 'Grupo' +tinyproxy_tinyproxy_user = 'Usuário' +tinyproxy_tinyproxy_viaproxyname = 'Valor do cabeçalho "Via-Header"' +tinyproxy_tinyproxy_xtinyproxy = 'Incluir o IP do cliente' +tinyproxy_type_proxy = 'Via proxy' +tinyproxy_type_reject = 'Rejeitar o acesso' +tinyproxy_upstream = 'Controle de Upstream' +tinyproxy_upstream_target = 'Host de destino' +tinyproxy_upstream_type = 'Tipo' +tinyproxy_upstream_via = 'Proxy para Upstream' diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.xml b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.xml new file mode 100644 index 0000000..54ad83c --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/i18n/tinyproxy.pt-br.xml @@ -0,0 +1,40 @@ + + + + +Tinyproxy +Tinyproxy é um pequeno e rápido Proxy-HTTP(S) sem suporte à cache +Permitir acesso de +Cabeçalhos permitidos para proxy anônimo +Associar o tráfego de saída ao endereço +Portas permitidas para o método CONNECT +0 = desativado, vazio = todas +Documento de erro +Lista de filtros +Filtros "case sensitive" +A lista de filtros é uma lista branca +Filtros com suporte à expressões regulares +Filtrar URLs em vez de domínios +Escutar no endereço +Arquivo de log +Nível do log +Número máximo de clientes +Máximo de solicitações por thread +Max. servidores sobressalentes +Min. servidores sobressalentes +Servidores sobressalentes iniciar com +Documento de estatísticas +Escrever para syslog +Timeout de conexão +Grupo +Usuário +Valor do cabeçalho "Via-Header" +Incluir o IP do cliente +Via proxy +Rejeitar o acesso +Controle de Upstream +Host de destino +Tipo +Proxy para Upstream + + diff --git a/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/model/cbi/tinyproxy.lua b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/model/cbi/tinyproxy.lua new file mode 100644 index 0000000..9a216d7 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-tinyproxy/luasrc/model/cbi/tinyproxy.lua @@ -0,0 +1,80 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tinyproxy.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +m = Map("tinyproxy", translate("tinyproxy"), translate("tinyproxy_desc")) + +s = m:section(TypedSection, "tinyproxy", translate("general")) +s.anonymous = true + +s:option(Flag, "enable", translate("enable")) + +s:option(Value, "Port", translate("port")) +s:option(Value, "Listen").optional = true +s:option(Value, "Bind").optional = true +s:option(Value, "Timeout").optional = true + +s:option(Value, "DefaultErrorFile").optional = true +s:option(Value, "StatFile").optional = true + +s:option(Flag, "Syslog").optional = true +f = s:option(Value, "Logfile") +f.optional = true + +l = s:option(ListValue, "LogLevel") +l.optional = true +l:value("Critical") +l:value("Error") +l:value("Warning") +l:value("Notice") +l:value("Connect") +l:value("Info") + +s:option(DynamicList, "XTinyproxy").optional = true + +s:option(DynamicList, "Allow") +s:option(Value, "ViaProxyName") + +s:option(FileUpload, "Filter") +s:option(Flag, "FilterURLs") +s:option(Flag, "FilterExtended") +s:option(Flag, "FilterCaseSensitive") +s:option(Flag, "FilterDefaultDeny") + +s:option(DynamicList, "Anonymous") +s:option(DynamicList, "ConnectPort") + +s:option(Value, "User").optional = true +s:option(Value, "Group").optional = true +s:option(Value, "MaxClients").optional = true +s:option(Value, "MinSpareServers").optional = true +s:option(Value, "MaxSpareServers").optional = true +s:option(Value, "StartServers").optional = true +s:option(Value, "MaxRequestsPerChild").optional = true + + +s = m:section(TypedSection, "upstream") +s.anonymous = true +s.addremove = true + +t = s:option(ListValue, "type") +t:value("proxy", translate("tinyproxy_type_proxy")) +t:value("reject", translate("tinyproxy_type_reject")) + +ta = s:option(Value, "target") +ta.rmempty = true + +v = s:option(Value, "via") +v:depends({type="proxy"}) + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-upnp/Makefile b/openwrt/packages/luci/applications/luci-upnp/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/controller/upnp.lua b/openwrt/packages/luci/applications/luci-upnp/luasrc/controller/upnp.lua new file mode 100644 index 0000000..7343bcc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/controller/upnp.lua @@ -0,0 +1,30 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upnp.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.upnp", package.seeall) + +function index() + if not luci.fs.access("/etc/config/upnpd") then + return + end + + local page = entry({"admin", "services", "upnp"}, cbi("upnp/upnp"), "UPNP") + page.i18n = "upnp" + page.dependent = true + + + local page = entry({"mini", "network", "upnp"}, cbi("upnp/upnpmini", {autoapply=true}), "UPNP") + page.i18n = "upnp" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.lua b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.lua new file mode 100644 index 0000000..777ae87 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.lua @@ -0,0 +1,7 @@ +upnpd = 'Universal Plug & Play' +upnpd_desc = 'UPNP ermöglicht die automatische Konfiguration des Routers durch Clients im lokalen Netzwerk.' +upnpd_config_desc = 'UPNP sollte nur wenn unbedingt nötig aktiviert werden, da es ein Sicherheitsrisiko für das Netzwerk darstellen kann.' +upnpd_config_securemode = 'Sicheren Modus aktivieren' +upnpd_config_logoutput = 'Ausgabe protokollieren' +upnpd_config_download = 'Downlink' +upnpd_config_upload = 'Uplink' diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.xml b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.xml new file mode 100644 index 0000000..2a21b7b --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.de.xml @@ -0,0 +1,12 @@ + + + + +Universal Plug & Play +UPNP ermöglicht die automatische Konfiguration des Routers durch Clients im lokalen Netzwerk. +UPNP sollte nur wenn unbedingt nötig aktiviert werden, da es ein Sicherheitsrisiko für das Netzwerk darstellen kann. +Sicheren Modus aktivieren +Ausgabe protokollieren +Downlink +Uplink + diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.lua b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.lua new file mode 100644 index 0000000..8e6c825 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.lua @@ -0,0 +1,7 @@ +upnpd = 'Universal Plug & Play' +upnpd_desc = 'UPNP allows clients in the local network to automatically configure the router.' +upnpd_config_desc = 'UPNP should only be enabled if absolutely necessary as it can result in high security risks for your network.' +upnpd_config_securemode = 'Enable secure mode' +upnpd_config_logoutput = 'Log output' +upnpd_config_download = 'Downlink' +upnpd_config_upload = 'Uplink' diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.xml b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.xml new file mode 100644 index 0000000..60d6225 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.en.xml @@ -0,0 +1,12 @@ + + + + +Universal Plug & Play +UPNP allows clients in the local network to automatically configure the router. +UPNP should only be enabled if absolutely necessary as it can result in high security risks for your network. +Enable secure mode +Log output +Downlink +Uplink + diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.lua b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.lua new file mode 100644 index 0000000..cf2c3db --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.lua @@ -0,0 +1,7 @@ +upnpd = 'Plug & Play Universal' +upnpd_desc = 'UPNP permite os clientes da rede local automaticamente configurar o roteador.' +upnpd_config_desc = 'O UPNP deve ser ativado apenas se for absolutamente necessário, pois ele pode resultar em elevados riscos de segurança para sua rede.' +upnpd_config_securemode = 'Enable secure mode' +upnpd_config_logoutput = 'Log de saída' +upnpd_config_download = 'Link para download' +upnpd_config_upload = 'Link para Upload' diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.xml b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.xml new file mode 100644 index 0000000..c239d90 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/i18n/upnp.pt-br.xml @@ -0,0 +1,12 @@ + + + + +Plug & Play Universal +UPNP permite os clientes da rede local automaticamente configurar o roteador. +O UPNP deve ser ativado apenas se for absolutamente necessário, pois ele pode resultar em elevados riscos de segurança para sua rede. +Enable secure mode +Log de saída +Link para download +Link para Upload + diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnp.lua b/openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnp.lua new file mode 100644 index 0000000..1bc6e84 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnp.lua @@ -0,0 +1,38 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upnp.lua 4179 2009-01-28 18:32:47Z jow $ +]]-- +m = Map("upnpd", translate("upnpd"), translate("upnpd_desc")) + +s = m:section(NamedSection, "config", "upnpd", "") +e = s:option(Flag, "enabled", translate("enable")) +e.rmempty = false + +function e.write(self, section, value) + local cmd = (value == "1") and "enable" or "disable" + if value ~= "1" then + os.execute("/etc/init.d/miniupnpd stop") + end + os.execute("/etc/init.d/miniupnpd " .. cmd) +end + +function e.cfgvalue(self, section) + return (os.execute("/etc/init.d/miniupnpd enabled") == 0) and "1" or "0" +end + +s:option(Flag, "secure_mode").rmempty = true +s:option(Flag, "log_output").rmempty = true +s:option(Value, "download", nil, "kByte/s").rmempty = true +s:option(Value, "upload", nil, "kByte/s").rmempty = true + +return m diff --git a/openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnpmini.lua b/openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnpmini.lua new file mode 100644 index 0000000..2b2a78a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/luasrc/model/cbi/upnp/upnpmini.lua @@ -0,0 +1,36 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upnpmini.lua 4179 2009-01-28 18:32:47Z jow $ +]]-- +m = Map("upnpd", translate("upnpd"), translate("upnpd_desc")) + +s = m:section(NamedSection, "config", "upnpd", "") +e = s:option(Flag, "enabled", translate("enable")) +e.rmempty = false + +function e.write(self, section, value) + local cmd = (value == "1") and "enable" or "disable" + if value ~= "1" then + os.execute("/etc/init.d/miniupnpd stop") + end + os.execute("/etc/init.d/miniupnpd " .. cmd) +end + +function e.cfgvalue(self, section) + return (os.execute("/etc/init.d/miniupnpd enabled") == 0) and "1" or "0" +end + +s:option(Value, "download", nil, "kByte/s").rmempty = true +s:option(Value, "upload", nil, "kByte/s").rmempty = true + +return m diff --git a/openwrt/packages/luci/applications/luci-upnp/root/etc/uci-defaults/luci-upnp b/openwrt/packages/luci/applications/luci-upnp/root/etc/uci-defaults/luci-upnp new file mode 100755 index 0000000..3165b07 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/root/etc/uci-defaults/luci-upnp @@ -0,0 +1,3 @@ +#!/bin/sh +/etc/init.d/miniupnpd stop +/etc/init.d/miniupnpd disable diff --git a/openwrt/packages/luci/applications/luci-upnp/root/lib/uci/schema/default/upnpd b/openwrt/packages/luci/applications/luci-upnp/root/lib/uci/schema/default/upnpd new file mode 100644 index 0000000..8574d03 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-upnp/root/lib/uci/schema/default/upnpd @@ -0,0 +1,28 @@ +package upnpd + +config package + option title 'Miniupnpd UPNP daemon' + +config section + option name 'upnpd' + option title 'Settings' + option package 'upnpd' + option unique true + +config variable + option name 'download' + option title 'Download bandwidth in kBit/s' + option section 'upnpd.upnpd' + option datatype 'integer' + +config variable + option name 'upload' + option title 'Upload bandwidth in kBit/s' + option section 'upnpd.upnpd' + option datatype 'integer' + +config variable + option name 'log_output' + option title 'Enable log messages' + option section 'upnpd.upnpd' + option datatype 'boolean' diff --git a/openwrt/packages/luci/applications/luci-ushare/Makefile b/openwrt/packages/luci/applications/luci-ushare/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/applications/luci-ushare/ipkg/postinst b/openwrt/packages/luci/applications/luci-ushare/ipkg/postinst new file mode 100644 index 0000000..f392489 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-ushare ) && rm -f /etc/uci-defaults/luci-ushare +} diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/controller/ushare.lua b/openwrt/packages/luci/applications/luci-ushare/luasrc/controller/ushare.lua new file mode 100644 index 0000000..702e446 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/controller/ushare.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI uShare +(c) 2008 Yanira + +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: ushare.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.ushare", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("ushare") + if not luci.fs.access("/etc/config/ushare") then + return + end + + local page = entry({"admin", "services", "ushare"}, cbi("ushare"), luci.i18n.translate("ushare", "uShare"), 60) + page.i18n = "uvc_streamer" + page.dependent = true +end diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.lua b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.lua new file mode 100644 index 0000000..a5f239a --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.lua @@ -0,0 +1,8 @@ +content_directories = 'Freigabeverzeichnisse' +disable_telnet = 'Telnet-Konsole deaktivieren' +disable_webif = 'Webinterface deaktivieren' +options = 'Optionen' +servername = 'Servername' +settings = 'Einstellungen' +ushare = 'uShare' +ushare_desc = 'uShare' diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.xml b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.xml new file mode 100644 index 0000000..c803524 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.de.xml @@ -0,0 +1,14 @@ + + + + +Freigabeverzeichnisse +Telnet-Konsole deaktivieren +Webinterface deaktivieren +Optionen +Servername +Einstellungen +uShare +uShare + + diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.lua b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.lua new file mode 100644 index 0000000..834fa91 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.lua @@ -0,0 +1,8 @@ +content_directories = 'Content directories' +disable_telnet = 'Disable telnet console' +disable_webif = 'Disable webinterface' +options = 'Options' +servername = 'Servername' +settings = 'Settings' +ushare = 'uShare' +ushare_desc = 'uShare' diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.xml b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.xml new file mode 100644 index 0000000..0275e2f --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.en.xml @@ -0,0 +1,14 @@ + + + + +Content directories +Disable telnet console +Disable webinterface +Options +Servername +Settings +uShare +uShare + + diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.lua b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.lua new file mode 100644 index 0000000..492c4ce --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.lua @@ -0,0 +1,8 @@ +content_directories = 'Diretórios de conteúdo' +disable_telnet = 'Desativar console telnet' +disable_webif = 'Desativar interface web' +options = 'Opções' +servername = 'Nome do servidor' +settings = 'Configurações' +ushare = 'uShare' +ushare_desc = 'uShare' diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.xml b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.xml new file mode 100644 index 0000000..729e056 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/i18n/ushare.pt-br.xml @@ -0,0 +1,14 @@ + + + + +Diretórios de conteúdo +Desativar console telnet +Desativar interface web +Opções +Nome do servidor +Configurações +uShare +uShare + + diff --git a/openwrt/packages/luci/applications/luci-ushare/luasrc/model/cbi/ushare.lua b/openwrt/packages/luci/applications/luci-ushare/luasrc/model/cbi/ushare.lua new file mode 100644 index 0000000..8063aea --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/luasrc/model/cbi/ushare.lua @@ -0,0 +1,42 @@ +--[[ + +LuCI uShare +(c) 2008 Yanira + +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: ushare.lua 3423 2008-09-24 21:13:42Z jow $ + +]]-- + +m = Map("ushare", translate("ushare"), + translate("ushare_desc")) + +s = m:section(TypedSection, "ushare", translate("settings")) +s.addremove = false +s.anonymous = true + +s:option(Flag, "enabled", translate("enabled", "Enable")) + +s:option(Value, "username", translate("username")) + +s:option(Value, "servername", translate("servername")) + +dif = s:option( Value, "interface", translate("interface")) +for _, nif in ipairs(luci.sys.net.devices()) do + if nif ~= "lo" then dif:value(nif) end +end + +s:option(Value, "content_directories", translate("content_directories")) + +s:option(Flag, "disable_webif", translate("disable_webif")) + +s:option(Flag, "disable_telnet", translate("disable_telnet")) + +s:option(Value, "options", translate("options")) + +return m diff --git a/openwrt/packages/luci/applications/luci-ushare/root/etc/uci-defaults/luci-ushare b/openwrt/packages/luci/applications/luci-ushare/root/etc/uci-defaults/luci-ushare new file mode 100644 index 0000000..262420e --- /dev/null +++ b/openwrt/packages/luci/applications/luci-ushare/root/etc/uci-defaults/luci-ushare @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack ushare + set ucitrack.@ushare[-1].init=ushare + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/Makefile b/openwrt/packages/luci/applications/luci-uvc_streamer/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/ipkg/postinst b/openwrt/packages/luci/applications/luci-uvc_streamer/ipkg/postinst new file mode 100755 index 0000000..492bc85 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-uvc_streamer ) && rm -f /etc/uci-defaults/luci-uvc_streamer +} diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/controller/uvc_streamer.lua b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/controller/uvc_streamer.lua new file mode 100644 index 0000000..7de7895 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/controller/uvc_streamer.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI UVC Streamer +(c) 2008 Yanira + +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: uvc_streamer.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.uvc_streamer", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("uvc_streamer") + if not luci.fs.access("/etc/config/uvc-streamer") then + return + end + + local page = entry({"admin", "services", "uvc_streamer"}, cbi("uvc_streamer"), luci.i18n.translate("uvc_streamer", "UVC Streaming"), 60) + page.i18n = "uvc_streamer" + page.dependent = true +end diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.lua b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.lua new file mode 100644 index 0000000..b340fd4 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.lua @@ -0,0 +1,5 @@ +framespersecond = 'Bilder pro Sekunde' +resolution = 'Auflösung' +settings = 'Konfiguration' +uvc_streamer = 'Webcam Stream' +uvc_streamer_desc = 'Linux-UVC Webcam Konfiguration. Im Browser z.B. http://%s:%i/ laden.' diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.xml b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.xml new file mode 100644 index 0000000..1d7b946 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.de.xml @@ -0,0 +1,11 @@ + + + + +Bilder pro Sekunde +Auflösung +Konfiguration +Webcam Stream +Linux-UVC Webcam Konfiguration. Im Browser z.B. http://%s:%i/ laden. + + diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.lua b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.lua new file mode 100644 index 0000000..e56eacc --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.lua @@ -0,0 +1,5 @@ +framespersecond = 'Frames per second' +resolution = 'Resolution' +settings = 'Settings' +uvc_streamer = 'Webcam streaming' +uvc_streamer_desc = 'Configure your Linux-UVC compatible webcam. Point your browser to e.g. http://%s:%i/' diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.xml b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.xml new file mode 100644 index 0000000..5d20d21 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.en.xml @@ -0,0 +1,11 @@ + + + + +Frames per second +Resolution +Settings +Webcam streaming +Configure your Linux-UVC compatible webcam. Point your browser to e.g. http://%s:%i/ + + diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.lua b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.lua new file mode 100644 index 0000000..97523af --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.lua @@ -0,0 +1,5 @@ +framespersecond = 'Images par seconde' +resolution = 'Résolution' +settings = 'Paramètres' +uvc_streamer = 'Webcam streaming' +uvc_streamer_desc = 'Configurez le pilote linux UVC-webcam pour votre webcam. Pointez votre navigateur par exemple surhttp://%s:%i/' diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.xml b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.xml new file mode 100644 index 0000000..ab3ecf3 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.fr.xml @@ -0,0 +1,11 @@ + + + + +Images par seconde +Résolution +Paramètres +Webcam streaming +Configurez le pilote linux UVC-webcam pour votre webcam. Pointez votre navigateur par exemple surhttp://%s:%i/ + + diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.lua b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.lua new file mode 100644 index 0000000..624a885 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.lua @@ -0,0 +1,5 @@ +framespersecond = 'Frames por segundo' +resolution = 'Resolução' +settings = 'Configurações' +uvc_streamer = 'Webcam streaming' +uvc_streamer_desc = 'Configure a sua webcam compatível com o Linux-UVC. Coloque no seu browser por ex. http://%s:%i/' diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.xml b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.xml new file mode 100644 index 0000000..8594cc1 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/i18n/uvc_streamer.pt-br.xml @@ -0,0 +1,11 @@ + + + + +Frames por segundo +Resolução +Configurações +Webcam streaming +Configure a sua webcam compatível com o Linux-UVC. Coloque no seu browser por ex. http://%s:%i/ + + diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/model/cbi/uvc_streamer.lua b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/model/cbi/uvc_streamer.lua new file mode 100644 index 0000000..ead6534 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/luasrc/model/cbi/uvc_streamer.lua @@ -0,0 +1,47 @@ +--[[ + +LuCI UVC Streamer +(c) 2008 Yanira + +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: uvc_streamer.lua 3242 2008-09-11 18:54:51Z Cyrus $ + +]]-- + +-- find current lan address and port of first uvc_streamer config section +local uci = luci.model.uci.cursor_state() +local addr = uci:get("network", "lan", "ipaddr") +local port + +uci:foreach( "uvc-streamer", "uvc-streamer", + function(section) port = port or tonumber(section.port) end ) + +addr = addr or "192.168.1.1" +port = port or 8080 + +m = Map("uvc-streamer", translate("uvc_streamer"), + translatef("uvc_streamer_desc", nil, addr, port, addr, port)) + +s = m:section(TypedSection, "uvc-streamer", translate("settings")) +s.addremove = false +s.anonymous = true + +s:option(Flag, "enabled", translate("enabled", "Enable")) + +s:option(Value, "device", translate("device")).rmempty = true + +nm = s:option(Value, "resolution", translate("resolution")) +nm:value("640x480") +nm:value("320x240") +nm:value("160x120") + +s:option(Value, "framespersecond", translate("framespersecond")).rmempty = true + +s:option(Value, "port", translate("port", "Port")).rmempty = true + +return m diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/root/etc/uci-defaults/luci-uvc_streamer b/openwrt/packages/luci/applications/luci-uvc_streamer/root/etc/uci-defaults/luci-uvc_streamer new file mode 100644 index 0000000..42372f0 --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/root/etc/uci-defaults/luci-uvc_streamer @@ -0,0 +1,7 @@ +#!/bin/sh + +uci batch <<-EOF + add ucitrack uvc-streamer + set ucitrack.@uvc-streamer[-1].init=uvc-streamer + commit ucitrack +EOF diff --git a/openwrt/packages/luci/applications/luci-uvc_streamer/root/lib/uci/schema/default/uvc-streamer b/openwrt/packages/luci/applications/luci-uvc_streamer/root/lib/uci/schema/default/uvc-streamer new file mode 100644 index 0000000..9ea255c --- /dev/null +++ b/openwrt/packages/luci/applications/luci-uvc_streamer/root/lib/uci/schema/default/uvc-streamer @@ -0,0 +1,41 @@ +#package uvc-streamer + +config package + option title 'UVC-Streamer webcam streaming configuration' + +config section + option name 'uvc-streamer' + option package 'uvc-streamer' + option title 'Settings' + option unique true + option required true + +config variable + option name 'enabled' + option section 'uvc-streamer.uvc-streamer' + option title 'Enable' + option required true + option datatype boolean + +config variable + option name 'device' + option section 'uvc-streamer.uvc-streamer' + option title 'Device' + +config variable + option name 'resolution' + option section 'uvc-streamer.uvc-streamer' + option title 'Resolution' + option required true + +config variable + option name 'framespersecond' + option section 'uvc-streamer.uvc-streamer' + option title 'Frames per second' + option datatype uint + +config variable + option name 'port' + option section 'uvc-streamer.uvc-streamer' + option title 'Port' + option datatype port diff --git a/openwrt/packages/luci/applications/myapplication/Makefile b/openwrt/packages/luci/applications/myapplication/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/applications/myapplication/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/build/cbi2uvl.lua b/openwrt/packages/luci/build/cbi2uvl.lua new file mode 100755 index 0000000..feb878f --- /dev/null +++ b/openwrt/packages/luci/build/cbi2uvl.lua @@ -0,0 +1,135 @@ +#!/usr/bin/lua +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: cbi2uvl.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local cbi = require "luci.cbi" +local i18n = require "luci.i18n" +local util = require "luci.util" + +if not arg[1] then + util.perror("Usage %s path/to/cbi/model.lua [i18nfilename]" % arg[0]) + os.exit(1) +end + +i18n.load("default", "en") +i18n.load("admin-core", "en") +i18n.load("wifi", "en") + +if arg[2] then + i18n.load(arg[2], "en") +end + +if arg[3] then + pcall(function() + require "uci" + require "luci.model.uci".cursor = function(config, save) + return uci.cursor(config or arg[3] .. "/etc/config", save or arg[3] .. "/tmp/.uci") + end + end) +end + +local map = cbi.load(arg[1])[1] +assert(map) + +print ("package "..map.config) +print ("\nconfig package") + +if #map.title > 0 then + print (" option title '%s'" % util.striptags(map.title)) +end + +if #map.description > 0 then + print (" option description '%s'" % util.striptags(map.description)) +end + +for i, sec in pairs(map.children) do if util.instanceof(sec, cbi.AbstractSection) then + print ("\nconfig section") + print (" option name '%s'" % sec.sectiontype) + print (" option package '%s'" % map.config) + + if #sec.title > 0 then + print (" option title '%s'" % util.striptags(sec.title)) + end + + if #sec.description > 0 then + print (" option description '%s'" % util.striptags(sec.description)) + end + + if not sec.addremove then + print (" option unique true") + print (" option required true") + end + + if not sec.anonymous then + print (" option named true") + end + + if sec.dynamic then + print (" option dynamic true") + end + + for j, opt in ipairs(sec.children) do + if opt.option:sub(1,1) ~= "_" or util.instanceof(opt, cbi.Value) then + print ("\nconfig variable") + print (" option name '%s'" % opt.option) + print (" option section '%s.%s'" % {map.config, sec.sectiontype}) + if #opt.title > 0 then + print (" option title '%s'" % util.striptags(opt.title)) + end + + if #opt.description > 0 then + print (" option description '%s'" % util.striptags(opt.description)) + end + + if not opt.rmempty and not opt.optional then + print (" option required true") + end + + if util.instanceof(opt, cbi.Flag) then + print (" option datatype boolean") + elseif util.instanceof(opt, cbi.DynamicList) then + print (" option type list") + elseif util.instanceof(opt, cbi.ListValue) then + print (" option type enum") + util.perror("*** Warning: Please verify '%s.%s.%s' ***" % + {map.config, sec.sectiontype, opt.option} ) + end + + for i, dep in ipairs(opt.deps) do + if not dep.add or dep.add == "" then + local depstring + for k, v in pairs(dep.deps) do + depstring = (depstring and depstring .. "," or "") .. "%s=%s" % {k, v} + end + print (" list depends '%s'" % depstring) + else + util.perror("*** Warning: Unable to decode dependency '%s' in '%s.%s.%s[%s]' ***" % + {util.serialize_data(dep.deps), map.config, sec.sectiontype, opt.option, dep.add}) + end + end + + if util.instanceof(opt, cbi.ListValue) then + for k, key in ipairs(opt.keylist) do + print ("\nconfig enum") + print (" option variable '%s.%s.%s'" % {map.config, sec.sectiontype, opt.option}) + print (" option value '%s'" % key) + if opt.vallist[k] and opt.vallist[k] ~= opt.keylist[k] then + print (" option title '%s'" % util.striptags(opt.vallist[k])) + end + end + end + end + end +end end diff --git a/openwrt/packages/luci/build/config.mk b/openwrt/packages/luci/build/config.mk new file mode 100644 index 0000000..bac250d --- /dev/null +++ b/openwrt/packages/luci/build/config.mk @@ -0,0 +1,16 @@ +LUAC = luac +LUAC_OPTIONS = -s +LUA_TARGET ?= source + +LUA_MODULEDIR = /usr/lib/lua +LUA_LIBRARYDIR = /usr/lib/lua + +LUCI_MODULEDIR = $(LUA_MODULEDIR)/luci +LUCI_LIBRARYDIR = $(LUA_LIBRARYDIR)/luci + +UVL_SCHEMEDIR = host/lib/uci/schema + +HTDOCS = /www + +LUA=$(shell which lua) +XSLTPROC=$(shell which xsltproc) diff --git a/openwrt/packages/luci/build/gccconfig.mk b/openwrt/packages/luci/build/gccconfig.mk new file mode 100644 index 0000000..d6af2c3 --- /dev/null +++ b/openwrt/packages/luci/build/gccconfig.mk @@ -0,0 +1,22 @@ +OS ?= $(shell uname) + +LUA_SHLIBS = $(shell pkg-config --silence-errors --libs lua5.1 || pkg-config --silence-errors --libs lua) +LUA_LIBS = $(if $(LUA_SHLIBS),$(LUA_SHLIBS),$(firstword $(wildcard /usr/lib/liblua.a /usr/local/lib/liblua.a /opt/local/lib/liblua.a))) +LUA_CFLAGS = $(shell pkg-config --silence-errors --cflags lua5.1 || pkg-config --silence-errors --cflags lua) + +CC = gcc +AR = ar +RANLIB = ranlib +CFLAGS = -O2 +FPIC = -fPIC +EXTRA_CFLAGS = --std=gnu99 +WFLAGS = -Wall -Werror -pedantic +CPPFLAGS = +COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) $(WFLAGS) +ifeq ($(OS),Darwin) + SHLIB_FLAGS = -bundle -undefined dynamic_lookup +else + SHLIB_FLAGS = -shared +endif +LINK = $(CC) $(LDFLAGS) + diff --git a/openwrt/packages/luci/build/hostenv.sh b/openwrt/packages/luci/build/hostenv.sh new file mode 100755 index 0000000..fbf7ca1 --- /dev/null +++ b/openwrt/packages/luci/build/hostenv.sh @@ -0,0 +1,7 @@ +#!/bin/sh +export LD_LIBRARY_PATH="$1/usr/lib:$LD_LIBRARY_PATH" +export PATH="$1/bin:$1/usr/bin:$PATH" +export LUA_PATH="$1/$2/?.lua;$1/$2/?/init.lua;;" +export LUA_CPATH="$1/$3/?.so;;" +export LUCI_SYSROOT="$1" +$4 diff --git a/openwrt/packages/luci/build/i18n-lua-xhtml1.xsl b/openwrt/packages/luci/build/i18n-lua-xhtml1.xsl new file mode 100644 index 0000000..53bd7be --- /dev/null +++ b/openwrt/packages/luci/build/i18n-lua-xhtml1.xsl @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + = ' + + + + + + + + + + + ' + + + + + + + < + + + > + + </ + + > + + + + <span class=" + + " + + > + + </span> + + + + <br + + /> + + + + <img + + /> + + + + + + + + xml: + + + =" + + + + + + + " + + + + + + + + + + + xml:lang=" + + " + lang=" + + " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openwrt/packages/luci/build/i18n-lua2xml.lua b/openwrt/packages/luci/build/i18n-lua2xml.lua new file mode 100755 index 0000000..674c8ad --- /dev/null +++ b/openwrt/packages/luci/build/i18n-lua2xml.lua @@ -0,0 +1,22 @@ +#!/usr/bin/lua +local util = require "luci.util" + +assert(arg[1]) + +local x = {} +local f = loadfile(arg[1]) +setfenv(f, x) +f() + +print '' +print '' +print '' +print '' + +for k, v in util.kspairs(x) do + print ('%s' % {k, v}) +end + +print '' +print '' + diff --git a/openwrt/packages/luci/build/i18n-xml2lua.sh b/openwrt/packages/luci/build/i18n-xml2lua.sh new file mode 100644 index 0000000..d70e135 --- /dev/null +++ b/openwrt/packages/luci/build/i18n-xml2lua.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# Copyright (C) 2008 Alina Friedrichsen +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +i18n_xml2lua() { + echo '' + echo + echo '' + echo + LANG=C sed -e 's/^\s*\([A-Za-z][0-9A-Za-z_]*\)\s*[=]\s*\[\[//' -e 's/\]\]\s*$/<\/i18n:msg>/' -e 's/^\s*\([A-Za-z][0-9A-Za-z_]*\)\s*[=]\s*["]\(.*\)["]\s*$/\2<\/i18n:msg>/' -e 's/^\s*$//' + echo + echo '' + return 0 +} + +for file in "$@"; do + i18n_xml2lua < "$file" > "$(dirname "$file")/$(basename "$file" .lua).xml" || exit 1 +done diff --git a/openwrt/packages/luci/build/makedocs.sh b/openwrt/packages/luci/build/makedocs.sh new file mode 100755 index 0000000..2f7f573 --- /dev/null +++ b/openwrt/packages/luci/build/makedocs.sh @@ -0,0 +1,2 @@ +luadoc -d $2 --no-files $(for f in $(find $1 -name '*.lua' -type f); do if grep -q -- "@return" $f; then echo $f; fi; done) +echo API-Documentation was created in $2. diff --git a/openwrt/packages/luci/build/mkversion.sh b/openwrt/packages/luci/build/mkversion.sh new file mode 100755 index 0000000..2361e5f --- /dev/null +++ b/openwrt/packages/luci/build/mkversion.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +local variant + +if [ "${4%%/*}" = "branches" ]; then + variant="LuCI ${4##*[-/]} Branch" +elif [ "${4%%/*}" = "tags" ]; then + variant="LuCI ${4##*[-/]} Release" +else + variant="LuCI Trunk" +fi + +cat < $1 +module "luci.version" + +distname = "${2:-OpenWrt}" +distversion = "${3:-Development Snapshot}" + +luciname = "$variant" +luciversion = "${5:-svn}" +EOF diff --git a/openwrt/packages/luci/build/module.mk b/openwrt/packages/luci/build/module.mk new file mode 100644 index 0000000..8f3964a --- /dev/null +++ b/openwrt/packages/luci/build/module.mk @@ -0,0 +1,42 @@ +MAKEPATH:=$(dir $(lastword $(MAKEFILE_LIST))) +-include $(MAKEPATH)config.mk +-include $(MAKEPATH)gccconfig.mk + +.PHONY: all build compile luacompile luasource clean luaclean + +all: build + +build: luabuild gccbuild + +luabuild: i18n lua$(LUA_TARGET) + +gccbuild: compile +compile: + +clean: luaclean + +i18n: + [ -n "$(XSLTPROC)" ] && for i in luasrc/i18n/*.xml; do [ "$$i" -nt "$${i%%[.]xml}.lua" ]\ + && $(XSLTPROC) $(MAKEPATH)i18n-lua-xhtml1.xsl $$i > $${i%%[.]xml}.lua; done || true + +luasource: + mkdir -p dist$(LUA_MODULEDIR) + mkdir -p dist$(LUCI_MODULEDIR) + mkdir -p dist$(HTDOCS) + cp -pR root/* dist 2>/dev/null || true + cp -pR luasrc/* dist$(LUCI_MODULEDIR) 2>/dev/null || true + cp -pR lua/* dist$(LUA_MODULEDIR) 2>/dev/null || true + cp -pR htdocs/* dist$(HTDOCS) 2>/dev/null || true + for i in $$(find dist -name .svn); do rm -rf $$i || true; done + for i in dist$(LUCI_MODULEDIR)/i18n/*.xml; do [ -f "$$i" ] && rm $$i; done || true + + +luastrip: luasource + for i in $$(find dist -type f -name '*.lua'); do perl -e 'undef $$/; open( F, "< $$ARGV[0]" ) || die $$!; $$src = ; close F; $$src =~ s/--\[\[.*?\]\](--)?//gs; $$src =~ s/^\s*--.*?\n//gm; open( F, "> $$ARGV[0]" ) || die $$!; print F $$src; close F' $$i; done + +luacompile: luasource + for i in $$(find dist -name *.lua -not -name debug.lua); do $(LUAC) $(LUAC_OPTIONS) -o $$i $$i; done + +luaclean: + rm -rf dist + diff --git a/openwrt/packages/luci/build/uvl2cbi.lua b/openwrt/packages/luci/build/uvl2cbi.lua new file mode 100644 index 0000000..08b3dc8 --- /dev/null +++ b/openwrt/packages/luci/build/uvl2cbi.lua @@ -0,0 +1,88 @@ +#!/usr/bin/lua +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: uvl2cbi.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local uvl = require "luci.uvl" +local util = require "luci.util" + +if not arg[1] then + util.perror("Usage %s scheme_name" % arg[0]) + os.exit(1) +end + + + +local scheme, error = uvl.UVL():get_scheme(arg[1]) + +if not scheme then + print( error:string() ) + os.exit(1) +end + + +print('cbimap = Map(%q, %q, %q)\n' + % { scheme.name, scheme.title or scheme.name, scheme.description or "" } ) + + +for sn, sv in util.kspairs(scheme.sections) do + print('%s = cbimap:section(TypedSection, %q, %q, %q)' + % { sn, sn, sv.title or "", sv.description or "" } ) + + if not sv.named then print('%s.anonymous = true' % sn) end + if not sv.unique then print('%s.addremove = true' % sn) end + if sv.dynamic then print('%s.dynamic = true' % sn) end + + if sv.depends then + for _, dep in ipairs(sv.depends) do + print('%s:depends(%s)' % { sn, util.serialize_data(dep) } ) + end + end + + print('') + + for vn, vv in util.kspairs(scheme.variables[sn]) do + if not vv.type or vv.type == "variable" then + print('%s = %s:option(%s, %q, %q, %q)' + % { vn, sn, vv.datatype == "boolean" and "Flag" or "Value", + vn, vv.title or "", vv.description or "" } ) + elseif vv.type == "enum" then + print('%s = %s:option(%s, %q, %q, %q)' + % { vn, sn, vv.multival and "MultiValue" or "ListValue", + vn, vv.title or "", vv.description or "" } ) + + for _, val in ipairs(vv.valuelist or {}) do + print('%s:value(%q, %q)' + % { vn, val.value, val.title or val.value } ) + end + elseif vv.type == "list" or vv.type == "lazylist" then + print('%s = %s:option(DynamicList, %q, %q, %q)' + % { vn, sn, vn, vv.title or "", vv.description or "" } ) + else + print('-- option: type(%s) ?' % { vv.type or "" } ) + end + + if vv.default then print('%s.default = %q' % { vn, vv.default } ) end + if vv.required then print('%s.optional = false' % vn ) end + if not vv.required then print('%s.rmempty = true' % vn ) end + + for _, dep in ipairs(vv.depends or {}) do + print('%s:depends(%s)' % { vn, util.serialize_data(dep) } ) + end + + print('') + end + + print('\nreturn cbimap') +end diff --git a/openwrt/packages/luci/build/uvl2i18n.lua b/openwrt/packages/luci/build/uvl2i18n.lua new file mode 100755 index 0000000..7d8c1e2 --- /dev/null +++ b/openwrt/packages/luci/build/uvl2i18n.lua @@ -0,0 +1,33 @@ +#!/usr/bin/lua +-- uvl2i18n.lua - Convert uvl schemes to i18n files +-- $Id: uvl2i18n.lua 3941 2008-12-23 21:39:38Z jow $ + +require("luci.util") +require("luci.uvl") + +local shm = luci.uvl.UVL():get_scheme(arg[1]) + +for s, o in luci.util.kspairs(shm.sections) do + print( string.format( '%s_%s = %q', shm.name, s:gsub("_",""), o.title or s ) ) + + if o.description and #o.description > 0 then + print( string.format( + '%s_%s_desc = %q', shm.name, s:gsub("_",""), o.description + ) ) + end + + for v, o in luci.util.kspairs(shm.variables[s]) do + print( string.format( + '%s_%s_%s = %q', shm.name, s:gsub("_",""), v:gsub("_",""), o.title or v + ) ) + + if o.description and #o.description > 0 then + print( string.format( + '%s_%s_%s_desc = %q', shm.name, s:gsub("_",""), + v:gsub("_",""), o.description + ) ) + end + end + + print() +end diff --git a/openwrt/packages/luci/build/uvldoc b/openwrt/packages/luci/build/uvldoc new file mode 100755 index 0000000..a6e9cc8 --- /dev/null +++ b/openwrt/packages/luci/build/uvldoc @@ -0,0 +1,24 @@ +#!/usr/bin/env lua +local fs = require "luci.fs" +local util = require "luci.util" +local uvldoc = require "luci.uvldoc.renderer" + +pcall(function() + require "uci" + require "luci.model.uci".cursor = function(config, save) + return uci.cursor(config or arg[1] .. "/etc/config", save or arg[1] .. "/tmp/.uci") + end +end) + +local schemes = {} +if not arg[4] or #arg[4] == 0 then + for i, name in ipairs(fs.dir(arg[2].."/default/")) do + if name ~= "." and name ~= ".." then + schemes[#schemes+1] = name + end + end +else + schemes = util.split(arg[4], "[,;%s]+", nil, true) +end + +uvldoc.Generator(schemes, arg[3], arg[2]):make() diff --git a/openwrt/packages/luci/build/zoneinfo2lua.pl b/openwrt/packages/luci/build/zoneinfo2lua.pl new file mode 100644 index 0000000..6a2211b --- /dev/null +++ b/openwrt/packages/luci/build/zoneinfo2lua.pl @@ -0,0 +1,138 @@ +#!/usr/bin/perl +# zoneinfo2lua.pl - Make Lua module from /usr/share/zoneinfo +# Execute from within /usr/share/zoneinfo +# $Id: zoneinfo2lua.pl 3941 2008-12-23 21:39:38Z jow $ + +use strict; + +my %TZ; + +local $/ = "\012"; +open( ZTAB, "< ./zone.tab" ) || die "Unable to open zone.tab: $!"; + +while( ! eof ZTAB ) { + chomp( my $line = readline ZTAB ); + next if $line =~ /^#/ || $line =~ /^\s+$/; + + my ( undef, undef, $zone, @comment ) = split /\s+/, $line; + + printf STDERR "%-40s", $zone; + + if( open ZONE, "< ./$zone" ) { + seek ZONE, -2, 2; + + while( tell(ZONE) > 0 ) { + read ZONE, my $char, 1; + ( $char eq "\012" ) ? last : seek ZONE, -2, 1; + } + + chomp( my $tz = readline ZONE ); + print STDERR ( $tz || "(no tzinfo found)" ), "\n"; + close ZONE; + + if( $tz ) { + $zone =~ s/_/ /g; + $TZ{$zone} = $tz; + } + } + else + { + print STDERR "Unable to open $zone: $!\n"; + } +} + +close ZTAB; + + +print <server_name, value, MAXREQUESTLENGTH); + } ++ else if (strcmp(buf, "Content-Type:") == 0 ) ++ { ++ my_strncpy(cn->content_type, value, MAXREQUESTLENGTH); ++ } + else if (strcmp(buf, "Connection:") == 0 && strcmp(value, "close") == 0) + { + cn->close_when_done = 1; +@@ -673,8 +677,9 @@ + type = "POST"; + sprintf(cgienv[cgi_index++], + "CONTENT_LENGTH=%d", cn->content_length); +- strcpy(cgienv[cgi_index++], /* hard-code? */ +- "CONTENT_TYPE=application/x-www-form-urlencoded"); ++ snprintf(cgienv[cgi_index++], MAXREQUESTLENGTH, ++ "CONTENT_TYPE=%s", cn->content_type); ++ + break; + } + diff --git a/openwrt/packages/luci/contrib/axtls/patches/004-cgi-nph-mode.patch b/openwrt/packages/luci/contrib/axtls/patches/004-cgi-nph-mode.patch new file mode 100644 index 0000000..2b6cc5c --- /dev/null +++ b/openwrt/packages/luci/contrib/axtls/patches/004-cgi-nph-mode.patch @@ -0,0 +1,20 @@ +--- axTLS/httpd/proc.c 2008-11-13 14:05:02.000000000 +0100 ++++ axTLS.new/httpd/proc.c 2008-11-13 16:07:12.000000000 +0100 +@@ -556,13 +556,13 @@ + int tmp_stdout; + #endif + +- snprintf(cgienv[0], MAXREQUESTLENGTH, ++ if (cn->reqtype == TYPE_HEAD) ++ { ++ snprintf(cgienv[0], MAXREQUESTLENGTH, + HTTP_VERSION" 200 OK\nServer: %s\n%s", + server_version, (cn->reqtype == TYPE_HEAD) ? "\n" : ""); +- special_write(cn, cgienv[0], strlen(cgienv[0])); ++ special_write(cn, cgienv[0], strlen(cgienv[0])); + +- if (cn->reqtype == TYPE_HEAD) +- { + removeconnection(cn); + return; + } diff --git a/openwrt/packages/luci/contrib/bitlib/.gitignore b/openwrt/packages/luci/contrib/bitlib/.gitignore new file mode 100644 index 0000000..7211268 --- /dev/null +++ b/openwrt/packages/luci/contrib/bitlib/.gitignore @@ -0,0 +1 @@ +bitlib-* diff --git a/openwrt/packages/luci/contrib/bitlib/Makefile b/openwrt/packages/luci/contrib/bitlib/Makefile new file mode 100644 index 0000000..ea08c97 --- /dev/null +++ b/openwrt/packages/luci/contrib/bitlib/Makefile @@ -0,0 +1,36 @@ +include ../../build/config.mk +include ../../build/gccconfig.mk + +BITLIB_VERSION = 25 +BITLIB_SITE = http://dev.luci.freifunk-halle.net/sources/ +BITLIB_DIR = bitlib-$(BITLIB_VERSION) +BITLIB_FILE = $(BITLIB_DIR).tar.gz +BITLIB_URL = $(BITLIB_SITE)/$(BITLIB_FILE) + +all: compile + +include ../../build/module.mk + +$(BITLIB_FILE): + wget -O $@ $(BITLIB_URL) || rm -f $@ + +$(BITLIB_DIR)/.prepared: $(BITLIB_FILE) + rm -rf $(BITLIB_DIR) + tar xvfz $(BITLIB_FILE) + test -f $(BITLIB_DIR)/config.h || cp $(BITLIB_DIR)/config.h.in $(BITLIB_DIR)/config.h + touch $@ + +compile: $(BITLIB_DIR)/.prepared dist$(LUA_LIBRARYDIR)/bit.so + +dist$(LUA_LIBRARYDIR)/bit.so: + mkdir -p dist$(LUA_LIBRARYDIR) + $(COMPILE) -DHAVE_CONFIG_H -I$(BITLIB_DIR) -O2 -c $(BITLIB_DIR)/lbitlib.c $(FPIC) $(LUA_CFLAGS) -o $(BITLIB_DIR)/lbitlib.o + $(LINK) $(SHLIB_FLAGS) $(LDFLAGS) $(BITLIB_DIR)/lbitlib.o $(LUA_SHLIBS) -lm -ldl -o dist$(LUA_LIBRARYDIR)/bit.so + +luasource: +luastrip: +luacompile: +compile-all: compile + +clean: + rm -rf $(BITLIB_DIR) $(BITLIB_FILE) diff --git a/openwrt/packages/luci/contrib/lpeg/.gitignore b/openwrt/packages/luci/contrib/lpeg/.gitignore new file mode 100644 index 0000000..8cb74f1 --- /dev/null +++ b/openwrt/packages/luci/contrib/lpeg/.gitignore @@ -0,0 +1 @@ +lpeg-* diff --git a/openwrt/packages/luci/contrib/lpeg/Makefile b/openwrt/packages/luci/contrib/lpeg/Makefile new file mode 100644 index 0000000..90f4208 --- /dev/null +++ b/openwrt/packages/luci/contrib/lpeg/Makefile @@ -0,0 +1,33 @@ +include ../../build/config.mk +include ../../build/gccconfig.mk + +LPEG_VERSION = 0.8.1 +LPEG_SITE = http://www.inf.puc-rio.br/~roberto/lpeg +LPEG_DIR = lpeg-$(LPEG_VERSION) +LPEG_FILE = $(LPEG_DIR).tar.gz +LPEG_URL = $(LPEG_SITE)/$(LPEG_FILE) + +all: compile + +include ../../build/module.mk + +$(LPEG_FILE): + wget -O $@ $(LPEG_URL) || rm -f $@ + +$(LPEG_DIR)/.prepared: $(LPEG_FILE) + rm -rf $(LPEG_DIR) + tar xvfz $(LPEG_FILE) + touch $@ + +compile: $(LPEG_DIR)/.prepared + $(MAKE) -C $(LPEG_DIR) CC=$(CC) COPT="$(CFLAGS) $(LUA_CFLAGS) -fpic" + mkdir -p dist$(LUA_LIBRARYDIR) + cp $(LPEG_DIR)/{lpeg.so,re.lua} dist$(LUA_LIBRARYDIR) + +luasource: +luastrip: +luacompile: +compile-all: compile + +clean: + rm -rf $(LPEG_DIR) $(LPEG_FILE) diff --git a/openwrt/packages/luci/contrib/luacurses/Makefile b/openwrt/packages/luci/contrib/luacurses/Makefile new file mode 100644 index 0000000..2ae73bf --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/Makefile @@ -0,0 +1,10 @@ +include ../../build/module.mk +include ../../build/config.mk +include ../../build/gccconfig.mk + +compile: dist$(LUA_LIBRARYDIR)/curses.so + +dist$(LUA_LIBRARYDIR)/curses.so: + mkdir -p dist$(LUA_LIBRARYDIR) + $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) $(SHLIB_FLAGS) -pedantic \ + -Wall $(FPIC) $(LUA_CFLAGS) -o dist$(LUA_LIBRARYDIR)/curses.so src/curses.c src/luacurses.c diff --git a/openwrt/packages/luci/contrib/luacurses/doc/curses.pdf b/openwrt/packages/luci/contrib/luacurses/doc/curses.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b4dd7529d3de7cb2e8d60383b45063adb5f67e91 GIT binary patch literal 39485 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/contrib/luacurses/src/curses.c b/openwrt/packages/luci/contrib/luacurses/src/curses.c new file mode 100644 index 0000000..9e6760a --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/src/curses.c @@ -0,0 +1,3630 @@ +#include +#include + +#include +#include +#include + +typedef struct mklualib_regnum +{ + const char* name; + lua_Number num; +} mklualib_regnum; + +void mklualib_regstring(lua_State* L, const char* name, const char* s) +{ + lua_pushstring(L, name); + lua_pushstring(L, s); + lua_settable(L, -3); +} + +void mklualib_regchar(lua_State* L, const char* name, char c) +{ + lua_pushstring(L, name); + lua_pushlstring(L, &c, 1); + lua_settable(L, -3); +} + +void mklualib_regnumbers(lua_State* L, const mklualib_regnum* l) +{ + for (; l->name; l++) + { + lua_pushstring(L, l->name); + lua_pushnumber(L, l->num); + lua_settable(L, -3); + } +} + + +#include +#include "luacurses.h" +#define MKLUALIB_MODULE_CURSES "curses" +/* curses.COLORS*/ +int mklualib_curses_COLORS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_COLORS_ret = (int) COLORS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_COLORS_ret); + return 1; +} + +/* curses.COLOR_PAIRS*/ +int mklualib_curses_COLOR_PAIRS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_COLOR_PAIRS_ret = (int) COLOR_PAIRS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_COLOR_PAIRS_ret); + return 1; +} + +/* curses.NCURSES_ACS*/ +int mklualib_curses_NCURSES_ACS(lua_State* mklualib_lua_state) +{ + char c = (char) lua_tostring(mklualib_lua_state, 1)[0]; + int mklualib_curses_NCURSES_ACS_ret = (int) NCURSES_ACS(c); + lua_pushnumber(mklualib_lua_state, mklualib_curses_NCURSES_ACS_ret); + return 1; +} + +/* curses.ACS_ULCORNER*/ +int mklualib_curses_ACS_ULCORNER(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_ULCORNER_ret = (int) ACS_ULCORNER; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_ULCORNER_ret); + return 1; +} + +/* curses.ACS_LLCORNER*/ +int mklualib_curses_ACS_LLCORNER(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_LLCORNER_ret = (int) ACS_LLCORNER; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_LLCORNER_ret); + return 1; +} + +/* curses.ACS_URCORNER*/ +int mklualib_curses_ACS_URCORNER(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_URCORNER_ret = (int) ACS_URCORNER; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_URCORNER_ret); + return 1; +} + +/* curses.ACS_LRCORNER*/ +int mklualib_curses_ACS_LRCORNER(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_LRCORNER_ret = (int) ACS_LRCORNER; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_LRCORNER_ret); + return 1; +} + +/* curses.ACS_LTEE*/ +int mklualib_curses_ACS_LTEE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_LTEE_ret = (int) ACS_LTEE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_LTEE_ret); + return 1; +} + +/* curses.ACS_RTEE*/ +int mklualib_curses_ACS_RTEE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_RTEE_ret = (int) ACS_RTEE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_RTEE_ret); + return 1; +} + +/* curses.ACS_BTEE*/ +int mklualib_curses_ACS_BTEE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BTEE_ret = (int) ACS_BTEE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BTEE_ret); + return 1; +} + +/* curses.ACS_TTEE*/ +int mklualib_curses_ACS_TTEE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_TTEE_ret = (int) ACS_TTEE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_TTEE_ret); + return 1; +} + +/* curses.ACS_HLINE*/ +int mklualib_curses_ACS_HLINE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_HLINE_ret = (int) ACS_HLINE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_HLINE_ret); + return 1; +} + +/* curses.ACS_VLINE*/ +int mklualib_curses_ACS_VLINE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_VLINE_ret = (int) ACS_VLINE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_VLINE_ret); + return 1; +} + +/* curses.ACS_PLUS*/ +int mklualib_curses_ACS_PLUS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_PLUS_ret = (int) ACS_PLUS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_PLUS_ret); + return 1; +} + +/* curses.ACS_S1*/ +int mklualib_curses_ACS_S1(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_S1_ret = (int) ACS_S1; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_S1_ret); + return 1; +} + +/* curses.ACS_S9*/ +int mklualib_curses_ACS_S9(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_S9_ret = (int) ACS_S9; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_S9_ret); + return 1; +} + +/* curses.ACS_DIAMOND*/ +int mklualib_curses_ACS_DIAMOND(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_DIAMOND_ret = (int) ACS_DIAMOND; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_DIAMOND_ret); + return 1; +} + +/* curses.ACS_CKBOARD*/ +int mklualib_curses_ACS_CKBOARD(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_CKBOARD_ret = (int) ACS_CKBOARD; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_CKBOARD_ret); + return 1; +} + +/* curses.ACS_DEGREE*/ +int mklualib_curses_ACS_DEGREE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_DEGREE_ret = (int) ACS_DEGREE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_DEGREE_ret); + return 1; +} + +/* curses.ACS_PLMINUS*/ +int mklualib_curses_ACS_PLMINUS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_PLMINUS_ret = (int) ACS_PLMINUS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_PLMINUS_ret); + return 1; +} + +/* curses.ACS_BULLET*/ +int mklualib_curses_ACS_BULLET(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BULLET_ret = (int) ACS_BULLET; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BULLET_ret); + return 1; +} + +/* curses.ACS_LARROW*/ +int mklualib_curses_ACS_LARROW(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_LARROW_ret = (int) ACS_LARROW; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_LARROW_ret); + return 1; +} + +/* curses.ACS_RARROW*/ +int mklualib_curses_ACS_RARROW(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_RARROW_ret = (int) ACS_RARROW; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_RARROW_ret); + return 1; +} + +/* curses.ACS_DARROW*/ +int mklualib_curses_ACS_DARROW(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_DARROW_ret = (int) ACS_DARROW; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_DARROW_ret); + return 1; +} + +/* curses.ACS_UARROW*/ +int mklualib_curses_ACS_UARROW(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_UARROW_ret = (int) ACS_UARROW; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_UARROW_ret); + return 1; +} + +/* curses.ACS_BOARD*/ +int mklualib_curses_ACS_BOARD(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BOARD_ret = (int) ACS_BOARD; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BOARD_ret); + return 1; +} + +/* curses.ACS_LANTERN*/ +int mklualib_curses_ACS_LANTERN(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_LANTERN_ret = (int) ACS_LANTERN; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_LANTERN_ret); + return 1; +} + +/* curses.ACS_BLOCK*/ +int mklualib_curses_ACS_BLOCK(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BLOCK_ret = (int) ACS_BLOCK; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BLOCK_ret); + return 1; +} + +/* curses.ACS_S3*/ +int mklualib_curses_ACS_S3(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_S3_ret = (int) ACS_S3; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_S3_ret); + return 1; +} + +/* curses.ACS_S7*/ +int mklualib_curses_ACS_S7(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_S7_ret = (int) ACS_S7; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_S7_ret); + return 1; +} + +/* curses.ACS_LEQUAL*/ +int mklualib_curses_ACS_LEQUAL(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_LEQUAL_ret = (int) ACS_LEQUAL; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_LEQUAL_ret); + return 1; +} + +/* curses.ACS_GEQUAL*/ +int mklualib_curses_ACS_GEQUAL(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_GEQUAL_ret = (int) ACS_GEQUAL; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_GEQUAL_ret); + return 1; +} + +/* curses.ACS_PI*/ +int mklualib_curses_ACS_PI(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_PI_ret = (int) ACS_PI; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_PI_ret); + return 1; +} + +/* curses.ACS_NEQUAL*/ +int mklualib_curses_ACS_NEQUAL(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_NEQUAL_ret = (int) ACS_NEQUAL; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_NEQUAL_ret); + return 1; +} + +/* curses.ACS_STERLING*/ +int mklualib_curses_ACS_STERLING(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_STERLING_ret = (int) ACS_STERLING; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_STERLING_ret); + return 1; +} + +/* curses.ACS_BSSB*/ +int mklualib_curses_ACS_BSSB(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BSSB_ret = (int) ACS_BSSB; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BSSB_ret); + return 1; +} + +/* curses.ACS_SSBB*/ +int mklualib_curses_ACS_SSBB(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_SSBB_ret = (int) ACS_SSBB; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_SSBB_ret); + return 1; +} + +/* curses.ACS_BBSS*/ +int mklualib_curses_ACS_BBSS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BBSS_ret = (int) ACS_BBSS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BBSS_ret); + return 1; +} + +/* curses.ACS_SBBS*/ +int mklualib_curses_ACS_SBBS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_SBBS_ret = (int) ACS_SBBS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_SBBS_ret); + return 1; +} + +/* curses.ACS_SBSS*/ +int mklualib_curses_ACS_SBSS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_SBSS_ret = (int) ACS_SBSS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_SBSS_ret); + return 1; +} + +/* curses.ACS_SSSB*/ +int mklualib_curses_ACS_SSSB(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_SSSB_ret = (int) ACS_SSSB; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_SSSB_ret); + return 1; +} + +/* curses.ACS_SSBS*/ +int mklualib_curses_ACS_SSBS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_SSBS_ret = (int) ACS_SSBS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_SSBS_ret); + return 1; +} + +/* curses.ACS_BSSS*/ +int mklualib_curses_ACS_BSSS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BSSS_ret = (int) ACS_BSSS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BSSS_ret); + return 1; +} + +/* curses.ACS_BSBS*/ +int mklualib_curses_ACS_BSBS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_BSBS_ret = (int) ACS_BSBS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_BSBS_ret); + return 1; +} + +/* curses.ACS_SBSB*/ +int mklualib_curses_ACS_SBSB(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_SBSB_ret = (int) ACS_SBSB; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_SBSB_ret); + return 1; +} + +/* curses.ACS_SSSS*/ +int mklualib_curses_ACS_SSSS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ACS_SSSS_ret = (int) ACS_SSSS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ACS_SSSS_ret); + return 1; +} + +/* curses.delscreen */ +/* SCREEN*:delscreen */ +int mklualib_curses_delscreen(lua_State* mklualib_lua_state) +{ + SCREEN* _arg0 = luacurses_toscreen(mklualib_lua_state, 1); + delscreen(_arg0); + return 0; +} + +/* curses.set_term */ +/* SCREEN*:set_term */ +int mklualib_curses_set_term(lua_State* mklualib_lua_state) +{ + SCREEN* _arg0 = luacurses_toscreen(mklualib_lua_state, 1); + SCREEN* mklualib_curses_set_term_ret = (SCREEN*) set_term(_arg0); + SCREEN** mklualib_curses_set_term_ret_retptr = luacurses_newscreen(mklualib_lua_state); + *mklualib_curses_set_term_ret_retptr = mklualib_curses_set_term_ret; + return 1; +} + +/* SCREEN*:__tostring */ +int mklualib_curses_screen___tostring(lua_State* mklualib_lua_state) +{ + SCREEN* s = luacurses_toscreen(mklualib_lua_state, 1); + char* mklualib_curses_screen___tostring_ret = (char*) luacurses_screen_tostring(s); + lua_pushstring(mklualib_lua_state, mklualib_curses_screen___tostring_ret); + free(mklualib_curses_screen___tostring_ret); + return 1; +} + +/* SCREEN*:__gc */ +int mklualib_curses_screen___gc(lua_State* mklualib_lua_state) +{ + SCREEN* s = luacurses_toscreen(mklualib_lua_state, 1); + luacurses_screen_free(s); + return 0; +} + +/* WINDOW*:__tostring */ +int mklualib_curses_window___tostring(lua_State* mklualib_lua_state) +{ + WINDOW* w = luacurses_towindow(mklualib_lua_state, 1); + char* mklualib_curses_window___tostring_ret = (char*) luacurses_window_tostring(w); + lua_pushstring(mklualib_lua_state, mklualib_curses_window___tostring_ret); + free(mklualib_curses_window___tostring_ret); + return 1; +} + +/* WINDOW*:__gc */ +int mklualib_curses_window___gc(lua_State* mklualib_lua_state) +{ + WINDOW* w = luacurses_towindow(mklualib_lua_state, 1); + luacurses_window_free(w); + return 0; +} + +/* curses.box */ +/* WINDOW*:box */ +int mklualib_curses_box(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + chtype _arg2 = (chtype) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_box_ret = (int) box(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_box_ret); + return 1; +} + +/* curses.clearok */ +/* WINDOW*:clearok */ +int mklualib_curses_clearok(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_clearok_ret = (int) clearok(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_clearok_ret); + return 1; +} + +/* curses.delwin */ +/* WINDOW*:delwin */ +int mklualib_curses_delwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_delwin_ret = (int) delwin(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_delwin_ret); + return 1; +} + +/* curses.derwin */ +/* WINDOW*:derwin */ +int mklualib_curses_derwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + WINDOW* mklualib_curses_derwin_ret = (WINDOW*) derwin(_arg0, _arg1, _arg2, _arg3, _arg4); + WINDOW** mklualib_curses_derwin_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_derwin_ret_retptr = mklualib_curses_derwin_ret; + return 1; +} + +/* curses.dupwin */ +/* WINDOW*:dupwin */ +int mklualib_curses_dupwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + WINDOW* mklualib_curses_dupwin_ret = (WINDOW*) dupwin(_arg0); + WINDOW** mklualib_curses_dupwin_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_dupwin_ret_retptr = mklualib_curses_dupwin_ret; + return 1; +} + +/* curses.getbkgd */ +/* WINDOW*:getbkgd */ +int mklualib_curses_getbkgd(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype mklualib_curses_getbkgd_ret = (chtype) getbkgd(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_getbkgd_ret); + return 1; +} + +/* curses.idcok */ +/* WINDOW*:idcok */ +int mklualib_curses_idcok(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + idcok(_arg0, _arg1); + return 0; +} + +/* curses.idlok */ +/* WINDOW*:idlok */ +int mklualib_curses_idlok(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_idlok_ret = (int) idlok(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_idlok_ret); + return 1; +} + +/* curses.immedok */ +/* WINDOW*:immedok */ +int mklualib_curses_immedok(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + immedok(_arg0, _arg1); + return 0; +} + +/* curses.intrflush */ +/* WINDOW*:intrflush */ +int mklualib_curses_intrflush(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_intrflush_ret = (int) intrflush(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_intrflush_ret); + return 1; +} + +/* curses.is_linetouched */ +/* WINDOW*:is_linetouched */ +int mklualib_curses_is_linetouched(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_is_linetouched_ret = (bool) is_linetouched(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_is_linetouched_ret); + return 1; +} + +/* curses.is_wintouched */ +/* WINDOW*:is_wintouched */ +int mklualib_curses_is_wintouched(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool mklualib_curses_is_wintouched_ret = (bool) is_wintouched(_arg0); + lua_pushboolean(mklualib_lua_state, mklualib_curses_is_wintouched_ret); + return 1; +} + +/* curses.keypad */ +/* WINDOW*:keypad */ +int mklualib_curses_keypad(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_keypad_ret = (int) keypad(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_keypad_ret); + return 1; +} + +/* curses.leaveok */ +/* WINDOW*:leaveok */ +int mklualib_curses_leaveok(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_leaveok_ret = (int) leaveok(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_leaveok_ret); + return 1; +} + +/* curses.meta */ +/* WINDOW*:meta */ +int mklualib_curses_meta(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_meta_ret = (int) meta(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_meta_ret); + return 1; +} + +/* curses.mvderwin */ +/* WINDOW*:mvderwin */ +int mklualib_curses_mvderwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_mvderwin_ret = (int) mvderwin(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvderwin_ret); + return 1; +} + +/* curses.mvwaddch */ +/* WINDOW*:mvaddch */ +int mklualib_curses_mvwaddch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + chtype _arg3 = (chtype) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvwaddch_ret = (int) mvwaddch(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwaddch_ret); + return 1; +} + +/* curses.mvwaddstr */ +/* WINDOW*:mvaddstr */ +int mklualib_curses_mvwaddstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + char* _arg3 = (char*) lua_tostring(mklualib_lua_state, 4); + int mklualib_curses_mvwaddstr_ret = (int) mvwaddstr(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwaddstr_ret); + return 1; +} + +/* curses.mvwchgat */ +/* WINDOW*:mvchgat */ +int mklualib_curses_mvwchgat(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + attr_t _arg4 = (attr_t) lua_tonumber(mklualib_lua_state, 5); + short _arg5 = (short) lua_tonumber(mklualib_lua_state, 6); + int mklualib_curses_mvwchgat_ret = (int) mvwchgat(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwchgat_ret); + return 1; +} + +/* curses.mvwdelch */ +/* WINDOW*:mvdelch */ +int mklualib_curses_mvwdelch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_mvwdelch_ret = (int) mvwdelch(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwdelch_ret); + return 1; +} + +/* curses.mvwgetch */ +/* WINDOW*:mvgetch */ +int mklualib_curses_mvwgetch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_mvwgetch_ret = (int) mvwgetch(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwgetch_ret); + return 1; +} + +/* curses.mvwgetnstr */ +/* WINDOW*:mvgetnstr */ +int mklualib_curses_mvwgetnstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + char* mklualib_curses_mvwgetnstr_ret = (char*) luacurses_mvwgetnstr(_arg0, _arg1, _arg2, _arg3); + lua_pushstring(mklualib_lua_state, mklualib_curses_mvwgetnstr_ret); + return 1; +} + +/* curses.mvwhline */ +/* WINDOW*:mvhline */ +int mklualib_curses_mvwhline(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + chtype _arg3 = (chtype) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + int mklualib_curses_mvwhline_ret = (int) mvwhline(_arg0, _arg1, _arg2, _arg3, _arg4); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwhline_ret); + return 1; +} + +/* curses.mvwin */ +/* WINDOW*:mvin */ +int mklualib_curses_mvwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_mvwin_ret = (int) mvwin(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwin_ret); + return 1; +} + +/* curses.mvwinch */ +/* WINDOW*:mvinch */ +int mklualib_curses_mvwinch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + chtype mklualib_curses_mvwinch_ret = (chtype) mvwinch(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwinch_ret); + return 1; +} + +/* curses.mvwinnstr */ +/* WINDOW*:mvinnstr */ +int mklualib_curses_mvwinnstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + char* _arg3 = (char*) lua_tostring(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + int mklualib_curses_mvwinnstr_ret = (int) mvwinnstr(_arg0, _arg1, _arg2, _arg3, _arg4); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwinnstr_ret); + return 1; +} + +/* curses.mvwinsch */ +/* WINDOW*:mvinsch */ +int mklualib_curses_mvwinsch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + chtype _arg3 = (chtype) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvwinsch_ret = (int) mvwinsch(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwinsch_ret); + return 1; +} + +/* curses.mvwinsnstr */ +/* WINDOW*:mvinsnstr */ +int mklualib_curses_mvwinsnstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + char* _arg3 = (char*) lua_tostring(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + int mklualib_curses_mvwinsnstr_ret = (int) mvwinsnstr(_arg0, _arg1, _arg2, _arg3, _arg4); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwinsnstr_ret); + return 1; +} + +/* curses.mvwinsstr */ +/* WINDOW*:mvinsstr */ +int mklualib_curses_mvwinsstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + char* _arg3 = (char*) lua_tostring(mklualib_lua_state, 4); + int mklualib_curses_mvwinsstr_ret = (int) mvwinsstr(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwinsstr_ret); + return 1; +} + +/* curses.mvwinstr */ +/* WINDOW*:mvinstr */ +int mklualib_curses_mvwinstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + char* _arg3 = (char*) lua_tostring(mklualib_lua_state, 4); + int mklualib_curses_mvwinstr_ret = (int) mvwinstr(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwinstr_ret); + return 1; +} + +/* curses.mvwvline */ +/* WINDOW*:mvvline */ +int mklualib_curses_mvwvline(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + chtype _arg3 = (chtype) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + int mklualib_curses_mvwvline_ret = (int) mvwvline(_arg0, _arg1, _arg2, _arg3, _arg4); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvwvline_ret); + return 1; +} + +/* curses.nodelay */ +/* WINDOW*:nodelay */ +int mklualib_curses_nodelay(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_nodelay_ret = (int) nodelay(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_nodelay_ret); + return 1; +} + +/* curses.notimeout */ +/* WINDOW*:notimeout */ +int mklualib_curses_notimeout(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_notimeout_ret = (int) notimeout(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_notimeout_ret); + return 1; +} + +/* curses.pechochar */ +/* WINDOW*:pechochar */ +int mklualib_curses_pechochar(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_pechochar_ret = (int) pechochar(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_pechochar_ret); + return 1; +} + +/* curses.pnoutrefresh */ +/* WINDOW*:pnoutrefresh */ +int mklualib_curses_pnoutrefresh(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + int _arg5 = (int) lua_tonumber(mklualib_lua_state, 6); + int _arg6 = (int) lua_tonumber(mklualib_lua_state, 7); + int mklualib_curses_pnoutrefresh_ret = (int) pnoutrefresh(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6); + lua_pushnumber(mklualib_lua_state, mklualib_curses_pnoutrefresh_ret); + return 1; +} + +/* curses.prefresh */ +/* WINDOW*:prefresh */ +int mklualib_curses_prefresh(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + int _arg5 = (int) lua_tonumber(mklualib_lua_state, 6); + int _arg6 = (int) lua_tonumber(mklualib_lua_state, 7); + int mklualib_curses_prefresh_ret = (int) prefresh(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6); + lua_pushnumber(mklualib_lua_state, mklualib_curses_prefresh_ret); + return 1; +} + +/* curses.putwin */ +/* WINDOW*:putwin */ +int mklualib_curses_putwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + FILE* _arg1 = tofile(mklualib_lua_state, 2); + int mklualib_curses_putwin_ret = (int) putwin(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_putwin_ret); + return 1; +} + +/* curses.redrawwin */ +/* WINDOW*:redrawwin */ +int mklualib_curses_redrawwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_redrawwin_ret = (int) redrawwin(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_redrawwin_ret); + return 1; +} + +/* curses.scroll */ +/* WINDOW*:scroll */ +int mklualib_curses_scroll(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_scroll_ret = (int) scroll(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_scroll_ret); + return 1; +} + +/* curses.scrollok */ +/* WINDOW*:scrollok */ +int mklualib_curses_scrollok(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_scrollok_ret = (int) scrollok(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_scrollok_ret); + return 1; +} + +/* curses.touchline */ +/* WINDOW*:touchline */ +int mklualib_curses_touchline(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_touchline_ret = (int) touchline(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_touchline_ret); + return 1; +} + +/* curses.touchwin */ +/* WINDOW*:touchwin */ +int mklualib_curses_touchwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_touchwin_ret = (int) touchwin(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_touchwin_ret); + return 1; +} + +/* curses.untouchwin */ +/* WINDOW*:untouchwin */ +int mklualib_curses_untouchwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_untouchwin_ret = (int) untouchwin(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_untouchwin_ret); + return 1; +} + +/* curses.waddch */ +/* WINDOW*:addch */ +int mklualib_curses_waddch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_waddch_ret = (int) waddch(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_waddch_ret); + return 1; +} + +/* curses.waddnstr */ +/* WINDOW*:addnstr */ +int mklualib_curses_waddnstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + char* _arg1 = (char*) lua_tostring(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_waddnstr_ret = (int) waddnstr(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_waddnstr_ret); + return 1; +} + +/* curses.waddstr */ +/* WINDOW*:addstr */ +int mklualib_curses_waddstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + char* _arg1 = (char*) lua_tostring(mklualib_lua_state, 2); + int mklualib_curses_waddstr_ret = (int) waddstr(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_waddstr_ret); + return 1; +} + +/* curses.wattron */ +/* WINDOW*:attron */ +int mklualib_curses_wattron(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wattron_ret = (int) wattron(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wattron_ret); + return 1; +} + +/* curses.wattroff */ +/* WINDOW*:attroff */ +int mklualib_curses_wattroff(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wattroff_ret = (int) wattroff(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wattroff_ret); + return 1; +} + +/* curses.wattrset */ +/* WINDOW*:attrset */ +int mklualib_curses_wattrset(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wattrset_ret = (int) wattrset(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wattrset_ret); + return 1; +} + +/* curses.wattr_get */ +/* WINDOW*:attr_get */ +int mklualib_curses_wattr_get(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + attr_t _arg1; + short _arg2; + int mklualib_curses_wattr_get_ret = (int) wattr_get(_arg0, &_arg1, &_arg2, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wattr_get_ret); + lua_pushnumber(mklualib_lua_state, _arg1); + lua_pushnumber(mklualib_lua_state, _arg2); + return 3; +} + +/* curses.wattr_on */ +/* WINDOW*:attr_on */ +int mklualib_curses_wattr_on(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + attr_t _arg1 = (attr_t) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wattr_on_ret = (int) wattr_on(_arg0, _arg1, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wattr_on_ret); + return 1; +} + +/* curses.wattr_off */ +/* WINDOW*:attr_off */ +int mklualib_curses_wattr_off(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + attr_t _arg1 = (attr_t) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wattr_off_ret = (int) wattr_off(_arg0, _arg1, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wattr_off_ret); + return 1; +} + +/* curses.wattr_set */ +/* WINDOW*:attr_set */ +int mklualib_curses_wattr_set(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + attr_t _arg1 = (attr_t) lua_tonumber(mklualib_lua_state, 2); + short _arg2 = (short) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_wattr_set_ret = (int) wattr_set(_arg0, _arg1, _arg2, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wattr_set_ret); + return 1; +} + +/* curses.wbkgd */ +/* WINDOW*:bkgd */ +int mklualib_curses_wbkgd(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wbkgd_ret = (int) wbkgd(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wbkgd_ret); + return 1; +} + +/* curses.wbkgdset */ +/* WINDOW*:bkgdset */ +int mklualib_curses_wbkgdset(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + wbkgdset(_arg0, _arg1); + return 0; +} + +/* curses.wborder */ +/* WINDOW*:border */ +int mklualib_curses_wborder(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + chtype _arg2 = (chtype) lua_tonumber(mklualib_lua_state, 3); + chtype _arg3 = (chtype) lua_tonumber(mklualib_lua_state, 4); + chtype _arg4 = (chtype) lua_tonumber(mklualib_lua_state, 5); + chtype _arg5 = (chtype) lua_tonumber(mklualib_lua_state, 6); + chtype _arg6 = (chtype) lua_tonumber(mklualib_lua_state, 7); + chtype _arg7 = (chtype) lua_tonumber(mklualib_lua_state, 8); + chtype _arg8 = (chtype) lua_tonumber(mklualib_lua_state, 9); + int mklualib_curses_wborder_ret = (int) wborder(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wborder_ret); + return 1; +} + +/* curses.wchgat */ +/* WINDOW*:chgat */ +int mklualib_curses_wchgat(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + attr_t _arg2 = (attr_t) lua_tonumber(mklualib_lua_state, 3); + short _arg3 = (short) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_wchgat_ret = (int) wchgat(_arg0, _arg1, _arg2, _arg3, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wchgat_ret); + return 1; +} + +/* curses.wclear */ +/* WINDOW*:clear */ +int mklualib_curses_wclear(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wclear_ret = (int) wclear(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wclear_ret); + return 1; +} + +/* curses.wclrtobot */ +/* WINDOW*:clrtobot */ +int mklualib_curses_wclrtobot(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wclrtobot_ret = (int) wclrtobot(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wclrtobot_ret); + return 1; +} + +/* curses.wclrtoeol */ +/* WINDOW*:clrtoeol */ +int mklualib_curses_wclrtoeol(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wclrtoeol_ret = (int) wclrtoeol(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wclrtoeol_ret); + return 1; +} + +/* curses.wcolor_set */ +/* WINDOW*:color_set */ +int mklualib_curses_wcolor_set(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + short _arg1 = (short) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wcolor_set_ret = (int) wcolor_set(_arg0, _arg1, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wcolor_set_ret); + return 1; +} + +/* curses.wcursyncup */ +/* WINDOW*:cursyncup */ +int mklualib_curses_wcursyncup(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + wcursyncup(_arg0); + return 0; +} + +/* curses.wdelch */ +/* WINDOW*:delch */ +int mklualib_curses_wdelch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wdelch_ret = (int) wdelch(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wdelch_ret); + return 1; +} + +/* curses.wdeleteln */ +/* WINDOW*:deleteln */ +int mklualib_curses_wdeleteln(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wdeleteln_ret = (int) wdeleteln(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wdeleteln_ret); + return 1; +} + +/* curses.wechochar */ +/* WINDOW*:echochar */ +int mklualib_curses_wechochar(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wechochar_ret = (int) wechochar(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wechochar_ret); + return 1; +} + +/* curses.werase */ +/* WINDOW*:erase */ +int mklualib_curses_werase(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_werase_ret = (int) werase(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_werase_ret); + return 1; +} + +/* curses.wgetch */ +/* WINDOW*:getch */ +int mklualib_curses_wgetch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wgetch_ret = (int) wgetch(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wgetch_ret); + return 1; +} + +/* curses.wgetnstr */ +/* WINDOW*:getnstr */ +int mklualib_curses_wgetnstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* mklualib_curses_wgetnstr_ret = (char*) luacurses_wgetnstr(_arg0, _arg1); + lua_pushstring(mklualib_lua_state, mklualib_curses_wgetnstr_ret); + return 1; +} + +/* curses.whline */ +/* WINDOW*:hline */ +int mklualib_curses_whline(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_whline_ret = (int) whline(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_whline_ret); + return 1; +} + +/* curses.winch */ +/* WINDOW*:inch */ +int mklualib_curses_winch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype mklualib_curses_winch_ret = (chtype) winch(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winch_ret); + return 1; +} + +/* curses.winnstr */ +/* WINDOW*:innstr */ +int mklualib_curses_winnstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + char* _arg1 = (char*) lua_tostring(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_winnstr_ret = (int) winnstr(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winnstr_ret); + return 1; +} + +/* curses.winsch */ +/* WINDOW*:insch */ +int mklualib_curses_winsch(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_winsch_ret = (int) winsch(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winsch_ret); + return 1; +} + +/* curses.winsdelln */ +/* WINDOW*:insdelln */ +int mklualib_curses_winsdelln(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_winsdelln_ret = (int) winsdelln(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winsdelln_ret); + return 1; +} + +/* curses.winsertln */ +/* WINDOW*:insertln */ +int mklualib_curses_winsertln(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_winsertln_ret = (int) winsertln(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winsertln_ret); + return 1; +} + +/* curses.winsnstr */ +/* WINDOW*:insnstr */ +int mklualib_curses_winsnstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + char* _arg1 = (char*) lua_tostring(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_winsnstr_ret = (int) winsnstr(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winsnstr_ret); + return 1; +} + +/* curses.winsstr */ +/* WINDOW*:insstr */ +int mklualib_curses_winsstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + char* _arg1 = (char*) lua_tostring(mklualib_lua_state, 2); + int mklualib_curses_winsstr_ret = (int) winsstr(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winsstr_ret); + return 1; +} + +/* curses.winstr */ +/* WINDOW*:instr */ +int mklualib_curses_winstr(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + char* _arg1 = (char*) lua_tostring(mklualib_lua_state, 2); + int mklualib_curses_winstr_ret = (int) winstr(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_winstr_ret); + return 1; +} + +/* curses.wmove */ +/* WINDOW*:move */ +int mklualib_curses_wmove(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_wmove_ret = (int) wmove(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wmove_ret); + return 1; +} + +/* curses.wnoutrefresh */ +/* WINDOW*:noutrefresh */ +int mklualib_curses_wnoutrefresh(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wnoutrefresh_ret = (int) wnoutrefresh(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wnoutrefresh_ret); + return 1; +} + +/* curses.wredrawln */ +/* WINDOW*:redrawln */ +int mklualib_curses_wredrawln(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_wredrawln_ret = (int) wredrawln(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wredrawln_ret); + return 1; +} + +/* curses.wrefresh */ +/* WINDOW*:refresh */ +int mklualib_curses_wrefresh(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wrefresh_ret = (int) wrefresh(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wrefresh_ret); + return 1; +} + +/* curses.wscrl */ +/* WINDOW*:scrl */ +int mklualib_curses_wscrl(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_wscrl_ret = (int) wscrl(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wscrl_ret); + return 1; +} + +/* curses.wsetscrreg */ +/* WINDOW*:setscrreg */ +int mklualib_curses_wsetscrreg(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_wsetscrreg_ret = (int) wsetscrreg(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wsetscrreg_ret); + return 1; +} + +/* curses.wstandout */ +/* WINDOW*:standout */ +int mklualib_curses_wstandout(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wstandout_ret = (int) wstandout(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wstandout_ret); + return 1; +} + +/* curses.wstandend */ +/* WINDOW*:standend */ +int mklualib_curses_wstandend(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int mklualib_curses_wstandend_ret = (int) wstandend(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wstandend_ret); + return 1; +} + +/* curses.wsyncdown */ +/* WINDOW*:syncdown */ +int mklualib_curses_wsyncdown(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + wsyncdown(_arg0); + return 0; +} + +/* curses.wsyncup */ +/* WINDOW*:syncup */ +int mklualib_curses_wsyncup(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + wsyncup(_arg0); + return 0; +} + +/* curses.wtimeout */ +/* WINDOW*:timeout */ +int mklualib_curses_wtimeout(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + wtimeout(_arg0, _arg1); + return 0; +} + +/* curses.wtouchln */ +/* WINDOW*:touchln */ +int mklualib_curses_wtouchln(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_wtouchln_ret = (int) wtouchln(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wtouchln_ret); + return 1; +} + +/* curses.wvline */ +/* WINDOW*:vline */ +int mklualib_curses_wvline(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_wvline_ret = (int) wvline(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wvline_ret); + return 1; +} + +/* curses.wenclose */ +/* WINDOW*:enclose */ +int mklualib_curses_wenclose(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + bool mklualib_curses_wenclose_ret = (bool) wenclose(_arg0, _arg1, _arg2); + lua_pushboolean(mklualib_lua_state, mklualib_curses_wenclose_ret); + return 1; +} + +/* curses.wmouse_trafo */ +/* WINDOW*:mouse_trafo */ +int mklualib_curses_wmouse_trafo(lua_State* mklualib_lua_state) +{ + WINDOW* win = luacurses_towindow(mklualib_lua_state, 1); + int y = (int) lua_tonumber(mklualib_lua_state, 2); + int x = (int) lua_tonumber(mklualib_lua_state, 3); + bool to_screen = (bool) lua_toboolean(mklualib_lua_state, 4); + bool mklualib_curses_wmouse_trafo_ret = (bool) wmouse_trafo(win, &y, &x, to_screen); + lua_pushboolean(mklualib_lua_state, mklualib_curses_wmouse_trafo_ret); + lua_pushnumber(mklualib_lua_state, y); + lua_pushnumber(mklualib_lua_state, x); + return 3; +} + +/* curses.stdscr*/ +int mklualib_curses_stdscr(lua_State* mklualib_lua_state) +{ + WINDOW* mklualib_curses_stdscr_ret = (WINDOW*) stdscr; + WINDOW** mklualib_curses_stdscr_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_stdscr_ret_retptr = mklualib_curses_stdscr_ret; + return 1; +} + +/* curses.curscr*/ +int mklualib_curses_curscr(lua_State* mklualib_lua_state) +{ + WINDOW* mklualib_curses_curscr_ret = (WINDOW*) curscr; + WINDOW** mklualib_curses_curscr_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_curscr_ret_retptr = mklualib_curses_curscr_ret; + return 1; +} + +/* curses.newscr*/ +int mklualib_curses_newscr(lua_State* mklualib_lua_state) +{ + WINDOW* mklualib_curses_newscr_ret = (WINDOW*) newscr; + WINDOW** mklualib_curses_newscr_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_newscr_ret_retptr = mklualib_curses_newscr_ret; + return 1; +} + +/* curses.LINES*/ +int mklualib_curses_LINES(lua_State* mklualib_lua_state) +{ + int mklualib_curses_LINES_ret = (int) LINES; + lua_pushnumber(mklualib_lua_state, mklualib_curses_LINES_ret); + return 1; +} + +/* curses.COLS*/ +int mklualib_curses_COLS(lua_State* mklualib_lua_state) +{ + int mklualib_curses_COLS_ret = (int) COLS; + lua_pushnumber(mklualib_lua_state, mklualib_curses_COLS_ret); + return 1; +} + +/* curses.TABSIZE*/ +int mklualib_curses_TABSIZE(lua_State* mklualib_lua_state) +{ + int mklualib_curses_TABSIZE_ret = (int) TABSIZE; + lua_pushnumber(mklualib_lua_state, mklualib_curses_TABSIZE_ret); + return 1; +} + +/* curses.ESCDELAY*/ +int mklualib_curses_ESCDELAY(lua_State* mklualib_lua_state) +{ + int mklualib_curses_ESCDELAY_ret = (int) ESCDELAY; + lua_pushnumber(mklualib_lua_state, mklualib_curses_ESCDELAY_ret); + return 1; +} + +/* curses.is_term_resized*/ +int mklualib_curses_is_term_resized(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_is_term_resized_ret = (bool) is_term_resized(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_is_term_resized_ret); + return 1; +} + +/* curses.keybound*/ +int mklualib_curses_keybound(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* mklualib_curses_keybound_ret = (char*) keybound(_arg0, _arg1); + lua_pushstring(mklualib_lua_state, mklualib_curses_keybound_ret); + free(mklualib_curses_keybound_ret); + return 1; +} + +/* curses.curses_version*/ +int mklualib_curses_curses_version(lua_State* mklualib_lua_state) +{ + char* mklualib_curses_curses_version_ret = (char*) curses_version(); + lua_pushstring(mklualib_lua_state, mklualib_curses_curses_version_ret); + return 1; +} + +/* curses.assume_default_colors*/ +int mklualib_curses_assume_default_colors(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_assume_default_colors_ret = (int) assume_default_colors(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_assume_default_colors_ret); + return 1; +} + +/* curses.define_key*/ +int mklualib_curses_define_key(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_define_key_ret = (int) define_key(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_define_key_ret); + return 1; +} + +/* curses.key_defined*/ +int mklualib_curses_key_defined(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_key_defined_ret = (int) key_defined(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_key_defined_ret); + return 1; +} + +/* curses.keyok*/ +int mklualib_curses_keyok(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_keyok_ret = (int) keyok(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_keyok_ret); + return 1; +} + +/* curses.resize_term*/ +int mklualib_curses_resize_term(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_resize_term_ret = (int) resize_term(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_resize_term_ret); + return 1; +} + +/* curses.resizeterm*/ +int mklualib_curses_resizeterm(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_resizeterm_ret = (int) resizeterm(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_resizeterm_ret); + return 1; +} + +/* curses.use_default_colors*/ +int mklualib_curses_use_default_colors(lua_State* mklualib_lua_state) +{ + int mklualib_curses_use_default_colors_ret = (int) use_default_colors(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_use_default_colors_ret); + return 1; +} + +/* curses.use_extended_names*/ +int mklualib_curses_use_extended_names(lua_State* mklualib_lua_state) +{ + bool _arg0 = (bool) lua_toboolean(mklualib_lua_state, 1); + int mklualib_curses_use_extended_names_ret = (int) use_extended_names(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_use_extended_names_ret); + return 1; +} + +/* curses.wresize*/ +int mklualib_curses_wresize(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_wresize_ret = (int) wresize(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_wresize_ret); + return 1; +} + +/* curses.addch*/ +int mklualib_curses_addch(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_addch_ret = (int) addch(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_addch_ret); + return 1; +} + +/* curses.addnstr*/ +int mklualib_curses_addnstr(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_addnstr_ret = (int) addnstr(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_addnstr_ret); + return 1; +} + +/* curses.addstr*/ +int mklualib_curses_addstr(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_addstr_ret = (int) addstr(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_addstr_ret); + return 1; +} + +/* curses.attroff*/ +int mklualib_curses_attroff(lua_State* mklualib_lua_state) +{ + attr_t _arg0 = (attr_t) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_attroff_ret = (int) attroff(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_attroff_ret); + return 1; +} + +/* curses.attron*/ +int mklualib_curses_attron(lua_State* mklualib_lua_state) +{ + attr_t _arg0 = (attr_t) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_attron_ret = (int) attron(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_attron_ret); + return 1; +} + +/* curses.attrset*/ +int mklualib_curses_attrset(lua_State* mklualib_lua_state) +{ + attr_t _arg0 = (attr_t) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_attrset_ret = (int) attrset(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_attrset_ret); + return 1; +} + +/* curses.attr_get*/ +int mklualib_curses_attr_get(lua_State* mklualib_lua_state) +{ + attr_t _arg0; + short _arg1; + int mklualib_curses_attr_get_ret = (int) attr_get(&_arg0, &_arg1, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_attr_get_ret); + lua_pushnumber(mklualib_lua_state, _arg0); + lua_pushnumber(mklualib_lua_state, _arg1); + return 3; +} + +/* curses.attr_off*/ +int mklualib_curses_attr_off(lua_State* mklualib_lua_state) +{ + attr_t _arg0 = (attr_t) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_attr_off_ret = (int) attr_off(_arg0, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_attr_off_ret); + return 1; +} + +/* curses.attr_on*/ +int mklualib_curses_attr_on(lua_State* mklualib_lua_state) +{ + attr_t _arg0 = (attr_t) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_attr_on_ret = (int) attr_on(_arg0, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_attr_on_ret); + return 1; +} + +/* curses.attr_set*/ +int mklualib_curses_attr_set(lua_State* mklualib_lua_state) +{ + attr_t _arg0 = (attr_t) lua_tonumber(mklualib_lua_state, 1); + short _arg1 = (short) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_attr_set_ret = (int) attr_set(_arg0, _arg1, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_attr_set_ret); + return 1; +} + +/* curses.baudrate*/ +int mklualib_curses_baudrate(lua_State* mklualib_lua_state) +{ + int mklualib_curses_baudrate_ret = (int) baudrate(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_baudrate_ret); + return 1; +} + +/* curses.beep*/ +int mklualib_curses_beep(lua_State* mklualib_lua_state) +{ + int mklualib_curses_beep_ret = (int) beep(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_beep_ret); + return 1; +} + +/* curses.bkgd*/ +int mklualib_curses_bkgd(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_bkgd_ret = (int) bkgd(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_bkgd_ret); + return 1; +} + +/* curses.bkgdset*/ +int mklualib_curses_bkgdset(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + bkgdset(_arg0); + return 0; +} + +/* curses.border*/ +int mklualib_curses_border(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + chtype _arg1 = (chtype) lua_tonumber(mklualib_lua_state, 2); + chtype _arg2 = (chtype) lua_tonumber(mklualib_lua_state, 3); + chtype _arg3 = (chtype) lua_tonumber(mklualib_lua_state, 4); + chtype _arg4 = (chtype) lua_tonumber(mklualib_lua_state, 5); + chtype _arg5 = (chtype) lua_tonumber(mklualib_lua_state, 6); + chtype _arg6 = (chtype) lua_tonumber(mklualib_lua_state, 7); + chtype _arg7 = (chtype) lua_tonumber(mklualib_lua_state, 8); + int mklualib_curses_border_ret = (int) border(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7); + lua_pushnumber(mklualib_lua_state, mklualib_curses_border_ret); + return 1; +} + +/* curses.can_change_color*/ +int mklualib_curses_can_change_color(lua_State* mklualib_lua_state) +{ + bool mklualib_curses_can_change_color_ret = (bool) can_change_color(); + lua_pushboolean(mklualib_lua_state, mklualib_curses_can_change_color_ret); + return 1; +} + +/* curses.cbreak*/ +int mklualib_curses_cbreak(lua_State* mklualib_lua_state) +{ + int mklualib_curses_cbreak_ret = (int) cbreak(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_cbreak_ret); + return 1; +} + +/* curses.chgat*/ +int mklualib_curses_chgat(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + attr_t _arg1 = (attr_t) lua_tonumber(mklualib_lua_state, 2); + short _arg2 = (short) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_chgat_ret = (int) chgat(_arg0, _arg1, _arg2, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_chgat_ret); + return 1; +} + +/* curses.clear*/ +int mklualib_curses_clear(lua_State* mklualib_lua_state) +{ + int mklualib_curses_clear_ret = (int) clear(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_clear_ret); + return 1; +} + +/* curses.clrtobot*/ +int mklualib_curses_clrtobot(lua_State* mklualib_lua_state) +{ + int mklualib_curses_clrtobot_ret = (int) clrtobot(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_clrtobot_ret); + return 1; +} + +/* curses.clrtoeol*/ +int mklualib_curses_clrtoeol(lua_State* mklualib_lua_state) +{ + int mklualib_curses_clrtoeol_ret = (int) clrtoeol(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_clrtoeol_ret); + return 1; +} + +/* curses.color_content*/ +int mklualib_curses_color_content(lua_State* mklualib_lua_state) +{ + short _arg0 = (short) lua_tonumber(mklualib_lua_state, 1); + short _arg1; + short _arg2; + short _arg3; + int mklualib_curses_color_content_ret = (int) color_content(_arg0, &_arg1, &_arg2, &_arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_color_content_ret); + lua_pushnumber(mklualib_lua_state, _arg1); + lua_pushnumber(mklualib_lua_state, _arg2); + lua_pushnumber(mklualib_lua_state, _arg3); + return 4; +} + +/* curses.color_set*/ +int mklualib_curses_color_set(lua_State* mklualib_lua_state) +{ + short _arg0 = (short) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_color_set_ret = (int) color_set(_arg0, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_color_set_ret); + return 1; +} + +/* curses.COLOR_PAIR*/ +int mklualib_curses_COLOR_PAIR(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_COLOR_PAIR_ret = (int) COLOR_PAIR(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_COLOR_PAIR_ret); + return 1; +} + +/* curses.copywin*/ +int mklualib_curses_copywin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + WINDOW* _arg1 = luacurses_towindow(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + int _arg5 = (int) lua_tonumber(mklualib_lua_state, 6); + int _arg6 = (int) lua_tonumber(mklualib_lua_state, 7); + int _arg7 = (int) lua_tonumber(mklualib_lua_state, 8); + int _arg8 = (int) lua_tonumber(mklualib_lua_state, 9); + int mklualib_curses_copywin_ret = (int) copywin(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8); + lua_pushnumber(mklualib_lua_state, mklualib_curses_copywin_ret); + return 1; +} + +/* curses.curs_set*/ +int mklualib_curses_curs_set(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_curs_set_ret = (int) curs_set(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_curs_set_ret); + return 1; +} + +/* curses.def_prog_mode*/ +int mklualib_curses_def_prog_mode(lua_State* mklualib_lua_state) +{ + int mklualib_curses_def_prog_mode_ret = (int) def_prog_mode(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_def_prog_mode_ret); + return 1; +} + +/* curses.def_shell_mode*/ +int mklualib_curses_def_shell_mode(lua_State* mklualib_lua_state) +{ + int mklualib_curses_def_shell_mode_ret = (int) def_shell_mode(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_def_shell_mode_ret); + return 1; +} + +/* curses.delay_output*/ +int mklualib_curses_delay_output(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_delay_output_ret = (int) delay_output(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_delay_output_ret); + return 1; +} + +/* curses.delch*/ +int mklualib_curses_delch(lua_State* mklualib_lua_state) +{ + int mklualib_curses_delch_ret = (int) delch(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_delch_ret); + return 1; +} + +/* curses.deleteln*/ +int mklualib_curses_deleteln(lua_State* mklualib_lua_state) +{ + int mklualib_curses_deleteln_ret = (int) deleteln(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_deleteln_ret); + return 1; +} + +/* curses.doupdate*/ +int mklualib_curses_doupdate(lua_State* mklualib_lua_state) +{ + int mklualib_curses_doupdate_ret = (int) doupdate(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_doupdate_ret); + return 1; +} + +/* curses.echo*/ +int mklualib_curses_echo(lua_State* mklualib_lua_state) +{ + int mklualib_curses_echo_ret = (int) echo(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_echo_ret); + return 1; +} + +/* curses.echochar*/ +int mklualib_curses_echochar(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_echochar_ret = (int) echochar(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_echochar_ret); + return 1; +} + +/* curses.erase*/ +int mklualib_curses_erase(lua_State* mklualib_lua_state) +{ + int mklualib_curses_erase_ret = (int) erase(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_erase_ret); + return 1; +} + +/* curses.endwin*/ +int mklualib_curses_endwin(lua_State* mklualib_lua_state) +{ + int mklualib_curses_endwin_ret = (int) endwin(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_endwin_ret); + return 1; +} + +/* curses.erasechar*/ +int mklualib_curses_erasechar(lua_State* mklualib_lua_state) +{ + char mklualib_curses_erasechar_ret = (char) erasechar(); + lua_pushlstring(mklualib_lua_state, &mklualib_curses_erasechar_ret, 1); + return 1; +} + +/* curses.filter*/ +int mklualib_curses_filter(lua_State* mklualib_lua_state) +{ + filter(); + return 0; +} + +/* curses.flash*/ +int mklualib_curses_flash(lua_State* mklualib_lua_state) +{ + int mklualib_curses_flash_ret = (int) flash(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_flash_ret); + return 1; +} + +/* curses.flushinp*/ +int mklualib_curses_flushinp(lua_State* mklualib_lua_state) +{ + int mklualib_curses_flushinp_ret = (int) flushinp(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_flushinp_ret); + return 1; +} + +/* curses.getch*/ +int mklualib_curses_getch(lua_State* mklualib_lua_state) +{ + int mklualib_curses_getch_ret = (int) getch(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_getch_ret); + return 1; +} + +/* curses.getnstr*/ +int mklualib_curses_getnstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + char* mklualib_curses_getnstr_ret = (char*) luacurses_getnstr(_arg0); + lua_pushstring(mklualib_lua_state, mklualib_curses_getnstr_ret); + return 1; +} + +/* curses.getwin*/ +int mklualib_curses_getwin(lua_State* mklualib_lua_state) +{ + FILE* _arg0 = tofile(mklualib_lua_state, 1); + WINDOW* mklualib_curses_getwin_ret = (WINDOW*) getwin(_arg0); + WINDOW** mklualib_curses_getwin_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_getwin_ret_retptr = mklualib_curses_getwin_ret; + return 1; +} + +/* curses.halfdelay*/ +int mklualib_curses_halfdelay(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_halfdelay_ret = (int) halfdelay(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_halfdelay_ret); + return 1; +} + +/* curses.has_colors*/ +int mklualib_curses_has_colors(lua_State* mklualib_lua_state) +{ + bool mklualib_curses_has_colors_ret = (bool) has_colors(); + lua_pushboolean(mklualib_lua_state, mklualib_curses_has_colors_ret); + return 1; +} + +/* curses.has_ic*/ +int mklualib_curses_has_ic(lua_State* mklualib_lua_state) +{ + bool mklualib_curses_has_ic_ret = (bool) has_ic(); + lua_pushboolean(mklualib_lua_state, mklualib_curses_has_ic_ret); + return 1; +} + +/* curses.has_il*/ +int mklualib_curses_has_il(lua_State* mklualib_lua_state) +{ + bool mklualib_curses_has_il_ret = (bool) has_il(); + lua_pushboolean(mklualib_lua_state, mklualib_curses_has_il_ret); + return 1; +} + +/* curses.hline*/ +int mklualib_curses_hline(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_hline_ret = (int) hline(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_hline_ret); + return 1; +} + +/* curses.inch*/ +int mklualib_curses_inch(lua_State* mklualib_lua_state) +{ + chtype mklualib_curses_inch_ret = (chtype) inch(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_inch_ret); + return 1; +} + +/* curses.initscr*/ +int mklualib_curses_initscr(lua_State* mklualib_lua_state) +{ + WINDOW* mklualib_curses_initscr_ret = (WINDOW*) initscr(); + WINDOW** mklualib_curses_initscr_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_initscr_ret_retptr = mklualib_curses_initscr_ret; + return 1; +} + +/* curses.init_color*/ +int mklualib_curses_init_color(lua_State* mklualib_lua_state) +{ + short _arg0 = (short) lua_tonumber(mklualib_lua_state, 1); + short _arg1 = (short) lua_tonumber(mklualib_lua_state, 2); + short _arg2 = (short) lua_tonumber(mklualib_lua_state, 3); + short _arg3 = (short) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_init_color_ret = (int) init_color(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_init_color_ret); + return 1; +} + +/* curses.init_pair*/ +int mklualib_curses_init_pair(lua_State* mklualib_lua_state) +{ + short _arg0 = (short) lua_tonumber(mklualib_lua_state, 1); + short _arg1 = (short) lua_tonumber(mklualib_lua_state, 2); + short _arg2 = (short) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_init_pair_ret = (int) init_pair(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_init_pair_ret); + return 1; +} + +/* curses.innstr*/ +int mklualib_curses_innstr(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_innstr_ret = (int) innstr(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_innstr_ret); + return 1; +} + +/* curses.insch*/ +int mklualib_curses_insch(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_insch_ret = (int) insch(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_insch_ret); + return 1; +} + +/* curses.insdelln*/ +int mklualib_curses_insdelln(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_insdelln_ret = (int) insdelln(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_insdelln_ret); + return 1; +} + +/* curses.insertln*/ +int mklualib_curses_insertln(lua_State* mklualib_lua_state) +{ + int mklualib_curses_insertln_ret = (int) insertln(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_insertln_ret); + return 1; +} + +/* curses.insnstr*/ +int mklualib_curses_insnstr(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_insnstr_ret = (int) insnstr(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_insnstr_ret); + return 1; +} + +/* curses.insstr*/ +int mklualib_curses_insstr(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_insstr_ret = (int) insstr(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_insstr_ret); + return 1; +} + +/* curses.instr*/ +int mklualib_curses_instr(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_instr_ret = (int) instr(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_instr_ret); + return 1; +} + +/* curses.isendwin*/ +int mklualib_curses_isendwin(lua_State* mklualib_lua_state) +{ + bool mklualib_curses_isendwin_ret = (bool) isendwin(); + lua_pushboolean(mklualib_lua_state, mklualib_curses_isendwin_ret); + return 1; +} + +/* curses.keyname*/ +int mklualib_curses_keyname(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + char* mklualib_curses_keyname_ret = (char*) keyname(_arg0); + lua_pushstring(mklualib_lua_state, mklualib_curses_keyname_ret); + return 1; +} + +/* curses.killchar*/ +int mklualib_curses_killchar(lua_State* mklualib_lua_state) +{ + char mklualib_curses_killchar_ret = (char) killchar(); + lua_pushlstring(mklualib_lua_state, &mklualib_curses_killchar_ret, 1); + return 1; +} + +/* curses.longname*/ +int mklualib_curses_longname(lua_State* mklualib_lua_state) +{ + char* mklualib_curses_longname_ret = (char*) longname(); + lua_pushstring(mklualib_lua_state, mklualib_curses_longname_ret); + return 1; +} + +/* curses.move*/ +int mklualib_curses_move(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_move_ret = (int) move(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_move_ret); + return 1; +} + +/* curses.mvaddch*/ +int mklualib_curses_mvaddch(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + chtype _arg2 = (chtype) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_mvaddch_ret = (int) mvaddch(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvaddch_ret); + return 1; +} + +/* curses.mvaddnstr*/ +int mklualib_curses_mvaddnstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* _arg2 = (char*) lua_tostring(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvaddnstr_ret = (int) mvaddnstr(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvaddnstr_ret); + return 1; +} + +/* curses.mvaddstr*/ +int mklualib_curses_mvaddstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* _arg2 = (char*) lua_tostring(mklualib_lua_state, 3); + int mklualib_curses_mvaddstr_ret = (int) mvaddstr(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvaddstr_ret); + return 1; +} + +/* curses.mvchgat*/ +int mklualib_curses_mvchgat(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + attr_t _arg3 = (attr_t) lua_tonumber(mklualib_lua_state, 4); + short _arg4 = (short) lua_tonumber(mklualib_lua_state, 5); + int mklualib_curses_mvchgat_ret = (int) mvchgat(_arg0, _arg1, _arg2, _arg3, _arg4, 0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvchgat_ret); + return 1; +} + +/* curses.mvcur*/ +int mklualib_curses_mvcur(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvcur_ret = (int) mvcur(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvcur_ret); + return 1; +} + +/* curses.mvdelch*/ +int mklualib_curses_mvdelch(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_mvdelch_ret = (int) mvdelch(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvdelch_ret); + return 1; +} + +/* curses.mvgetch*/ +int mklualib_curses_mvgetch(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_mvgetch_ret = (int) mvgetch(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvgetch_ret); + return 1; +} + +/* curses.mvgetnstr*/ +int mklualib_curses_mvgetnstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + char* mklualib_curses_mvgetnstr_ret = (char*) luacurses_mvgetnstr(_arg0, _arg1, _arg2); + lua_pushstring(mklualib_lua_state, mklualib_curses_mvgetnstr_ret); + return 1; +} + +/* curses.mvhline*/ +int mklualib_curses_mvhline(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + chtype _arg2 = (chtype) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvhline_ret = (int) mvhline(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvhline_ret); + return 1; +} + +/* curses.mvinch*/ +int mklualib_curses_mvinch(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + chtype mklualib_curses_mvinch_ret = (chtype) mvinch(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvinch_ret); + return 1; +} + +/* curses.mvinnstr*/ +int mklualib_curses_mvinnstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* _arg2 = (char*) lua_tostring(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvinnstr_ret = (int) mvinnstr(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvinnstr_ret); + return 1; +} + +/* curses.mvinsch*/ +int mklualib_curses_mvinsch(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + chtype _arg2 = (chtype) lua_tonumber(mklualib_lua_state, 3); + int mklualib_curses_mvinsch_ret = (int) mvinsch(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvinsch_ret); + return 1; +} + +/* curses.mvinsnstr*/ +int mklualib_curses_mvinsnstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* _arg2 = (char*) lua_tostring(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvinsnstr_ret = (int) mvinsnstr(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvinsnstr_ret); + return 1; +} + +/* curses.mvinsstr*/ +int mklualib_curses_mvinsstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* _arg2 = (char*) lua_tostring(mklualib_lua_state, 3); + int mklualib_curses_mvinsstr_ret = (int) mvinsstr(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvinsstr_ret); + return 1; +} + +/* curses.mvinstr*/ +int mklualib_curses_mvinstr(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + char* _arg2 = (char*) lua_tostring(mklualib_lua_state, 3); + int mklualib_curses_mvinstr_ret = (int) mvinstr(_arg0, _arg1, _arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvinstr_ret); + return 1; +} + +/* curses.mvvline*/ +int mklualib_curses_mvvline(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + chtype _arg2 = (chtype) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int mklualib_curses_mvvline_ret = (int) mvvline(_arg0, _arg1, _arg2, _arg3); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mvvline_ret); + return 1; +} + +/* curses.napms*/ +int mklualib_curses_napms(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_napms_ret = (int) napms(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_napms_ret); + return 1; +} + +/* curses.newpad*/ +int mklualib_curses_newpad(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + WINDOW* mklualib_curses_newpad_ret = (WINDOW*) newpad(_arg0, _arg1); + WINDOW** mklualib_curses_newpad_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_newpad_ret_retptr = mklualib_curses_newpad_ret; + return 1; +} + +/* curses.newterm*/ +int mklualib_curses_newterm(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + FILE* _arg1 = tofile(mklualib_lua_state, 2); + FILE* _arg2 = tofile(mklualib_lua_state, 3); + SCREEN* mklualib_curses_newterm_ret = (SCREEN*) newterm(_arg0, _arg1, _arg2); + SCREEN** mklualib_curses_newterm_ret_retptr = luacurses_newscreen(mklualib_lua_state); + *mklualib_curses_newterm_ret_retptr = mklualib_curses_newterm_ret; + return 1; +} + +/* curses.newwin*/ +int mklualib_curses_newwin(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + WINDOW* mklualib_curses_newwin_ret = (WINDOW*) newwin(_arg0, _arg1, _arg2, _arg3); + WINDOW** mklualib_curses_newwin_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_newwin_ret_retptr = mklualib_curses_newwin_ret; + return 1; +} + +/* curses.nl*/ +int mklualib_curses_nl(lua_State* mklualib_lua_state) +{ + int mklualib_curses_nl_ret = (int) nl(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_nl_ret); + return 1; +} + +/* curses.nocbreak*/ +int mklualib_curses_nocbreak(lua_State* mklualib_lua_state) +{ + int mklualib_curses_nocbreak_ret = (int) nocbreak(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_nocbreak_ret); + return 1; +} + +/* curses.noecho*/ +int mklualib_curses_noecho(lua_State* mklualib_lua_state) +{ + int mklualib_curses_noecho_ret = (int) noecho(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_noecho_ret); + return 1; +} + +/* curses.nonl*/ +int mklualib_curses_nonl(lua_State* mklualib_lua_state) +{ + int mklualib_curses_nonl_ret = (int) nonl(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_nonl_ret); + return 1; +} + +/* curses.noqiflush*/ +int mklualib_curses_noqiflush(lua_State* mklualib_lua_state) +{ + noqiflush(); + return 0; +} + +/* curses.noraw*/ +int mklualib_curses_noraw(lua_State* mklualib_lua_state) +{ + int mklualib_curses_noraw_ret = (int) noraw(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_noraw_ret); + return 1; +} + +/* curses.overlay*/ +int mklualib_curses_overlay(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + WINDOW* _arg1 = luacurses_towindow(mklualib_lua_state, 2); + int mklualib_curses_overlay_ret = (int) overlay(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_overlay_ret); + return 1; +} + +/* curses.overwrite*/ +int mklualib_curses_overwrite(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + WINDOW* _arg1 = luacurses_towindow(mklualib_lua_state, 2); + int mklualib_curses_overwrite_ret = (int) overwrite(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_overwrite_ret); + return 1; +} + +/* curses.pair_content*/ +int mklualib_curses_pair_content(lua_State* mklualib_lua_state) +{ + short _arg0 = (short) lua_tonumber(mklualib_lua_state, 1); + short _arg1; + short _arg2; + int mklualib_curses_pair_content_ret = (int) pair_content(_arg0, &_arg1, &_arg2); + lua_pushnumber(mklualib_lua_state, mklualib_curses_pair_content_ret); + lua_pushnumber(mklualib_lua_state, _arg1); + lua_pushnumber(mklualib_lua_state, _arg2); + return 3; +} + +/* curses.PAIR_NUMBER*/ +int mklualib_curses_PAIR_NUMBER(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_PAIR_NUMBER_ret = (int) PAIR_NUMBER(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_PAIR_NUMBER_ret); + return 1; +} + +/* curses.putp*/ +int mklualib_curses_putp(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_putp_ret = (int) putp(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_putp_ret); + return 1; +} + +/* curses.qiflush*/ +int mklualib_curses_qiflush(lua_State* mklualib_lua_state) +{ + qiflush(); + return 0; +} + +/* curses.raw*/ +int mklualib_curses_raw(lua_State* mklualib_lua_state) +{ + int mklualib_curses_raw_ret = (int) raw(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_raw_ret); + return 1; +} + +/* curses.refresh*/ +int mklualib_curses_refresh(lua_State* mklualib_lua_state) +{ + int mklualib_curses_refresh_ret = (int) refresh(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_refresh_ret); + return 1; +} + +/* curses.resetty*/ +int mklualib_curses_resetty(lua_State* mklualib_lua_state) +{ + int mklualib_curses_resetty_ret = (int) resetty(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_resetty_ret); + return 1; +} + +/* curses.reset_prog_mode*/ +int mklualib_curses_reset_prog_mode(lua_State* mklualib_lua_state) +{ + int mklualib_curses_reset_prog_mode_ret = (int) reset_prog_mode(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_reset_prog_mode_ret); + return 1; +} + +/* curses.reset_shell_mode*/ +int mklualib_curses_reset_shell_mode(lua_State* mklualib_lua_state) +{ + int mklualib_curses_reset_shell_mode_ret = (int) reset_shell_mode(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_reset_shell_mode_ret); + return 1; +} + +/* curses.savetty*/ +int mklualib_curses_savetty(lua_State* mklualib_lua_state) +{ + int mklualib_curses_savetty_ret = (int) savetty(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_savetty_ret); + return 1; +} + +/* curses.scr_dump*/ +int mklualib_curses_scr_dump(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_scr_dump_ret = (int) scr_dump(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_scr_dump_ret); + return 1; +} + +/* curses.scr_init*/ +int mklualib_curses_scr_init(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_scr_init_ret = (int) scr_init(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_scr_init_ret); + return 1; +} + +/* curses.scrl*/ +int mklualib_curses_scrl(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_scrl_ret = (int) scrl(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_scrl_ret); + return 1; +} + +/* curses.scr_restore*/ +int mklualib_curses_scr_restore(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_scr_restore_ret = (int) scr_restore(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_scr_restore_ret); + return 1; +} + +/* curses.scr_set*/ +int mklualib_curses_scr_set(lua_State* mklualib_lua_state) +{ + char* _arg0 = (char*) lua_tostring(mklualib_lua_state, 1); + int mklualib_curses_scr_set_ret = (int) scr_set(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_scr_set_ret); + return 1; +} + +/* curses.setscrreg*/ +int mklualib_curses_setscrreg(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_setscrreg_ret = (int) setscrreg(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_setscrreg_ret); + return 1; +} + +/* curses.standout*/ +int mklualib_curses_standout(lua_State* mklualib_lua_state) +{ + int mklualib_curses_standout_ret = (int) standout(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_standout_ret); + return 1; +} + +/* curses.standend*/ +int mklualib_curses_standend(lua_State* mklualib_lua_state) +{ + int mklualib_curses_standend_ret = (int) standend(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_standend_ret); + return 1; +} + +/* curses.start_color*/ +int mklualib_curses_start_color(lua_State* mklualib_lua_state) +{ + int mklualib_curses_start_color_ret = (int) start_color(); + lua_pushnumber(mklualib_lua_state, mklualib_curses_start_color_ret); + return 1; +} + +/* curses.subpad*/ +int mklualib_curses_subpad(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + WINDOW* mklualib_curses_subpad_ret = (WINDOW*) subpad(_arg0, _arg1, _arg2, _arg3, _arg4); + WINDOW** mklualib_curses_subpad_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_subpad_ret_retptr = mklualib_curses_subpad_ret; + return 1; +} + +/* curses.subwin*/ +int mklualib_curses_subwin(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int _arg2 = (int) lua_tonumber(mklualib_lua_state, 3); + int _arg3 = (int) lua_tonumber(mklualib_lua_state, 4); + int _arg4 = (int) lua_tonumber(mklualib_lua_state, 5); + WINDOW* mklualib_curses_subwin_ret = (WINDOW*) subwin(_arg0, _arg1, _arg2, _arg3, _arg4); + WINDOW** mklualib_curses_subwin_ret_retptr = luacurses_newwindow(mklualib_lua_state); + *mklualib_curses_subwin_ret_retptr = mklualib_curses_subwin_ret; + return 1; +} + +/* curses.syncok*/ +int mklualib_curses_syncok(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + bool _arg1 = (bool) lua_toboolean(mklualib_lua_state, 2); + int mklualib_curses_syncok_ret = (int) syncok(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_syncok_ret); + return 1; +} + +/* curses.timeout*/ +int mklualib_curses_timeout(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + timeout(_arg0); + return 0; +} + +/* curses.typeahead*/ +int mklualib_curses_typeahead(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_typeahead_ret = (int) typeahead(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_typeahead_ret); + return 1; +} + +/* curses.ungetch*/ +int mklualib_curses_ungetch(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_ungetch_ret = (int) ungetch(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_ungetch_ret); + return 1; +} + +/* curses.use_env*/ +int mklualib_curses_use_env(lua_State* mklualib_lua_state) +{ + bool _arg0 = (bool) lua_toboolean(mklualib_lua_state, 1); + use_env(_arg0); + return 0; +} + +/* curses.vidattr*/ +int mklualib_curses_vidattr(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_vidattr_ret = (int) vidattr(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_vidattr_ret); + return 1; +} + +/* curses.vline*/ +int mklualib_curses_vline(lua_State* mklualib_lua_state) +{ + chtype _arg0 = (chtype) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + int mklualib_curses_vline_ret = (int) vline(_arg0, _arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_vline_ret); + return 1; +} + +/* curses.getyx*/ +int mklualib_curses_getyx(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int y; + int x; + getyx(_arg0, y, x); + lua_pushnumber(mklualib_lua_state, y); + lua_pushnumber(mklualib_lua_state, x); + return 2; +} + +/* curses.getbegyx*/ +int mklualib_curses_getbegyx(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int y; + int x; + getbegyx(_arg0, y, x); + lua_pushnumber(mklualib_lua_state, y); + lua_pushnumber(mklualib_lua_state, x); + return 2; +} + +/* curses.getmaxyx*/ +int mklualib_curses_getmaxyx(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int y; + int x; + getmaxyx(_arg0, y, x); + lua_pushnumber(mklualib_lua_state, y); + lua_pushnumber(mklualib_lua_state, x); + return 2; +} + +/* curses.getparyx*/ +int mklualib_curses_getparyx(lua_State* mklualib_lua_state) +{ + WINDOW* _arg0 = luacurses_towindow(mklualib_lua_state, 1); + int y; + int x; + getparyx(_arg0, y, x); + lua_pushnumber(mklualib_lua_state, y); + lua_pushnumber(mklualib_lua_state, x); + return 2; +} + +/* curses.KEY_F*/ +int mklualib_curses_KEY_F(lua_State* mklualib_lua_state) +{ + int n = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_KEY_F_ret = (int) KEY_F(n); + lua_pushnumber(mklualib_lua_state, mklualib_curses_KEY_F_ret); + return 1; +} + +/* curses.BUTTON_RELEASE*/ +int mklualib_curses_BUTTON_RELEASE(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_BUTTON_RELEASE_ret = (bool) BUTTON_RELEASE(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_BUTTON_RELEASE_ret); + return 1; +} + +/* curses.BUTTON_PRESS*/ +int mklualib_curses_BUTTON_PRESS(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_BUTTON_PRESS_ret = (bool) BUTTON_PRESS(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_BUTTON_PRESS_ret); + return 1; +} + +/* curses.BUTTON_CLICK*/ +int mklualib_curses_BUTTON_CLICK(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_BUTTON_CLICK_ret = (bool) BUTTON_CLICK(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_BUTTON_CLICK_ret); + return 1; +} + +/* curses.BUTTON_DOUBLE_CLICK*/ +int mklualib_curses_BUTTON_DOUBLE_CLICK(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_BUTTON_DOUBLE_CLICK_ret = (bool) BUTTON_DOUBLE_CLICK(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_BUTTON_DOUBLE_CLICK_ret); + return 1; +} + +/* curses.BUTTON_TRIPLE_CLICK*/ +int mklualib_curses_BUTTON_TRIPLE_CLICK(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_BUTTON_TRIPLE_CLICK_ret = (bool) BUTTON_TRIPLE_CLICK(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_BUTTON_TRIPLE_CLICK_ret); + return 1; +} + +/* curses.BUTTON_RESERVED_EVENT*/ +int mklualib_curses_BUTTON_RESERVED_EVENT(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool mklualib_curses_BUTTON_RESERVED_EVENT_ret = (bool) BUTTON_RESERVED_EVENT(_arg0, _arg1); + lua_pushboolean(mklualib_lua_state, mklualib_curses_BUTTON_RESERVED_EVENT_ret); + return 1; +} + +/* curses.getmouse*/ +int mklualib_curses_getmouse(lua_State* mklualib_lua_state) +{ + short id; + int x; + int y; + int z; + mmask_t bstate; + bool mklualib_curses_getmouse_ret = (bool) luacurses_getmouse(&id, &x, &y, &z, &bstate); + lua_pushboolean(mklualib_lua_state, mklualib_curses_getmouse_ret); + lua_pushnumber(mklualib_lua_state, id); + lua_pushnumber(mklualib_lua_state, x); + lua_pushnumber(mklualib_lua_state, y); + lua_pushnumber(mklualib_lua_state, z); + lua_pushnumber(mklualib_lua_state, bstate); + return 6; +} + +/* curses.ungetmouse*/ +int mklualib_curses_ungetmouse(lua_State* mklualib_lua_state) +{ + short id = (short) lua_tonumber(mklualib_lua_state, 1); + int x = (int) lua_tonumber(mklualib_lua_state, 2); + int y = (int) lua_tonumber(mklualib_lua_state, 3); + int z = (int) lua_tonumber(mklualib_lua_state, 4); + mmask_t bstate = (mmask_t) lua_tonumber(mklualib_lua_state, 5); + bool mklualib_curses_ungetmouse_ret = (bool) luacurses_ungetmouse(id, x, y, z, bstate); + lua_pushboolean(mklualib_lua_state, mklualib_curses_ungetmouse_ret); + return 1; +} + +/* curses.mousemask*/ +int mklualib_curses_mousemask(lua_State* mklualib_lua_state) +{ + mmask_t _arg0 = (mmask_t) lua_tonumber(mklualib_lua_state, 1); + mmask_t _arg1; + mmask_t mklualib_curses_mousemask_ret = (mmask_t) mousemask(_arg0, &_arg1); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mousemask_ret); + lua_pushnumber(mklualib_lua_state, _arg1); + return 2; +} + +/* curses.addmousemask*/ +int mklualib_curses_addmousemask(lua_State* mklualib_lua_state) +{ + mmask_t _arg0 = (mmask_t) lua_tonumber(mklualib_lua_state, 1); + mmask_t mklualib_curses_addmousemask_ret = (mmask_t) luacurses_addmousemask(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_addmousemask_ret); + return 1; +} + +/* curses.mouseinterval*/ +int mklualib_curses_mouseinterval(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int mklualib_curses_mouseinterval_ret = (int) mouseinterval(_arg0); + lua_pushnumber(mklualib_lua_state, mklualib_curses_mouseinterval_ret); + return 1; +} + +/* curses.mouse_trafo*/ +int mklualib_curses_mouse_trafo(lua_State* mklualib_lua_state) +{ + int _arg0 = (int) lua_tonumber(mklualib_lua_state, 1); + int _arg1 = (int) lua_tonumber(mklualib_lua_state, 2); + bool _arg2 = (bool) lua_toboolean(mklualib_lua_state, 3); + bool mklualib_curses_mouse_trafo_ret = (bool) mouse_trafo(&_arg0, &_arg1, _arg2); + lua_pushboolean(mklualib_lua_state, mklualib_curses_mouse_trafo_ret); + lua_pushnumber(mklualib_lua_state, _arg0); + lua_pushnumber(mklualib_lua_state, _arg1); + return 3; +} + +const luaL_reg mklualib_curses_lib[] = { + {"COLORS", mklualib_curses_COLORS}, + {"COLOR_PAIRS", mklualib_curses_COLOR_PAIRS}, + {"NCURSES_ACS", mklualib_curses_NCURSES_ACS}, + {"ACS_ULCORNER", mklualib_curses_ACS_ULCORNER}, + {"ACS_LLCORNER", mklualib_curses_ACS_LLCORNER}, + {"ACS_URCORNER", mklualib_curses_ACS_URCORNER}, + {"ACS_LRCORNER", mklualib_curses_ACS_LRCORNER}, + {"ACS_LTEE", mklualib_curses_ACS_LTEE}, + {"ACS_RTEE", mklualib_curses_ACS_RTEE}, + {"ACS_BTEE", mklualib_curses_ACS_BTEE}, + {"ACS_TTEE", mklualib_curses_ACS_TTEE}, + {"ACS_HLINE", mklualib_curses_ACS_HLINE}, + {"ACS_VLINE", mklualib_curses_ACS_VLINE}, + {"ACS_PLUS", mklualib_curses_ACS_PLUS}, + {"ACS_S1", mklualib_curses_ACS_S1}, + {"ACS_S9", mklualib_curses_ACS_S9}, + {"ACS_DIAMOND", mklualib_curses_ACS_DIAMOND}, + {"ACS_CKBOARD", mklualib_curses_ACS_CKBOARD}, + {"ACS_DEGREE", mklualib_curses_ACS_DEGREE}, + {"ACS_PLMINUS", mklualib_curses_ACS_PLMINUS}, + {"ACS_BULLET", mklualib_curses_ACS_BULLET}, + {"ACS_LARROW", mklualib_curses_ACS_LARROW}, + {"ACS_RARROW", mklualib_curses_ACS_RARROW}, + {"ACS_DARROW", mklualib_curses_ACS_DARROW}, + {"ACS_UARROW", mklualib_curses_ACS_UARROW}, + {"ACS_BOARD", mklualib_curses_ACS_BOARD}, + {"ACS_LANTERN", mklualib_curses_ACS_LANTERN}, + {"ACS_BLOCK", mklualib_curses_ACS_BLOCK}, + {"ACS_S3", mklualib_curses_ACS_S3}, + {"ACS_S7", mklualib_curses_ACS_S7}, + {"ACS_LEQUAL", mklualib_curses_ACS_LEQUAL}, + {"ACS_GEQUAL", mklualib_curses_ACS_GEQUAL}, + {"ACS_PI", mklualib_curses_ACS_PI}, + {"ACS_NEQUAL", mklualib_curses_ACS_NEQUAL}, + {"ACS_STERLING", mklualib_curses_ACS_STERLING}, + {"ACS_BSSB", mklualib_curses_ACS_BSSB}, + {"ACS_SSBB", mklualib_curses_ACS_SSBB}, + {"ACS_BBSS", mklualib_curses_ACS_BBSS}, + {"ACS_SBBS", mklualib_curses_ACS_SBBS}, + {"ACS_SBSS", mklualib_curses_ACS_SBSS}, + {"ACS_SSSB", mklualib_curses_ACS_SSSB}, + {"ACS_SSBS", mklualib_curses_ACS_SSBS}, + {"ACS_BSSS", mklualib_curses_ACS_BSSS}, + {"ACS_BSBS", mklualib_curses_ACS_BSBS}, + {"ACS_SBSB", mklualib_curses_ACS_SBSB}, + {"ACS_SSSS", mklualib_curses_ACS_SSSS}, + {"delscreen", mklualib_curses_delscreen}, + {"set_term", mklualib_curses_set_term}, + {"box", mklualib_curses_box}, + {"clearok", mklualib_curses_clearok}, + {"delwin", mklualib_curses_delwin}, + {"derwin", mklualib_curses_derwin}, + {"dupwin", mklualib_curses_dupwin}, + {"getbkgd", mklualib_curses_getbkgd}, + {"idcok", mklualib_curses_idcok}, + {"idlok", mklualib_curses_idlok}, + {"immedok", mklualib_curses_immedok}, + {"intrflush", mklualib_curses_intrflush}, + {"is_linetouched", mklualib_curses_is_linetouched}, + {"is_wintouched", mklualib_curses_is_wintouched}, + {"keypad", mklualib_curses_keypad}, + {"leaveok", mklualib_curses_leaveok}, + {"meta", mklualib_curses_meta}, + {"mvderwin", mklualib_curses_mvderwin}, + {"mvwaddch", mklualib_curses_mvwaddch}, + {"mvwaddstr", mklualib_curses_mvwaddstr}, + {"mvwchgat", mklualib_curses_mvwchgat}, + {"mvwdelch", mklualib_curses_mvwdelch}, + {"mvwgetch", mklualib_curses_mvwgetch}, + {"mvwgetnstr", mklualib_curses_mvwgetnstr}, + {"mvwhline", mklualib_curses_mvwhline}, + {"mvwin", mklualib_curses_mvwin}, + {"mvwinch", mklualib_curses_mvwinch}, + {"mvwinnstr", mklualib_curses_mvwinnstr}, + {"mvwinsch", mklualib_curses_mvwinsch}, + {"mvwinsnstr", mklualib_curses_mvwinsnstr}, + {"mvwinsstr", mklualib_curses_mvwinsstr}, + {"mvwinstr", mklualib_curses_mvwinstr}, + {"mvwvline", mklualib_curses_mvwvline}, + {"nodelay", mklualib_curses_nodelay}, + {"notimeout", mklualib_curses_notimeout}, + {"pechochar", mklualib_curses_pechochar}, + {"pnoutrefresh", mklualib_curses_pnoutrefresh}, + {"prefresh", mklualib_curses_prefresh}, + {"putwin", mklualib_curses_putwin}, + {"redrawwin", mklualib_curses_redrawwin}, + {"scroll", mklualib_curses_scroll}, + {"scrollok", mklualib_curses_scrollok}, + {"touchline", mklualib_curses_touchline}, + {"touchwin", mklualib_curses_touchwin}, + {"untouchwin", mklualib_curses_untouchwin}, + {"waddch", mklualib_curses_waddch}, + {"waddnstr", mklualib_curses_waddnstr}, + {"waddstr", mklualib_curses_waddstr}, + {"wattron", mklualib_curses_wattron}, + {"wattroff", mklualib_curses_wattroff}, + {"wattrset", mklualib_curses_wattrset}, + {"wattr_get", mklualib_curses_wattr_get}, + {"wattr_on", mklualib_curses_wattr_on}, + {"wattr_off", mklualib_curses_wattr_off}, + {"wattr_set", mklualib_curses_wattr_set}, + {"wbkgd", mklualib_curses_wbkgd}, + {"wbkgdset", mklualib_curses_wbkgdset}, + {"wborder", mklualib_curses_wborder}, + {"wchgat", mklualib_curses_wchgat}, + {"wclear", mklualib_curses_wclear}, + {"wclrtobot", mklualib_curses_wclrtobot}, + {"wclrtoeol", mklualib_curses_wclrtoeol}, + {"wcolor_set", mklualib_curses_wcolor_set}, + {"wcursyncup", mklualib_curses_wcursyncup}, + {"wdelch", mklualib_curses_wdelch}, + {"wdeleteln", mklualib_curses_wdeleteln}, + {"wechochar", mklualib_curses_wechochar}, + {"werase", mklualib_curses_werase}, + {"wgetch", mklualib_curses_wgetch}, + {"wgetnstr", mklualib_curses_wgetnstr}, + {"whline", mklualib_curses_whline}, + {"winch", mklualib_curses_winch}, + {"winnstr", mklualib_curses_winnstr}, + {"winsch", mklualib_curses_winsch}, + {"winsdelln", mklualib_curses_winsdelln}, + {"winsertln", mklualib_curses_winsertln}, + {"winsnstr", mklualib_curses_winsnstr}, + {"winsstr", mklualib_curses_winsstr}, + {"winstr", mklualib_curses_winstr}, + {"wmove", mklualib_curses_wmove}, + {"wnoutrefresh", mklualib_curses_wnoutrefresh}, + {"wredrawln", mklualib_curses_wredrawln}, + {"wrefresh", mklualib_curses_wrefresh}, + {"wscrl", mklualib_curses_wscrl}, + {"wsetscrreg", mklualib_curses_wsetscrreg}, + {"wstandout", mklualib_curses_wstandout}, + {"wstandend", mklualib_curses_wstandend}, + {"wsyncdown", mklualib_curses_wsyncdown}, + {"wsyncup", mklualib_curses_wsyncup}, + {"wtimeout", mklualib_curses_wtimeout}, + {"wtouchln", mklualib_curses_wtouchln}, + {"wvline", mklualib_curses_wvline}, + {"wenclose", mklualib_curses_wenclose}, + {"wmouse_trafo", mklualib_curses_wmouse_trafo}, + {"stdscr", mklualib_curses_stdscr}, + {"curscr", mklualib_curses_curscr}, + {"newscr", mklualib_curses_newscr}, + {"LINES", mklualib_curses_LINES}, + {"COLS", mklualib_curses_COLS}, + {"TABSIZE", mklualib_curses_TABSIZE}, + {"ESCDELAY", mklualib_curses_ESCDELAY}, + {"is_term_resized", mklualib_curses_is_term_resized}, + {"keybound", mklualib_curses_keybound}, + {"curses_version", mklualib_curses_curses_version}, + {"assume_default_colors", mklualib_curses_assume_default_colors}, + {"define_key", mklualib_curses_define_key}, + {"key_defined", mklualib_curses_key_defined}, + {"keyok", mklualib_curses_keyok}, + {"resize_term", mklualib_curses_resize_term}, + {"resizeterm", mklualib_curses_resizeterm}, + {"use_default_colors", mklualib_curses_use_default_colors}, + {"use_extended_names", mklualib_curses_use_extended_names}, + {"wresize", mklualib_curses_wresize}, + {"addch", mklualib_curses_addch}, + {"addnstr", mklualib_curses_addnstr}, + {"addstr", mklualib_curses_addstr}, + {"attroff", mklualib_curses_attroff}, + {"attron", mklualib_curses_attron}, + {"attrset", mklualib_curses_attrset}, + {"attr_get", mklualib_curses_attr_get}, + {"attr_off", mklualib_curses_attr_off}, + {"attr_on", mklualib_curses_attr_on}, + {"attr_set", mklualib_curses_attr_set}, + {"baudrate", mklualib_curses_baudrate}, + {"beep", mklualib_curses_beep}, + {"bkgd", mklualib_curses_bkgd}, + {"bkgdset", mklualib_curses_bkgdset}, + {"border", mklualib_curses_border}, + {"can_change_color", mklualib_curses_can_change_color}, + {"cbreak", mklualib_curses_cbreak}, + {"chgat", mklualib_curses_chgat}, + {"clear", mklualib_curses_clear}, + {"clrtobot", mklualib_curses_clrtobot}, + {"clrtoeol", mklualib_curses_clrtoeol}, + {"color_content", mklualib_curses_color_content}, + {"color_set", mklualib_curses_color_set}, + {"COLOR_PAIR", mklualib_curses_COLOR_PAIR}, + {"copywin", mklualib_curses_copywin}, + {"curs_set", mklualib_curses_curs_set}, + {"def_prog_mode", mklualib_curses_def_prog_mode}, + {"def_shell_mode", mklualib_curses_def_shell_mode}, + {"delay_output", mklualib_curses_delay_output}, + {"delch", mklualib_curses_delch}, + {"deleteln", mklualib_curses_deleteln}, + {"doupdate", mklualib_curses_doupdate}, + {"echo", mklualib_curses_echo}, + {"echochar", mklualib_curses_echochar}, + {"erase", mklualib_curses_erase}, + {"endwin", mklualib_curses_endwin}, + {"erasechar", mklualib_curses_erasechar}, + {"filter", mklualib_curses_filter}, + {"flash", mklualib_curses_flash}, + {"flushinp", mklualib_curses_flushinp}, + {"getch", mklualib_curses_getch}, + {"getnstr", mklualib_curses_getnstr}, + {"getwin", mklualib_curses_getwin}, + {"halfdelay", mklualib_curses_halfdelay}, + {"has_colors", mklualib_curses_has_colors}, + {"has_ic", mklualib_curses_has_ic}, + {"has_il", mklualib_curses_has_il}, + {"hline", mklualib_curses_hline}, + {"inch", mklualib_curses_inch}, + {"initscr", mklualib_curses_initscr}, + {"init_color", mklualib_curses_init_color}, + {"init_pair", mklualib_curses_init_pair}, + {"innstr", mklualib_curses_innstr}, + {"insch", mklualib_curses_insch}, + {"insdelln", mklualib_curses_insdelln}, + {"insertln", mklualib_curses_insertln}, + {"insnstr", mklualib_curses_insnstr}, + {"insstr", mklualib_curses_insstr}, + {"instr", mklualib_curses_instr}, + {"isendwin", mklualib_curses_isendwin}, + {"keyname", mklualib_curses_keyname}, + {"killchar", mklualib_curses_killchar}, + {"longname", mklualib_curses_longname}, + {"move", mklualib_curses_move}, + {"mvaddch", mklualib_curses_mvaddch}, + {"mvaddnstr", mklualib_curses_mvaddnstr}, + {"mvaddstr", mklualib_curses_mvaddstr}, + {"mvchgat", mklualib_curses_mvchgat}, + {"mvcur", mklualib_curses_mvcur}, + {"mvdelch", mklualib_curses_mvdelch}, + {"mvgetch", mklualib_curses_mvgetch}, + {"mvgetnstr", mklualib_curses_mvgetnstr}, + {"mvhline", mklualib_curses_mvhline}, + {"mvinch", mklualib_curses_mvinch}, + {"mvinnstr", mklualib_curses_mvinnstr}, + {"mvinsch", mklualib_curses_mvinsch}, + {"mvinsnstr", mklualib_curses_mvinsnstr}, + {"mvinsstr", mklualib_curses_mvinsstr}, + {"mvinstr", mklualib_curses_mvinstr}, + {"mvvline", mklualib_curses_mvvline}, + {"napms", mklualib_curses_napms}, + {"newpad", mklualib_curses_newpad}, + {"newterm", mklualib_curses_newterm}, + {"newwin", mklualib_curses_newwin}, + {"nl", mklualib_curses_nl}, + {"nocbreak", mklualib_curses_nocbreak}, + {"noecho", mklualib_curses_noecho}, + {"nonl", mklualib_curses_nonl}, + {"noqiflush", mklualib_curses_noqiflush}, + {"noraw", mklualib_curses_noraw}, + {"overlay", mklualib_curses_overlay}, + {"overwrite", mklualib_curses_overwrite}, + {"pair_content", mklualib_curses_pair_content}, + {"PAIR_NUMBER", mklualib_curses_PAIR_NUMBER}, + {"putp", mklualib_curses_putp}, + {"qiflush", mklualib_curses_qiflush}, + {"raw", mklualib_curses_raw}, + {"refresh", mklualib_curses_refresh}, + {"resetty", mklualib_curses_resetty}, + {"reset_prog_mode", mklualib_curses_reset_prog_mode}, + {"reset_shell_mode", mklualib_curses_reset_shell_mode}, + {"savetty", mklualib_curses_savetty}, + {"scr_dump", mklualib_curses_scr_dump}, + {"scr_init", mklualib_curses_scr_init}, + {"scrl", mklualib_curses_scrl}, + {"scr_restore", mklualib_curses_scr_restore}, + {"scr_set", mklualib_curses_scr_set}, + {"setscrreg", mklualib_curses_setscrreg}, + {"standout", mklualib_curses_standout}, + {"standend", mklualib_curses_standend}, + {"start_color", mklualib_curses_start_color}, + {"subpad", mklualib_curses_subpad}, + {"subwin", mklualib_curses_subwin}, + {"syncok", mklualib_curses_syncok}, + {"timeout", mklualib_curses_timeout}, + {"typeahead", mklualib_curses_typeahead}, + {"ungetch", mklualib_curses_ungetch}, + {"use_env", mklualib_curses_use_env}, + {"vidattr", mklualib_curses_vidattr}, + {"vline", mklualib_curses_vline}, + {"getyx", mklualib_curses_getyx}, + {"getbegyx", mklualib_curses_getbegyx}, + {"getmaxyx", mklualib_curses_getmaxyx}, + {"getparyx", mklualib_curses_getparyx}, + {"KEY_F", mklualib_curses_KEY_F}, + {"BUTTON_RELEASE", mklualib_curses_BUTTON_RELEASE}, + {"BUTTON_PRESS", mklualib_curses_BUTTON_PRESS}, + {"BUTTON_CLICK", mklualib_curses_BUTTON_CLICK}, + {"BUTTON_DOUBLE_CLICK", mklualib_curses_BUTTON_DOUBLE_CLICK}, + {"BUTTON_TRIPLE_CLICK", mklualib_curses_BUTTON_TRIPLE_CLICK}, + {"BUTTON_RESERVED_EVENT", mklualib_curses_BUTTON_RESERVED_EVENT}, + {"getmouse", mklualib_curses_getmouse}, + {"ungetmouse", mklualib_curses_ungetmouse}, + {"mousemask", mklualib_curses_mousemask}, + {"addmousemask", mklualib_curses_addmousemask}, + {"mouseinterval", mklualib_curses_mouseinterval}, + {"mouse_trafo", mklualib_curses_mouse_trafo}, + {0, 0} +}; + +const mklualib_regnum mklualib_curses_lib_nums[] = { + {"OK", OK}, + {"ERR", ERR}, + {"WA_ATTRIBUTES", WA_ATTRIBUTES}, + {"WA_NORMAL", WA_NORMAL}, + {"WA_STANDOUT", WA_STANDOUT}, + {"WA_UNDERLINE", WA_UNDERLINE}, + {"WA_REVERSE", WA_REVERSE}, + {"WA_BLINK", WA_BLINK}, + {"WA_DIM", WA_DIM}, + {"WA_BOLD", WA_BOLD}, + {"WA_ALTCHARSET", WA_ALTCHARSET}, + {"WA_INVIS", WA_INVIS}, + {"WA_PROTECT", WA_PROTECT}, + {"WA_HORIZONTAL", WA_HORIZONTAL}, + {"WA_LEFT", WA_LEFT}, + {"WA_LOW", WA_LOW}, + {"WA_RIGHT", WA_RIGHT}, + {"WA_TOP", WA_TOP}, + {"WA_VERTICAL", WA_VERTICAL}, + {"COLOR_BLACK", COLOR_BLACK}, + {"COLOR_RED", COLOR_RED}, + {"COLOR_GREEN", COLOR_GREEN}, + {"COLOR_YELLOW", COLOR_YELLOW}, + {"COLOR_BLUE", COLOR_BLUE}, + {"COLOR_MAGENTA", COLOR_MAGENTA}, + {"COLOR_CYAN", COLOR_CYAN}, + {"COLOR_WHITE", COLOR_WHITE}, + {"A_NORMAL", A_NORMAL}, + {"A_ATTRIBUTES", A_ATTRIBUTES}, + {"A_CHARTEXT", A_CHARTEXT}, + {"A_COLOR", A_COLOR}, + {"A_STANDOUT", A_STANDOUT}, + {"A_UNDERLINE", A_UNDERLINE}, + {"A_REVERSE", A_REVERSE}, + {"A_BLINK", A_BLINK}, + {"A_DIM", A_DIM}, + {"A_BOLD", A_BOLD}, + {"A_ALTCHARSET", A_ALTCHARSET}, + {"A_INVIS", A_INVIS}, + {"A_PROTECT", A_PROTECT}, + {"A_HORIZONTAL", A_HORIZONTAL}, + {"A_LEFT", A_LEFT}, + {"A_LOW", A_LOW}, + {"A_RIGHT", A_RIGHT}, + {"A_TOP", A_TOP}, + {"A_VERTICAL", A_VERTICAL}, + {"KEY_CODE_YES", KEY_CODE_YES}, + {"KEY_MIN", KEY_MIN}, + {"KEY_BREAK", KEY_BREAK}, + {"KEY_SRESET", KEY_SRESET}, + {"KEY_RESET", KEY_RESET}, + {"KEY_DOWN", KEY_DOWN}, + {"KEY_UP", KEY_UP}, + {"KEY_LEFT", KEY_LEFT}, + {"KEY_RIGHT", KEY_RIGHT}, + {"KEY_HOME", KEY_HOME}, + {"KEY_BACKSPACE", KEY_BACKSPACE}, + {"KEY_F0", KEY_F0}, + {"KEY_DL", KEY_DL}, + {"KEY_IL", KEY_IL}, + {"KEY_DC", KEY_DC}, + {"KEY_IC", KEY_IC}, + {"KEY_EIC", KEY_EIC}, + {"KEY_CLEAR", KEY_CLEAR}, + {"KEY_EOS", KEY_EOS}, + {"KEY_EOL", KEY_EOL}, + {"KEY_SF", KEY_SF}, + {"KEY_SR", KEY_SR}, + {"KEY_NPAGE", KEY_NPAGE}, + {"KEY_PPAGE", KEY_PPAGE}, + {"KEY_STAB", KEY_STAB}, + {"KEY_CTAB", KEY_CTAB}, + {"KEY_CATAB", KEY_CATAB}, + {"KEY_ENTER", KEY_ENTER}, + {"KEY_PRINT", KEY_PRINT}, + {"KEY_LL", KEY_LL}, + {"KEY_A1", KEY_A1}, + {"KEY_A3", KEY_A3}, + {"KEY_B2", KEY_B2}, + {"KEY_C1", KEY_C1}, + {"KEY_C3", KEY_C3}, + {"KEY_BTAB", KEY_BTAB}, + {"KEY_BEG", KEY_BEG}, + {"KEY_CANCEL", KEY_CANCEL}, + {"KEY_CLOSE", KEY_CLOSE}, + {"KEY_COMMAND", KEY_COMMAND}, + {"KEY_COPY", KEY_COPY}, + {"KEY_CREATE", KEY_CREATE}, + {"KEY_END", KEY_END}, + {"KEY_EXIT", KEY_EXIT}, + {"KEY_FIND", KEY_FIND}, + {"KEY_HELP", KEY_HELP}, + {"KEY_MARK", KEY_MARK}, + {"KEY_MESSAGE", KEY_MESSAGE}, + {"KEY_MOVE", KEY_MOVE}, + {"KEY_NEXT", KEY_NEXT}, + {"KEY_OPEN", KEY_OPEN}, + {"KEY_OPTIONS", KEY_OPTIONS}, + {"KEY_PREVIOUS", KEY_PREVIOUS}, + {"KEY_REDO", KEY_REDO}, + {"KEY_REFERENCE", KEY_REFERENCE}, + {"KEY_REFRESH", KEY_REFRESH}, + {"KEY_REPLACE", KEY_REPLACE}, + {"KEY_RESTART", KEY_RESTART}, + {"KEY_RESUME", KEY_RESUME}, + {"KEY_SAVE", KEY_SAVE}, + {"KEY_SBEG", KEY_SBEG}, + {"KEY_SCANCEL", KEY_SCANCEL}, + {"KEY_SCOMMAND", KEY_SCOMMAND}, + {"KEY_SCOPY", KEY_SCOPY}, + {"KEY_SCREATE", KEY_SCREATE}, + {"KEY_SDC", KEY_SDC}, + {"KEY_SDL", KEY_SDL}, + {"KEY_SELECT", KEY_SELECT}, + {"KEY_SEND", KEY_SEND}, + {"KEY_SEOL", KEY_SEOL}, + {"KEY_SEXIT", KEY_SEXIT}, + {"KEY_SFIND", KEY_SFIND}, + {"KEY_SHELP", KEY_SHELP}, + {"KEY_SHOME", KEY_SHOME}, + {"KEY_SIC", KEY_SIC}, + {"KEY_SLEFT", KEY_SLEFT}, + {"KEY_SMESSAGE", KEY_SMESSAGE}, + {"KEY_SMOVE", KEY_SMOVE}, + {"KEY_SNEXT", KEY_SNEXT}, + {"KEY_SOPTIONS", KEY_SOPTIONS}, + {"KEY_SPREVIOUS", KEY_SPREVIOUS}, + {"KEY_SPRINT", KEY_SPRINT}, + {"KEY_SREDO", KEY_SREDO}, + {"KEY_SREPLACE", KEY_SREPLACE}, + {"KEY_SRIGHT", KEY_SRIGHT}, + {"KEY_SRSUME", KEY_SRSUME}, + {"KEY_SSAVE", KEY_SSAVE}, + {"KEY_SSUSPEND", KEY_SSUSPEND}, + {"KEY_SUNDO", KEY_SUNDO}, + {"KEY_SUSPEND", KEY_SUSPEND}, + {"KEY_UNDO", KEY_UNDO}, + {"KEY_MOUSE", KEY_MOUSE}, + {"KEY_RESIZE", KEY_RESIZE}, + {"KEY_EVENT", KEY_EVENT}, + {"KEY_MAX", KEY_MAX}, + {"BUTTON1_RELEASED", BUTTON1_RELEASED}, + {"BUTTON1_PRESSED", BUTTON1_PRESSED}, + {"BUTTON1_CLICKED", BUTTON1_CLICKED}, + {"BUTTON1_DOUBLE_CLICKED", BUTTON1_DOUBLE_CLICKED}, + {"BUTTON1_TRIPLE_CLICKED", BUTTON1_TRIPLE_CLICKED}, + {"BUTTON1_RESERVED_EVENT", BUTTON1_RESERVED_EVENT}, + {"BUTTON2_RELEASED", BUTTON2_RELEASED}, + {"BUTTON2_PRESSED", BUTTON2_PRESSED}, + {"BUTTON2_CLICKED", BUTTON2_CLICKED}, + {"BUTTON2_DOUBLE_CLICKED", BUTTON2_DOUBLE_CLICKED}, + {"BUTTON2_TRIPLE_CLICKED", BUTTON2_TRIPLE_CLICKED}, + {"BUTTON2_RESERVED_EVENT", BUTTON2_RESERVED_EVENT}, + {"BUTTON3_RELEASED", BUTTON3_RELEASED}, + {"BUTTON3_PRESSED", BUTTON3_PRESSED}, + {"BUTTON3_CLICKED", BUTTON3_CLICKED}, + {"BUTTON3_DOUBLE_CLICKED", BUTTON3_DOUBLE_CLICKED}, + {"BUTTON3_TRIPLE_CLICKED", BUTTON3_TRIPLE_CLICKED}, + {"BUTTON3_RESERVED_EVENT", BUTTON3_RESERVED_EVENT}, + {"BUTTON4_RELEASED", BUTTON4_RELEASED}, + {"BUTTON4_PRESSED", BUTTON4_PRESSED}, + {"BUTTON4_CLICKED", BUTTON4_CLICKED}, + {"BUTTON4_DOUBLE_CLICKED", BUTTON4_DOUBLE_CLICKED}, + {"BUTTON4_TRIPLE_CLICKED", BUTTON4_TRIPLE_CLICKED}, + {"BUTTON4_RESERVED_EVENT", BUTTON4_RESERVED_EVENT}, + {"BUTTON_CTRL", BUTTON_CTRL}, + {"BUTTON_SHIFT", BUTTON_SHIFT}, + {"BUTTON_ALT", BUTTON_ALT}, + {"ALL_MOUSE_EVENTS", ALL_MOUSE_EVENTS}, + {"REPORT_MOUSE_POSITION", REPORT_MOUSE_POSITION}, + {0, 0} +}; + +const luaL_reg mklualib_curses_window_lib[] = { + {"__tostring", mklualib_curses_window___tostring}, + {"__gc", mklualib_curses_window___gc}, + {"box", mklualib_curses_box}, + {"clearok", mklualib_curses_clearok}, + {"delwin", mklualib_curses_delwin}, + {"derwin", mklualib_curses_derwin}, + {"dupwin", mklualib_curses_dupwin}, + {"getbkgd", mklualib_curses_getbkgd}, + {"idcok", mklualib_curses_idcok}, + {"idlok", mklualib_curses_idlok}, + {"immedok", mklualib_curses_immedok}, + {"intrflush", mklualib_curses_intrflush}, + {"is_linetouched", mklualib_curses_is_linetouched}, + {"is_wintouched", mklualib_curses_is_wintouched}, + {"keypad", mklualib_curses_keypad}, + {"leaveok", mklualib_curses_leaveok}, + {"meta", mklualib_curses_meta}, + {"mvderwin", mklualib_curses_mvderwin}, + {"mvaddch", mklualib_curses_mvwaddch}, + {"mvaddstr", mklualib_curses_mvwaddstr}, + {"mvchgat", mklualib_curses_mvwchgat}, + {"mvdelch", mklualib_curses_mvwdelch}, + {"mvgetch", mklualib_curses_mvwgetch}, + {"mvgetnstr", mklualib_curses_mvwgetnstr}, + {"mvhline", mklualib_curses_mvwhline}, + {"mvin", mklualib_curses_mvwin}, + {"mvinch", mklualib_curses_mvwinch}, + {"mvinnstr", mklualib_curses_mvwinnstr}, + {"mvinsch", mklualib_curses_mvwinsch}, + {"mvinsnstr", mklualib_curses_mvwinsnstr}, + {"mvinsstr", mklualib_curses_mvwinsstr}, + {"mvinstr", mklualib_curses_mvwinstr}, + {"mvvline", mklualib_curses_mvwvline}, + {"nodelay", mklualib_curses_nodelay}, + {"notimeout", mklualib_curses_notimeout}, + {"pechochar", mklualib_curses_pechochar}, + {"pnoutrefresh", mklualib_curses_pnoutrefresh}, + {"prefresh", mklualib_curses_prefresh}, + {"putwin", mklualib_curses_putwin}, + {"redrawwin", mklualib_curses_redrawwin}, + {"scroll", mklualib_curses_scroll}, + {"scrollok", mklualib_curses_scrollok}, + {"touchline", mklualib_curses_touchline}, + {"touchwin", mklualib_curses_touchwin}, + {"untouchwin", mklualib_curses_untouchwin}, + {"addch", mklualib_curses_waddch}, + {"addnstr", mklualib_curses_waddnstr}, + {"addstr", mklualib_curses_waddstr}, + {"attron", mklualib_curses_wattron}, + {"attroff", mklualib_curses_wattroff}, + {"attrset", mklualib_curses_wattrset}, + {"attr_get", mklualib_curses_wattr_get}, + {"attr_on", mklualib_curses_wattr_on}, + {"attr_off", mklualib_curses_wattr_off}, + {"attr_set", mklualib_curses_wattr_set}, + {"bkgd", mklualib_curses_wbkgd}, + {"bkgdset", mklualib_curses_wbkgdset}, + {"border", mklualib_curses_wborder}, + {"chgat", mklualib_curses_wchgat}, + {"clear", mklualib_curses_wclear}, + {"clrtobot", mklualib_curses_wclrtobot}, + {"clrtoeol", mklualib_curses_wclrtoeol}, + {"color_set", mklualib_curses_wcolor_set}, + {"cursyncup", mklualib_curses_wcursyncup}, + {"delch", mklualib_curses_wdelch}, + {"deleteln", mklualib_curses_wdeleteln}, + {"echochar", mklualib_curses_wechochar}, + {"erase", mklualib_curses_werase}, + {"getch", mklualib_curses_wgetch}, + {"getnstr", mklualib_curses_wgetnstr}, + {"hline", mklualib_curses_whline}, + {"inch", mklualib_curses_winch}, + {"innstr", mklualib_curses_winnstr}, + {"insch", mklualib_curses_winsch}, + {"insdelln", mklualib_curses_winsdelln}, + {"insertln", mklualib_curses_winsertln}, + {"insnstr", mklualib_curses_winsnstr}, + {"insstr", mklualib_curses_winsstr}, + {"instr", mklualib_curses_winstr}, + {"move", mklualib_curses_wmove}, + {"noutrefresh", mklualib_curses_wnoutrefresh}, + {"redrawln", mklualib_curses_wredrawln}, + {"refresh", mklualib_curses_wrefresh}, + {"scrl", mklualib_curses_wscrl}, + {"setscrreg", mklualib_curses_wsetscrreg}, + {"standout", mklualib_curses_wstandout}, + {"standend", mklualib_curses_wstandend}, + {"syncdown", mklualib_curses_wsyncdown}, + {"syncup", mklualib_curses_wsyncup}, + {"timeout", mklualib_curses_wtimeout}, + {"touchln", mklualib_curses_wtouchln}, + {"vline", mklualib_curses_wvline}, + {"enclose", mklualib_curses_wenclose}, + {"mouse_trafo", mklualib_curses_wmouse_trafo}, + {0, 0} +}; + +void mklualib_create_curses_window(lua_State* mklualib_lua_state) +{ + luaL_newmetatable(mklualib_lua_state, MKLUALIB_META_CURSES_WINDOW); + lua_pushliteral(mklualib_lua_state, "__index"); + lua_pushvalue(mklualib_lua_state, -2); + lua_rawset(mklualib_lua_state, -3); + luaL_register(mklualib_lua_state, 0, mklualib_curses_window_lib); +} + +const luaL_reg mklualib_curses_screen_lib[] = { + {"delscreen", mklualib_curses_delscreen}, + {"set_term", mklualib_curses_set_term}, + {"__tostring", mklualib_curses_screen___tostring}, + {"__gc", mklualib_curses_screen___gc}, + {0, 0} +}; + +void mklualib_create_curses_screen(lua_State* mklualib_lua_state) +{ + luaL_newmetatable(mklualib_lua_state, MKLUALIB_META_CURSES_SCREEN); + lua_pushliteral(mklualib_lua_state, "__index"); + lua_pushvalue(mklualib_lua_state, -2); + lua_rawset(mklualib_lua_state, -3); + luaL_register(mklualib_lua_state, 0, mklualib_curses_screen_lib); +} + +int luaopen_curses(lua_State* mklualib_lua_state) +{ + mklualib_create_curses_window(mklualib_lua_state); + mklualib_create_curses_screen(mklualib_lua_state); + luaL_register(mklualib_lua_state, MKLUALIB_MODULE_CURSES, mklualib_curses_lib); + mklualib_regnumbers(mklualib_lua_state, mklualib_curses_lib_nums); + return 1; +} + diff --git a/openwrt/packages/luci/contrib/luacurses/src/luacurses.c b/openwrt/packages/luci/contrib/luacurses/src/luacurses.c new file mode 100644 index 0000000..0cbd2fe --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/src/luacurses.c @@ -0,0 +1,137 @@ + +#include + +#include +#include +#include + +#include +#include "luacurses.h" + +SCREEN* luacurses_toscreen(lua_State* L, int index) +{ + SCREEN** pscreen = (SCREEN**) luaL_checkudata(L, index, MKLUALIB_META_CURSES_SCREEN); + if (!pscreen) luaL_argerror(L, index, "bad screen"); + if (!*pscreen) luaL_error(L, "attempt to use invalid screen"); + return *pscreen; +} + +SCREEN** luacurses_newscreen(lua_State* L) +{ + SCREEN** pscreen = (SCREEN**) lua_newuserdata(L, sizeof(SCREEN*)); + *pscreen = 0; + luaL_getmetatable(L, MKLUALIB_META_CURSES_SCREEN); + lua_setmetatable(L, -2); + return pscreen; +} + +void luacurses_regscreen(lua_State* L, const char* name, SCREEN* userdata) +{ + lua_pushstring(L, name); + SCREEN** pscreen = luacurses_newscreen(L); + *pscreen = userdata; + lua_settable(L, -3); +} + +WINDOW* luacurses_towindow(lua_State* L, int index) +{ + WINDOW** pwindow = (WINDOW**) luaL_checkudata(L, index, MKLUALIB_META_CURSES_WINDOW); + if (!pwindow) luaL_argerror(L, index, "bad window"); + if (!*pwindow) luaL_error(L, "attempt to use invalid window"); + return *pwindow; +} + +WINDOW** luacurses_newwindow(lua_State* L) +{ + WINDOW** pwindow = (WINDOW**) lua_newuserdata(L, sizeof(WINDOW*)); + *pwindow = 0; + luaL_getmetatable(L, MKLUALIB_META_CURSES_WINDOW); + lua_setmetatable(L, -2); + return pwindow; +} + +void luacurses_regwindow(lua_State* L, const char* name, WINDOW* userdata) +{ + lua_pushstring(L, name); + WINDOW** pwindow = luacurses_newwindow(L); + *pwindow = userdata; + lua_settable(L, -3); +} + +FILE* tofile(lua_State* L, int index) +{ + FILE** pf = (FILE**) luaL_checkudata(L, index, MKLUALIB_META_CURSES_FILE); + if (!pf) luaL_argerror(L, index, "bad file"); + if (!*pf) luaL_error(L, "attempt to use invalid file"); + return *pf; +} + +FILE** newfile(lua_State* L) +{ + FILE** pf = (FILE**) lua_newuserdata(L, sizeof(FILE*)); + *pf = 0; + luaL_getmetatable(L, MKLUALIB_META_CURSES_FILE); + lua_setmetatable(L, -2); + return pf; +} + +void luacurses_regfile(lua_State* L, const char* name, FILE* f) +{ + lua_pushstring(L, name); + FILE** pf = newfile(L); + *pf = f; + lua_settable(L, -3); +} + +char* luacurses_wgetnstr(WINDOW* w, int n) +{ + char* s = (char*) malloc(n + 1); + wgetnstr(w, s, n); + return s; +} + +char* luacurses_window_tostring(WINDOW* w) +{ + char* buf = (char*) malloc(64); + sprintf(buf, "window %p", w); + return buf; +} + +char* luacurses_screen_tostring(SCREEN* s) +{ + char* buf = (char*) malloc(64); + sprintf(buf, "screen %p", s); + return buf; +} + +bool luacurses_getmouse(short* id, int* x, int* y, int* z, mmask_t* bstate) +{ + MEVENT e; + int res = getmouse(&e); + + *id = e.id; + *x = e.x; + *y = e.y; + *z = e.z; + *bstate = e.bstate; + return (res == OK); +} + +bool luacurses_ungetmouse (short id, int x, int y, int z, mmask_t bstate) +{ + MEVENT e; + e.id = id; + e.x = x; + e.y = y; + e.z = z; + e.bstate = bstate; + return (ungetmouse(&e) == OK); +} + +mmask_t luacurses_addmousemask(mmask_t m) +{ + mmask_t old; + mousemask(m, &old); + return mousemask(old | m, 0); +} + diff --git a/openwrt/packages/luci/contrib/luacurses/src/luacurses.h b/openwrt/packages/luci/contrib/luacurses/src/luacurses.h new file mode 100644 index 0000000..2dc426c --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/src/luacurses.h @@ -0,0 +1,38 @@ + +#include + +#define MKLUALIB_META_CURSES_SCREEN "SCREEN*" + +SCREEN* luacurses_toscreen(lua_State* L, int index); +SCREEN** luacurses_newscreen(lua_State* L); +void luacurses_regscreen(lua_State* L, const char* name, SCREEN* userdata); + +#define MKLUALIB_META_CURSES_WINDOW "WINDOW*" + +WINDOW* luacurses_towindow(lua_State* L, int index); +WINDOW** luacurses_newwindow(lua_State* L); +void luacurses_regwindow(lua_State* L, const char* name, WINDOW* userdata); + +#define MKLUALIB_META_CURSES_FILE "FILE*" + +FILE* tofile(lua_State* L, int index); +FILE** newfile(lua_State* L); +void luacurses_regfile(lua_State* L, const char* name, FILE* f); + +char* luacurses_wgetnstr(WINDOW* w, int n); +char* luacurses_wgetstr(WINDOW* w); + +#define luacurses_mvwgetnstr(w, y, x, n) (wmove(w, y, x) == ERR ? 0 : luacurses_wgetnstr(w, n)) +#define luacurses_getnstr(n) luacurses_wgetnstr(stdscr, n) +#define luacurses_mvgetnstr(y, x, n) luacurses_mvwgetnstr(stdscr, y, x, n) + +char* luacurses_window_tostring(WINDOW* w); +char* luacurses_screen_tostring(SCREEN* s); + +#define luacurses_window_free(w) {delwin(w); w = 0;} +#define luacurses_screen_free(s) {delscreen(s); s = 0;} + +bool luacurses_getmouse(short* id, int* x, int* y, int* z, mmask_t* bstate); +bool luacurses_ungetmouse (short id, int x, int y, int z, mmask_t bstate); +mmask_t luacurses_addmousemask(mmask_t m); + diff --git a/openwrt/packages/luci/contrib/luacurses/test/filter.lua b/openwrt/packages/luci/contrib/luacurses/test/filter.lua new file mode 100644 index 0000000..f8f6ef5 --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/test/filter.lua @@ -0,0 +1,49 @@ + +require("curses"); + +function read_cmd() + curses.attron(curses.A_BOLD); + curses.addstr("Command: "); + curses.attron(underline); + local s = ""; + while (true) do + local c = string.char(curses.getch()); + if (c == '\n') then break; end + s = s .. c; + end + curses.attroff(underline); + curses.attroff(curses.A_BOLD); + curses.addch("\n"); + + return s; +end + + +curses.filter(); +curses.initscr(); +curses.cbreak(); +curses.keypad(curses.stdscr(), TRUE); + +if (curses.has_colors()) then + curses.start_color(); + curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK); + underline = curses.COLOR_PAIR(1); +else + underline = curses.A_UNDERLINE; +end + +while (true) do + local s = read_cmd(); + if (s == "exit") then break; end + curses.reset_shell_mode(); + io.write("\n"); + io.flush(io.stdout); + os.execute(s); + curses.reset_prog_mode(); + curses.touchwin(curses.stdscr()); + curses.erase(); + curses.refresh(); +end + +curses.endwin(); + diff --git a/openwrt/packages/luci/contrib/luacurses/test/getnstr.lua b/openwrt/packages/luci/contrib/luacurses/test/getnstr.lua new file mode 100644 index 0000000..172365e --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/test/getnstr.lua @@ -0,0 +1,12 @@ + +require("curses"); + +curses.initscr(); + +curses.keypad(curses.stdscr(), true); +s = curses.mvgetnstr(10, 10, 10); +curses.addstr(s); +curses.getch(); + +curses.endwin(); + diff --git a/openwrt/packages/luci/contrib/luacurses/test/getyx.lua b/openwrt/packages/luci/contrib/luacurses/test/getyx.lua new file mode 100644 index 0000000..4600236 --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/test/getyx.lua @@ -0,0 +1,13 @@ + +require("curses"); + +curses.initscr(); +while (true) do + local s = curses.getnstr(1000); + curses.addstr(s); + curses.addstr(":" .. table.concat({curses.getyx(curses.stdscr())}, ' ') .. "\n"); + if (s == "exit") then break; end +end + +curses.endwin(); + diff --git a/openwrt/packages/luci/contrib/luacurses/test/hello.lua b/openwrt/packages/luci/contrib/luacurses/test/hello.lua new file mode 100644 index 0000000..6a1d28a --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/test/hello.lua @@ -0,0 +1,20 @@ + +require("curses"); + +function show_message(message) + local width = string.len(message) + 6; + win = curses.newwin(5, width, (curses.LINES() - 5) / 2, (curses.COLS() - width) / 2); + win:box('|', '-'); + win:mvaddstr(2, 3, message); + win:getch(); + win:delwin(); +end + +curses.initscr(); +curses.cbreak(); +curses.mvaddstr((curses.LINES() - 5) / 2, (curses.COLS() - 10) / 2, "Hit any key"); +curses.getch(); +show_message("Hello, World!") + +curses.endwin(); + diff --git a/openwrt/packages/luci/contrib/luacurses/test/mouse.lua b/openwrt/packages/luci/contrib/luacurses/test/mouse.lua new file mode 100644 index 0000000..0129cd8 --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/test/mouse.lua @@ -0,0 +1,54 @@ + +require("curses"); + +function show_message(m) + local width = string.len(m) + 6; + local win = curses.newwin(5, width, (lines - 5) / 2, (cols - width) / 2); + win:keypad(true); + win:attron(curses.COLOR_PAIR(curses.COLOR_RED)); + win:box('|', '-', '+'); + win:mvaddstr(2, 3, m); + win:refresh(); + win:getch(); + win:delwin(); +end + +curses.initscr(); +curses.start_color(); +curses.init_pair(curses.COLOR_BLUE, curses.COLOR_BLUE, curses.COLOR_WHITE); +curses.init_pair(curses.COLOR_RED, curses.COLOR_RED, curses.COLOR_WHITE); +curses.cbreak(); +curses.noecho(); +curses.keypad(curses.stdscr(), true); + +lines = curses.LINES(); +cols = curses.COLS(); + +mmasks = +{ + curses.BUTTON1_CLICKED, + curses.BUTTON2_CLICKED, + curses.BUTTON3_CLICKED, + curses.BUTTON4_CLICKED +}; + +table.foreachi(mmasks, function(_i, _m) curses.addmousemask(_m) end); +curses.attron(curses.COLOR_PAIR(curses.COLOR_BLUE)); +curses.attron(curses.A_BOLD); +curses.mvaddstr((lines - 5) / 2, (cols - 10) / 2, "click"); + +curses.refresh(); +while(true) do + local c = curses.getch(); + if (c == curses.KEY_MOUSE) then + local r, id, x, y, z, bstate = curses.getmouse(); + if (r) then + show_message("id = " .. id .. ", x = " .. x .. ", y = " .. y .. ", z = " .. z .. ", bstate = " .. + string.format("0x%x", bstate)); + end + break; + end +end + +curses.endwin(); + diff --git a/openwrt/packages/luci/contrib/luacurses/test/pair.lua b/openwrt/packages/luci/contrib/luacurses/test/pair.lua new file mode 100644 index 0000000..f269800 --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/test/pair.lua @@ -0,0 +1,18 @@ + +require("curses"); + +curses.initscr(); + +curses.start_color(); +curses.init_pair(1, curses.COLOR_BLUE, curses.COLOR_YELLOW); +curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_RED); + +for i = 1, 2 do + local r, f, b = curses.pair_content(i); + curses.attrset(curses.COLOR_PAIR(i)); + curses.addstr(f .. ", " .. b .. "\n"); +end + +curses.getch(); +curses.endwin(); + diff --git a/openwrt/packages/luci/contrib/luacurses/test/rain.lua b/openwrt/packages/luci/contrib/luacurses/test/rain.lua new file mode 100644 index 0000000..35e4691 --- /dev/null +++ b/openwrt/packages/luci/contrib/luacurses/test/rain.lua @@ -0,0 +1,89 @@ + +require("curses"); + +curses.initscr(); +curses.nl(); +curses.noecho(); + + +if (curses.has_colors()) then + curses.start_color(); + curses.init_pair(1, curses.COLOR_BLUE, curses.COLOR_BLACK); + curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK); +end + +curses.curs_set(0); +curses.timeout(0); + +math.randomseed(os.time()); + +lines = curses.LINES(); +cols = curses.COLS(); + +xpos = {}; +ypos = {}; +r = lines - 4; +c = cols - 4; +for i = 0, 4 do + xpos[i] = c * math.random() + 2; + ypos[i] = r * math.random() + 2; +end + +function dec(i, max) + if (curses.has_colors()) then + local z = 3 * math.random(); + local c = curses.COLOR_PAIR(z); + curses.attrset(c); + if (math.floor(z) > 0) then + curses.attron(curses.A_BOLD); + end + end + + if (i > 0) then return i - 1; + else return max; + end +end + +i = 0; +while(true) do + x = c * math.random() + 2; + y = r * math.random() + 2; + + curses.mvaddstr(y, x, "."); + + curses.mvaddstr(ypos[i], xpos[i], "o"); + + i = dec(i, 4); + curses.mvaddstr(ypos[i], xpos[i], "O"); + + i = dec(i, 4); + curses.mvaddstr(ypos[i] - 1, xpos[i], "-"); + curses.mvaddstr(ypos[i], xpos[i] - 1, "|.|"); + curses.mvaddstr(ypos[i] + 1, xpos[i], "-"); + + i = dec(i, 4); + curses.mvaddstr(ypos[i] - 2, xpos[i], "-"); + curses.mvaddstr(ypos[i] - 1, xpos[i] - 1, "/ \\"); + curses.mvaddstr(ypos[i], xpos[i] - 2, "| O |"); + curses.mvaddstr(ypos[i] + 1, xpos[i] - 1, "\\ /"); + curses.mvaddstr(ypos[i] + 2, xpos[i], "-"); + + i = dec(i, 4); + curses.mvaddstr(ypos[i] - 2, xpos[i], " "); + curses.mvaddstr(ypos[i] - 1, xpos[i] - 1, " "); + curses.mvaddstr(ypos[i], xpos[i] - 2, " "); + curses.mvaddstr(ypos[i] + 1, xpos[i] - 1, " "); + curses.mvaddstr(ypos[i] + 2, xpos[i], " "); + + + xpos[i] = x; + ypos[i] = y; + + local ch = curses.getch(); + if (ch == string.byte('q', 1)) or (ch == string.byte('Q', 1)) then break; end + curses.refresh(); + curses.napms(50); +end + +curses.endwin(); + diff --git a/openwrt/packages/luci/contrib/luadoc/Makefile b/openwrt/packages/luci/contrib/luadoc/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/contrib/luadoc/hostfiles/bin/luadoc b/openwrt/packages/luci/contrib/luadoc/hostfiles/bin/luadoc new file mode 100755 index 0000000..ba99a37 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/hostfiles/bin/luadoc @@ -0,0 +1,121 @@ +#!/usr/bin/env lua +------------------------------------------------------------------------------- +-- LuaDoc launcher. +-- @release $Id: luadoc.lua.in,v 1.1 2008/02/17 06:42:51 jasonsantos Exp $ +------------------------------------------------------------------------------- + +require "luadoc" + +------------------------------------------------------------------------------- +-- Print version number. + +local function print_version () + print (string.format("%s\n%s\n%s", + luadoc._VERSION, + luadoc._DESCRIPTION, + luadoc._COPYRIGHT)) +end + +------------------------------------------------------------------------------- +-- Print usage message. + +local function print_help () + print ("Usage: "..arg[0]..[[ [options|files] +Generate documentation from files. Available options are: + -d path output directory path + -t path template directory path + -h, --help print this help and exit + --noindexpage do not generate global index page + --nofiles do not generate documentation for files + --nomodules do not generate documentation for modules + --doclet doclet_module doclet module to generate output + --taglet taglet_module taglet module to parse input code + -q, --quiet suppress all normal output + -v, --version print version information]]) +end + +local function off_messages (arg, i, options) + options.verbose = nil +end + +------------------------------------------------------------------------------- +-- Process options. TODO: use getopts. +-- @class table +-- @name OPTIONS + +local OPTIONS = { + d = function (arg, i, options) + local dir = arg[i+1] + if string.sub (dir, -2) ~= "/" then + dir = dir..'/' + end + options.output_dir = dir + return 1 + end, + t = function (arg, i, options) + local dir = arg[i+1] + if string.sub (dir, -2) ~= "/" then + dir = dir..'/' + end + options.template_dir = dir + return 1 + end, + h = print_help, + help = print_help, + q = off_messages, + quiet = off_messages, + v = print_version, + version = print_version, + doclet = function (arg, i, options) + options.doclet = arg[i+1] + return 1 + end, + taglet = function (arg, i, options) + options.taglet = arg[i+1] + return 1 + end, +} + +------------------------------------------------------------------------------- + +local function process_options (arg) + local files = {} + local options = require "luadoc.config" + local i = 1 + while i <= #arg do + local argi = arg[i] + if string.sub (argi, 1, 1) ~= '-' then + table.insert (files, argi) + else + local opt = string.sub (argi, 2) + if string.sub (opt, 1, 1) == '-' then + opt = string.gsub (opt, "%-", "") + end + if OPTIONS[opt] then + if OPTIONS[opt] (arg, i, options) then + i = i + 1 + end + else + options[opt] = 1 + end + end + i = i+1 + end + return files, options +end + +------------------------------------------------------------------------------- +-- Main function. Process command-line parameters and call luadoc processor. + +function main (arg) + -- Process options + local argc = #arg + if argc < 1 then + print_help () + return + end + local files, options = process_options (arg) + return luadoc.main(files, options) +end + +main(arg) diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/config.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/config.lua new file mode 100644 index 0000000..2738cf5 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/config.lua @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +-- LuaDoc configuration file. This file contains the default options for +-- luadoc operation. These options can be overriden by the command line tool +-- @see luadoc.print_help +-- @release $Id: config.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +module "luadoc.config" + +------------------------------------------------------------------------------- +-- Default options +-- @class table +-- @name default_options +-- @field output_dir default output directory for generated documentation, used +-- by several doclets +-- @field taglet parser used to analyze source code input +-- @field doclet documentation generator +-- @field template_dir directory with documentation templates, used by the html +-- doclet +-- @field verbose command line tool configuration to output processing +-- information + +local default_options = { + output_dir = "", + taglet = "luadoc.taglet.standard", + doclet = "luadoc.doclet.html", + -- TODO: find a way to define doclet specific options + template_dir = "luadoc/doclet/html/", + nomodules = false, + nofiles = false, + verbose = true, +} + +return default_options diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/debug.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/debug.lua new file mode 100644 index 0000000..33966cb --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/debug.lua @@ -0,0 +1,46 @@ +----------------------------------------------------------------- +-- LuaDoc debugging facilities. +-- @release $Id: debug.lua 3941 2008-12-23 21:39:38Z jow $ +----------------------------------------------------------------- + +module "luadoc.doclet.debug" + +function printline() + print(string.rep('-', 79)) +end + +----------------------------------------------------------------- +-- Print debug information about document +-- @param doc Table with the structured documentation. + +function start (doc) + print("Files:") + for _, filepath in ipairs(doc.files) do + print('\t', filepath) + end + printline() + + print("Modules:") + for _, modulename in ipairs(doc.modules) do + print('\t', modulename) + end + printline() + + for i, v in pairs(doc.files) do + print('\t', i, v) + end + printline() + for i, v in pairs(doc.files[doc.files[1]]) do + print(i, v) + end + + printline() + for i, v in pairs(doc.files[doc.files[1]].doc[1]) do + print(i, v) + end + printline() + print("Params") + for i, v in pairs(doc.files[doc.files[1]].doc[1].param) do + print(i, v) + end +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/formatter.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/formatter.lua new file mode 100644 index 0000000..40a7ce0 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/formatter.lua @@ -0,0 +1,84 @@ +------------------------------------------------------------------------------- +-- Doclet to format source code according to LuaDoc standard tags. This doclet +-- (re)write .lua files adding missing standard tags. Texts are formatted to +-- 80 columns and function parameters are added based on code analysis. +-- +-- @release $Id: formatter.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local util = require "luadoc.util" +local assert, ipairs, pairs, type = assert, ipairs, pairs, type +local string = require"string" +local table = require"table" + +module "luadoc.doclet.formatter" + +options = { + output_dir = "./", +} + +------------------------------------------------------------------------------- +-- Assembly the output filename for an input file. +-- TODO: change the name of this function +function out_file (filename) + local h = filename + h = options.output_dir..h + return h +end + +------------------------------------------------------------------------------- +-- Generate a new lua file for each input lua file. If the user does not +-- specify a different output directory input files will be rewritten. +-- @param doc documentation table + +function start (doc) + local todo = "" + + -- Process files + for i, file_doc in ipairs(doc.files) do + -- assembly the filename + local filename = out_file(file_doc.name) + luadoc.logger:info(string.format("generating file `%s'", filename)) + + -- TODO: confirm file overwrite + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + + for _, block in ipairs(file_doc.doc) do + + -- write reorganized comments + f:write(string.rep("-", 80).."\n") + + -- description + f:write(util.comment(util.wrap(block.description, 77))) + f:write("\n") + + if block.class == "function" then + -- parameters + table.foreachi(block.param, function (_, param_name) + f:write(util.comment(util.wrap(string.format("@param %s %s", param_name, block.param[param_name] or todo), 77))) + f:write("\n") + end) + + -- return + if type(block.ret) == "table" then + table.foreachi(block.ret, function (_, ret) + f:write(util.comment(util.wrap(string.format("@return %s", ret), 77)).."\n") + end) + else + f:write(util.comment(util.wrap(string.format("@return %s", block.ret or todo), 77)).."\n") + end + end + + -- TODO: usage + -- TODO: see + + -- write code + for _, line in ipairs(block.code) do + f:write(line.."\n") + end + end + + f:close() + end +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html.lua new file mode 100644 index 0000000..cd55e2e --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html.lua @@ -0,0 +1,275 @@ +------------------------------------------------------------------------------- +-- Doclet that generates HTML output. This doclet generates a set of html files +-- based on a group of templates. The main templates are: +--
    +--
  • index.lp: index of modules and files;
  • +--
  • file.lp: documentation for a lua file;
  • +--
  • module.lp: documentation for a lua module;
  • +--
  • function.lp: documentation for a lua function. This is a +-- sub-template used by the others.
  • +--
+-- +-- @release $Id: html.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local assert, getfenv, ipairs, loadstring, pairs, setfenv, tostring, tonumber, type = assert, getfenv, ipairs, loadstring, pairs, setfenv, tostring, tonumber, type +local io = require"io" +local posix = require "posix" +local lp = require "luadoc.lp" +local luadoc = require"luadoc" +local package = package +local string = require"string" +local table = require"table" + +module "luadoc.doclet.html" + +------------------------------------------------------------------------------- +-- Looks for a file `name' in given path. Removed from compat-5.1 +-- @param path String with the path. +-- @param name String with the name to look for. +-- @return String with the complete path of the file found +-- or nil in case the file is not found. + +local function search (path, name) + for c in string.gfind(path, "[^;]+") do + c = string.gsub(c, "%?", name) + local f = io.open(c) + if f then -- file exist? + f:close() + return c + end + end + return nil -- file not found +end + +------------------------------------------------------------------------------- +-- Include the result of a lp template into the current stream. + +function include (template, env) + -- template_dir is relative to package.path + local templatepath = options.template_dir .. template + + -- search using package.path (modified to search .lp instead of .lua + local search_path = string.gsub(package.path, "%.lua", "") + local templatepath = search(search_path, templatepath) + assert(templatepath, string.format("template `%s' not found", template)) + + env = env or {} + env.table = table + env.io = io + env.lp = lp + env.ipairs = ipairs + env.tonumber = tonumber + env.tostring = tostring + env.type = type + env.luadoc = luadoc + env.options = options + + return lp.include(templatepath, env) +end + +------------------------------------------------------------------------------- +-- Returns a link to a html file, appending "../" to the link to make it right. +-- @param html Name of the html file to link to +-- @return link to the html file + +function link (html, from) + local h = html + from = from or "" + string.gsub(from, "/", function () h = "../" .. h end) + return h +end + +------------------------------------------------------------------------------- +-- Returns the name of the html file to be generated from a module. +-- Files with "lua" or "luadoc" extensions are replaced by "html" extension. +-- @param modulename Name of the module to be processed, may be a .lua file or +-- a .luadoc file. +-- @return name of the generated html file for the module + +function module_link (modulename, doc, from) + -- TODO: replace "." by "/" to create directories? + -- TODO: how to deal with module names with "/"? + assert(modulename) + assert(doc) + from = from or "" + + if doc.modules[modulename] == nil then +-- logger:error(string.format("unresolved reference to module `%s'", modulename)) + return + end + + local href = "modules/" .. modulename .. ".html" + string.gsub(from, "/", function () href = "../" .. href end) + return href +end + +------------------------------------------------------------------------------- +-- Returns the name of the html file to be generated from a lua(doc) file. +-- Files with "lua" or "luadoc" extensions are replaced by "html" extension. +-- @param to Name of the file to be processed, may be a .lua file or +-- a .luadoc file. +-- @param from path of where am I, based on this we append ..'s to the +-- beginning of path +-- @return name of the generated html file + +function file_link (to, from) + assert(to) + from = from or "" + + local href = to + href = string.gsub(href, "lua$", "html") + href = string.gsub(href, "luadoc$", "html") + href = "files/" .. href + string.gsub(from, "/", function () href = "../" .. href end) + return href +end + +------------------------------------------------------------------------------- +-- Returns a link to a function or to a table +-- @param fname name of the function or table to link to. +-- @param doc documentation table +-- @param kind String specying the kinf of element to link ("functions" or "tables"). + +function link_to (fname, doc, module_doc, file_doc, from, kind) + assert(fname) + assert(doc) + from = from or "" + kind = kind or "functions" + + if file_doc then + for _, func_name in pairs(file_doc[kind]) do + if func_name == fname then + return file_link(file_doc.name, from) .. "#" .. fname + end + end + end + + if module_doc and module_doc[kind] then + for func_name, tbl in pairs(module_doc[kind]) do + if func_name == fname then + return "#" .. fname + end + end + end + + local _, _, modulename, fname = string.find(fname, "^(.-)[%.%:]?([^%.%:]*)$") + assert(fname) + + -- if fname does not specify a module, use the module_doc + if string.len(modulename) == 0 and module_doc then + modulename = module_doc.name + end + + local module_doc = doc.modules[modulename] + if not module_doc then +-- logger:error(string.format("unresolved reference to function `%s': module `%s' not found", fname, modulename)) + return + end + + for _, func_name in pairs(module_doc[kind]) do + if func_name == fname then + return module_link(modulename, doc, from) .. "#" .. fname + end + end + +-- logger:error(string.format("unresolved reference to function `%s' of module `%s'", fname, modulename)) +end + +------------------------------------------------------------------------------- +-- Make a link to a file, module or function + +function symbol_link (symbol, doc, module_doc, file_doc, from) + assert(symbol) + assert(doc) + + local href = +-- file_link(symbol, from) or + module_link(symbol, doc, from) or + link_to(symbol, doc, module_doc, file_doc, from, "functions") or + link_to(symbol, doc, module_doc, file_doc, from, "tables") + + if not href then + logger:error(string.format("unresolved reference to symbol `%s'", symbol)) + end + + return href or "" +end + +------------------------------------------------------------------------------- +-- Assembly the output filename for an input file. +-- TODO: change the name of this function +function out_file (filename) + local h = filename + h = string.gsub(h, "lua$", "html") + h = string.gsub(h, "luadoc$", "html") + h = "files/" .. h +-- h = options.output_dir .. string.gsub (h, "^.-([%w_]+%.html)$", "%1") + h = options.output_dir .. h + return h +end + +------------------------------------------------------------------------------- +-- Assembly the output filename for a module. +-- TODO: change the name of this function +function out_module (modulename) + local h = modulename .. ".html" + h = "modules/" .. h + h = options.output_dir .. h + return h +end + +----------------------------------------------------------------- +-- Generate the output. +-- @param doc Table with the structured documentation. + +function start (doc) + -- Generate index file + if (#doc.files > 0 or #doc.modules > 0) and (not options.noindexpage) then + local filename = options.output_dir.."index.html" + logger:info(string.format("generating file `%s'", filename)) + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + io.output(f) + include("index.lp", { doc = doc }) + f:close() + end + + -- Process modules + if not options.nomodules then + for _, modulename in ipairs(doc.modules) do + local module_doc = doc.modules[modulename] + -- assembly the filename + local filename = out_module(modulename) + logger:info(string.format("generating file `%s'", filename)) + + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + io.output(f) + include("module.lp", { doc = doc, module_doc = module_doc }) + f:close() + end + end + + -- Process files + if not options.nofiles then + for _, filepath in ipairs(doc.files) do + local file_doc = doc.files[filepath] + -- assembly the filename + local filename = out_file(file_doc.name) + logger:info(string.format("generating file `%s'", filename)) + + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + io.output(f) + include("file.lp", { doc = doc, file_doc = file_doc} ) + f:close() + end + end + + -- copy extra files + local f = posix.open(options.output_dir.."luadoc.css", "w") + io.output(f) + include("luadoc.css") + f:close() +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/constant.lp b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/constant.lp new file mode 100644 index 0000000..2e35392 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/constant.lp @@ -0,0 +1,28 @@ +<% +if module_doc then + from = "modules/"..module_doc.name +elseif file_doc then + from = "files/.."..file_doc.name +else + from = "" +end +%> + +
<%=const.private and "local " or ""%><%=const.name:gsub(".+%.","")%>
+
+<%=const.description or ""%> + +<%if type(const.see) == "string" then %> +

See also:

+ <%=const.see%> +<%elseif type(const.see) == "table" and #const.see > 0 then %> +

See also:

+ +
diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/file.lp b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/file.lp new file mode 100644 index 0000000..67926b4 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/file.lp @@ -0,0 +1,112 @@ + + + + Reference + + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ +

File <%=file_doc.name%>

+ +<%if file_doc.description then%> +

<%=file_doc.description%>

+<%end%> +<%if file_doc.author then%> +

<%= #file_doc.author>1 and "Authors" or "Author" %>: + +<%for _, author in ipairs(file_doc.author) do%> + +<%end%> +
<%= author %>
+

+<%end%> +<%if file_doc.copyright then%> +

Copyright ©<%=file_doc.copyright%>

+<%end%> +<%if file_doc.release then%> +

Release: <%=file_doc.release%>

+<%end%> + +<%if #file_doc.functions > 0 then%> +

Functions

+ +<%for _, func_name in ipairs(file_doc.functions) do + local func_data = file_doc.functions[func_name]%> + + + + +<%end%> +
<%=func_data.private and "local " or ""%><%=func_name%> (<%=table.concat(func_data.param, ", ")%>)<%=func_data.summary%>
+<%end%> + + +<%if #file_doc.tables > 0 then%> +

Tables

+ +<%for _, tab_name in ipairs(file_doc.tables) do%> + + + + +<%end%> +
<%=tab_name%><%=file_doc.tables[tab_name].summary%>
+<%end%> + + +
+
+ + + +<%if #file_doc.functions > 0 then%> +

Functions

+
+<%for _, func_name in ipairs(file_doc.functions) do%> +<%=luadoc.doclet.html.include("function.lp", { doc=doc, file_doc=file_doc, func=file_doc.functions[func_name] })%> +<%end%> +
+<%end%> + + +<%if #file_doc.tables > 0 then%> +

Tables

+
+<%for _, tab_name in ipairs(file_doc.tables) do%> +<%=luadoc.doclet.html.include("table.lp", { doc=doc, file_doc=file_doc, tab=file_doc.tables[tab_name] })%> +<%end%> +
+<%end%> + + + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/function.lp b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/function.lp new file mode 100644 index 0000000..a870ff8 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/function.lp @@ -0,0 +1,64 @@ +<% +if module_doc then + from = "modules/"..module_doc.name +elseif file_doc then + from = "files/.."..file_doc.name +else + from = "" +end +%> + +
<%=func.private and "local " or ""%><%=(oop and func.name:gsub("%.",":") or func.name:gsub(".+%.",""))%> (<%=table.concat(func.param or {}, ", ")%>)
+
+<%=func.description or ""%> + +<%if type(func.param) == "table" and #func.param > 0 then%> +

Parameters

+
    + <%for p = 1, #func.param do%> +
  • + <%=func.param[p]%>: <%=func.param[func.param[p]] or ""%> +
  • + <%end%> +
+<%end%> + + +<%if type(func.usage) == "string" then%> +

Usage:

+<%=func.usage%> +<%elseif type(func.usage) == "table" then%> +

Usage

+
    + <%for _, usage in ipairs(func.usage) do%> +
  • <%= usage %> + <%end%> +
+<%end%> + +<%if type(func.ret) == "string" then%> +

Return value:

+<%=func.ret%> +<%elseif type(func.ret) == "table" then%> +

Return values:

+
    + <%for _, ret in ipairs(func.ret) do%> +
  1. <%= ret %> + <%end%> +
+<%end%> + +<%if type(func.see) == "string" then %> +

See also:

+ <%=func.see%> +<%elseif type(func.see) == "table" and #func.see > 0 then %> +

See also:

+ +
diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/index.lp b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/index.lp new file mode 100644 index 0000000..b4b9f5c --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/index.lp @@ -0,0 +1,67 @@ + + + + Reference + " type="text/css" /> + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ + +<%if not options.nomodules and #doc.modules > 0 then%> +

Modules

+ + +<%for _, modulename in ipairs(doc.modules) do%> + + + + +<%end%> +
<%=modulename%><%=doc.modules[modulename].summary%>
+<%end%> + + + +<%if not options.nofiles and #doc.files > 0 then%> +

Files

+ + +<%for _, filepath in ipairs(doc.files) do%> + + + + +<%end%> +
<%=filepath%>
+<%end%> + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/luadoc.css b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/luadoc.css new file mode 100644 index 0000000..bc0f98a --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/luadoc.css @@ -0,0 +1,286 @@ +body { + margin-left: 1em; + margin-right: 1em; + font-family: arial, helvetica, geneva, sans-serif; + background-color:#ffffff; margin:0px; +} + +code { + font-family: "Andale Mono", monospace; +} + +tt { + font-family: "Andale Mono", monospace; +} + +body, td, th { font-size: 11pt; } + +h1, h2, h3, h4 { margin-left: 0em; } + +textarea, pre, tt { font-size:10pt; } +body, td, th { color:#000000; } +small { font-size:0.85em; } +h1 { font-size:1.5em; } +h2 { font-size:1.25em; } +h3 { font-size:1.15em; } +h4 { font-size:1.06em; } + +a:link { font-weight:bold; color: #004080; text-decoration: none; } +a:visited { font-weight:bold; color: #006699; text-decoration: none; } +a:link:hover { text-decoration:underline; } +hr { color:#cccccc } +img { border-width: 0px; } + + +h3 { padding-top: 1em; } + +p { margin-left: 1em; } + +p.name { + font-family: "Andale Mono", monospace; + padding-top: 1em; + margin-left: 0em; +} + +blockquote { margin-left: 3em; } + +pre.example { + background-color: rgb(245, 245, 245); + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-color: silver; + border-right-color: silver; + border-bottom-color: silver; + border-left-color: silver; + padding: 1em; + margin-left: 1em; + margin-right: 1em; + font-family: "Andale Mono", monospace; + font-size: smaller; +} + + +hr { + margin-left: 0em; + background: #00007f; + border: 0px; + height: 1px; +} + +ul { list-style-type: disc; } + +table.index { border: 1px #00007f; } +table.index td { text-align: left; vertical-align: top; } +table.index ul { padding-top: 0em; margin-top: 0em; } + +table { + border: 1px solid black; + border-collapse: collapse; + margin-left: auto; + margin-right: auto; +} +th { + border: 1px solid black; + padding: 0.5em; +} +td { + border: 1px solid black; + padding: 0.5em; +} +div.header, div.footer { margin-left: 0em; } + +#container +{ + margin-left: 1em; + margin-right: 1em; + background-color: #f0f0f0; +} + +#product +{ + text-align: center; + border-bottom: 1px solid #cccccc; + background-color: #ffffff; +} + +#product big { + font-size: 2em; +} + +#product_logo +{ +} + +#product_name +{ +} + +#product_description +{ +} + +#main +{ + background-color: #f0f0f0; + border-left: 2px solid #cccccc; +} + +#navigation +{ + float: left; + width: 18em; + margin: 0; + vertical-align: top; + background-color: #f0f0f0; + overflow:visible; +} + +#navigation h1 { + background-color:#e7e7e7; + font-size:1.1em; + color:#000000; + text-align:left; + margin:0px; + padding:0.2em; + border-top:1px solid #dddddd; + border-bottom:1px solid #dddddd; +} + +#navigation ul +{ + font-size:1em; + list-style-type: none; + padding: 0; + margin: 1px; +} + +#navigation li +{ + text-indent: -1em; + margin: 0em 0em 0em 0.5em; + display: block; + padding: 3px 0px 0px 12px; +} + +#navigation li li a +{ + padding: 0px 3px 0px -1em; +} + +#content +{ + margin-left: 18em; + padding: 1em; + border-left: 2px solid #cccccc; + border-right: 2px solid #cccccc; + background-color: #ffffff; +} + +#about +{ + clear: both; + margin: 0; + padding: 5px; + border-top: 2px solid #cccccc; + background-color: #ffffff; +} + +@media print { + body { + font: 12pt "Times New Roman", "TimeNR", Times, serif; + } + a { font-weight:bold; color: #004080; text-decoration: underline; } + + #main { background-color: #ffffff; border-left: 0px; } + #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } + + #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } + + #navigation { display: none; + } + pre.example { + font-family: "Andale Mono", monospace; + font-size: 10pt; + page-break-inside: avoid; + } +} + +table.module_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.module_list td.name { background-color: #f0f0f0; } +table.module_list td.summary { width: 100%; } + +table.file_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.file_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.file_list td.name { background-color: #f0f0f0; } +table.file_list td.summary { width: 100%; } + + +table.function_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.function_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.function_list td.name { background-color: #f0f0f0; } +table.function_list td.summary { width: 100%; } + + +table.table_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.table_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.table_list td.name { background-color: #f0f0f0; } +table.table_list td.summary { width: 100%; } + +dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} +dl.function dd {padding-bottom: 1em;} +dl.function h3 {padding: 0; margin: 0; font-size: medium;} + +dl.table dt {border-top: 1px solid #ccc; padding-top: 1em;} +dl.table dd {padding-bottom: 1em;} +dl.table h3 {padding: 0; margin: 0; font-size: medium;} + +#TODO: make module_list, file_list, function_list, table_list inherit from a list + diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/menu.lp b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/menu.lp new file mode 100644 index 0000000..0fe3652 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/menu.lp @@ -0,0 +1,55 @@ +<% +if module_doc then + from = "modules/"..module_doc.name +elseif file_doc then + from = "files/.."..file_doc.name +else + from = "" +end +%> + +

LuaDoc

+
    + <%if not module_doc and not file_doc then%> +
  • Index
  • + <%else%> +
  • ">Index
  • + <%end%> +
+ + + +<%if not options.nomodules and #doc.modules > 0 then%> +

Modules

+
    +<%for _, modulename in ipairs(doc.modules) do + if module_doc and module_doc.name == modulename then%> +
  • <%=modulename%>
  • + <%else%> +
  • + <%=modulename%> +
  • +<% end +end%> +
+<%end%> + + + +<%if not options.nofiles and #doc.files > 0 then%> +

Files

+
    +<%for _, filepath in ipairs(doc.files) do + if file_doc and file_doc.name == filepath then%> +
  • <%=filepath%>
  • + <%else%> +
  • + <%=filepath%> +
  • +<% end +end%> +
+<%end%> + + + diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/module.lp b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/module.lp new file mode 100644 index 0000000..daa7086 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/module.lp @@ -0,0 +1,120 @@ + + + + Reference + + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ +

<%=( oop and "Object Instance" or "Class" )%> <%=module_doc.name%>

+ +

<%=module_doc.description%>

+<%if module_doc.author then%> +

<%= #module_doc.author>1 and "Authors" or "Author" %>: + +<%for _, author in ipairs(module_doc.author) do%> + +<%end%> +
<%= author %>
+

+<%end%> +<%if module_doc.copyright then%> +

Copyright© <%=module_doc.copyright%>

+<%end%> +<%if module_doc.release then%> +

Release: <%=module_doc.release%>

+<%end%> + +<%if #module_doc.constants > 0 then %> +

Constants

+ +<%for _, const_name in ipairs(module_doc.constants) do + local const_data = module_doc.constants[const_name]%> + + + + +<%end%> +
<%=const_data.private and "local " or ""%><%=(const_name:gsub(".+%.",""))%><%=const_data.summary%>
+<%end%> + +<%if #module_doc.functions > 0 then %> +

Functions

+ +<%for _, func_name in ipairs(module_doc.functions) do + local func_data = module_doc.functions[func_name]%> + + + + +<%end%> +
<%=func_data.private and "local " or ""%><%=(oop and func_name:gsub("%.",":") or func_name:gsub(".+%.",""))%> (<%=table.concat(module_doc.functions[func_name].param or {}, ", ")%>)<%=module_doc.functions[func_name].summary%>
+<%end%> + + +<%if #module_doc.tables > 0 then%> +

Tables

+ +<%for _, tab_name in ipairs(module_doc.tables) do%> + + + + +<%end%> +
<%=tab_name%><%=module_doc.tables[tab_name].summary%>
+<%end%> + + +
+
+ +<%if #module_doc.functions > 0 then%> +

Functions

+
+<%for _, func_name in ipairs(module_doc.functions) do%> +<%=luadoc.doclet.html.include("function.lp", { doc=doc, module_doc=module_doc, func=module_doc.functions[func_name], oop=oop })%> +<%end%> +
+<%end%> + +<%if #module_doc.tables > 0 then%> +

Tables

+
+<%for _, tab_name in ipairs(module_doc.tables) do%> +<%=luadoc.doclet.html.include("table.lp", { doc=doc, module_doc=module_doc, tab=module_doc.tables[tab_name] })%> +<%end%> +
+<%end%> + + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/table.lp b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/table.lp new file mode 100644 index 0000000..5cd0239 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/html/table.lp @@ -0,0 +1,15 @@ +
<%=tab.name%>
+
<%=tab.description%> + +<%if type(tab.field) == "table" and #tab.field > 0 then%> +Fields +
    + <%for p = 1, #tab.field do%> +
  • + <%=tab.field[p]%>: <%=tab.field[tab.field[p]] or ""%> +
  • + <%end%> +
+<%end%> + +
diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/raw.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/raw.lua new file mode 100644 index 0000000..6c8ba6f --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/doclet/raw.lua @@ -0,0 +1,12 @@ +----------------------------------------------------------------- +-- @release $Id: raw.lua 3941 2008-12-23 21:39:38Z jow $ +----------------------------------------------------------------- + +module "luadoc.doclet.raw" + +----------------------------------------------------------------- +-- Generate the output. +-- @param doc Table with the structured documentation. + +function start (doc) +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/init.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/init.lua new file mode 100644 index 0000000..dedf379 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/init.lua @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------- +-- LuaDoc main function. +-- @release $Id: init.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local require = require + +local util = require "luadoc.util" + +logger = {} + +module ("luadoc") + +------------------------------------------------------------------------------- +-- LuaDoc version number. + +_COPYRIGHT = "Copyright (c) 2003-2007 The Kepler Project" +_DESCRIPTION = "Documentation Generator Tool for the Lua language" +_VERSION = "LuaDoc 3.0.1" + +------------------------------------------------------------------------------- +-- Main function +-- @see luadoc.doclet.html, luadoc.doclet.formatter, luadoc.doclet.raw +-- @see luadoc.taglet.standard + +function main (files, options) + logger = util.loadlogengine(options) + + -- load config file + if options.config ~= nil then + -- load specified config file + dofile(options.config) + else + -- load default config file + require("luadoc.config") + end + + local taglet = require(options.taglet) + local doclet = require(options.doclet) + + -- analyze input + taglet.options = options + taglet.logger = logger + local doc = taglet.start(files) + + -- generate output + doclet.options = options + doclet.logger = logger + doclet.start(doc) +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/lp.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/lp.lua new file mode 100644 index 0000000..f880ab7 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/lp.lua @@ -0,0 +1,130 @@ +---------------------------------------------------------------------------- +-- Lua Pages Template Preprocessor. +-- +-- @release $Id: lp.lua 3941 2008-12-23 21:39:38Z jow $ +---------------------------------------------------------------------------- + +local assert, error, getfenv, loadstring, setfenv = assert, error, getfenv, loadstring, setfenv +local find, format, gsub, strsub = string.find, string.format, string.gsub, string.sub +local concat, tinsert = table.concat, table.insert +local open = io.open + +module (...) + +---------------------------------------------------------------------------- +-- function to do output +local outfunc = "io.write" +-- accepts the old expression field: `$| |$' +local compatmode = true + +-- +-- Builds a piece of Lua code which outputs the (part of the) given string. +-- @param s String. +-- @param i Number with the initial position in the string. +-- @param f Number with the final position in the string (default == -1). +-- @return String with the correspondent Lua code which outputs the part of the string. +-- +local function out (s, i, f) + s = strsub(s, i, f or -1) + if s == "" then return s end + -- we could use `%q' here, but this way we have better control + s = gsub(s, "([\\\n\'])", "\\%1") + -- substitute '\r' by '\'+'r' and let `loadstring' reconstruct it + s = gsub(s, "\r", "\\r") + return format(" %s('%s'); ", outfunc, s) +end + + +---------------------------------------------------------------------------- +-- Translate the template to Lua code. +-- @param s String to translate. +-- @return String with translated code. +---------------------------------------------------------------------------- +function translate (s) + if compatmode then + s = gsub(s, "$|(.-)|%$", "") + s = gsub(s, "", "") + end + s = gsub(s, "<%%(.-)%%>", "") + local res = {} + local start = 1 -- start of untranslated part in `s' + while true do + local ip, fp, target, exp, code = find(s, "<%?(%w*)[ \t]*(=?)(.-)%?>", start) + if not ip then break end + tinsert(res, out(s, start, ip-1)) + if target ~= "" and target ~= "lua" then + -- not for Lua; pass whole instruction to the output + tinsert(res, out(s, ip, fp)) + else + if exp == "=" then -- expression? + tinsert(res, format(" %s(%s);", outfunc, code)) + else -- command + tinsert(res, format(" %s ", code)) + end + end + start = fp + 1 + end + tinsert(res, out(s, start)) + return concat(res) +end + + +---------------------------------------------------------------------------- +-- Defines the name of the output function. +-- @param f String with the name of the function which produces output. + +function setoutfunc (f) + outfunc = f +end + +---------------------------------------------------------------------------- +-- Turns on or off the compatibility with old CGILua 3.X behavior. +-- @param c Boolean indicating if the compatibility mode should be used. + +function setcompatmode (c) + compatmode = c +end + +---------------------------------------------------------------------------- +-- Internal compilation cache. + +local cache = {} + +---------------------------------------------------------------------------- +-- Translates a template into a Lua function. +-- Does NOT execute the resulting function. +-- Uses a cache of templates. +-- @param string String with the template to be translated. +-- @param chunkname String with the name of the chunk, for debugging purposes. +-- @return Function with the resulting translation. + +function compile (string, chunkname) + local f, err = cache[string] + if f then return f end + f, err = loadstring (translate (string), chunkname) + if not f then error (err, 3) end + cache[string] = f + return f +end + +---------------------------------------------------------------------------- +-- Translates and executes a template in a given file. +-- The translation creates a Lua function which will be executed in an +-- optionally given environment. +-- @param filename String with the name of the file containing the template. +-- @param env Table with the environment to run the resulting function. + +function include (filename, env) + -- read the whole contents of the file + local fh = assert (open (filename)) + local src = fh:read("*a") + fh:close() + -- translates the file into a function + local prog = compile (src, '@'..filename) + local _env + if env then + _env = getfenv (prog) + setfenv (prog, env) + end + prog () +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard.lua new file mode 100644 index 0000000..d4654b7 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard.lua @@ -0,0 +1,565 @@ +------------------------------------------------------------------------------- +-- @release $Id: standard.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local assert, pairs, tostring, type = assert, pairs, tostring, type +local io = require "io" +local posix = require "posix" +local luadoc = require "luadoc" +local util = require "luadoc.util" +local tags = require "luadoc.taglet.standard.tags" +local string = require "string" +local table = require "table" + +module 'luadoc.taglet.standard' + +------------------------------------------------------------------------------- +-- Creates an iterator for an array base on a class type. +-- @param t array to iterate over +-- @param class name of the class to iterate over + +function class_iterator (t, class) + return function () + local i = 1 + return function () + while t[i] and t[i].class ~= class do + i = i + 1 + end + local v = t[i] + i = i + 1 + return v + end + end +end + +-- Patterns for function recognition +local identifiers_list_pattern = "%s*(.-)%s*" +local identifier_pattern = "[^%(%s]+" +local function_patterns = { + "^()%s*function%s*("..identifier_pattern..")%s*%("..identifiers_list_pattern.."%)", + "^%s*(local%s)%s*function%s*("..identifier_pattern..")%s*%("..identifiers_list_pattern.."%)", + "^()%s*("..identifier_pattern..")%s*%=%s*function%s*%("..identifiers_list_pattern.."%)", +} + +------------------------------------------------------------------------------- +-- Checks if the line contains a function definition +-- @param line string with line text +-- @return function information or nil if no function definition found + +local function check_function (line) + line = util.trim(line) + + local info = table.foreachi(function_patterns, function (_, pattern) + local r, _, l, id, param = string.find(line, pattern) + if r ~= nil then + return { + name = id, + private = (l == "local"), + param = { } --util.split("%s*,%s*", param), + } + end + end) + + -- TODO: remove these assert's? + if info ~= nil then + assert(info.name, "function name undefined") + assert(info.param, string.format("undefined parameter list for function `%s'", info.name)) + end + + return info +end + +------------------------------------------------------------------------------- +-- Checks if the line contains a module definition. +-- @param line string with line text +-- @param currentmodule module already found, if any +-- @return the name of the defined module, or nil if there is no module +-- definition + +local function check_module (line, currentmodule) + line = util.trim(line) + + -- module"x.y" + -- module'x.y' + -- module[[x.y]] + -- module("x.y") + -- module('x.y') + -- module([[x.y]]) + -- module(...) + + local r, _, modulename = string.find(line, "^module%s*[%s\"'(%[]+([^,\"')%]]+)") + if r then + -- found module definition + logger:debug(string.format("found module `%s'", modulename)) + return modulename + end + return currentmodule +end + +-- Patterns for constant recognition +local constant_patterns = { + "^()%s*([A-Z][A-Z0-9_]*)%s*=", + "^%s*(local%s)%s*([A-Z][A-Z0-9_]*)%s*=", +} + +------------------------------------------------------------------------------- +-- Checks if the line contains a constant definition +-- @param line string with line text +-- @return constant information or nil if no constant definition found + +local function check_constant (line) + line = util.trim(line) + + local info = table.foreachi(constant_patterns, function (_, pattern) + local r, _, l, id = string.find(line, pattern) + if r ~= nil then + return { + name = id, + private = (l == "local"), + } + end + end) + + -- TODO: remove these assert's? + if info ~= nil then + assert(info.name, "constant name undefined") + end + + return info +end + +------------------------------------------------------------------------------- +-- Extracts summary information from a description. The first sentence of each +-- doc comment should be a summary sentence, containing a concise but complete +-- description of the item. It is important to write crisp and informative +-- initial sentences that can stand on their own +-- @param description text with item description +-- @return summary string or nil if description is nil + +local function parse_summary (description) + -- summary is never nil... + description = description or "" + + -- append an " " at the end to make the pattern work in all cases + description = description.." " + + -- read until the first period followed by a space or tab + local summary = string.match(description, "(.-%.)[%s\t]") + + -- if pattern did not find the first sentence, summary is the whole description + summary = summary or description + + return summary +end + +------------------------------------------------------------------------------- +-- @param f file handle +-- @param line current line being parsed +-- @param modulename module already found, if any +-- @return current line +-- @return code block +-- @return modulename if found + +local function parse_code (f, line, modulename) + local code = {} + while line ~= nil do + if string.find(line, "^[\t ]*%-%-%-") then + -- reached another luadoc block, end this parsing + return line, code, modulename + else + -- look for a module definition + modulename = check_module(line, modulename) + + table.insert(code, line) + line = f:read() + end + end + -- reached end of file + return line, code, modulename +end + +------------------------------------------------------------------------------- +-- Parses the information inside a block comment +-- @param block block with comment field +-- @return block parameter + +local function parse_comment (block, first_line, modulename) + + -- get the first non-empty line of code + local code = table.foreachi(block.code, function(_, line) + if not util.line_empty(line) then + -- `local' declarations are ignored in two cases: + -- when the `nolocals' option is turned on; and + -- when the first block of a file is parsed (this is + -- necessary to avoid confusion between the top + -- local declarations and the `module' definition. + if (options.nolocals or first_line) and line:find"^%s*local" then + return + end + return line + end + end) + + -- parse first line of code + if code ~= nil then + local func_info = check_function(code) + local module_name = check_module(code) + local const_info = check_constant(code) + if func_info then + block.class = "function" + block.name = func_info.name + block.param = func_info.param + block.private = func_info.private + elseif const_info then + block.class = "constant" + block.name = const_info.name + block.private = const_info.private + elseif module_name then + block.class = "module" + block.name = module_name + block.param = {} + else + block.param = {} + end + else + -- TODO: comment without any code. Does this means we are dealing + -- with a file comment? + end + + -- parse @ tags + local currenttag = "description" + local currenttext + + table.foreachi(block.comment, function (_, line) + line = util.trim_comment(line) + + local r, _, tag, text = string.find(line, "@([_%w%.]+)%s+(.*)") + if r ~= nil then + -- found new tag, add previous one, and start a new one + -- TODO: what to do with invalid tags? issue an error? or log a warning? + tags.handle(currenttag, block, currenttext) + + currenttag = tag + currenttext = text + else + currenttext = util.concat(currenttext, line) + assert(string.sub(currenttext, 1, 1) ~= " ", string.format("`%s', `%s'", currenttext, line)) + end + end) + tags.handle(currenttag, block, currenttext) + + -- extracts summary information from the description + block.summary = parse_summary(block.description) + assert(string.sub(block.description, 1, 1) ~= " ", string.format("`%s'", block.description)) + + if block.name and block.class == "module" then + modulename = block.name + end + + return block, modulename +end + +------------------------------------------------------------------------------- +-- Parses a block of comment, started with ---. Read until the next block of +-- comment. +-- @param f file handle +-- @param line being parsed +-- @param modulename module already found, if any +-- @return line +-- @return block parsed +-- @return modulename if found + +local function parse_block (f, line, modulename, first) + local block = { + comment = {}, + code = {}, + } + + while line ~= nil do + if string.find(line, "^[\t ]*%-%-") == nil then + -- reached end of comment, read the code below it + -- TODO: allow empty lines + line, block.code, modulename = parse_code(f, line, modulename) + + -- parse information in block comment + block, modulename = parse_comment(block, first, modulename) + + return line, block, modulename + else + table.insert(block.comment, line) + line = f:read() + end + end + -- reached end of file + + -- parse information in block comment + block, modulename = parse_comment(block, first, modulename) + + return line, block, modulename +end + +------------------------------------------------------------------------------- +-- Parses a file documented following luadoc format. +-- @param filepath full path of file to parse +-- @param doc table with documentation +-- @return table with documentation + +function parse_file (filepath, doc, handle, prev_line, prev_block, prev_modname) + local blocks = { prev_block } + local modulename = prev_modname + + -- read each line + local f = handle or io.open(filepath, "r") + local i = 1 + local line = prev_line or f:read() + local first = true + while line ~= nil do + + if string.find(line, "^[\t ]*%-%-%-") then + -- reached a luadoc block + local block, newmodname + line, block, newmodname = parse_block(f, line, modulename, first) + + if modulename and newmodname and newmodname ~= modulename then + doc = parse_file( nil, doc, f, line, block, newmodname ) + else + table.insert(blocks, block) + modulename = newmodname + end + else + -- look for a module definition + local newmodname = check_module(line, modulename) + + if modulename and newmodname and newmodname ~= modulename then + parse_file( nil, doc, f ) + else + modulename = newmodname + end + + -- TODO: keep beginning of file somewhere + + line = f:read() + end + first = false + i = i + 1 + end + + if not handle then + f:close() + end + + if filepath then + -- store blocks in file hierarchy + assert(doc.files[filepath] == nil, string.format("doc for file `%s' already defined", filepath)) + table.insert(doc.files, filepath) + doc.files[filepath] = { + type = "file", + name = filepath, + doc = blocks, + -- functions = class_iterator(blocks, "function"), + -- tables = class_iterator(blocks, "table"), + } + -- + local first = doc.files[filepath].doc[1] + if first and modulename then + doc.files[filepath].author = first.author + doc.files[filepath].copyright = first.copyright + doc.files[filepath].description = first.description + doc.files[filepath].release = first.release + doc.files[filepath].summary = first.summary + end + end + + -- if module definition is found, store in module hierarchy + if modulename ~= nil then + if modulename == "..." then + assert( filepath, "Can't determine name for virtual module from filepatch" ) + modulename = string.gsub (filepath, "%.lua$", "") + modulename = string.gsub (modulename, "/", ".") + end + if doc.modules[modulename] ~= nil then + -- module is already defined, just add the blocks + table.foreachi(blocks, function (_, v) + table.insert(doc.modules[modulename].doc, v) + end) + else + -- TODO: put this in a different module + table.insert(doc.modules, modulename) + doc.modules[modulename] = { + type = "module", + name = modulename, + doc = blocks, +-- functions = class_iterator(blocks, "function"), +-- tables = class_iterator(blocks, "table"), + author = first and first.author, + copyright = first and first.copyright, + description = "", + release = first and first.release, + summary = "", + } + + -- find module description + for m in class_iterator(blocks, "module")() do + doc.modules[modulename].description = util.concat( + doc.modules[modulename].description, + m.description) + doc.modules[modulename].summary = util.concat( + doc.modules[modulename].summary, + m.summary) + if m.author then + doc.modules[modulename].author = m.author + end + if m.copyright then + doc.modules[modulename].copyright = m.copyright + end + if m.release then + doc.modules[modulename].release = m.release + end + if m.name then + doc.modules[modulename].name = m.name + end + end + doc.modules[modulename].description = doc.modules[modulename].description or (first and first.description) or "" + doc.modules[modulename].summary = doc.modules[modulename].summary or (first and first.summary) or "" + end + + -- make functions table + doc.modules[modulename].functions = {} + for f in class_iterator(blocks, "function")() do + if f and f.name then + table.insert(doc.modules[modulename].functions, f.name) + doc.modules[modulename].functions[f.name] = f + end + end + + -- make tables table + doc.modules[modulename].tables = {} + for t in class_iterator(blocks, "table")() do + if t and t.name then + table.insert(doc.modules[modulename].tables, t.name) + doc.modules[modulename].tables[t.name] = t + end + end + + -- make constants table + doc.modules[modulename].constants = {} + for c in class_iterator(blocks, "constant")() do + if c and c.name then + table.insert(doc.modules[modulename].constants, c.name) + doc.modules[modulename].constants[c.name] = c + end + end + end + + if filepath then + -- make functions table + doc.files[filepath].functions = {} + for f in class_iterator(blocks, "function")() do + if f and f.name then + table.insert(doc.files[filepath].functions, f.name) + doc.files[filepath].functions[f.name] = f + end + end + + -- make tables table + doc.files[filepath].tables = {} + for t in class_iterator(blocks, "table")() do + if t and t.name then + table.insert(doc.files[filepath].tables, t.name) + doc.files[filepath].tables[t.name] = t + end + end + end + + return doc +end + +------------------------------------------------------------------------------- +-- Checks if the file is terminated by ".lua" or ".luadoc" and calls the +-- function that does the actual parsing +-- @param filepath full path of the file to parse +-- @param doc table with documentation +-- @return table with documentation +-- @see parse_file + +function file (filepath, doc) + local patterns = { "%.lua$", "%.luadoc$" } + local valid = table.foreachi(patterns, function (_, pattern) + if string.find(filepath, pattern) ~= nil then + return true + end + end) + + if valid then + logger:info(string.format("processing file `%s'", filepath)) + doc = parse_file(filepath, doc) + end + + return doc +end + +------------------------------------------------------------------------------- +-- Recursively iterates through a directory, parsing each file +-- @param path directory to search +-- @param doc table with documentation +-- @return table with documentation + +function directory (path, doc) + for f in posix.files(path) do + local fullpath = path .. "/" .. f + local attr = posix.stat(fullpath) + assert(attr, string.format("error stating file `%s'", fullpath)) + + if attr.type == "regular" then + doc = file(fullpath, doc) + elseif attr.type == "directory" and f ~= "." and f ~= ".." then + doc = directory(fullpath, doc) + end + end + return doc +end + +-- Recursively sorts the documentation table +local function recsort (tab) + table.sort (tab) + -- sort list of functions by name alphabetically + for f, doc in pairs(tab) do + if doc.functions then + table.sort(doc.functions) + end + if doc.tables then + table.sort(doc.tables) + end + end +end + +------------------------------------------------------------------------------- + +function start (files, doc) + assert(files, "file list not specified") + + -- Create an empty document, or use the given one + doc = doc or { + files = {}, + modules = {}, + } + assert(doc.files, "undefined `files' field") + assert(doc.modules, "undefined `modules' field") + + table.foreachi(files, function (_, path) + local attr = posix.stat(path) + assert(attr, string.format("error stating path `%s'", path)) + + if attr.type == "regular" then + doc = file(path, doc) + elseif attr.type == "directory" then + doc = directory(path, doc) + end + end) + + -- order arrays alphabetically + recsort(doc.files) + recsort(doc.modules) + + return doc +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard/tags.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard/tags.lua new file mode 100644 index 0000000..293e186 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/taglet/standard/tags.lua @@ -0,0 +1,178 @@ +------------------------------------------------------------------------------- +-- Handlers for several tags +-- @release $Id: tags.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local luadoc = require "luadoc" +local util = require "luadoc.util" +local string = require "string" +local table = require "table" +local assert, type, tostring = assert, type, tostring + +module "luadoc.taglet.standard.tags" + +------------------------------------------------------------------------------- + +local function author (tag, block, text) + block[tag] = block[tag] or {} + if not text then + luadoc.logger:warn("author `name' not defined [["..text.."]]: skipping") + return + end + table.insert (block[tag], text) +end + +------------------------------------------------------------------------------- +-- Set the class of a comment block. Classes can be "module", "function", +-- "table". The first two classes are automatic, extracted from the source code + +local function class (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function cstyle (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function copyright (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function description (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function field (tag, block, text) + if block["class"] ~= "table" then + luadoc.logger:warn("documenting `field' for block that is not a `table'") + end + block[tag] = block[tag] or {} + + local _, _, name, desc = string.find(text, "^([_%w%.]+)%s+(.*)") + assert(name, "field name not defined") + + table.insert(block[tag], name) + block[tag][name] = desc +end + +------------------------------------------------------------------------------- +-- Set the name of the comment block. If the block already has a name, issue +-- an error and do not change the previous value + +local function name (tag, block, text) + if block[tag] and block[tag] ~= text then + luadoc.logger:error(string.format("block name conflict: `%s' -> `%s'", block[tag], text)) + end + + block[tag] = text +end + +------------------------------------------------------------------------------- +-- Processes a parameter documentation. +-- @param tag String with the name of the tag (it must be "param" always). +-- @param block Table with previous information about the block. +-- @param text String with the current line beeing processed. + +local function param (tag, block, text) + block[tag] = block[tag] or {} + -- TODO: make this pattern more flexible, accepting empty descriptions + local _, _, name, desc = string.find(text, "^([_%w%.]+)%s+(.*)") + if not name then + luadoc.logger:warn("parameter `name' not defined [["..text.."]]: skipping") + return + end + local i = table.foreachi(block[tag], function (i, v) + if v == name then + return i + end + end) + if i == nil then + luadoc.logger:warn(string.format("documenting undefined parameter `%s'", name)) + table.insert(block[tag], name) + end + block[tag][name] = desc +end + +------------------------------------------------------------------------------- + +local function release (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function ret (tag, block, text) + tag = "ret" + if type(block[tag]) == "string" then + block[tag] = { block[tag], text } + elseif type(block[tag]) == "table" then + table.insert(block[tag], text) + else + block[tag] = text + end +end + +------------------------------------------------------------------------------- +-- @see ret + +local function see (tag, block, text) + -- see is always an array + block[tag] = block[tag] or {} + + -- remove trailing "." + text = string.gsub(text, "(.*)%.$", "%1") + + local s = util.split("%s*,%s*", text) + + table.foreachi(s, function (_, v) + table.insert(block[tag], v) + end) +end + +------------------------------------------------------------------------------- +-- @see ret + +local function usage (tag, block, text) + if type(block[tag]) == "string" then + block[tag] = { block[tag], text } + elseif type(block[tag]) == "table" then + table.insert(block[tag], text) + else + block[tag] = text + end +end + +------------------------------------------------------------------------------- + +local handlers = {} +handlers["author"] = author +handlers["class"] = class +handlers["cstyle"] = cstyle +handlers["copyright"] = copyright +handlers["description"] = description +handlers["field"] = field +handlers["name"] = name +handlers["param"] = param +handlers["release"] = release +handlers["return"] = ret +handlers["see"] = see +handlers["usage"] = usage + +------------------------------------------------------------------------------- + +function handle (tag, block, text) + if not handlers[tag] then + luadoc.logger:error(string.format("undefined handler for tag `%s'", tag)) + return + end +-- assert(handlers[tag], string.format("undefined handler for tag `%s'", tag)) + return handlers[tag](tag, block, text) +end diff --git a/openwrt/packages/luci/contrib/luadoc/lua/luadoc/util.lua b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/util.lua new file mode 100644 index 0000000..21470f5 --- /dev/null +++ b/openwrt/packages/luci/contrib/luadoc/lua/luadoc/util.lua @@ -0,0 +1,201 @@ +------------------------------------------------------------------------------- +-- General utilities. +-- @release $Id: util.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local posix = require "posix" +local type, table, string, io, assert, tostring, setmetatable, pcall = type, table, string, io, assert, tostring, setmetatable, pcall + +------------------------------------------------------------------------------- +-- Module with several utilities that could not fit in a specific module + +module "luadoc.util" + +------------------------------------------------------------------------------- +-- Removes spaces from the begining and end of a given string +-- @param s string to be trimmed +-- @return trimmed string + +function trim (s) + return (string.gsub(s, "^%s*(.-)%s*$", "%1")) +end + +------------------------------------------------------------------------------- +-- Removes spaces from the begining and end of a given string, considering the +-- string is inside a lua comment. +-- @param s string to be trimmed +-- @return trimmed string +-- @see trim +-- @see string.gsub + +function trim_comment (s) + s = string.gsub(s, "%-%-+(.*)$", "%1") + return trim(s) +end + +------------------------------------------------------------------------------- +-- Checks if a given line is empty +-- @param line string with a line +-- @return true if line is empty, false otherwise + +function line_empty (line) + return (string.len(trim(line)) == 0) +end + +------------------------------------------------------------------------------- +-- Appends two string, but if the first one is nil, use to second one +-- @param str1 first string, can be nil +-- @param str2 second string +-- @return str1 .. " " .. str2, or str2 if str1 is nil + +function concat (str1, str2) + if str1 == nil or string.len(str1) == 0 then + return str2 + else + return str1 .. " " .. str2 + end +end + +------------------------------------------------------------------------------- +-- Split text into a list consisting of the strings in text, +-- separated by strings matching delim (which may be a pattern). +-- @param delim if delim is "" then action is the same as %s+ except that +-- field 1 may be preceeded by leading whitespace +-- @usage split(",%s*", "Anna, Bob, Charlie,Dolores") +-- @usage split(""," x y") gives {"x","y"} +-- @usage split("%s+"," x y") gives {"", "x","y"} +-- @return array with strings +-- @see table.concat + +function split(delim, text) + local list = {} + if string.len(text) > 0 then + delim = delim or "" + local pos = 1 + -- if delim matches empty string then it would give an endless loop + if string.find("", delim, 1) and delim ~= "" then + error("delim matches empty string!") + end + local first, last + while 1 do + if delim ~= "" then + first, last = string.find(text, delim, pos) + else + first, last = string.find(text, "%s+", pos) + if first == 1 then + pos = last+1 + first, last = string.find(text, "%s+", pos) + end + end + if first then -- found? + table.insert(list, string.sub(text, pos, first-1)) + pos = last+1 + else + table.insert(list, string.sub(text, pos)) + break + end + end + end + return list +end + +------------------------------------------------------------------------------- +-- Comments a paragraph. +-- @param text text to comment with "--", may contain several lines +-- @return commented text + +function comment (text) + text = string.gsub(text, "\n", "\n-- ") + return "-- " .. text +end + +------------------------------------------------------------------------------- +-- Wrap a string into a paragraph. +-- @param s string to wrap +-- @param w width to wrap to [80] +-- @param i1 indent of first line [0] +-- @param i2 indent of subsequent lines [0] +-- @return wrapped paragraph + +function wrap(s, w, i1, i2) + w = w or 80 + i1 = i1 or 0 + i2 = i2 or 0 + assert(i1 < w and i2 < w, "the indents must be less than the line width") + s = string.rep(" ", i1) .. s + local lstart, len = 1, string.len(s) + while len - lstart > w do + local i = lstart + w + while i > lstart and string.sub(s, i, i) ~= " " do i = i - 1 end + local j = i + while j > lstart and string.sub(s, j, j) == " " do j = j - 1 end + s = string.sub(s, 1, j) .. "\n" .. string.rep(" ", i2) .. + string.sub(s, i + 1, -1) + local change = i2 + 1 - (i - j) + lstart = j + change + len = len + change + end + return s +end + +------------------------------------------------------------------------------- +-- Opens a file, creating the directories if necessary +-- @param filename full path of the file to open (or create) +-- @param mode mode of opening +-- @return file handle + +function posix.open (filename, mode) + local f = io.open(filename, mode) + if f == nil then + filename = string.gsub(filename, "\\", "/") + local dir = "" + for d in string.gfind(filename, ".-/") do + dir = dir .. d + posix.mkdir(dir) + end + f = io.open(filename, mode) + end + return f +end + + +---------------------------------------------------------------------------------- +-- Creates a Logger with LuaLogging, if present. Otherwise, creates a mock logger. +-- @param options a table with options for the logging mechanism +-- @return logger object that will implement log methods + +function loadlogengine(options) + local logenabled = pcall(function() + require "logging" + require "logging.console" + end) + + local logging = logenabled and logging + + if logenabled then + if options.filelog then + logger = logging.file("luadoc.log") -- use this to get a file log + else + logger = logging.console("[%level] %message\n") + end + + if options.verbose then + logger:setLevel(logging.INFO) + else + logger:setLevel(logging.WARN) + end + + else + noop = {__index=function(...) + return function(...) + -- noop + end + end} + + logger = {} + setmetatable(logger, noop) + end + + return logger +end + diff --git a/openwrt/packages/luci/contrib/luaposix/.gitignore b/openwrt/packages/luci/contrib/luaposix/.gitignore new file mode 100644 index 0000000..1407d23 --- /dev/null +++ b/openwrt/packages/luci/contrib/luaposix/.gitignore @@ -0,0 +1,3 @@ +luaposix-* +lua-posix_* +patches/series diff --git a/openwrt/packages/luci/contrib/luaposix/Makefile b/openwrt/packages/luci/contrib/luaposix/Makefile new file mode 100644 index 0000000..70d3c9c --- /dev/null +++ b/openwrt/packages/luci/contrib/luaposix/Makefile @@ -0,0 +1,35 @@ +include ../../build/config.mk +include ../../build/gccconfig.mk + +LUAPOSIX_VERSION = 5.1.4 +LUAPOSIX_SITE = http://dev.luci.freifunk-halle.net/sources/ +LUAPOSIX_DIR = luaposix-$(LUAPOSIX_VERSION) +LUAPOSIX_FILE = lua-posix_5.1.4.orig.tar.gz +LUAPOSIX_URL = $(LUAPOSIX_SITE)/$(LUAPOSIX_FILE) +LUAPOSIX_PATCHDIR = patches + +all: compile + +include ../../build/module.mk + +$(LUAPOSIX_FILE): + wget -O $@ $(LUAPOSIX_URL) || rm -f $@ + +$(LUAPOSIX_DIR)/.prepared: $(LUAPOSIX_FILE) + rm -rf $(LUAPOSIX_DIR) + tar xvfz $(LUAPOSIX_FILE) + touch $@ + +compile: $(LUAPOSIX_DIR)/.prepared + $(MAKE) -C $(LUAPOSIX_DIR) CC=$(CC) CFLAGS="$(CFLAGS) $(LUA_CFLAGS)" LDFLAGS="$(LDFLAGS) $(LUA_SHLIBS)" OS="$(OS)" + mkdir -p dist$(LUA_LIBRARYDIR) + cp $(LUAPOSIX_DIR)/posix.so dist$(LUA_LIBRARYDIR) + +luasource: +luastrip: +luacompile: +compile-all: compile + +clean: + rm -rf $(LUAPOSIX_DIR) $(LUAPOSIX_FILE) + rm -f $(LUAPOSIX_PATCHDIR)/series diff --git a/openwrt/packages/luci/contrib/luasocket/.gitignore b/openwrt/packages/luci/contrib/luasocket/.gitignore new file mode 100644 index 0000000..1a4bd6d --- /dev/null +++ b/openwrt/packages/luci/contrib/luasocket/.gitignore @@ -0,0 +1 @@ +luasocket-* diff --git a/openwrt/packages/luci/contrib/luasocket/Makefile b/openwrt/packages/luci/contrib/luasocket/Makefile new file mode 100644 index 0000000..b389484 --- /dev/null +++ b/openwrt/packages/luci/contrib/luasocket/Makefile @@ -0,0 +1,32 @@ +include ../../build/config.mk +include ../../build/gccconfig.mk + +LUASOCKET_VERSION = 2.0.2 +LUASOCKET_SITE = http://dev.luci.freifunk-halle.net/sources/ +LUASOCKET_DIR = luasocket-$(LUASOCKET_VERSION) +LUASOCKET_FILE = $(LUASOCKET_DIR).tar.gz +LUASOCKET_URL = $(LUASOCKET_SITE)/$(LUASOCKET_FILE) +INSTALL_MODULEDIR = dist$(LUA_MODULEDIR) +INSTALL_LIBRARYDIR = dist$(LUA_LIBRARYDIR) + +all: compile + +include ../../build/module.mk + +$(LUASOCKET_FILE): + wget -O $@ $(LUASOCKET_URL) || rm -f $@ + +$(LUASOCKET_DIR)/.prepared: $(LUASOCKET_FILE) + rm -rf $(LUASOCKET_DIR) + tar xvfz $(LUASOCKET_FILE) + touch $@ + +compile: $(LUASOCKET_DIR)/.prepared + $(MAKE) -C $(LUASOCKET_DIR) CC=$(CC) CFLAGS="$(CFLAGS) $(LUA_CFLAGS) $(FPIC)" LDFLAGS="$(LDFLAGS) $(LUA_SHLIBS) $(SHLIB_FLAGS)" OS="$(OS)" + mkdir -p $(INSTALL_LIBRARYDIR) $(INSTALL_MODULEDIR) + $(MAKE) -C $(LUASOCKET_DIR) install INSTALL_TOP_SHARE=../../$(INSTALL_MODULEDIR) INSTALL_TOP_LIB=../../$(INSTALL_LIBRARYDIR) + +compile-all: compile + +clean: + rm -rf $(LUASOCKET_DIR) $(LUASOCKET_FILE) diff --git a/openwrt/packages/luci/contrib/package/Makefile b/openwrt/packages/luci/contrib/package/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/contrib/package/lpeg/Makefile b/openwrt/packages/luci/contrib/package/lpeg/Makefile new file mode 100644 index 0000000..3764c21 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/lpeg/Makefile @@ -0,0 +1,42 @@ +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id$ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=lpeg +PKG_VERSION:=0.8.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.inf.puc-rio.br/~roberto/lpeg +PKG_MD5SUM:=b6b172bbcdcba5c87b37eef9bb5ae199 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +include $(INCLUDE_DIR)/package.mk + +define Package/lpeg + SECTION:=lang + CATEGORY:=Languages + SUBMENU:=LUA + TITLE:=LPEG - Parsing Expression Grammars + URL:=http://www.inf.puc-rio.br/~roberto/lpeg.html + DEPENDS:=+liblua +endef + +MAKE_FLAGS += COPT="$(TARGET_CFLAGS) $(FPIC) -I$(STAGING_DIR)/usr/include" + +define Build/Configure +endef + +define Package/lpeg/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(CP) $(PKG_BUILD_DIR)/{lpeg.so,re.lua} $(1)/usr/lib/lua +endef + +$(eval $(call BuildPackage,lpeg)) diff --git a/openwrt/packages/luci/contrib/package/luasocket/Makefile b/openwrt/packages/luci/contrib/package/luasocket/Makefile new file mode 100644 index 0000000..254385a --- /dev/null +++ b/openwrt/packages/luci/contrib/package/luasocket/Makefile @@ -0,0 +1,40 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=luasocket +PKG_VERSION:=2.0.2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://dev.luci.freifunk-halle.net/sources/\ + http://luaforge.net/frs/download.php/2664/ +PKG_MD5SUM:=41445b138deb7bcfe97bff957503da8e + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +include $(INCLUDE_DIR)/package.mk + +define Package/luasocket + SECTION:=lang + CATEGORY:=Languages + SUBMENU:=LUA + TITLE:=Socket support for Lua + URL:=http://luaforge.net/projects/luasockets/ + DEPENDS:=+liblua +endef + +define Build/Configure +endef + +define Build/Compile + for i in $(PKG_BUILD_DIR)/src/*.lua; do luac -s -o $$$$i $$$$i; done + $(call Build/Compile/Default) +endef + +MAKE_FLAGS += LD="$(TARGET_CC)" CFLAGS="$(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include -pedantic -Wall -fpic" LDFLAGS="$(TARGET_LDFLAGS) -shared -fpic" + +define Package/luasocket/install + $(MAKE) -C$(PKG_BUILD_DIR) install INSTALL_TOP_SHARE=$(1)/usr/lib/lua INSTALL_TOP_LIB=$(1)/usr/lib/lua +endef + +$(eval $(call BuildPackage,luasocket)) diff --git a/openwrt/packages/luci/contrib/package/luaxyssl/Makefile b/openwrt/packages/luci/contrib/package/luaxyssl/Makefile new file mode 100644 index 0000000..bd74926 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/luaxyssl/Makefile @@ -0,0 +1,43 @@ +include $(TOPDIR)/rules.mk + +PKG_BRANCH:=trunk +PKG_NAME:=luaxyssl +PKG_RELEASE:=1 +PKG_SOURCE_URL:=http://luaxyssl.googlecode.com/svn/$(PKG_BRANCH) +PKG_REV:=65 +PKG_VERSION:=0.2+svn$(PKG_REV) +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz +PKG_SOURCE_PROTO:=svn +PKG_SOURCE_VERSION:=$(PKG_REV) + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +include $(INCLUDE_DIR)/package.mk + +define Package/luaxyssl + SECTION:=lang + CATEGORY:=Languages + SUBMENU:=LUA + TITLE:=xyssl-Bindings for Lua + URL:=http://code.google.com/p/luaxyssl + DEPENDS:=+liblua +libxyssl +endef + +define Build/Configure +endef + +define Build/Compile + $(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) -shared -fpic -pedantic -Wall \ + -I$(STAGING_DIR)/usr/include \ + -DXYSSL=9 \ + -o $(PKG_BUILD_DIR)/lxyssl.so -lxyssl $(PKG_BUILD_DIR)/lxyssl.c +endef + +define Package/luaxyssl/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(INSTALL_DATA) $(PKG_BUILD_DIR)/lxyssl.so $(1)/usr/lib/lua +endef + +$(eval $(call BuildPackage,luaxyssl)) diff --git a/openwrt/packages/luci/contrib/package/luaxyssl/patches/100-compile-fixes.patch b/openwrt/packages/luci/contrib/package/luaxyssl/patches/100-compile-fixes.patch new file mode 100644 index 0000000..94091f5 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/luaxyssl/patches/100-compile-fixes.patch @@ -0,0 +1,273 @@ +Index: luaxyssl-0.2+svn65/lxyssl.c +=================================================================== +--- luaxyssl-0.2+svn65.orig/lxyssl.c 2008-07-01 17:28:52.000000000 +0200 ++++ luaxyssl-0.2+svn65/lxyssl.c 2008-07-01 17:32:00.000000000 +0200 +@@ -5,6 +5,7 @@ + * This code can be distributed under the LGPL license + */ + ++#include + #include + #include + #include +@@ -12,6 +13,7 @@ + #include + #include + #include ++#include + #else + #include + #include +@@ -326,7 +328,7 @@ + return 1; + } + if (lua_isstring(L, -1)) { +- int len; ++ size_t len; + const char *master = luaL_checklstring(L, -1, &len); + memcpy(ssl->session->master, master, len < sizeof(ssl->session->master) ? len : sizeof(ssl->session->master)); + lua_pop(L, 1); +@@ -479,7 +481,7 @@ + + static int Laes(lua_State *L) + { +- int klen; ++ size_t klen; + const unsigned char *key = luaL_checklstring(L, 1, &klen); + int bits = luaL_optinteger(L, 2, 128); + dual_aes_context *aes = lua_newuserdata(L,sizeof(dual_aes_context)); +@@ -503,7 +505,7 @@ + + static int Lrc4(lua_State *L) + { +- int klen; ++ size_t klen; + const unsigned char *key = luaL_checklstring(L, 1, &klen); + arc4_context *rc4 = lua_newuserdata(L,sizeof(arc4_context)); + arc4_setup(rc4, (unsigned char *)key, klen); +@@ -750,7 +752,7 @@ + static int Lhash(lua_State *L) + { + const char *type = luaL_checkstring(L,1); +- int klen=0; ++ size_t klen=0; + const unsigned char *key = luaL_optlstring(L, 2, NULL, &klen); + hash_context *obj = lua_newuserdata(L,sizeof(hash_context)); + +@@ -869,7 +871,7 @@ + static int Laes_encrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + int i; + luaL_Buffer B; +@@ -890,7 +892,7 @@ + static int Laes_decrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + int i; + luaL_Buffer B; +@@ -911,7 +913,7 @@ + static int Lrc4_crypt(lua_State *L) + { + arc4_context *obj=Pget_rc4(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + luaL_Buffer B; + unsigned char temp[256]; +@@ -938,9 +940,9 @@ + static int Laes_cbc_encrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int i=0; + luaL_Buffer B; +@@ -970,9 +972,9 @@ + static int Laes_cbc_decrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int i; + luaL_Buffer B; +@@ -1002,9 +1004,9 @@ + static int Laes_cfb_encrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int start = luaL_optinteger(L,4,0); + int i; +@@ -1039,9 +1041,9 @@ + static int Laes_cfb_decrypt(lua_State *L) + { + dual_aes_context *obj=Pget_aes(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); +- int iv_len; ++ size_t iv_len; + const char *IV = luaL_checklstring(L, 3, &iv_len); + int start = luaL_optinteger(L,4,0); + int i; +@@ -1079,7 +1081,7 @@ + static int Lhash_update(lua_State *L) + { + hash_context *obj=Pget_hash(L,1); +- int len; ++ size_t len; + const char *data = luaL_checklstring(L, 2, &len); + obj->update(&obj->eng, (unsigned char *)data, len); + lua_pushvalue(L, 1); +@@ -1091,7 +1093,7 @@ + { + hash_context *obj=Pget_hash(L,1); + unsigned char out[64]; +- int len; ++ size_t len; + const char *data = luaL_optlstring(L, 2, "", &len); + obj->update(&obj->eng, (unsigned char *)data, len); + obj->finish(&obj->eng, out); +@@ -1166,7 +1168,7 @@ + static int LaddTrustedCA(lua_State *L) + { + int ret; +- int ca_len; ++ size_t ca_len; + const char *ca = luaL_checklstring(L, 1, &ca_len); + + ret = x509_add_certs( &trustedCA, (unsigned char *) ca, ca_len); +@@ -1311,9 +1313,9 @@ + static int Lsessinfo(lua_State *L) /** sessinfo(c) */ + { + xyssl_context *xyssl=Pget(L,1); +- int id_len; ++ size_t id_len; + char *sessid = (char *)luaL_optlstring(L, 2, NULL, &id_len); +- int master_len; ++ size_t master_len; + char *master = (char *)luaL_optlstring(L, 3, NULL, &master_len); + int cipher = (int) luaL_optnumber(L,4,0); + time_t start = (time_t) luaL_optnumber(L,5,time(NULL)); +@@ -1597,7 +1599,7 @@ + static int LsessionCA(lua_State *L) /** setca(ca) **/ + { + int top = lua_gettop(L); +- int ca_len; ++ size_t ca_len; + int ret; + xyssl_context *xyssl=Pget(L,1); + x509_cert *cacert = &xyssl->cacert; +@@ -1624,9 +1626,9 @@ + ssl_context *ssl=&xyssl->ssl; + x509_cert *mycert= &xyssl->mycert; + rsa_context *rsa = &xyssl->mykey; +- int cert_len; +- int key_len; +- int pwd_len; ++ size_t cert_len; ++ size_t key_len; ++ size_t pwd_len; + int ret; + const char *cert = luaL_optlstring(L, 2, ssl->endpoint ? test_srv_crt: NULL, &cert_len); + const char *key = luaL_optlstring(L, 3, ssl->endpoint ? test_srv_key: NULL, &key_len); +@@ -1694,7 +1696,7 @@ + ssl_context *ssl=&xyssl->ssl; + x509_cert *cacert = &xyssl->cacert; + int verification = luaL_optinteger(L,2,0); +- int peer_len; ++ size_t peer_len; + const char *expected_peer= luaL_optlstring(L, 3, NULL, &peer_len); + ssl_set_authmode( ssl, verification ); + if (xyssl->peer_cn) free(xyssl->peer_cn); +@@ -1748,8 +1750,8 @@ + static int Lx509verify(lua_State *L) /** x509verify(ca, crt) */ + { + int top = lua_gettop(L); +- int crt_size; +- int ca_size; ++ size_t crt_size; ++ size_t ca_size; + int ret; + int flag; + x509_cert ca; +@@ -1797,9 +1799,9 @@ + static int Lrsaverify(lua_State *L) /** rsaverify(data, sig, [crt]) */ + { + int top = lua_gettop(L); +- int crt_size; +- int data_size; +- int sig_size; ++ size_t crt_size; ++ size_t data_size; ++ size_t sig_size; + int ret; + x509_cert cert; + const char *data = luaL_checklstring(L, 1, &data_size); +@@ -1833,8 +1835,8 @@ + static int Lrsaencrypt(lua_State *L) /** rsaencrypt(data, [crt]) */ + { + int top = lua_gettop(L); +- int crt_size; +- int data_size; ++ size_t crt_size; ++ size_t data_size; + unsigned char m[512]; + int ret; + x509_cert cert; +@@ -1868,9 +1870,9 @@ + static int Lrsasign(lua_State *L) /** rsasign(data, [key, [pw]]) */ + { + int top = lua_gettop(L); +- int key_size; +- int data_size; +- int pwd_len; ++ size_t key_size; ++ size_t data_size; ++ size_t pwd_len; + int ret; + unsigned char sig[512]; + rsa_context rsa; +@@ -1905,9 +1907,9 @@ + static int Lrsadecrypt(lua_State *L) /** rsadecrypt(data, [key, [pw]]) */ + { + int top = lua_gettop(L); +- int key_size; +- int data_size; +- int pwd_len; ++ size_t key_size; ++ size_t data_size; ++ size_t pwd_len; + int out_len; + int ret; + unsigned char m[512]; +@@ -2076,8 +2078,8 @@ + static int Ldhmsecret(lua_State *L) /** dhsecret(public, private, [P, [G]]) */ + { + int top = lua_gettop(L); +- int public_size; +- int private_size; ++ size_t public_size; ++ size_t private_size; + int ret; + dhm_context dhm; + unsigned char buf[512]; diff --git a/openwrt/packages/luci/contrib/package/luci/Makefile b/openwrt/packages/luci/contrib/package/luci/Makefile new file mode 100644 index 0000000..c0ede0e --- /dev/null +++ b/openwrt/packages/luci/contrib/package/luci/Makefile @@ -0,0 +1,956 @@ +include $(TOPDIR)/rules.mk + +PKG_BRANCH:=tags/0.8.6 + +ifeq ($(DUMP),) + USELOCAL:=$(shell grep luci ../../../.project 2>/dev/null >/dev/null && echo 1) +endif + +PKG_NAME:=luci +PKG_RELEASE:=1 + +ifeq ($(USELOCAL),1) + PKG_VERSION:=0.8+svn +else + PKG_SOURCE_URL:=http://svn.luci.subsignal.org/luci/$(PKG_BRANCH) + ifeq ($(DUMP),) + PKG_REV:=HEAD + PKG_VERSION:=0.8.6 + endif + PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) + PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz + PKG_SOURCE_PROTO:=svn + PKG_SOURCE_VERSION:=$(PKG_REV) +endif + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +PKG_BUILD_DEPENDS:=libnotimpl +LUA_TARGET:=source +PKG_SELECTED_MODULES:= + + +include $(INCLUDE_DIR)/package.mk + +ifeq ($(USELOCAL),1) + define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(TAR) c -C ../../../ . \ + --exclude=.pc --exclude=.svn --exclude=.git \ + --exclude='boa-0*' --exclude='*.o' --exclude='*.so' \ + --exclude=dist | \ + tar x -C $(PKG_BUILD_DIR)/ + endef +endif + +define Build/Configure +endef + +### Templates ### + +define Package/luci/libtemplate + SECTION:=admin + CATEGORY:=Administration + TITLE:=LuCI - Lua Configuration Interface + URL:=http://luci.freifunk-halle.net/ + MAINTAINER:=Steven Barth + SUBMENU:=LuCI Libraries + DEPENDS:=+luci-core +endef + +define Package/luci/fftemplate + $(call Package/luci/libtemplate) + SUBMENU:=LuCI Freifunk Support + DEPENDS:=+luci-mod-freifunk +endef + +define Package/luci/httpdtemplate + $(call Package/luci/libtemplate) + SUBMENU:=LuCIttpd + DEPENDS:=+luci-httpd +endef + +define Package/luci/i18ntemplate + $(call Package/luci/libtemplate) + SUBMENU:=LuCI Translations + DEPENDS:=+luci-web +endef + +define Package/luci/thtemplate + $(call Package/luci/libtemplate) + SUBMENU:=LuCI Themes + DEPENDS:=+luci-web +endef + +define Package/luci/webtemplate + $(call Package/luci/libtemplate) + SUBMENU:=LuCI Components +endef + + +define Package/luci/install/template + $(CP) -a $(PKG_BUILD_DIR)/$(2)/dist/* $(1)/ -R + $(CP) -a $(PKG_BUILD_DIR)/$(2)/ipkg/* $(1)/CONTROL/ 2>/dev/null || true +endef + + + +### Core package ### + +define Package/luci-core + $(call Package/luci/libtemplate) + DEPENDS:=+lua + TITLE:=LuCI core libraries +endef + +define Package/luci-core/install + $(call Package/luci/install/template,$(1),libs/core) + $(PKG_BUILD_DIR)/build/mkversion.sh $(1)/usr/lib/lua/luci/version.lua \ + "OpenWrt Firmware" \ + "$(OPENWRTVERSION)" \ + "$(PKG_BRANCH)" \ + "$(PKG_VERSION)" +endef + +define Package/luci-core/config + choice + prompt "Build Target" + default PACKAGE_luci-core_source + + config PACKAGE_luci-core_compile + bool "Precompiled" + + config PACKAGE_luci-core_stripped + bool "Stripped" + + config PACKAGE_luci-core_source + bool "Full Source" + + endchoice +endef + +ifneq ($(CONFIG_PACKAGE_luci-core_compile),) + LUA_TARGET:=compile +endif + +ifneq ($(CONFIG_PACKAGE_luci-core_stripped),) + LUA_TARGET:=strip +endif + + +### Libraries ### +define Package/luci-cbi + $(call Package/luci/libtemplate) + DEPENDS+=+luci-web +luci-uvl +luci-uci + TITLE:=Configuration Binding Interface +endef + +define Package/luci-cbi/install + $(call Package/luci/install/template,$(1),libs/cbi) +endef + + +define Package/luci-uci + $(call Package/luci/libtemplate) + DEPENDS+=+libuci-lua + TITLE:=High-Level UCI API +endef + +define Package/luci-uci/install + $(call Package/luci/install/template,$(1),libs/uci) +endef + + +define Package/luci-fastindex + $(call Package/luci/libtemplate) + TITLE:=Fastindex indexing module +endef + +define Package/luci-fastindex/install + $(call Package/luci/install/template,$(1),libs/fastindex) +endef + + +define Package/luci-http + $(call Package/luci/libtemplate) + TITLE:=HTTP Protocol implementation +endef + +define Package/luci-http/install + $(call Package/luci/install/template,$(1),libs/http) +endef + + +define Package/luci-ipkg + $(call Package/luci/libtemplate) + TITLE:=LuCI IPKG/OPKG call abstraction library +endef + +define Package/luci-ipkg/install + $(call Package/luci/install/template,$(1),libs/ipkg) +endef + + +define Package/luci-json + $(call Package/luci/libtemplate) + TITLE:=LuCI JSON Library +endef + +define Package/luci-json/install + $(call Package/luci/install/template,$(1),libs/json) +endef + + +define Package/luci-sys + $(call Package/luci/libtemplate) + TITLE:=LuCI Linux/POSIX system library +endef + +define Package/luci-sys/install + $(call Package/luci/install/template,$(1),libs/sys) +endef + + +define Package/luci-web + $(call Package/luci/libtemplate) + DEPENDS+=+luci-http +luci-sys +luci-uci +luci-sgi-cgi + TITLE:=MVC Webframework +endef + +define Package/luci-web/conffiles +/etc/config/luci +endef + +define Package/luci-web/install + $(call Package/luci/install/template,$(1),libs/web) +endef + + +define Package/luci-uvl + $(call Package/luci/libtemplate) + DEPENDS+=+luci-sys +luci-uci +luci-core + TITLE:=UVL - UCI Validation Layer +endef + +define Package/luci-uvl/install + $(call Package/luci/install/template,$(1),libs/uvl) +endef + + + +### HTTPD ### + +define Package/luci-httpd + $(call Package/luci/httpdtemplate) + DEPENDS:=+luci-http +libuci + TITLE:=Server Core +endef + +define Package/luci-httpd/install + $(call Package/luci/install/template,$(1),libs/lucittpd) +endef + + + +### Community Packages ### + +define Package/luci-freifunk-community + $(call Package/luci/fftemplate) + DEPENDS+= \ + +luci-sgi-cgi +luci-app-splash \ + +luci-app-ffwizard-leipzig \ + +luci-i18n-german \ + +PACKAGE_luci-freifunk-community:olsrd-luci +PACKAGE_luci-freifunk-community:olsrd-luci-mod-dyn-gw-plain \ + +PACKAGE_luci-freifunk-community:olsrd-luci-mod-txtinfo +PACKAGE_luci-freifunk-community:olsrd-luci-mod-nameservice \ + +PACKAGE_luci-freifunk-community:kmod-tun +PACKAGE_luci-freifunk-community:ip \ + +luci-app-olsr + TITLE:=Freifunk Community Meta-Package +endef + +define Package/luci-freifunk-community/install + $(call Package/luci/install/template,$(1),applications/freifunk-community) +endef + +### Modules ### + +define Package/luci-admin-core + $(call Package/luci/webtemplate) + DEPENDS+=+luci-web +luci-cbi +luci-theme-oxygen +luci-i18n-english + TITLE:=Web UI Core Module +endef + +define Package/luci-admin-core/conffiles +/etc/config/luci_hosts +/etc/config/luci_ethers +endef + +define Package/luci-admin-core/install + $(call Package/luci/install/template,$(1),modules/admin-core) + touch $(1)/etc/init.d/luci_fixtime || true +endef + + +define Package/luci-admin-mini + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core + TITLE:=LuCI Essentials - stripped down and user-friendly +endef + +define Package/luci-admin-mini/install + $(call Package/luci/install/template,$(1),modules/admin-mini) +endef + + +define Package/luci-admin-full + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core +luci-ipkg + TITLE:=LuCI Administration - full-featured for full control +endef + +define Package/luci-admin-full/install + $(call Package/luci/install/template,$(1),modules/admin-full) +endef + + +define Package/luci-admin-rpc + $(call Package/luci/webtemplate) + DEPENDS+=+luci-json + TITLE:=LuCI RPC - JSON-RPC API +endef + +define Package/luci-admin-rpc/install + $(call Package/luci/install/template,$(1),modules/rpc) +endef + + +define Package/luci-mod-freifunk + $(call Package/luci/fftemplate) + DEPENDS:=+luci-admin-full +luci-json + TITLE:=LuCI Freifunk module +endef + +define Package/luci-mod-freifunk/conffiles +/etc/config/freifunk +endef + +define Package/luci-mod-freifunk/install + $(call Package/luci/install/template,$(1),modules/freifunk) +endef + + + +### Applications ### + +define Package/luci-app-ffwizard-leipzig + $(call Package/luci/fftemplate) + TITLE:=Freifunk Leipzig configuration wizard +endef + +define Package/luci-app-ffwizard-leipzig/install + $(call Package/luci/install/template,$(1),applications/luci-ffwizard-leipzig) +endef + + +define Package/luci-app-firewall + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core +PACKAGE_luci-app-firewall:firewall + TITLE:=Firewall and Portforwarding application +endef + +define Package/luci-app-firewall/install + $(call Package/luci/install/template,$(1),applications/luci-fw) +endef + + +define Package/luci-app-olsr + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-olsr:olsrd-luci +PACKAGE_luci-app-olsr:olsrd-luci-mod-txtinfo + TITLE:=OLSR configuration and status module +endef + +define Package/luci-app-olsr/install + $(call Package/luci/install/template,$(1),applications/luci-olsr) +endef + + +define Package/luci-app-qos + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core +PACKAGE_luci-app-qos:qos-scripts + TITLE:=Quality of Service configuration module +endef + +define Package/luci-app-qos/install + $(call Package/luci/install/template,$(1),applications/luci-qos) +endef + + +define Package/luci-app-splash + $(call Package/luci/fftemplate) + DEPENDS+=+PACKAGE_luci-app-splash:luasocket + TITLE:=Freifunk DHCP-Splash application +endef + +define Package/luci-app-splash/conffiles +/etc/config/luci_splash +endef + +define Package/luci-app-splash/install + $(call Package/luci/install/template,$(1),applications/luci-splash) +endef + + +define Package/luci-app-statistics + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-statistics:collectd \ + +PACKAGE_luci-app-statistics:collectd-mod-rrdtool1 +PACKAGE_luci-app-statistics:rrdtool1 + TITLE:=LuCI Statistics Application +endef + +define Package/luci-app-statistics/conffiles +/etc/config/luci_statistics +endef + +define Package/luci-app-statistics/install + $(call Package/luci/install/template,$(1),applications/luci-statistics) +endef + + +define Package/luci-app-upnp + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core +PACKAGE_luci-app-upnp:miniupnpd + TITLE:=Universal Plug & Play configuration module +endef + +define Package/luci-app-upnp/install + $(call Package/luci/install/template,$(1),applications/luci-upnp) +endef + + +define Package/luci-app-ntpc + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core +PACKAGE_luci-app-ntpc:ntpclient + TITLE:=NTP time synchronisation client configuration module +endef + +define Package/luci-app-ntpc/install + $(call Package/luci/install/template,$(1),applications/luci-ntpc) +endef + + +define Package/luci-app-ddns + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core +PACKAGE_luci-app-ddns:ddns-scripts + TITLE:=Dynamic DNS configuration module +endef + +define Package/luci-app-ddns/install + $(call Package/luci/install/template,$(1),applications/luci-ddns) +endef + + +define Package/luci-app-samba + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-samba:samba3 + TITLE:=Network Shares - Samba SMB/CIFS module +endef + +define Package/luci-app-samba/install + $(call Package/luci/install/template,$(1),applications/luci-samba) +endef + + +define Package/luci-app-uvc_streamer + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-uvc_streamer:uvc-streamer + TITLE:=Webcam Streaming - UVC-Streamer module +endef + +define Package/luci-app-uvc_streamer/install + $(call Package/luci/install/template,$(1),applications/luci-uvc_streamer) +endef + + +define Package/luci-app-mmc_over_gpio + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-mmc_over_gpio:kmod-mmc-over-gpio + TITLE:=mmc_over_gpio +endef + +define Package/luci-app-mmc_over_gpio/install + $(call Package/luci/install/template,$(1),applications/luci-mmc_over_gpio) +endef + + +define Package/luci-app-p910nd + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-p910nd:p910nd + TITLE:=p910nd - Printer server module +endef + +define Package/luci-app-p910nd/install + $(call Package/luci/install/template,$(1),applications/luci-p910nd) +endef + + +define Package/luci-app-ushare + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-ushare:ushare + TITLE:=ushare - UPnP A/V & DLNA Media Server +endef + +define Package/luci-app-ushare/install + $(call Package/luci/install/template,$(1),applications/luci-ushare) +endef + +define Package/luci-app-hd_idle + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-hd_idle:hd-idle + TITLE:=hd-idle +endef + +define Package/luci-app-hd_idle/install + $(call Package/luci/install/template,$(1),applications/luci-hd_idle) +endef + +define Package/luci-app-tinyproxy + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full +PACKAGE_luci-app-tinyproxy:tinyproxy + TITLE:=Tinyproxy - HTTP(S)-Proxy +endef + +define Package/luci-app-tinyproxy/install + $(call Package/luci/install/template,$(1),applications/luci-tinyproxy) +endef + +define Package/luci-app-initmgr + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-full + TITLE:=LuCI Initscript Management +endef + +define Package/luci-app-initmgr/install + $(call Package/luci/install/template,$(1),applications/luci-initmgr) +endef + +define Package/luci-app-livestats + $(call Package/luci/webtemplate) + DEPENDS+=+luci-admin-core +luci-admin-rpc + TITLE:=LuCI Realtime Statistics +endef + +define Package/luci-app-livestats/install + $(call Package/luci/install/template,$(1),applications/luci-livestats) +endef + +define Package/luci-app-polipo + $(call Package/luci/webtemplate) + TITLE:=LuCI Support for the Polipo Proxy + DEPENDS+=+luci-admin-core +PACKAGE_luci-app-polipo:polipo +endef + +define Package/luci-app-polipo/install + $(call Package/luci/install/template,$(1),applications/luci-polipo) +endef + + +### Server Gateway Interfaces ### + +define Package/luci-sgi-cgi + $(call Package/luci/libtemplate) + TITLE:=SGI for CGI +endef + +define Package/luci-sgi-cgi/install + $(call Package/luci/install/template,$(1),libs/sgi-cgi) +endef + +define Package/luci-sgi-luci + $(call Package/luci/libtemplate) + DEPENDS+=+luci-httpd + TITLE:=SGI for LuCIttpd +endef + +define Package/luci-sgi-luci/install + $(call Package/luci/install/template,$(1),libs/sgi-luci) +endef + +define Package/luci-sgi-webuci + $(call Package/luci/libtemplate) + TITLE:=SGI for Webuci +endef + +define Package/luci-sgi-webuci/install + $(call Package/luci/install/template,$(1),libs/sgi-webuci) +endef + +### Themes ### +define Package/luci-theme-base + $(call Package/luci/thtemplate) + DEPENDS:=+luci-web + TITLE:=Common base for all themes +endef + +define Package/luci-theme-base/install + $(call Package/luci/install/template,$(1),themes/base) +endef + +define Package/luci-theme-fledermaus + $(call Package/luci/fftemplate) + DEPENDS:=+luci-web + TITLE:=Fledermaus Theme +endef + +define Package/luci-theme-fledermaus/install + $(call Package/luci/install/template,$(1),themes/fledermaus) +endef + +define Package/luci-theme-freifunk + $(call Package/luci/fftemplate) + DEPENDS:=+luci-web + MAINTAINER:=Stefan Pirwitz + TITLE:=alternative Freifunk Theme +endef + +define Package/luci-theme-freifunk/install + $(call Package/luci/install/template,$(1),themes/freifunk) +endef + +define Package/luci-theme-freifunk-bno + $(call Package/luci/fftemplate) + DEPENDS:=+luci-web + MAINTAINER:=Stefan Pirwitz + TITLE:=Freifunk Berlin Nordost Theme +endef + +define Package/luci-theme-freifunk-bno/install + $(call Package/luci/install/template,$(1),themes/freifunk-bno) +endef + +define Package/luci-theme-openwrt + $(call Package/luci/thtemplate) + TITLE:=OpenWrt.org + DEPENDS:=+luci-theme-base +endef + +define Package/luci-theme-openwrt/install + $(call Package/luci/install/template,$(1),themes/openwrt.org) +endef + +define Package/luci-theme-openwrtlight + $(call Package/luci/thtemplate) + TITLE:=OpenWrt.org - light variant without images + DEPENDS:=+luci-theme-base +endef + +define Package/luci-theme-openwrtlight/install + $(call Package/luci/install/template,$(1),themes/openwrt-light) +endef + +define Package/luci-theme-oxygen + $(call Package/luci/thtemplate) + TITLE:=Oxygen (default) + DEPENDS:=+luci-theme-base +endef + +define Package/luci-theme-oxygen/install + $(call Package/luci/install/template,$(1),themes/oxygen) +endef + +### Translations ### +define Package/luci-i18n-german + $(call Package/luci/i18ntemplate) + TITLE:=German +endef + +define Package/luci-i18n-german/install + $(call Package/luci/install/template,$(1),i18n/german) +endef + + +define Package/luci-i18n-english + $(call Package/luci/i18ntemplate) + TITLE:=English +endef + +define Package/luci-i18n-english/install + $(call Package/luci/install/template,$(1),i18n/english) +endef + + +define Package/luci-i18n-french + $(call Package/luci/i18ntemplate) + TITLE:=French (by Florian Fainelli) +endef + +define Package/luci-i18n-french/install + $(call Package/luci/install/template,$(1),i18n/french) +endef + + +define Package/luci-i18n-italian + $(call Package/luci/i18ntemplate) + TITLE:=Italian (by Matteo Croce) +endef + +define Package/luci-i18n-italian/install + $(call Package/luci/install/template,$(1),i18n/italian) +endef + + +define Package/luci-i18n-russian + $(call Package/luci/i18ntemplate) + TITLE:=Russian (by Skryabin Dmitry) +endef + +define Package/luci-i18n-russian/install + $(call Package/luci/install/template,$(1),i18n/russian) +endef + + +define Package/luci-i18n-portuguese_brazilian + $(call Package/luci/i18ntemplate) + TITLE:=Portuguese (Brazilian) (by Carlos Cesario) +endef + +define Package/luci-i18n-portuguese_brazilian/install + $(call Package/luci/install/template,$(1),i18n/portuguese_brazilian) +endef + + +### Compile ### +ifneq ($(CONFIG_PACKAGE_luci-core),) + PKG_SELECTED_MODULES+=libs/core +endif +ifneq ($(CONFIG_PACKAGE_luci-cbi),) + PKG_SELECTED_MODULES+=libs/cbi +endif +ifneq ($(CONFIG_PACKAGE_luci-fastindex),) + PKG_SELECTED_MODULES+=libs/fastindex +endif +ifneq ($(CONFIG_PACKAGE_luci-http),) + PKG_SELECTED_MODULES+=libs/http +endif +ifneq ($(CONFIG_PACKAGE_luci-ipkg),) + PKG_SELECTED_MODULES+=libs/ipkg +endif +ifneq ($(CONFIG_PACKAGE_luci-json),) + PKG_SELECTED_MODULES+=libs/json +endif +ifneq ($(CONFIG_PACKAGE_luci-uci),) + PKG_SELECTED_MODULES+=libs/uci +endif +ifneq ($(CONFIG_PACKAGE_luci-sys),) + PKG_SELECTED_MODULES+=libs/sys +endif +ifneq ($(CONFIG_PACKAGE_luci-web),) + PKG_SELECTED_MODULES+=libs/web +endif +ifneq ($(CONFIG_PACKAGE_luci-uvl),) + PKG_SELECTED_MODULES+=libs/uvl +endif + +ifneq ($(CONFIG_PACKAGE_luci-httpd),) + PKG_SELECTED_MODULES+=libs/lucittpd +endif + +ifneq ($(CONFIG_PACKAGE_luci-admin-core),) + PKG_SELECTED_MODULES+=modules/admin-core +endif +ifneq ($(CONFIG_PACKAGE_luci-admin-mini),) + PKG_SELECTED_MODULES+=modules/admin-mini +endif +ifneq ($(CONFIG_PACKAGE_luci-admin-full),) + PKG_SELECTED_MODULES+=modules/admin-full +endif +ifneq ($(CONFIG_PACKAGE_luci-admin-rpc),) + PKG_SELECTED_MODULES+=modules/rpc +endif +ifneq ($(CONFIG_PACKAGE_luci-mod-freifunk),) + PKG_SELECTED_MODULES+=modules/freifunk +endif + +ifneq ($(CONFIG_PACKAGE_luci-freifunk-community),) + PKG_SELECTED_MODULES+=applications/freifunk-community +endif + +ifneq ($(CONFIG_PACKAGE_luci-app-ffwizard-leipzig),) + PKG_SELECTED_MODULES+=applications/luci-ffwizard-leipzig +endif +ifneq ($(CONFIG_PACKAGE_luci-app-firewall),) + PKG_SELECTED_MODULES+=applications/luci-fw +endif +ifneq ($(CONFIG_PACKAGE_luci-app-olsr),) + PKG_SELECTED_MODULES+=applications/luci-olsr +endif +ifneq ($(CONFIG_PACKAGE_luci-app-qos),) + PKG_SELECTED_MODULES+=applications/luci-qos +endif +ifneq ($(CONFIG_PACKAGE_luci-app-splash),) + PKG_SELECTED_MODULES+=applications/luci-splash +endif +ifneq ($(CONFIG_PACKAGE_luci-app-statistics),) + PKG_SELECTED_MODULES+=applications/luci-statistics +endif +ifneq ($(CONFIG_PACKAGE_luci-app-upnp),) + PKG_SELECTED_MODULES+=applications/luci-upnp +endif +ifneq ($(CONFIG_PACKAGE_luci-app-ntpc),) + PKG_SELECTED_MODULES+=applications/luci-ntpc +endif +ifneq ($(CONFIG_PACKAGE_luci-app-ddns),) + PKG_SELECTED_MODULES+=applications/luci-ddns +endif +ifneq ($(CONFIG_PACKAGE_luci-app-samba),) + PKG_SELECTED_MODULES+=applications/luci-samba +endif +ifneq ($(CONFIG_PACKAGE_luci-app-uvc_streamer),) + PKG_SELECTED_MODULES+=applications/luci-uvc_streamer +endif +ifneq ($(CONFIG_PACKAGE_luci-app-mmc_over_gpio),) + PKG_SELECTED_MODULES+=applications/luci-mmc_over_gpio +endif +ifneq ($(CONFIG_PACKAGE_luci-app-p910nd),) + PKG_SELECTED_MODULES+=applications/luci-p910nd +endif +ifneq ($(CONFIG_PACKAGE_luci-app-ushare),) + PKG_SELECTED_MODULES+=applications/luci-ushare +endif +ifneq ($(CONFIG_PACKAGE_luci-app-hd_idle),) + PKG_SELECTED_MODULES+=applications/luci-hd_idle +endif +ifneq ($(CONFIG_PACKAGE_luci-app-tinyproxy),) + PKG_SELECTED_MODULES+=applications/luci-tinyproxy +endif +ifneq ($(CONFIG_PACKAGE_luci-app-initmgr),) + PKG_SELECTED_MODULES+=applications/luci-initmgr +endif +ifneq ($(CONFIG_PACKAGE_luci-app-livestats),) + PKG_SELECTED_MODULES+=applications/luci-livestats +endif +ifneq ($(CONFIG_PACKAGE_luci-app-polipo),) + PKG_SELECTED_MODULES+=applications/luci-polipo +endif + + +ifneq ($(CONFIG_PACKAGE_luci-sgi-cgi),) + PKG_SELECTED_MODULES+=libs/sgi-cgi +endif +ifneq ($(CONFIG_PACKAGE_luci-sgi-luci),) + PKG_SELECTED_MODULES+=libs/sgi-luci +endif +ifneq ($(CONFIG_PACKAGE_luci-sgi-webuci),) + PKG_SELECTED_MODULES+=libs/sgi-webuci +endif + +ifneq ($(CONFIG_PACKAGE_luci-theme-base),) + PKG_SELECTED_MODULES+=themes/base +endif +ifneq ($(CONFIG_PACKAGE_luci-theme-fledermaus),) + PKG_SELECTED_MODULES+=themes/fledermaus +endif +ifneq ($(CONFIG_PACKAGE_luci-theme-freifunk-bno),) + PKG_SELECTED_MODULES+=themes/freifunk-bno +endif +ifneq ($(CONFIG_PACKAGE_luci-theme-freifunk),) + PKG_SELECTED_MODULES+=themes/freifunk +endif +ifneq ($(CONFIG_PACKAGE_luci-theme-openwrt),) + PKG_SELECTED_MODULES+=themes/openwrt.org +endif +ifneq ($(CONFIG_PACKAGE_luci-theme-openwrtlight),) + PKG_SELECTED_MODULES+=themes/openwrt-light +endif + +ifneq ($(CONFIG_PACKAGE_luci-theme-oxygen),) + PKG_SELECTED_MODULES+=themes/oxygen +endif + +ifneq ($(CONFIG_PACKAGE_luci-i18n-german),) + PKG_SELECTED_MODULES+=i18n/german +endif +ifneq ($(CONFIG_PACKAGE_luci-i18n-english),) + PKG_SELECTED_MODULES+=i18n/english +endif +ifneq ($(CONFIG_PACKAGE_luci-i18n-french),) + PKG_SELECTED_MODULES+=i18n/french +endif +ifneq ($(CONFIG_PACKAGE_luci-i18n-italian),) + PKG_SELECTED_MODULES+=i18n/italian +endif +ifneq ($(CONFIG_PACKAGE_luci-i18n-russian),) + PKG_SELECTED_MODULES+=i18n/russian +endif +ifneq ($(CONFIG_PACKAGE_luci-i18n-portuguese_brazilian),) + PKG_SELECTED_MODULES+=i18n/portuguese_brazilian +endif + + +MAKE_FLAGS += \ + MODULES="$(PKG_SELECTED_MODULES)" \ + LUA_TARGET="$(LUA_TARGET)" \ + LUA_SHLIBS="-llua -lm -ldl -lcrypt" \ + CFLAGS="$(TARGET_CFLAGS) -I$(STAGING_DIR)/usr/include" \ + LDFLAGS="$(TARGET_LDFLAGS) -L$(STAGING_DIR)/usr/lib" \ + OS="Linux" + + +$(eval $(call BuildPackage,luci-core)) +$(eval $(call BuildPackage,luci-cbi)) +$(eval $(call BuildPackage,luci-fastindex)) +$(eval $(call BuildPackage,luci-http)) +$(eval $(call BuildPackage,luci-ipkg)) +$(eval $(call BuildPackage,luci-json)) +$(eval $(call BuildPackage,luci-uci)) +$(eval $(call BuildPackage,luci-sys)) +$(eval $(call BuildPackage,luci-web)) +$(eval $(call BuildPackage,luci-uvl)) + +$(eval $(call BuildPackage,luci-httpd)) + +$(eval $(call BuildPackage,luci-admin-core)) +$(eval $(call BuildPackage,luci-admin-mini)) +$(eval $(call BuildPackage,luci-admin-full)) +$(eval $(call BuildPackage,luci-admin-rpc)) +$(eval $(call BuildPackage,luci-mod-freifunk)) + +$(eval $(call BuildPackage,luci-freifunk-community)) + +$(eval $(call BuildPackage,luci-app-ffwizard-leipzig)) +$(eval $(call BuildPackage,luci-app-firewall)) +$(eval $(call BuildPackage,luci-app-olsr)) +$(eval $(call BuildPackage,luci-app-qos)) +$(eval $(call BuildPackage,luci-app-splash)) +$(eval $(call BuildPackage,luci-app-statistics)) +$(eval $(call BuildPackage,luci-app-upnp)) +$(eval $(call BuildPackage,luci-app-ntpc)) +$(eval $(call BuildPackage,luci-app-ddns)) +$(eval $(call BuildPackage,luci-app-samba)) +$(eval $(call BuildPackage,luci-app-uvc_streamer)) +$(eval $(call BuildPackage,luci-app-mmc_over_gpio)) +$(eval $(call BuildPackage,luci-app-p910nd)) +$(eval $(call BuildPackage,luci-app-ushare)) +$(eval $(call BuildPackage,luci-app-hd_idle)) +$(eval $(call BuildPackage,luci-app-tinyproxy)) +$(eval $(call BuildPackage,luci-app-initmgr)) +$(eval $(call BuildPackage,luci-app-livestats)) +$(eval $(call BuildPackage,luci-app-polipo)) + +$(eval $(call BuildPackage,luci-sgi-cgi)) +$(eval $(call BuildPackage,luci-sgi-luci)) +$(eval $(call BuildPackage,luci-sgi-webuci)) + +$(eval $(call BuildPackage,luci-theme-base)) +$(eval $(call BuildPackage,luci-theme-fledermaus)) +$(eval $(call BuildPackage,luci-theme-freifunk)) +$(eval $(call BuildPackage,luci-theme-freifunk-bno)) +$(eval $(call BuildPackage,luci-theme-openwrt)) +$(eval $(call BuildPackage,luci-theme-openwrtlight)) +$(eval $(call BuildPackage,luci-theme-oxygen)) + +$(eval $(call BuildPackage,luci-i18n-german)) +$(eval $(call BuildPackage,luci-i18n-english)) +$(eval $(call BuildPackage,luci-i18n-french)) +$(eval $(call BuildPackage,luci-i18n-italian)) +$(eval $(call BuildPackage,luci-i18n-russian)) +$(eval $(call BuildPackage,luci-i18n-portuguese_brazilian)) diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/Makefile b/openwrt/packages/luci/contrib/package/olsrd-luci/Makefile new file mode 100644 index 0000000..f667888 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/Makefile @@ -0,0 +1,210 @@ +# +# Copyright (C) 2008-2009 Freifunk Leipzig +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: Makefile 4202 2009-01-31 02:22:48Z jow $ +# + +include $(TOPDIR)/rules.mk + +PKG_BASENAME:=olsrd +PKG_NAME:=$(PKG_BASENAME)-luci +PKG_BASEVER:=0.5.6-r3 +PKG_VERSION:=$(PKG_BASEVER)+freifunk +PKG_RELEASE:=1 + +#PKG_HGREV:=a7316f987848 +#PKG_SOURCE:=$(PKG_HGREV).tar.gz +#PKG_SOURCE_URL:=http://gredler.at/hg/olsrd/archive +#PKG_MD5SUM:=b228b5452af158cd4313f9ed416d9c84 +#PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_HGREV) +#PKG_UNPACK=$(HOST_TAR) -C $(PKG_BUILD_DIR) --strip-components=1 -xzf $(DL_DIR)/$(PKG_SOURCE) + +PKG_SOURCE:=$(PKG_BASENAME)-$(PKG_BASEVER).tar.bz2 +PKG_SOURCE_URL:=http://www.olsr.org/releases/0.5 +PKG_MD5SUM:=0935688fa0fb5b0e073fe53ec654c5b2 +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_BASEVER) +PKG_UNPACK=$(HOST_TAR) -C $(PKG_BUILD_DIR) --strip-components=1 -xjf $(DL_DIR)/$(PKG_SOURCE) + +include $(INCLUDE_DIR)/package.mk + + +define Package/olsrd-luci/common_info + SECTION:=net + CATEGORY:=Network + TITLE:=OLSR - Optimized Link State Routing Daemon + URL:=http://www.olsr.org/ + MAINTAINER:=Jo-Philipp Wich +endef + +define Package/olsrd-luci + $(call Package/olsrd-luci/common_info) + MENU:=1 + DEPENDS:=+libpthread +endef + +define Package/olsrd-luci/conffiles +/etc/config/olsrd +endef + +define Package/olsrd-luci-mod-arprefresh + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - ARP Refresh Plugin + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-dot-draw + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - Dot Draw Plugin + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-bmf + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - Basic Multicast Forwarding Plugin + DEPENDS:=olsrd-luci +kmod-tun +endef + +define Package/olsrd-luci-mod-dyn-gw + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - Dynamic Gateway Plugin + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-dyn-gw-plain + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - Dynamic Gateway Plugin (Plain Version) + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-httpinfo + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - HTTP/HTML Info Plugin + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-nameservice + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - Hostname Propagation Plugin + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-secure + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - Security Extensions Plugin + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-txtinfo + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - HTTP/Plaintext Info Plugin + DEPENDS:=olsrd-luci +endef + +define Package/olsrd-luci-mod-quagga + $(call Package/olsrd-luci/common_info) + MENU:=1 + TITLE:=OLSR - Quagga Plugin + DEPENDS:=olsrd-luci +endef + +TARGET_CFLAGS += $(FPIC) + +define Build/Compile + $(MAKE) -C "$(PKG_BUILD_DIR)" olsrd libs \ + $(TARGET_CONFIGURE_OPTS) \ + NODEBUG=1 \ + CFLAGS="$(TARGET_CFLAGS)" \ + OS="linux" \ + INSTALL_PREFIX="$(PKG_INSTALL_DIR)" \ + LIBDIR="$(PKG_INSTALL_DIR)/usr/lib" \ + SBINDIR="$(PKG_INSTALL_DIR)/usr/sbin/" \ + ETCDIR="$(PKG_INSTALL_DIR)/etc" \ + MANDIR="$(PKG_INSTALL_DIR)/usr/share/man" \ + STRIP="true" \ + INSTALL_LIB="true" \ + SUBDIRS="arprefresh bmf dot_draw dyn_gw dyn_gw_plain httpinfo nameservice secure txtinfo quagga" +endef + +define Package/olsrd-luci/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) $(PKG_BUILD_DIR)/olsrd $(1)/usr/sbin/ + $(INSTALL_BIN) ./files/etc/init.d/olsrd $(1)/etc/init.d/ + $(INSTALL_CONF) ./files/etc/config/olsrd $(1)/etc/config/ +endef + +define Package/olsrd-luci-mod-arprefresh/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/arprefresh/olsrd_arprefresh.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-dot-draw/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/dot_draw/olsrd_dot_draw.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-bmf/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/bmf/olsrd_bmf.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-dyn-gw/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/dyn_gw/olsrd_dyn_gw.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-dyn-gw-plain/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/dyn_gw_plain/olsrd_dyn_gw_plain.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-httpinfo/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/httpinfo/olsrd_httpinfo.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-nameservice/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/nameservice/olsrd_nameservice.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-secure/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/secure/olsrd_secure.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-txtinfo/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/txtinfo/olsrd_txtinfo.so.* $(1)/usr/lib/ +endef + +define Package/olsrd-luci-mod-quagga/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/quagga/olsrd_quagga.so.* $(1)/usr/lib/ +endef + + +$(eval $(call BuildPackage,olsrd-luci)) +$(eval $(call BuildPackage,olsrd-luci-mod-arprefresh)) +$(eval $(call BuildPackage,olsrd-luci-mod-dot-draw)) +$(eval $(call BuildPackage,olsrd-luci-mod-bmf)) +$(eval $(call BuildPackage,olsrd-luci-mod-dyn-gw)) +$(eval $(call BuildPackage,olsrd-luci-mod-dyn-gw-plain)) +$(eval $(call BuildPackage,olsrd-luci-mod-httpinfo)) +$(eval $(call BuildPackage,olsrd-luci-mod-nameservice)) +$(eval $(call BuildPackage,olsrd-luci-mod-secure)) +$(eval $(call BuildPackage,olsrd-luci-mod-txtinfo)) +$(eval $(call BuildPackage,olsrd-luci-mod-quagga)) diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/config/olsrd b/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/config/olsrd new file mode 100644 index 0000000..4158590 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/config/olsrd @@ -0,0 +1,22 @@ +config 'olsrd' + option 'IpVersion' '4' + option 'FIBMetric' 'flat' + option 'LinkQualityAlgorithm' 'etx_ff' + +config 'Interface' + option 'ignore' '1' + option 'interface' 'ff' + option 'Ip4Broadcast' '255.255.255.255' + +config 'LoadPlugin' + option 'library' 'olsrd_dyn_gw_plain.so.0.4' + +config 'LoadPlugin' + option 'library' 'olsrd_nameservice.so.0.3' + option 'name' 'luci-node' + option 'suffix' '.olsr' + option 'hosts_file' '/var/etc/hosts.olsr' + +config 'LoadPlugin' + option 'library' 'olsrd_txtinfo.so.0.1' + option 'accept' '127.0.0.1' diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/default/olsrd b/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/default/olsrd new file mode 100644 index 0000000..d89e007 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/default/olsrd @@ -0,0 +1,8 @@ +# you can override olsrd's startup variables here +#BIN=/usr/sbin/olsrd +#CONF=/var/etc/olsrd.conf +#PID=/var/run/olsrd.pid + +# place your custom olsrd parameters here +OPTIONS= + diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/init.d/olsrd b/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/init.d/olsrd new file mode 100755 index 0000000..b90c3b9 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/files/etc/init.d/olsrd @@ -0,0 +1,575 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2008 Alina Friedrichsen +# Special thanks to bittorf wireless )) +START=50 + +BIN=/usr/sbin/olsrd +CONF=/var/etc/olsrd.conf +PID=/var/run/olsrd.pid + +OLSRD_OLSRD_SCHEMA='ignore:internal config_file:internal DebugLevel=0 IpVersion=4 AllowNoInt:bool=1 Pollrate=0.025 TcRedundancy=2 MprCoverage=3 LinkQualityFishEye=1 LinkQualityDijkstraLimit=0+9.0 FIBMetric=flat ClearScreen:bool=1 Willingness=3 LinkQualityAging=0.1 LinkQualityAlgorithm=etx_fpm' +OLSRD_IPCCONNECT_SCHEMA='ignore:internal Host:list Net:list2' +OLSRD_LOADPLUGIN_SCHEMA='ignore:internal library:internal Host:list Net:list2 Ping:list redistribute:list NonOlsrIf:list name:list lat lon latlon_infile HNA:list2 hosts:list2' +OLSRD_INTERFACE_SCHEMA='ignore:internal interface:internal AutoDetectChanges:bool Ip4Broadcast HelloInterval=2.0 HelloValidityTime=40.0 TcInterval=5.0 TcValidityTime=100.0 MidInterval=18.0 MidValidityTime=324.0 HnaInterval=18.0 HnaValidityTime=108.0' + +T=' ' +N=' +' + +validate_varname() { + local varname=$1 + [ -z "$varname" -o "$varname" != "${varname%%[!A-Za-z0-9_]*}" ] && return 1 + return 0 +} + +validate_ifname() { + local ifname=$1 + [ -z "$ifname" -o "$ifname" != "${ifname%%[!A-Za-z0-9.:_-]*}" ] && return 1 + return 0 +} + +validate_olsrd_option() { + local str=$1 + [ -z "$str" -o "$str" != "${str%%[! 0-9A-Za-z./:_-]*}" ] && return 1 + return 0 +} + +get_ifname() { + IFNAME= + local interface=$1 + validate_varname "$interface" || return 1 + local ifname + + config_get ifname "$interface" ifname + validate_ifname "$ifname" || return 1 + IFNAME=$ifname + + return 0 +} + +system_config() { + local cfg=$1 + local cfgt + local hostname + local latlon + + config_get cfgt "$cfg" TYPE + + if [ "$cfgt" = "system" ]; then + config_get hostname "$cfg" hostname + hostname=${hostname:-OpenWrt} + SYSTEM_HOSTNAME=$hostname + fi + + if [ -z "$SYSTEM_LAT" -o -z "$SYSTEM_LON" ]; then + config_get latlon "$cfg" latlon + IFS=" ${T}${N}," + set -- $latlon + unset IFS + SYSTEM_LAT=$1 + SYSTEM_LON=$2 + fi +} + +olsrd_find_config_file() { + local cfg=$1 + validate_varname "$cfg" || return 0 + + config_get_bool ignore "$cfg" ignore 0 + [ "$ignore" -ne 0 ] && return 0 + config_get OLSRD_CONFIG_FILE "$cfg" config_file + + return 0 +} + +warning_invalid_value() { + local package=$1 + validate_varname "$package" || package= + local config=$2 + validate_varname "$config" || config= + local option=$3 + validate_varname "$option" || option= + + echo -n "Warning: Invalid value" 1>&2 + + if [ -n "$package" -a -n "$config" ]; then + echo -n " in option '$package.$config${option:+.}$option'" 1>&2 + fi + + echo ", skipped" 1>&2 + + return 0 +} + +olsrd_write_option() { + local param=$1 + local cfg=$2 + validate_varname "$cfg" || return 1 + local option=$3 + validate_varname "$option" || return 1 + local value=$4 + local option_type=$5 + + if [ "$option_type" = bool ]; then + case "$value" in + 1|on|true|enabled|yes) value=yes;; + 0|off|false|disabled|no) value=no;; + *) warning_invalid_value olsrd "$cfg" "$option"; return 1;; + esac + fi + + if ! validate_olsrd_option "$value"; then + warning_invalid_value olsrd "$cfg" "$option" + return 1 + fi + + if [ "$value" != "${value%%[G-Zg-z_-]*}" ]; then + if [ "$option" != "Ip6AddrType" -a "$value" != "yes" -a "$value" != "no" ]; then + value="\"$value\"" + fi + fi + + echo -n "${N}$param$option $value" + + return 0 +} + +olsrd_write_plparam() { + local param=$1 + local cfg=$2 + validate_varname "$cfg" || return 1 + local option=$3 + validate_varname "$option" || return 1 + local value=$4 + local option_type=$5 + local _option + + if [ "$option_type" = bool ]; then + case "$value" in + 1|on|true|enabled|yes) value=yes;; + 0|off|false|disabled|no) value=no;; + *) warning_invalid_value olsrd "$cfg" "$option"; return 1;; + esac + fi + + if ! validate_olsrd_option "$value"; then + warning_invalid_value olsrd "$cfg" "$option" + return 1 + fi + + IFS='-_' + set -- $option + option="$*" + unset IFS + _option="$option" + if [ "$option" = 'hosts' ]; then + set -- $value + option=$1 + shift + value="$*" + fi + + echo -n "${N}${param}PlParam \"$option\" \"$value\"" + + return 0 +} + +config_update_schema() { + unset IFS + local schema_varname=$1 + validate_varname "$schema_varname" || return 1 + local command=$2 + validate_varname "$command" || return 1 + local option=$3 + validate_varname "$option" || return 1 + local value=$4 + local schema + local cur_option + + case "$varname" in + *_LENGTH) return 0;; + *_ITEM*) return 0;; + esac + + eval "export -n -- \"schema=\${$schema_varname}\"" + + for cur_option in $schema; do + [ "${cur_option%%[:=]*}" = "$option" ] && return 0 + done + + if [ "$command" = list ]; then + set -- $value + if [ "$#" -ge "3" ]; then + schema_entry="$option:list3" + elif [ "$#" -ge "2" ]; then + schema_entry="$option:list2" + else + schema_entry="$option:list" + fi + else + schema_entry="$option" + fi + + append "$schema_varname" "$schema_entry" + + return 0 +} + +config_write_options() { + unset IFS + local schema=$1 + local cfg=$2 + validate_varname "$cfg" || return 1 + local write_func=$3 + [ -z "$write_func" ] && output_func=echo + local write_param=$4 + local schema_entry + local option + local option_length + local option_type + local default + local value + local list_size + local list_item + local list_value + local i + local position + + for schema_entry in $schema; do + default=${schema_entry#*[=]} + [ "$default" = "$schema_entry" ] && default= + option=${schema_entry%%[=]*} + IFS=':' + set -- $option + unset IFS + option=$1 + option_type=$2 + validate_varname "$option" || continue + [ -z "$option_type" ] || validate_varname "$option_type" || continue + [ "$option_type" = internal ] && continue + config_get value "$cfg" "$option" + + if [ -z "$value" ]; then + IFS='+' + set -- $default + unset IFS + value=$* + elif [ "$value" = '-' -a -n "$default" ]; then + continue + fi + + [ -z "$value" ] && continue + + case "$option_type" in + list) list_size=1;; + list2) list_size=2;; + list3) list_size=3;; + *) list_size=0;; + esac + + if [ "$list_size" -gt 0 ]; then + config_get option_length "$cfg" "${option}_LENGTH" + if [ -n "$option_length" ]; then + i=1 + while [ "$i" -le "$option_length" ]; do + config_get list_value "$cfg" "${option}_ITEM$i" + "$write_func" "$write_param" "$cfg" "$option" "$list_value" "$option_type" || break + i=$((i + 1)) + done + else + list_value= + i=0 + for list_item in $value; do + append "list_value" "$list_item" + i=$((i + 1)) + position=$((i % list_size)) + if [ "$position" -eq 0 ]; then + "$write_func" "$write_param" "$cfg" "$option" "$list_value" "$option_type" || break + list_value= + fi + done + [ "$position" -ne 0 ] && "$write_func" "$write_param" "$cfg" "$option" "$list_value" "$option_type" + fi + else + "$write_func" "$write_param" "$cfg" "$option" "$value" "$option_type" + fi + done + + return 0 +} + +olsrd_write_olsrd() { + local cfg=$1 + validate_varname "$cfg" || return 0 + local ignore + + config_get_bool ignore "$cfg" ignore 0 + [ "$ignore" -ne 0 ] && return 0 + + [ "$OLSRD_COUNT" -gt 0 ] && return 0 + + config_write_options "$OLSRD_OLSRD_SCHEMA" "$cfg" olsrd_write_option + echo + OLSRD_COUNT=$((OLSRD_COUNT + 1)) + + return 0 +} + +olsrd_write_ipcconnect() { + local cfg=$1 + validate_varname "$cfg" || return 0 + local ignore + + config_get_bool ignore "$cfg" ignore 0 + [ "$ignore" -ne 0 ] && return 0 + + [ "$IPCCONNECT_COUNT" -gt 0 ] && return 0 + + echo -n "${N}IpcConnect${N}{" + config_write_options "$OLSRD_IPCCONNECT_SCHEMA" "$cfg" olsrd_write_option "${T}" + echo "${N}}" + IPCCONNECT_COUNT=$((IPCCONNECT_COUNT + 1)) + + return 0 +} + +olsrd_write_hna4() { + local cfg=$1 + validate_varname "$cfg" || return 0 + local ignore + + config_get_bool ignore "$cfg" ignore 0 + [ "$ignore" -ne 0 ] && return 0 + + config_get netaddr "$cfg" netaddr + if ! validate_olsrd_option "$netaddr"; then + warning_invalid_value olsrd "$cfg" "netaddr" + return 0 + fi + + config_get netmask "$cfg" netmask + if ! validate_olsrd_option "$netmask"; then + warning_invalid_value olsrd "$cfg" "netmask" + return 0 + fi + + [ "$HNA4_COUNT" -le 0 ] && echo -n "${N}Hna4${N}{" + echo -n "${N}${T}$netaddr $netmask" + HNA4_COUNT=$((HNA4_COUNT + 1)) + + return 0 +} + +olsrd_write_hna6() { + local cfg=$1 + validate_varname "$cfg" || return 0 + local ignore + + config_get_bool ignore "$cfg" ignore 0 + [ "$ignore" -ne 0 ] && return 0 + + config_get netaddr "$cfg" netaddr + if ! validate_olsrd_option "$netaddr"; then + warning_invalid_value olsrd "$cfg" "netaddr" + return 0 + fi + + config_get prefix "$cfg" prefix + if ! validate_olsrd_option "$prefix"; then + warning_invalid_value olsrd "$cfg" "prefix" + return 0 + fi + + [ "$HNA6_COUNT" -le 0 ] && echo -n "${N}Hna6${N}{" + echo -n "${N}${T}$netaddr $prefix" + HNA6_COUNT=$((HNA6_COUNT + 1)) + + return 0 +} + +olsrd_write_loadplugin() { + local cfg=$1 + validate_varname "$cfg" || return 0 + local ignore + local name + local suffix + local lat + local lon + local latlon_infile + + config_get_bool ignore "$cfg" ignore 0 + [ "$ignore" -ne 0 ] && return 0 + + config_get library "$cfg" library + if ! validate_olsrd_option "$library"; then + warning_invalid_value olsrd "$cfg" "library" + return 0 + fi + if ! [ -x "/lib/$library" -o -x "/usr/lib/$library" -o -x "/usr/local/lib/$library" ]; then + echo "Warning: Plugin library '$library' not found, skipped" 1>&2 + return 0 + fi + + case "$library" in + olsrd_nameservice.*) + config_get name "$cfg" name + [ -z "$name" ] && config_set "$cfg" name $SYSTEM_HOSTNAME + + config_get suffix "$cfg" suffix + [ -z "$suffix" ] && config_set "$cfg" suffix '.olsr' + + config_get lat "$cfg" lat + config_get lon "$cfg" lon + config_get latlon_infile "$cfg" latlon_infile + if [ \( -z "$lat" -o -z "$lat" \) -a -z "$latlon_infile" ]; then + if [ -f '/var/run/latlon.txt' ]; then + config_set "$cfg" lat '' + config_set "$cfg" lon '' + config_set "$cfg" latlon_infile '/var/run/latlon.txt' + else + config_set "$cfg" lat "$SYSTEM_LAT" + config_set "$cfg" lon "$SYSTEM_LON" + fi + fi + + config_get latlon_file "$cfg" latlon_file + ;; + esac + + echo -n "${N}LoadPlugin \"$library\"${N}{" + config_write_options "$OLSRD_LOADPLUGIN_SCHEMA" "$cfg" olsrd_write_plparam "${T}" + echo "${N}}" + + return 0 +} + +olsrd_write_interface() { + local cfg=$1 + validate_varname "$cfg" || return 0 + local ignore + local interfaces + local interface + local ifnames + + config_get_bool ignore "$cfg" ignore 0 + [ "$ignore" -ne 0 ] && return 0 + + ifnames= + config_get interfaces "$cfg" interface + for interface in $interfaces; do + if validate_varname "$interface"; then + if get_ifname "$interface"; then + ifnames="$ifnames \"$IFNAME\"" + else + echo "Warning: Interface '$interface' not found, skipped" 1>&2 + fi + else + warning_invalid_value olsrd "$cfg" "interface" + fi + done + + [ -z "$ifnames" ] && return 0 + + echo -n "${N}Interface$ifnames${N}{" + config_write_options "$OLSRD_INTERFACE_SCHEMA" "$cfg" olsrd_write_option "${T}" + echo "${N}}" + INTERFACES_COUNT=$((INTERFACES_COUNT + 1)) + + return 0 +} + +olsrd_update_schema() { + local command="$1" + validate_varname "$command" || return 0 + local varname="$2" + validate_varname "$varname" || return 0 + local value="$3" + local cfg="$CONFIG_SECTION" + local cfgt + local cur_varname + + config_get cfgt "$cfg" TYPE + case "$cfgt" in + olsrd) config_update_schema OLSRD_OLSRD_SCHEMA "$command" "$varname" "$value";; + IpcConnect) config_update_schema OLSRD_IPCCONNECT_SCHEMA "$command" "$varname" "$value";; + LoadPlugin) config_update_schema OLSRD_LOADPLUGIN_SCHEMA "$command" "$varname" "$value";; + Interface) config_update_schema OLSRD_INTERFACE_SCHEMA "$command" "$varname" "$value";; + esac + + return 0 +} + +olsrd_write_config() { + OLSRD_COUNT=0 + config_foreach olsrd_write_olsrd olsrd + IPCCONNECT_COUNT=0 + config_foreach olsrd_write_ipcconnect IpcConnect + HNA4_COUNT=0 + config_foreach olsrd_write_hna4 Hna4 + [ "$HNA4_COUNT" -gt 0 ] && echo "${N}}" + HNA6_COUNT=0 + config_foreach olsrd_write_hna6 Hna6 + [ "$HNA6_COUNT" -gt 0 ] && echo "${N}}" + config_foreach olsrd_write_loadplugin LoadPlugin + INTERFACES_COUNT=0 + config_foreach olsrd_write_interface Interface + echo + + return 0 +} + +start() { + ### check for running instance + if [ -s $PID ]; then + if kill -0 $(cat $PID) 2>&-; then + echo "there is already a running instance ($(cat $PID))" + return 1 + fi + fi + + SYSTEM_HOSTNAME= + SYSTEM_LAT= + SYSTEM_LON= + config_load system + config_foreach system_config system + + option_cb() { + olsrd_update_schema "option" "$@" + } + + list_cb() { + olsrd_update_schema "list" "$@" + } + + include /lib/network + scan_interfaces + config_load olsrd + reset_cb + + OLSRD_CONFIG_FILE= + config_foreach olsrd_find_config_file olsrd + + if [ -z "$OLSRD_CONFIG_FILE" ]; then + ### generate config + mkdir -p ${CONF%/*} + olsrd_write_config > $CONF + if [ "$INTERFACES_COUNT" -gt 0 -a "$OLSRD_COUNT" -gt 0 ]; then + OLSRD_CONFIG_FILE=$CONF + fi + fi + + [ -z "$OLSRD_CONFIG_FILE" ] && return 1 + + ### start olsrd + start-stop-daemon -q -b -m -p $PID -x $BIN -S -- -f $CONF -nofork +} + +stop() { + ### stop olsrd + start-stop-daemon -q -p $PID -x $BIN -K +} + +restart() { + ### override generic restart because we need some time between stop and start + stop; sleep 3; start +} diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/ipkg/postinst b/openwrt/packages/luci/contrib/package/olsrd-luci/ipkg/postinst new file mode 100755 index 0000000..c96480c --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/ipkg/postinst @@ -0,0 +1,5 @@ +#!/bin/sh + +[ -n "${IPKG_INSTROOT}" ] || { + /etc/init.d/olsrd enabled || /etc/init.d/olsrd enable +} diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/patches/100-olsrd-hg-r3.patch b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/100-olsrd-hg-r3.patch new file mode 100644 index 0000000..a489004 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/100-olsrd-hg-r3.patch @@ -0,0 +1,500 @@ +diff --exclude='.hg*' -Nur olsrd-0.5.6-r3/lib/nameservice/README_NAMESERVICE /home/sven-ola/olsrd-0.5.6/lib/nameservice/README_NAMESERVICE +--- olsrd-0.5.6-r3/lib/nameservice/README_NAMESERVICE 2008-12-02 11:42:54.000000000 +0100 ++++ /home/sven-ola/olsrd-0.5.6/lib/nameservice/README_NAMESERVICE 2008-12-03 09:11:11.000000000 +0100 +@@ -112,12 +112,32 @@ + table. Useful for executing a script that uses the hosts file + to keep a website or a database updated. + ++PlParam "service" "http://me.olsr:80|tcp|my little homepage" ++ Add a new service announcement to be spreaded in the mesh. ++ ++PlParam "services-file" "/path/to/services_file" ++ File to write (default: /var/run/services_olsr) ++ + PlParam "services-change-script" "/path/to/script" + Similar to the previous parameter. Script to execute when there + is a change in the services list propagated by the nameserver + plugin. Useful for executing a script that uses the services file + to keep a website or a database updated. + ++PlParam "mac" "xx:xx:xx:xx:xx:xx[,0-255]" ++ Add a new MAC addr to be spreaded in the mesh. This MAC addr ++ may be used to fine control nerve-wreck-page solutions based ++ on MAC adresses. The optional dec. number designates a class. ++ ++PlParam "macs-file" "/path/to/macs_file" ++ File to write (default: /var/run/macs_olsr) ++ ++PlParam "macs-change-script" "/path/to/script" ++ Similar to the previous parameter. Script to execute when there ++ is a change in the macs list propagated by the nameserver ++ plugin. Useful for executing a script that uses the services file ++ to keep a website or a database updated. ++ + --------------------------------------------------------------------- + SAMPLE CONFIG + --------------------------------------------------------------------- +diff --exclude='.hg*' -Nur olsrd-0.5.6-r3/lib/nameservice/src/nameservice.c /home/sven-ola/olsrd-0.5.6/lib/nameservice/src/nameservice.c +--- olsrd-0.5.6-r3/lib/nameservice/src/nameservice.c 2008-12-02 11:50:01.000000000 +0100 ++++ /home/sven-ola/olsrd-0.5.6/lib/nameservice/src/nameservice.c 2008-12-03 09:20:01.000000000 +0100 +@@ -75,8 +75,10 @@ + static double my_timeout = NAME_VALID_TIME; + static char my_resolv_file[MAX_FILE + 1]; + static char my_services_file[MAX_FILE + 1]; ++static char my_macs_file[MAX_FILE + 1]; + static char my_name_change_script[MAX_FILE + 1]; + static char my_services_change_script[MAX_FILE + 1]; ++static char my_macs_change_script[MAX_FILE + 1]; + static char latlon_in_file[MAX_FILE + 1]; + static char my_latlon_file[MAX_FILE + 1]; + float my_lat = 0.0, my_lon = 0.0; +@@ -96,6 +98,10 @@ + static struct name_entry *my_services = NULL; + static olsr_bool service_table_changed = OLSR_TRUE; + ++static struct list_node mac_list[HASHSIZE]; ++static struct name_entry *my_macs = NULL; ++static olsr_bool mac_table_changed = OLSR_TRUE; ++ + static struct list_node forwarder_list[HASHSIZE]; + static struct name_entry *my_forwarders = NULL; + static olsr_bool forwarder_table_changed = OLSR_TRUE; +@@ -131,6 +137,7 @@ + + GetWindowsDirectory(my_hosts_file, MAX_FILE - 12); + GetWindowsDirectory(my_services_file, MAX_FILE - 12); ++ GetWindowsDirectory(my_macs_file, MAX_FILE - 12); + GetWindowsDirectory(my_resolv_file, MAX_FILE - 12); + + len = strlen(my_hosts_file); +@@ -143,6 +150,11 @@ + strscat(my_services_file, "\\", sizeof(my_services_file)); + strscat(my_services_file, "services_olsr", sizeof(my_services_file)); + ++ len = strlen(my_macs_file); ++ if (my_macs_file[len - 1] != '\\') ++ strscat(my_macs_file, "\\", sizeof(my_macs_file)); ++ strscat(my_macs_file, "macs_olsr", sizeof(my_macs_file)); ++ + len = strlen(my_resolv_file); + if (my_resolv_file[len - 1] != '\\') + strscat(my_resolv_file, "\\", sizeof(my_resolv_file)); +@@ -150,6 +162,7 @@ + #else + strscpy(my_hosts_file, "/var/run/hosts_olsr", sizeof(my_hosts_file)); + strscpy(my_services_file, "/var/run/services_olsr", sizeof(my_services_file)); ++ strscpy(my_macs_file, "/var/run/macs_olsr", sizeof(my_macs_file)); + strscpy(my_resolv_file, "/var/run/resolvconf_olsr", sizeof(my_resolv_file)); + *my_sighup_pid_file = 0; + #endif +@@ -160,12 +173,14 @@ + latlon_in_file[0] = '\0'; + my_name_change_script[0] = '\0'; + my_services_change_script[0] = '\0'; ++ my_macs_change_script[0] = '\0'; + + /* init the lists heads */ + for (i = 0; i < HASHSIZE; i++) { + list_head_init(&name_list[i]); + list_head_init(&forwarder_list[i]); + list_head_init(&service_list[i]); ++ list_head_init(&mac_list[i]); + list_head_init(&latlon_list[i]); + } + +@@ -232,58 +247,31 @@ + return 0; + } + ++/* *INDENT-OFF* */ + static const struct olsrd_plugin_parameters plugin_parameters[] = { +- {.name = "interval",.set_plugin_parameter = &set_plugin_int,.data = &my_interval}, +- {.name = "timeout",.set_plugin_parameter = &set_nameservice_float,.data = &my_timeout}, +- {.name = "sighup-pid-file",.set_plugin_parameter = &set_plugin_string,.data = &my_sighup_pid_file,.addon = +- {sizeof(my_sighup_pid_file)} +- } +- , +- {.name = "hosts-file",.set_plugin_parameter = &set_plugin_string,.data = &my_hosts_file,.addon = {sizeof(my_hosts_file)} +- } +- , +- {.name = "name-change-script",.set_plugin_parameter = &set_plugin_string,.data = &my_name_change_script,.addon = +- {sizeof(my_name_change_script)} +- } +- , +- {.name = "services-change-script",.set_plugin_parameter = &set_plugin_string,.data = &my_services_change_script,.addon = +- {sizeof(my_services_change_script)} +- } +- , +- {.name = "resolv-file",.set_plugin_parameter = &set_plugin_string,.data = &my_resolv_file,.addon = {sizeof(my_resolv_file)} +- } +- , +- {.name = "suffix",.set_plugin_parameter = &set_plugin_string,.data = &my_suffix,.addon = {sizeof(my_suffix)} +- } +- , +- {.name = "add-hosts",.set_plugin_parameter = &set_plugin_string,.data = &my_add_hosts,.addon = {sizeof(my_add_hosts)} +- } +- , +- {.name = "services-file",.set_plugin_parameter = &set_plugin_string,.data = &my_services_file,.addon = {sizeof(my_services_file)} +- } +- , +- {.name = "lat",.set_plugin_parameter = &set_nameservice_float,.data = &my_lat} +- , +- {.name = "lon",.set_plugin_parameter = &set_nameservice_float,.data = &my_lon} +- , +- {.name = "latlon-file",.set_plugin_parameter = &set_plugin_string,.data = &my_latlon_file,.addon = {sizeof(my_latlon_file)} +- } +- , +- {.name = "latlon-infile",.set_plugin_parameter = &set_plugin_string,.data = &latlon_in_file,.addon = {sizeof(latlon_in_file)} +- } +- , +- {.name = "dns-server",.set_plugin_parameter = &set_nameservice_server,.data = &my_forwarders,.addon = {NAME_FORWARDER} +- } +- , +- {.name = "name",.set_plugin_parameter = &set_nameservice_name,.data = &my_names,.addon = {NAME_HOST} +- } +- , +- {.name = "service",.set_plugin_parameter = &set_nameservice_name,.data = &my_services,.addon = {NAME_SERVICE} +- } +- , +- {.name = "",.set_plugin_parameter = &set_nameservice_host,.data = &my_names} +- , ++ { .name = "interval", .set_plugin_parameter = &set_plugin_int, .data = &my_interval }, ++ { .name = "timeout", .set_plugin_parameter = &set_nameservice_float, .data = &my_timeout }, ++ { .name = "sighup-pid-file", .set_plugin_parameter = &set_plugin_string, .data = &my_sighup_pid_file, .addon = {sizeof(my_sighup_pid_file)} }, ++ { .name = "hosts-file", .set_plugin_parameter = &set_plugin_string, .data = &my_hosts_file, .addon = {sizeof(my_hosts_file)} }, ++ { .name = "name-change-script", .set_plugin_parameter = &set_plugin_string, .data = &my_name_change_script, .addon = {sizeof(my_name_change_script)} }, ++ { .name = "services-change-script", .set_plugin_parameter = &set_plugin_string, .data = &my_services_change_script, .addon = {sizeof(my_services_change_script)} }, ++ { .name = "macs-change-script", .set_plugin_parameter = &set_plugin_string, .data = &my_macs_change_script, .addon = {sizeof(my_macs_change_script)} }, ++ { .name = "resolv-file", .set_plugin_parameter = &set_plugin_string, .data = &my_resolv_file, .addon = {sizeof(my_resolv_file)} }, ++ { .name = "suffix", .set_plugin_parameter = &set_plugin_string, .data = &my_suffix, .addon = {sizeof(my_suffix)} }, ++ { .name = "add-hosts", .set_plugin_parameter = &set_plugin_string, .data = &my_add_hosts, .addon = {sizeof(my_add_hosts)} }, ++ { .name = "services-file", .set_plugin_parameter = &set_plugin_string, .data = &my_services_file, .addon = {sizeof(my_services_file)} }, ++ { .name = "macs-file", .set_plugin_parameter = &set_plugin_string, .data = &my_macs_file, .addon = {sizeof(my_macs_file)} }, ++ { .name = "lat", .set_plugin_parameter = &set_nameservice_float, .data = &my_lat }, ++ { .name = "lon", .set_plugin_parameter = &set_nameservice_float, .data = &my_lon }, ++ { .name = "latlon-file", .set_plugin_parameter = &set_plugin_string, .data = &my_latlon_file, .addon = {sizeof(my_latlon_file)} }, ++ { .name = "latlon-infile", .set_plugin_parameter = &set_plugin_string, .data = &latlon_in_file, .addon = {sizeof(latlon_in_file)} }, ++ { .name = "dns-server", .set_plugin_parameter = &set_nameservice_server, .data = &my_forwarders, .addon = {NAME_FORWARDER} }, ++ { .name = "name", .set_plugin_parameter = &set_nameservice_name, .data = &my_names, .addon = {NAME_HOST} }, ++ { .name = "service", .set_plugin_parameter = &set_nameservice_name, .data = &my_services, .addon = {NAME_SERVICE} }, ++ { .name = "mac", .set_plugin_parameter = &set_nameservice_name, .data = &my_macs, .addon = {NAME_MACADDR} }, ++ { .name = "", .set_plugin_parameter = &set_nameservice_host, .data = &my_names }, + }; ++/* *INDENT-OFF* */ + + void + olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size) +@@ -404,6 +392,7 @@ + my_names = remove_nonvalid_names_from_list(my_names, NAME_HOST); + my_forwarders = remove_nonvalid_names_from_list(my_forwarders, NAME_FORWARDER); + my_services = remove_nonvalid_names_from_list(my_services, NAME_SERVICE); ++ my_macs = remove_nonvalid_names_from_list(my_macs, NAME_MACADDR); + + /* register functions with olsrd */ + olsr_parser_add_function(&olsr_parser, PARSER_TYPE); +@@ -435,6 +424,9 @@ + case NAME_SERVICE: + valid = allowed_service(my_list->name); + break; ++ case NAME_MACADDR: ++ valid = is_mac_wellformed(my_list->name); ++ break; + case NAME_LATLON: + valid = is_latlon_wellformed(my_list->name); + break; +@@ -470,10 +462,12 @@ + + free_name_entry_list(&my_names); + free_name_entry_list(&my_services); ++ free_name_entry_list(&my_macs); + free_name_entry_list(&my_forwarders); + + free_all_list_entries(name_list); + free_all_list_entries(service_list); ++ free_all_list_entries(mac_list); + free_all_list_entries(forwarder_list); + free_all_list_entries(latlon_list); + +@@ -517,11 +511,12 @@ + { + write_file_timer = NULL; + +- write_resolv_file(); /* if forwarder_table_changed */ +- write_hosts_file(); /* if name_table_changed */ +- write_services_file(); /* if service_table_changed */ ++ write_resolv_file(); /* if forwarder_table_changed */ ++ write_hosts_file(); /* if name_table_changed */ ++ write_services_file(OLSR_FALSE); /* if service_table_changed */ ++ write_services_file(OLSR_TRUE); /* if mac_table_changed */ + #ifdef WIN32 +- write_latlon_file(); /* if latlon_table_changed */ ++ write_latlon_file(); /* if latlon_table_changed */ + #endif + } + +@@ -688,7 +683,6 @@ + encap_namemsg(struct namemsg *msg) + { + struct name_entry *my_name; +- struct name_entry *my_service; + + // add the hostname, service and forwarder entries after the namemsg header + char *pos = (char *)msg + sizeof(struct namemsg); +@@ -705,8 +699,13 @@ + i++; + } + // services +- for (my_service = my_services; my_service != NULL; my_service = my_service->next) { +- pos = create_packet((struct name *)pos, my_service); ++ for (my_name = my_services; my_name != NULL; my_name = my_name->next) { ++ pos = create_packet((struct name *)pos, my_name); ++ i++; ++ } ++ // macs ++ for (my_name = my_macs; my_name != NULL; my_name = my_name->next) { ++ pos = create_packet((struct name *)pos, my_name); + i++; + } + // latlon +@@ -779,6 +778,7 @@ + //XXX: should I check the from_packet->ip here? If so, why not also check the ip from HOST and SERVICE? + if ((type_of_from_packet == NAME_HOST && !is_name_wellformed(name)) + || (type_of_from_packet == NAME_SERVICE && !is_service_wellformed(name)) ++ || (type_of_from_packet == NAME_MACADDR && !is_mac_wellformed(name)) + || (type_of_from_packet == NAME_LATLON && !is_latlon_wellformed(name))) { + OLSR_PRINTF(4, "NAME PLUGIN: invalid name [%s] received, skipping.\n", name); + return; +@@ -886,6 +886,9 @@ + case NAME_SERVICE: + insert_new_name_in_list(originator, service_list, from_packet, &service_table_changed, vtime); + break; ++ case NAME_MACADDR: ++ insert_new_name_in_list(originator, mac_list, from_packet, &mac_table_changed, vtime); ++ break; + case NAME_LATLON: + insert_new_name_in_list(originator, latlon_list, from_packet, &latlon_table_changed, vtime); + break; +@@ -1128,45 +1131,47 @@ + } + + /** +- * write services to a file in the format: +- * service #originator ip ++ * write services or macs to a file in the format: ++ * service-or-mac #originator ip + * + * since service has a special format + * each line will look similar to e.g. + * http://me.olsr:80|tcp|my little homepage ++ * while a mac line will look similar to ++ * 02:ca:ff:ee:ba:be,1 + */ + void +-write_services_file(void) ++write_services_file(olsr_bool writemacs) + { + int hash; + struct name_entry *name; + struct db_entry *entry; + struct list_node *list_head, *list_node; +- FILE *services_file; ++ FILE *file; + time_t currtime; + +- if (!service_table_changed) ++ if ((writemacs && !mac_table_changed) || (!writemacs && !service_table_changed)) + return; + +- OLSR_PRINTF(2, "NAME PLUGIN: writing services file\n"); ++ OLSR_PRINTF(2, "NAME PLUGIN: writing %s file\n", writemacs ? "macs" : "services"); + +- services_file = fopen(my_services_file, "w"); +- if (services_file == NULL) { +- OLSR_PRINTF(2, "NAME PLUGIN: cant write services_file file\n"); ++ file = fopen(writemacs ? my_macs_file : my_services_file, "w"); ++ if (file == NULL) { ++ OLSR_PRINTF(2, "NAME PLUGIN: cant write %s\n", writemacs ? my_macs_file : my_services_file); + return; + } + +- fprintf(services_file, "### this file is overwritten regularly by olsrd\n"); +- fprintf(services_file, "### do not edit\n\n"); ++ fprintf(file, "### this file is overwritten regularly by olsrd\n"); ++ fprintf(file, "### do not edit\n\n"); + +- // write own services +- for (name = my_services; name != NULL; name = name->next) { +- fprintf(services_file, "%s\t# my own service\n", name->name); ++ // write own services or macs ++ for (name = writemacs ? my_macs : my_services; name != NULL; name = name->next) { ++ fprintf(file, "%s\t# my own %s\n", name->name, writemacs ? "mac" : "service"); + } + +- // write received services ++ // write received services or macs + for (hash = 0; hash < HASHSIZE; hash++) { +- list_head = &service_list[hash]; ++ list_head = writemacs ? &mac_list[hash] : &service_list[hash]; + for (list_node = list_head->next; list_node != list_head; list_node = list_node->next) { + + entry = list2db(list_node); +@@ -1176,26 +1181,38 @@ + OLSR_PRINTF(6, "%s\t", name->name); + OLSR_PRINTF(6, "\t#%s\n", olsr_ip_to_string(&strbuf, &entry->originator)); + +- fprintf(services_file, "%s\t", name->name); +- fprintf(services_file, "\t#%s\n", olsr_ip_to_string(&strbuf, &entry->originator)); ++ fprintf(file, "%s\t", name->name); ++ fprintf(file, "\t#%s\n", olsr_ip_to_string(&strbuf, &entry->originator)); + } + } + } + + if (time(&currtime)) { +- fprintf(services_file, "\n### written by olsrd at %s", ctime(&currtime)); ++ fprintf(file, "\n### written by olsrd at %s", ctime(&currtime)); + } + +- fclose(services_file); +- service_table_changed = OLSR_FALSE; +- +- // Executes my_services_change_script after writing the services file +- if (my_services_change_script[0] != '\0') { +- if (system(my_services_change_script) != -1) { +- OLSR_PRINTF(2, "NAME PLUGIN: Service changed, %s executed\n", my_services_change_script); +- } else { +- OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on service change\n", my_services_change_script); ++ fclose(file); ++ if (writemacs) { ++ // Executes my_macs_change_script after writing the macs file ++ if (my_macs_change_script[0] != '\0') { ++ if (system(my_macs_change_script) != -1) { ++ OLSR_PRINTF(2, "NAME PLUGIN: Service changed, %s executed\n", my_macs_change_script); ++ } else { ++ OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on mac change\n", my_macs_change_script); ++ } + } ++ mac_table_changed = OLSR_FALSE; ++ } ++ else { ++ // Executes my_services_change_script after writing the services file ++ if (my_services_change_script[0] != '\0') { ++ if (system(my_services_change_script) != -1) { ++ OLSR_PRINTF(2, "NAME PLUGIN: Service changed, %s executed\n", my_services_change_script); ++ } else { ++ OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on service change\n", my_services_change_script); ++ } ++ } ++ service_table_changed = OLSR_FALSE; + } + } + +@@ -1348,6 +1365,9 @@ + case NAME_SERVICE: + service_table_changed = OLSR_TRUE; + break; ++ case NAME_MACADDR: ++ mac_table_changed = OLSR_TRUE; ++ break; + case NAME_LATLON: + latlon_table_changed = OLSR_TRUE; + break; +@@ -1498,6 +1518,22 @@ + return regexec(®ex_t_service, service_line, pmatch_service, regmatch_t_service, 0) == 0; + } + ++/* ++ * check if the mac matches the syntax ++ */ ++olsr_bool ++is_mac_wellformed(const char *mac_line) ++{ ++ size_t i; ++ olsr_bool ret; ++ int x[6], d = -1; ++ for(i = 0; i < ARRAYSIZE(x); i++) x[i] = -1; ++ sscanf(mac_line, "%02x:%02x:%02x:%02x:%02x:%02x,%d\n", &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &d); ++ ret = 0 <= d && d <= 0xffff; ++ for(i = 0; i < ARRAYSIZE(x); i++) ret = ret && 0 <= x[i]; ++ return ret; ++} ++ + /** + * check if the latlot matches the syntax + */ +diff --exclude='.hg*' -Nur olsrd-0.5.6-r3/lib/nameservice/src/nameservice.h /home/sven-ola/olsrd-0.5.6/lib/nameservice/src/nameservice.h +--- olsrd-0.5.6-r3/lib/nameservice/src/nameservice.h 2008-12-02 11:50:01.000000000 +0100 ++++ /home/sven-ola/olsrd-0.5.6/lib/nameservice/src/nameservice.h 2008-12-03 09:20:01.000000000 +0100 +@@ -145,7 +145,7 @@ + + void write_hosts_file(void); + +-void write_services_file(void); ++void write_services_file(olsr_bool writemacs); + + void write_resolv_file(void); + +@@ -161,7 +161,7 @@ + + olsr_bool is_service_wellformed(const char *service_line); + +-olsr_bool is_service_wellformed(const char *service_line); ++olsr_bool is_mac_wellformed(const char *service_line); + + olsr_bool is_latlon_wellformed(const char *latlon_line); + +diff --exclude='.hg*' -Nur olsrd-0.5.6-r3/lib/nameservice/src/nameservice_msg.h /home/sven-ola/olsrd-0.5.6/lib/nameservice/src/nameservice_msg.h +--- olsrd-0.5.6-r3/lib/nameservice/src/nameservice_msg.h 2008-12-02 11:50:01.000000000 +0100 ++++ /home/sven-ola/olsrd-0.5.6/lib/nameservice/src/nameservice_msg.h 2008-12-03 09:11:13.000000000 +0100 +@@ -43,6 +43,7 @@ + NAME_FORWARDER = 1, + NAME_SERVICE = 2, + NAME_LATLON = 3, ++ NAME_MACADDR = 4, + } NAME_TYPE; + + /** +diff --exclude='.hg*' -Nur olsrd-0.5.6-r3/lib/tas/src/lua/lobject.c /home/sven-ola/olsrd-0.5.6/lib/tas/src/lua/lobject.c +--- olsrd-0.5.6-r3/lib/tas/src/lua/lobject.c 2008-12-02 11:50:01.000000000 +0100 ++++ /home/sven-ola/olsrd-0.5.6/lib/tas/src/lua/lobject.c 2008-12-03 09:19:32.000000000 +0100 +@@ -42,11 +42,11 @@ + return (m << 3) | cast(int, x); + } + ++/* *INDENT-OFF* */ + int + luaO_log2(unsigned int x) + { + static const lu_byte log_8[255] = { +-/* *INDENT-OFF* */ + 0, + 1,1, + 2,2,2,2, +@@ -59,7 +59,6 @@ + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +-/* *INDENT-ON* */ + }; + if (x >= 0x00010000) { + if (x >= 0x01000000) +@@ -74,6 +73,7 @@ + return -1; /* special `log' for 0 */ + } + } ++/* *INDENT-ON* */ + + int + luaO_rawequalObj(const TObject * t1, const TObject * t2) +diff --exclude='.hg*' -Nur olsrd-0.5.6-r3/Makefile /home/sven-ola/olsrd-0.5.6/Makefile +--- olsrd-0.5.6-r3/Makefile 2008-12-02 11:50:01.000000000 +0100 ++++ /home/sven-ola/olsrd-0.5.6/Makefile 2008-12-03 09:11:10.000000000 +0100 +@@ -39,7 +39,7 @@ + # Please also write a new version to: + # gui/win32/Main/Frontend.rc (line 71, around "CAPTION [...]") + # gui/win32/Inst/installer.nsi (line 57, around "MessageBox MB_YESNO [...]") +-VERS = 0.5.6-r3 ++VERS = pre-0.5.6-r4 + + TOPDIR = . + include Makefile.inc diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/patches/131-olsrd-tweak-ffetx.patch b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/131-olsrd-tweak-ffetx.patch new file mode 100644 index 0000000..853a14f --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/131-olsrd-tweak-ffetx.patch @@ -0,0 +1,13 @@ +diff -Nur olsrd-0.5.6-r2.orig/src/lq_plugin_default_ff.h olsrd-0.5.6-r2/src/lq_plugin_default_ff.h +--- olsrd-0.5.6-r2.orig/src/lq_plugin_default_ff.h 2008-11-26 10:53:16.000000000 +0100 ++++ olsrd-0.5.6-r2/src/lq_plugin_default_ff.h 2008-11-26 10:53:16.000000000 +0100 +@@ -50,7 +50,8 @@ + + #define LQ_ALGORITHM_ETX_FF_NAME "etx_ff" + +-#define LQ_FF_WINDOW 32 ++/* 16,32,64 and max. 128 */ ++#define LQ_FF_WINDOW 64 + #define LQ_FF_QUICKSTART_INIT 4 + + struct default_lq_ff { diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/patches/137-olsrd-192.168.1.1.patch b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/137-olsrd-192.168.1.1.patch new file mode 100644 index 0000000..33a916b --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/137-olsrd-192.168.1.1.patch @@ -0,0 +1,11 @@ +diff -Nur olsrd-0.5.6-r2.orig/src/net_olsr.c olsrd-0.5.6-r2/src/net_olsr.c +--- olsrd-0.5.6-r2.orig/src/net_olsr.c 2008-11-26 10:53:53.000000000 +0100 ++++ olsrd-0.5.6-r2/src/net_olsr.c 2008-11-26 10:53:53.000000000 +0100 +@@ -78,6 +78,7 @@ + static const char *const deny_ipv4_defaults[] = { + "0.0.0.0", + "127.0.0.1", ++ "192.168.1.1", + NULL + }; + diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/patches/139-olsrd-magicarprefresh.patch b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/139-olsrd-magicarprefresh.patch new file mode 100644 index 0000000..642abe1 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/139-olsrd-magicarprefresh.patch @@ -0,0 +1,45 @@ +diff -Nur olsrd-0.5.6-r2.orig/lib/arprefresh/src/olsrd_arprefresh.c olsrd-0.5.6-r2/lib/arprefresh/src/olsrd_arprefresh.c +--- olsrd-0.5.6-r2.orig/lib/arprefresh/src/olsrd_arprefresh.c 2008-11-26 10:54:16.000000000 +0100 ++++ olsrd-0.5.6-r2/lib/arprefresh/src/olsrd_arprefresh.c 2008-11-26 10:56:15.000000000 +0100 +@@ -34,6 +34,8 @@ + * Plugin to refresh the local ARP cache from received OLSR broadcasts + */ + ++#undef ARPREFRESH_DEBUG ++ + #include + #include + #include +@@ -46,6 +48,9 @@ + #include + #include + #include ++#ifdef ARPREFRESH_DEBUG ++#include ++#endif + #include + #include + +@@ -53,7 +58,6 @@ + #include "kernel_routes.h" + #include "scheduler.h" + +-#undef ARPREFRESH_DEBUG + #define PLUGIN_INTERFACE_VERSION 5 + + /**************************************************************************** +@@ -128,7 +132,13 @@ + memcpy(&req.in_pa.sin_addr, &buf.ip.saddr, sizeof(buf.ip.saddr)); + req.arp.arp_ha.sa_family = AF_LOCAL; + memcpy(&req.arp.arp_ha.sa_data, &buf.eth.h_source, sizeof(buf.eth.h_source)); +- req.arp.arp_flags = ATF_COM; ++ /* ++ * Currently, temp arp entries work partially under linux-2.6 (the entries ++ * are timed out after a short period, not after the default 5 minutes. Under ++ * linux 2.4 this does not work. The ATF_MAGIC triggers a hack in the Freifunk ++ * firmware's kernel. ATF_MACIG seem not to be used anywhere... ++ */ ++ req.arp.arp_flags = ATF_COM | ATF_MAGIC; + if_indextoname(from.sll_ifindex, req.arp.arp_dev); + #ifdef ARPREFRESH_DEBUG + { diff --git a/openwrt/packages/luci/contrib/package/olsrd-luci/patches/140-olsrd-optimize-size.patch b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/140-olsrd-optimize-size.patch new file mode 100644 index 0000000..7aed872 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/olsrd-luci/patches/140-olsrd-optimize-size.patch @@ -0,0 +1,2139 @@ +diff -Nur olsrd-0.5.6-r3.orig/lib/bmf/src/NetworkInterfaces.c olsrd-0.5.6-r3/lib/bmf/src/NetworkInterfaces.c +--- olsrd-0.5.6-r3.orig/lib/bmf/src/NetworkInterfaces.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/lib/bmf/src/NetworkInterfaces.c 2008-12-03 10:01:07.000000000 +0100 +@@ -544,7 +544,9 @@ + OLSR_PRINTF(9, "%s: ----> Not forwarding to %s: no link found\n", PLUGIN_NAME_SHORT, + olsr_ip_to_string(&buf, &walker->neighbor_iface_addr)); + } else { ++#ifndef DEBUG + struct interface *bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr); ++#endif + + OLSR_PRINTF(9, "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %5.2f\n", + PLUGIN_NAME_SHORT, olsr_ip_to_string(&buf, &walker->neighbor_iface_addr), bestIntf->int_name, +diff -Nur olsrd-0.5.6-r3.orig/lib/httpinfo/Makefile olsrd-0.5.6-r3/lib/httpinfo/Makefile +--- olsrd-0.5.6-r3.orig/lib/httpinfo/Makefile 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/lib/httpinfo/Makefile 2008-12-03 10:01:07.000000000 +0100 +@@ -47,7 +47,11 @@ + CPPFLAGS += -DADMIN_INTERFACE + endif + ++ifdef SVEN_OLA_UNBLOAT ++ CFLAGS += -DSVEN_OLA ++else + OBJS += $(TOPDIR)/src/cfgparser/cfgfile_gen.o ++endif + + default_target: $(PLUGIN_FULLNAME) + ifdef ADMIN_INTERFACE +diff -Nur olsrd-0.5.6-r3.orig/lib/httpinfo/src/olsrd_httpinfo.c olsrd-0.5.6-r3/lib/httpinfo/src/olsrd_httpinfo.c +--- olsrd-0.5.6-r3.orig/lib/httpinfo/src/olsrd_httpinfo.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/lib/httpinfo/src/olsrd_httpinfo.c 2008-12-03 10:01:07.000000000 +0100 +@@ -67,7 +67,9 @@ + + #include "olsrd_httpinfo.h" + #include "admin_interface.h" ++#ifndef SVEN_OLA_UNBLOAT + #include "gfx.h" ++#endif /* SVEN_OLA_UNBLOAT */ + + #ifdef OS + #undef OS +@@ -181,7 +183,9 @@ + + static int build_about_body(char *, olsr_u32_t); + ++#ifndef SVEN_OLA_UNBLOAT + static int build_cfgfile_body(char *, olsr_u32_t); ++#endif /* SVEN_OLA_UNBLOAT */ + + static int check_allowed_ip(const struct allowed_net *const allowed_nets, const union olsr_ip_addr *const addr); + +@@ -217,10 +221,13 @@ + {"Admin", "admin", build_admin_body, OLSR_TRUE}, + #endif + {"About", "about", build_about_body, OLSR_TRUE}, ++#ifndef SVEN_OLA_UNBLOAT + {"FOO", "cfgfile", build_cfgfile_body, OLSR_FALSE}, ++#endif /* SVEN_OLA_UNBLOAT */ + {NULL, NULL, NULL, OLSR_FALSE} + }; + ++#ifndef SVEN_OLA_UNBLOAT + static const struct static_bin_file_entry static_bin_files[] = { + {"favicon.ico", favicon_ico, sizeof(favicon_ico)} + , +@@ -230,6 +237,7 @@ + , + {NULL, NULL, 0} + }; ++#endif /* SVEN_OLA_UNBLOAT */ + + static const struct static_txt_file_entry static_txt_files[] = { + {"httpinfo.css", httpinfo_css}, +@@ -408,6 +416,7 @@ + } else if (!strcmp(req_type, "GET")) { + int i = 0; + ++#ifndef SVEN_OLA_UNBLOAT + for (i = 0; static_bin_files[i].filename; i++) { + if (FILENREQ_MATCH(filename, static_bin_files[i].filename)) { + break; +@@ -423,6 +432,7 @@ + } + + i = 0; ++#endif /* SVEN_OLA_UNBLOAT */ + while (static_txt_files[i].filename) { + if (FILENREQ_MATCH(filename, static_txt_files[i].filename)) { + break; +@@ -462,16 +472,22 @@ + snprintf(&body[size], sizeof(body) - size, + "\n" "\n" + "\n" +- "olsr.org httpinfo plugin\n" "\n" ++ "olsr.org httpinfo plugin\n" ++#ifndef SVEN_OLA_UNBLOAT ++ "\n" + "\n" ++#endif /* SVEN_OLA_UNBLOAT */ + "\n" "\n" + "\n" ++#ifndef SVEN_OLA_UNBLOAT + "\n" + "\n" "\n" + "\n" "\n" +- "\n" "
\n" + "   olsr.org OLSR daemon\n" + "\"olsrd
\n", FRAMEWIDTH); ++ "\n" "\n", FRAMEWIDTH ++#endif /* SVEN_OLA_UNBLOAT */ ++ ); + + size += build_tabs(&body[size], sizeof(body) - size, i); + size += build_frame(&body[size], sizeof(body) - size, "Current Routes", "routes", FRAMEWIDTH, tab_entries[i].build_body_cb); +@@ -855,7 +871,7 @@ + size += snprintf(&buf[size], bufsize - size, "Status: DOWN\n"); + continue; + } +- ++#ifndef SVEN_OLA_UNBLOAT + if (olsr_cnf->ip_version == AF_INET) { + struct ipaddr_str addrbuf, maskbuf, bcastbuf; + size += +@@ -868,6 +884,7 @@ + snprintf(&buf[size], bufsize - size, "\n" "IP: %s\n" "MCAST: %s\n" "\n" "\n", + ip6_to_string(&addrbuf, &rifs->int6_addr.sin6_addr), ip6_to_string(&maskbuf, &rifs->int6_multaddr.sin6_addr)); + } ++#endif /* SVEN_OLA_UNBLOAT */ + size += + snprintf(&buf[size], bufsize - size, "\n" "MTU: %d\n" "WLAN: %s\n" "STATUS: UP\n" "\n", + rifs->int_mtu, rifs->is_wireless ? "Yes" : "No"); +@@ -1116,6 +1133,7 @@ + build_host); + } + ++#ifndef SVEN_OLA_UNBLOAT + static int + build_cfgfile_body(char *buf, olsr_u32_t bufsize) + { +@@ -1150,6 +1168,7 @@ + #endif + return size; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + static int + check_allowed_ip(const struct allowed_net *const allowed_nets, const union olsr_ip_addr *const addr) +diff -Nur olsrd-0.5.6-r3.orig/lib/nameservice/src/nameservice.c olsrd-0.5.6-r3/lib/nameservice/src/nameservice.c +--- olsrd-0.5.6-r3.orig/lib/nameservice/src/nameservice.c 2008-12-03 10:01:07.000000000 +0100 ++++ olsrd-0.5.6-r3/lib/nameservice/src/nameservice.c 2008-12-03 10:10:52.000000000 +0100 +@@ -65,6 +65,11 @@ + #include "mapwrite.h" + #include "compat.h" + ++#ifdef SVEN_OLA_UNBLOAT ++#undef OLSR_PRINTF ++#define OLSR_PRINTF(...) ++#endif /* SVEN_OLA_UNBLOAT */ ++ + /* config parameters */ + static char my_hosts_file[MAX_FILE + 1]; + static char my_sighup_pid_file[MAX_FILE + 1]; +@@ -73,12 +78,16 @@ + static char my_suffix[MAX_SUFFIX]; + static int my_interval = EMISSION_INTERVAL; + static double my_timeout = NAME_VALID_TIME; ++#ifndef SVEN_OLA_UNBLOAT + static char my_resolv_file[MAX_FILE + 1]; ++#endif /* SVEN_OLA_UNBLOAT */ + static char my_services_file[MAX_FILE + 1]; + static char my_macs_file[MAX_FILE + 1]; ++#ifndef SVEN_OLA_UNBLOAT + static char my_name_change_script[MAX_FILE + 1]; + static char my_services_change_script[MAX_FILE + 1]; + static char my_macs_change_script[MAX_FILE + 1]; ++#endif + static char latlon_in_file[MAX_FILE + 1]; + static char my_latlon_file[MAX_FILE + 1]; + float my_lat = 0.0, my_lon = 0.0; +@@ -102,9 +111,11 @@ + static struct name_entry *my_macs = NULL; + static olsr_bool mac_table_changed = OLSR_TRUE; + ++#ifndef SVEN_OLA_UNBLOAT + static struct list_node forwarder_list[HASHSIZE]; + static struct name_entry *my_forwarders = NULL; + static olsr_bool forwarder_table_changed = OLSR_TRUE; ++#endif /* SVEN_OLA_UNBLOAT */ + + struct list_node latlon_list[HASHSIZE]; + static olsr_bool latlon_table_changed = OLSR_TRUE; +@@ -138,7 +149,9 @@ + GetWindowsDirectory(my_hosts_file, MAX_FILE - 12); + GetWindowsDirectory(my_services_file, MAX_FILE - 12); + GetWindowsDirectory(my_macs_file, MAX_FILE - 12); ++#ifndef SVEN_OLA_UNBLOAT + GetWindowsDirectory(my_resolv_file, MAX_FILE - 12); ++#endif /* SVEN_OLA_UNBLOAT */ + + len = strlen(my_hosts_file); + if (my_hosts_file[len - 1] != '\\') +@@ -155,15 +168,19 @@ + strscat(my_macs_file, "\\", sizeof(my_macs_file)); + strscat(my_macs_file, "macs_olsr", sizeof(my_macs_file)); + ++#ifndef SVEN_OLA_UNBLOAT + len = strlen(my_resolv_file); + if (my_resolv_file[len - 1] != '\\') + strscat(my_resolv_file, "\\", sizeof(my_resolv_file)); + strscat(my_resolv_file, "resolvconf_olsr", sizeof(my_resolv_file)); ++#endif /* SVEN_OLA_UNBLOAT */ + #else + strscpy(my_hosts_file, "/var/run/hosts_olsr", sizeof(my_hosts_file)); + strscpy(my_services_file, "/var/run/services_olsr", sizeof(my_services_file)); + strscpy(my_macs_file, "/var/run/macs_olsr", sizeof(my_macs_file)); ++#ifndef SVEN_OLA_UNBLOAT + strscpy(my_resolv_file, "/var/run/resolvconf_olsr", sizeof(my_resolv_file)); ++#endif /* SVEN_OLA_UNBLOAT */ + *my_sighup_pid_file = 0; + #endif + +@@ -171,14 +188,18 @@ + my_add_hosts[0] = '\0'; + my_latlon_file[0] = '\0'; + latlon_in_file[0] = '\0'; ++#ifndef SVEN_OLA_UNBLOAT + my_name_change_script[0] = '\0'; + my_services_change_script[0] = '\0'; + my_macs_change_script[0] = '\0'; ++#endif /* SVEN_OLA_UNBLOAT */ + + /* init the lists heads */ + for (i = 0; i < HASHSIZE; i++) { + list_head_init(&name_list[i]); ++#ifndef SVEN_OLA_UNBLOAT + list_head_init(&forwarder_list[i]); ++#endif /* SVEN_OLA_UNBLOAT */ + list_head_init(&service_list[i]); + list_head_init(&mac_list[i]); + list_head_init(&latlon_list[i]); +@@ -186,6 +207,7 @@ + + } + ++#ifndef SVEN_OLA_UNBLOAT + static int + set_nameservice_server(const char *value, void *data, set_plugin_parameter_addon addon) + { +@@ -204,6 +226,7 @@ + } + return 1; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + static int + set_nameservice_name(const char *value, void *data, set_plugin_parameter_addon addon) +@@ -253,10 +276,12 @@ + { .name = "timeout", .set_plugin_parameter = &set_nameservice_float, .data = &my_timeout }, + { .name = "sighup-pid-file", .set_plugin_parameter = &set_plugin_string, .data = &my_sighup_pid_file, .addon = {sizeof(my_sighup_pid_file)} }, + { .name = "hosts-file", .set_plugin_parameter = &set_plugin_string, .data = &my_hosts_file, .addon = {sizeof(my_hosts_file)} }, ++#ifndef SVEN_OLA_UNBLOAT + { .name = "name-change-script", .set_plugin_parameter = &set_plugin_string, .data = &my_name_change_script, .addon = {sizeof(my_name_change_script)} }, + { .name = "services-change-script", .set_plugin_parameter = &set_plugin_string, .data = &my_services_change_script, .addon = {sizeof(my_services_change_script)} }, + { .name = "macs-change-script", .set_plugin_parameter = &set_plugin_string, .data = &my_macs_change_script, .addon = {sizeof(my_macs_change_script)} }, + { .name = "resolv-file", .set_plugin_parameter = &set_plugin_string, .data = &my_resolv_file, .addon = {sizeof(my_resolv_file)} }, ++#endif /* SVEN_OLA_UNBLOAT */ + { .name = "suffix", .set_plugin_parameter = &set_plugin_string, .data = &my_suffix, .addon = {sizeof(my_suffix)} }, + { .name = "add-hosts", .set_plugin_parameter = &set_plugin_string, .data = &my_add_hosts, .addon = {sizeof(my_add_hosts)} }, + { .name = "services-file", .set_plugin_parameter = &set_plugin_string, .data = &my_services_file, .addon = {sizeof(my_services_file)} }, +@@ -265,7 +290,9 @@ + { .name = "lon", .set_plugin_parameter = &set_nameservice_float, .data = &my_lon }, + { .name = "latlon-file", .set_plugin_parameter = &set_plugin_string, .data = &my_latlon_file, .addon = {sizeof(my_latlon_file)} }, + { .name = "latlon-infile", .set_plugin_parameter = &set_plugin_string, .data = &latlon_in_file, .addon = {sizeof(latlon_in_file)} }, ++#ifndef SVEN_OLA_UNBLOAT + { .name = "dns-server", .set_plugin_parameter = &set_nameservice_server, .data = &my_forwarders, .addon = {NAME_FORWARDER} }, ++#endif /* SVEN_OLA_UNBLOAT */ + { .name = "name", .set_plugin_parameter = &set_nameservice_name, .data = &my_names, .addon = {NAME_HOST} }, + { .name = "service", .set_plugin_parameter = &set_nameservice_name, .data = &my_services, .addon = {NAME_SERVICE} }, + { .name = "mac", .set_plugin_parameter = &set_nameservice_name, .data = &my_macs, .addon = {NAME_MACADDR} }, +@@ -381,16 +408,20 @@ + name->ip = olsr_cnf->main_addr; + } + } ++#ifndef SVEN_OLA_UNBLOAT + for (name = my_forwarders; name != NULL; name = name->next) { + if (name->ip.v4.s_addr == 0) { + OLSR_PRINTF(2, "NAME PLUGIN: insert main addr for name %s \n", name->name); + name->ip = olsr_cnf->main_addr; + } + } ++#endif /* SVEN_OLA_UNBLOAT */ + + //check if entries I want to announce myself are valid and allowed + my_names = remove_nonvalid_names_from_list(my_names, NAME_HOST); ++#ifndef SVEN_OLA_UNBLOAT + my_forwarders = remove_nonvalid_names_from_list(my_forwarders, NAME_FORWARDER); ++#endif /* SVEN_OLA_UNBLOAT */ + my_services = remove_nonvalid_names_from_list(my_services, NAME_SERVICE); + my_macs = remove_nonvalid_names_from_list(my_macs, NAME_MACADDR); + +@@ -463,12 +494,16 @@ + free_name_entry_list(&my_names); + free_name_entry_list(&my_services); + free_name_entry_list(&my_macs); ++#ifndef SVEN_OLA_UNBLOAT + free_name_entry_list(&my_forwarders); ++#endif /* SVEN_OLA_UNBLOAT */ + + free_all_list_entries(name_list); + free_all_list_entries(service_list); + free_all_list_entries(mac_list); ++#ifndef SVEN_OLA_UNBLOAT + free_all_list_entries(forwarder_list); ++#endif /* SVEN_OLA_UNBLOAT */ + free_all_list_entries(latlon_list); + + olsr_stop_timer(write_file_timer); +@@ -511,7 +546,9 @@ + { + write_file_timer = NULL; + ++#ifndef SVEN_OLA_UNBLOAT + write_resolv_file(); /* if forwarder_table_changed */ ++#endif /* SVEN_OLA_UNBLOAT */ + write_hosts_file(); /* if name_table_changed */ + write_services_file(OLSR_FALSE); /* if service_table_changed */ + write_services_file(OLSR_TRUE); /* if mac_table_changed */ +@@ -693,11 +730,13 @@ + pos = create_packet((struct name *)pos, my_name); + i++; + } ++#ifndef SVEN_OLA_UNBLOAT + // forwarders + for (my_name = my_forwarders; my_name != NULL; my_name = my_name->next) { + pos = create_packet((struct name *)pos, my_name); + i++; + } ++#endif /* SVEN_OLA_UNBLOAT */ + // services + for (my_name = my_services; my_name != NULL; my_name = my_name->next) { + pos = create_packet((struct name *)pos, my_name); +@@ -880,9 +919,11 @@ + case NAME_HOST: + insert_new_name_in_list(originator, name_list, from_packet, &name_table_changed, vtime); + break; ++#ifndef SVEN_OLA_UNBLOAT + case NAME_FORWARDER: + insert_new_name_in_list(originator, forwarder_list, from_packet, &forwarder_table_changed, vtime); + break; ++#endif /* SVEN_OLA_UNBLOAT */ + case NAME_SERVICE: + insert_new_name_in_list(originator, service_list, from_packet, &service_table_changed, vtime); + break; +@@ -901,9 +942,11 @@ + pos += sizeof(struct name); + pos += 1 + ((ntohs(from_packet->len) - 1) | 3); + } ++#ifdef DEBUG + if (i != 0) + OLSR_PRINTF(4, "NAME PLUGIN: Lost %d entries in received packet due to length inconsistency (%s)\n", i, + olsr_ip_to_string(&strbuf, originator)); ++#endif + } + + /** +@@ -1120,6 +1163,7 @@ + #endif + name_table_changed = OLSR_FALSE; + ++#ifndef SVEN_OLA_UNBLOAT + // Executes my_name_change_script after writing the hosts file + if (my_name_change_script[0] != '\0') { + if (system(my_name_change_script) != -1) { +@@ -1128,6 +1172,7 @@ + OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on hosts change\n", my_name_change_script); + } + } ++#endif /* SVEN_OLA_UNBLOAT */ + } + + /** +@@ -1193,6 +1238,7 @@ + + fclose(file); + if (writemacs) { ++#ifndef SVEN_OLA_UNBLOAT + // Executes my_macs_change_script after writing the macs file + if (my_macs_change_script[0] != '\0') { + if (system(my_macs_change_script) != -1) { +@@ -1201,9 +1247,11 @@ + OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on mac change\n", my_macs_change_script); + } + } ++#endif /* SVEN_OLA_UNBLOAT */ + mac_table_changed = OLSR_FALSE; + } + else { ++#ifndef SVEN_OLA_UNBLOAT + // Executes my_services_change_script after writing the services file + if (my_services_change_script[0] != '\0') { + if (system(my_services_change_script) != -1) { +@@ -1212,6 +1260,7 @@ + OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on service change\n", my_services_change_script); + } + } ++#endif /* SVEN_OLA_UNBLOAT */ + service_table_changed = OLSR_FALSE; + } + } +@@ -1222,6 +1271,7 @@ + * fresh entries are at the beginning of the array and + * the best entry is at the end of the array. + */ ++#ifndef SVEN_OLA_UNBLOAT + static void + select_best_nameserver(struct rt_entry **rt) + { +@@ -1253,11 +1303,13 @@ + } + } + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + * write the 3 best upstream DNS servers to resolv.conf file + * best means the 3 with the best etx value in routing table + */ ++#ifndef SVEN_OLA_UNBLOAT + void + write_resolv_file(void) + { +@@ -1341,6 +1393,7 @@ + fclose(resolv); + forwarder_table_changed = OLSR_FALSE; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + * completely free a list of name_entries +@@ -1359,9 +1412,11 @@ + case NAME_HOST: + name_table_changed = OLSR_TRUE; + break; ++#ifndef SVEN_OLA_UNBLOAT + case NAME_FORWARDER: + forwarder_table_changed = OLSR_TRUE; + break; ++#endif /* SVEN_OLA_UNBLOAT */ + case NAME_SERVICE: + service_table_changed = OLSR_TRUE; + break; +@@ -1459,8 +1514,14 @@ + * these are then used by allowed_hostname_or_ip_in_service + * see regexec(3) for more infos */ + if (!is_service_wellformed(service_line)) { ++#ifdef SVEN_OLA_UNBLOAT ++ olsr_printf(1, "NAME PLUGIN: %s: Not 'x://y:z/|tcp|Text'\n", service_line); ++#endif /* SVEN_OLA_UNBLOAT */ + return OLSR_FALSE; + } else if (!allowed_hostname_or_ip_in_service(service_line, &(regmatch_t_service[1]))) { ++#ifdef SVEN_OLA_UNBLOAT ++ olsr_printf(1, "NAME PLUGIN: %s: IP/Addr not yours and not HNA\n", service_line); ++#endif /* SVEN_OLA_UNBLOAT */ + return OLSR_FALSE; + } + +diff -Nur olsrd-0.5.6-r3.orig/Makefile.inc olsrd-0.5.6-r3/Makefile.inc +--- olsrd-0.5.6-r3.orig/Makefile.inc 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/Makefile.inc 2008-12-03 10:01:07.000000000 +0100 +@@ -204,6 +204,10 @@ + $(warning Use CPPFLAGS instead of DEFINES for -D) + endif + ++ifeq ($(SVEN_OLA_UNBLOAT),1) ++CPPFLAGS += -DSVEN_OLA_UNBLOAT -DNODEBUG ++endif ++ + TAGFILE ?= src/TAGS + + help: +diff -Nur olsrd-0.5.6-r3.orig/src/apm.h olsrd-0.5.6-r3/src/apm.h +--- olsrd-0.5.6-r3.orig/src/apm.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/apm.h 2008-12-03 10:01:07.000000000 +0100 +@@ -41,6 +41,7 @@ + + #ifndef _OLSR_APM + #define _OLSR_APM ++#ifndef SVEN_OLA_UNBLOAT + + /* + * Interface to OS dependent power management information +@@ -69,6 +70,7 @@ + int apm_read(struct olsr_apm_info *); + + #endif ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/cfgparser/local.mk olsrd-0.5.6-r3/src/cfgparser/local.mk +--- olsrd-0.5.6-r3.orig/src/cfgparser/local.mk 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/cfgparser/local.mk 2008-12-03 10:01:07.000000000 +0100 +@@ -41,8 +41,13 @@ + C=$(if $(CFGDIR),$(CFGDIR)/) + + # add the variables as we may have others already there ++ifeq ($(SVEN_OLA_UNBLOAT),1) ++SRCS += $(foreach file,olsrd_conf oparse oscan,$(C)$(file).c) ++OBJS += $(foreach file,olsrd_conf oparse oscan,$(C)$(file).o) ++else + SRCS += $(foreach file,olsrd_conf oparse oscan cfgfile_gen,$(C)$(file).c) + OBJS += $(foreach file,olsrd_conf oparse oscan cfgfile_gen,$(C)$(file).o) ++endif + HDRS += $(foreach file,olsrd_conf oparse,$(C)$(file).h) + + $(C)oscan.c: $(C)oscan.lex $(C)Makefile +diff -Nur olsrd-0.5.6-r3.orig/src/cfgparser/olsrd_conf.c olsrd-0.5.6-r3/src/cfgparser/olsrd_conf.c +--- olsrd-0.5.6-r3.orig/src/cfgparser/olsrd_conf.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/cfgparser/olsrd_conf.c 2008-12-03 10:01:07.000000000 +0100 +@@ -81,11 +81,13 @@ + } + + if ((cnf = olsrd_parse_cnf(argv[1])) != NULL) { ++#ifndef SVEN_OLA_UNBLOAT + if ((argc > 2) && (!strcmp(argv[2], "-print"))) { + olsrd_print_cnf(cnf); + olsrd_write_cnf(cnf, "./out.conf"); + } else + printf("Use -print to view parsed values\n"); ++#endif /* SVEN_OLA_UNBLOAT */ + printf("Configfile parsed OK\n"); + } else { + printf("Failed parsing \"%s\"\n", argv[1]); +@@ -152,7 +154,9 @@ + /* set various stuff */ + in->configured = OLSR_FALSE; + in->interf = NULL; ++#ifndef SVEN_OLA_UNBLOAT + in->host_emul = OLSR_FALSE; ++#endif /* SVEN_OLA_UNBLOAT */ + } + return olsr_cnf; + } +@@ -389,7 +393,9 @@ + + cnf->debug_level = DEF_DEBUGLVL; + cnf->no_fork = OLSR_FALSE; ++#ifndef SVEN_OLA_UNBLOAT + cnf->host_emul = OLSR_FALSE; ++#endif /* SVEN_OLA_UNBLOAT */ + cnf->ip_version = AF_INET; + cnf->ipsize = sizeof(struct in_addr); + cnf->maxplen = 32; +@@ -398,7 +404,9 @@ + cnf->rttable = 254; + cnf->rttable_default = 0; + cnf->willingness_auto = DEF_WILL_AUTO; ++#ifndef SVEN_OLA_UNBLOAT + cnf->ipc_connections = DEF_IPC_CONNECTIONS; ++#endif /* SVEN_OLA_UNBLOAT */ + cnf->fib_metric = DEF_FIB_METRIC; + + cnf->use_hysteresis = DEF_USE_HYST; +@@ -477,6 +485,7 @@ + + } + ++#ifndef SVEN_OLA_UNBLOAT + void + olsrd_print_cnf(struct olsrd_config *cnf) + { +@@ -613,6 +622,7 @@ + } + } + } ++#endif /* SVEN_OLA_UNBLOAT */ + + #if defined WIN32 + struct ioinfo { +diff -Nur olsrd-0.5.6-r3.orig/src/cfgparser/oparse.y olsrd-0.5.6-r3/src/cfgparser/oparse.y +--- olsrd-0.5.6-r3.orig/src/cfgparser/oparse.y 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/cfgparser/oparse.y 2008-12-03 10:01:07.000000000 +0100 +@@ -176,7 +176,6 @@ + %token TOK_RTTABLE + %token TOK_RTTABLE_DEFAULT + %token TOK_WILLINGNESS +-%token TOK_IPCCON + %token TOK_FIBMETRIC + %token TOK_USEHYST + %token TOK_HYSTSCALE +@@ -199,7 +198,6 @@ + + %token TOK_HOSTLABEL + %token TOK_NETLABEL +-%token TOK_MAXIPC + + %token TOK_IP4BROADCAST + %token TOK_IP6ADDRTYPE +@@ -258,7 +256,6 @@ + + block: TOK_HNA4 hna4body + | TOK_HNA6 hna6body +- | TOK_IPCCON ipcbody + | ifblock ifbody + | plblock plbody + ; +@@ -283,18 +280,6 @@ + | ihna6entry + ; + +-ipcbody: TOK_OPEN ipcstmts TOK_CLOSE +-; +- +-ipcstmts: | ipcstmts ipcstmt +-; +- +-ipcstmt: vcomment +- | imaxipc +- | ipchost +- | ipcnet +-; +- + ifblock: ifstart ifnicks + ; + +@@ -335,77 +320,6 @@ + | vcomment + ; + +-imaxipc: TOK_MAXIPC TOK_INTEGER +-{ +- olsr_cnf->ipc_connections = $2->integer; +- free($2); +-} +-; +- +-ipchost: TOK_HOSTLABEL TOK_IP4_ADDR +-{ +- union olsr_ip_addr ipaddr; +- PARSER_DEBUG_PRINTF("\tIPC host: %s\n", $2->string); +- +- if (inet_aton($2->string, &ipaddr.v4) == 0) { +- fprintf(stderr, "Failed converting IP address IPC %s\n", $2->string); +- YYABORT; +- } +- +- ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_cnf->maxplen); +- +- free($2->string); +- free($2); +-} +-; +- +-ipcnet: TOK_NETLABEL TOK_IP4_ADDR TOK_IP4_ADDR +-{ +- union olsr_ip_addr ipaddr, netmask; +- +- PARSER_DEBUG_PRINTF("\tIPC net: %s/%s\n", $2->string, $3->string); +- +- if (inet_pton(AF_INET, $2->string, &ipaddr.v4) == 0) { +- fprintf(stderr, "Failed converting IP net IPC %s\n", $2->string); +- YYABORT; +- } +- +- if (inet_pton(AF_INET, $3->string, &netmask.v4) == 0) { +- fprintf(stderr, "Failed converting IP mask IPC %s\n", $3->string); +- YYABORT; +- } +- +- ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, olsr_netmask_to_prefix(&netmask)); +- +- free($2->string); +- free($2); +- free($3->string); +- free($3); +-} +- | TOK_NETLABEL TOK_IP4_ADDR TOK_SLASH TOK_INTEGER +-{ +- union olsr_ip_addr ipaddr; +- +- PARSER_DEBUG_PRINTF("\tIPC net: %s/%s\n", $2->string, $3->string); +- +- if (inet_pton(AF_INET, $2->string, &ipaddr.v4) == 0) { +- fprintf(stderr, "Failed converting IP net IPC %s\n", $2->string); +- YYABORT; +- } +- +- if ($4->integer > olsr_cnf->maxplen) { +- fprintf(stderr, "ipcnet: Prefix len %u > %d is not allowed!\n", $4->integer, olsr_cnf->maxplen); +- YYABORT; +- } +- +- ip_prefix_list_add(&olsr_cnf->ipc_nets, &ipaddr, $4->integer); +- +- free($2->string); +- free($2); +- free($4); +-} +-; +- + iifweight: TOK_IFWEIGHT TOK_INTEGER + { + int ifcnt = ifs_in_curr_cfg; +diff -Nur olsrd-0.5.6-r3.orig/src/cfgparser/oscan.lex olsrd-0.5.6-r3/src/cfgparser/oscan.lex +--- olsrd-0.5.6-r3.orig/src/cfgparser/oscan.lex 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/cfgparser/oscan.lex 2008-12-03 10:01:07.000000000 +0100 +@@ -253,11 +253,6 @@ + return TOK_NETLABEL; + } + +-"MaxConnections" { +- yylval = NULL; +- return TOK_MAXIPC; +-} +- + "DebugLevel" { + yylval = NULL; + return TOK_DEBUGLEVEL; +@@ -323,11 +318,6 @@ + return TOK_WILLINGNESS; + } + +-"IpcConnect" { +- yylval = NULL; +- return TOK_IPCCON; +-} +- + "FIBMetric" { + yylval = NULL; + return TOK_FIBMETRIC; +diff -Nur olsrd-0.5.6-r3.orig/src/defs.h olsrd-0.5.6-r3/src/defs.h +--- olsrd-0.5.6-r3.orig/src/defs.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/defs.h 2008-12-03 10:01:07.000000000 +0100 +@@ -190,6 +190,8 @@ + */ + unsigned long olsr_times(void); + ++#ifndef SVEN_OLA_UNBLOAT ++ + /* + *IPC functions + *These are moved to a plugin soon +@@ -207,6 +209,7 @@ + int ipc_output(struct olsr *); + + #endif ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/duplicate_set.c olsrd-0.5.6-r3/src/duplicate_set.c +--- olsrd-0.5.6-r3.orig/src/duplicate_set.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/duplicate_set.c 2008-12-03 10:01:07.000000000 +0100 +@@ -174,6 +174,7 @@ + return OLSR_FALSE; /* no duplicate */ + } + ++#ifndef SVEN_OLA_UNBLOAT + void + olsr_print_duplicate_table(void) + { +@@ -192,6 +193,7 @@ + } OLSR_FOR_ALL_DUP_ENTRIES_END(entry); + #endif + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/hna_set.c olsrd-0.5.6-r3/src/hna_set.c +--- olsrd-0.5.6-r3.orig/src/hna_set.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/hna_set.c 2008-12-03 10:01:07.000000000 +0100 +@@ -279,6 +279,7 @@ + * + *@return nada + */ ++#ifndef SVEN_OLA_UNBLOAT + void + olsr_print_hna_set(void) + { +@@ -320,6 +321,7 @@ + } + #endif + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + *Process incoming HNA message. +diff -Nur olsrd-0.5.6-r3.orig/src/interfaces.c olsrd-0.5.6-r3/src/interfaces.c +--- olsrd-0.5.6-r3.orig/src/interfaces.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/interfaces.c 2008-12-03 10:01:07.000000000 +0100 +@@ -93,12 +93,16 @@ + OLSR_PRINTF(1, "\n ---- Interface configuration ---- \n\n"); + /* Run trough all interfaces immedeatly */ + for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) { ++#ifndef SVEN_OLA_UNBLOAT + if (!tmp_if->host_emul) { + if (!olsr_cnf->host_emul) /* XXX: TEMPORARY! */ ++#endif /* SVEN_OLA_UNBLOAT */ + chk_if_up(tmp_if, 1); ++#ifndef SVEN_OLA_UNBLOAT + } else { + add_hemu_if(tmp_if); + } ++#endif /* SVEN_OLA_UNBLOAT */ + } + + /* Kick a periodic timer for the network interface update function */ +@@ -244,7 +248,11 @@ + *@return nada + */ + struct olsr_if * ++#ifdef SVEN_OLA_UNBLOAT ++queue_if(const char *name) ++#else /* SVEN_OLA_UNBLOAT */ + queue_if(const char *name, int hemu) ++#endif /* SVEN_OLA_UNBLOAT */ + { + struct olsr_if *interf_n = olsr_cnf->interfaces; + size_t name_size; +@@ -268,7 +276,9 @@ + interf_n->interf = NULL; + interf_n->configured = 0; + ++#ifndef SVEN_OLA_UNBLOAT + interf_n->host_emul = hemu ? OLSR_TRUE : OLSR_FALSE; ++#endif /* SVEN_OLA_UNBLOAT */ + + strscpy(interf_n->name, name, name_size); + interf_n->next = olsr_cnf->interfaces; +diff -Nur olsrd-0.5.6-r3.orig/src/interfaces.h olsrd-0.5.6-r3/src/interfaces.h +--- olsrd-0.5.6-r3.orig/src/interfaces.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/interfaces.h 2008-12-03 10:01:07.000000000 +0100 +@@ -196,7 +196,12 @@ + + struct interface *if_ifwithindex(const int if_index); + +-struct olsr_if *queue_if(const char *, int); ++struct olsr_if * ++#ifdef SVEN_OLA_UNBLOAT ++ queue_if(const char *); ++#else /* SVEN_OLA_UNBLOAT */ ++ queue_if(const char *, int); ++#endif /* SVEN_OLA_UNBLOAT */ + + int add_ifchgf(int (*f) (struct interface *, int)); + +diff -Nur olsrd-0.5.6-r3.orig/src/ipcalc.c olsrd-0.5.6-r3/src/ipcalc.c +--- olsrd-0.5.6-r3.orig/src/ipcalc.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/ipcalc.c 2008-12-03 10:01:07.000000000 +0100 +@@ -122,6 +122,7 @@ + return prefix; + } + ++#ifndef SVEN_OLA_UNBLOAT + const char * + olsr_ip_prefix_to_string(const struct olsr_ip_prefix *prefix) + { +@@ -148,6 +149,7 @@ + } + return rv; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* see if the ipaddr is in the net. That is equivalent to the fact that the net part + * of both are equal. So we must compare the first bits. +diff -Nur olsrd-0.5.6-r3.orig/src/ipcalc.h olsrd-0.5.6-r3/src/ipcalc.h +--- olsrd-0.5.6-r3.orig/src/ipcalc.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/ipcalc.h 2008-12-03 10:01:07.000000000 +0100 +@@ -146,7 +146,9 @@ + return inet_ntop(olsr_cnf->ip_version, addr, buf->buf, sizeof(buf->buf)); + } + ++#ifndef SVEN_OLA_UNBLOAT + const char *olsr_ip_prefix_to_string(const struct olsr_ip_prefix *prefix); ++#endif /* SVEN_OLA_UNBLOAT */ + + static INLINE const char * + sockaddr4_to_string(struct ipaddr_str *const buf, const struct sockaddr *const addr) +diff -Nur olsrd-0.5.6-r3.orig/src/ipc_frontend.c olsrd-0.5.6-r3/src/ipc_frontend.c +--- olsrd-0.5.6-r3.orig/src/ipc_frontend.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/ipc_frontend.c 2008-12-03 10:01:07.000000000 +0100 +@@ -46,6 +46,7 @@ + * + */ + ++#ifndef SVEN_OLA_UNBLOAT + #include "ipc_frontend.h" + #include "link_set.h" + #include "olsr.h" +@@ -423,6 +424,7 @@ + + return 1; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/ipc_frontend.h olsrd-0.5.6-r3/src/ipc_frontend.h +--- olsrd-0.5.6-r3.orig/src/ipc_frontend.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/ipc_frontend.h 2008-12-03 10:01:07.000000000 +0100 +@@ -48,6 +48,7 @@ + + #ifndef _OLSR_IPC + #define _OLSR_IPC ++#ifndef SVEN_OLA_UNBLOAT + + #include + #include +@@ -103,6 +104,7 @@ + int ipc_route_send_rtentry(const union olsr_ip_addr *, const union olsr_ip_addr *, int, int, const char *); + + #endif ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/link_set.c olsrd-0.5.6-r3/src/link_set.c +--- olsrd-0.5.6-r3.orig/src/link_set.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/link_set.c 2008-12-03 10:01:07.000000000 +0100 +@@ -746,6 +746,7 @@ + return ret; + } + ++#ifndef SVEN_OLA_UNBLOAT + void + olsr_print_link_set(void) + { +@@ -767,6 +768,7 @@ + } OLSR_FOR_ALL_LINK_ENTRIES_END(walker); + #endif + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * called for every LQ HELLO message. +diff -Nur olsrd-0.5.6-r3.orig/src/linux/apm.c olsrd-0.5.6-r3/src/linux/apm.c +--- olsrd-0.5.6-r3.orig/src/linux/apm.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/linux/apm.c 2008-12-03 10:01:07.000000000 +0100 +@@ -44,6 +44,7 @@ + * Acpi-Power Enlightenment epplet + */ + ++#ifndef SVEN_OLA_UNBLOAT + #include "apm.h" + #include "defs.h" + #include +@@ -348,6 +349,7 @@ + /* No battery found */ + return -1; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/linux/kernel_routes.c olsrd-0.5.6-r3/src/linux/kernel_routes.c +--- olsrd-0.5.6-r3.orig/src/linux/kernel_routes.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/linux/kernel_routes.c 2008-12-03 10:01:07.000000000 +0100 +@@ -144,10 +144,12 @@ + h = NLMSG_NEXT(h, ret); + } + } ++#ifndef SVEN_OLA_UNBLOAT + if (0 <= ret && olsr_cnf->ipc_connections > 0) { + ipc_route_send_rtentry(&rt->rt_dst.prefix, &nexthop->gateway, metric, RTM_NEWROUTE == cmd, + if_ifwithindex_name(nexthop->iif_index)); + } ++#endif /* SVEN_OLA_UNBLOAT */ + } + return ret; + } +diff -Nur olsrd-0.5.6-r3.orig/src/linux/net.c olsrd-0.5.6-r3/src/linux/net.c +--- olsrd-0.5.6-r3.orig/src/linux/net.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/linux/net.c 2008-12-03 10:01:07.000000000 +0100 +@@ -69,8 +69,10 @@ + #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ + + /* The original state of the IP forwarding proc entry */ ++#ifndef SVEN_OLA_UNBLOAT + static char orig_fwd_state; + static char orig_global_redirect_state; ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + *Bind a socket to a device +@@ -91,6 +93,8 @@ + return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, dev_name, strlen(dev_name) + 1); + } + ++#ifndef SVEN_OLA_UNBLOAT ++ + /** + *Enable IP forwarding. + *Just writing "1" to the /proc/sys/net/ipv4/ip_forward +@@ -110,6 +114,9 @@ + const char *const procfile = version == AF_INET ? "/proc/sys/net/ipv4/ip_forward" : "/proc/sys/net/ipv6/conf/all/forwarding"; + + if ((proc_fwd = fopen(procfile, "r")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + /* IPv4 */ + if (version == AF_INET) + fprintf(stderr, +@@ -122,6 +129,7 @@ + procfile); + + sleep(3); ++#endif + return 0; + } + +@@ -131,9 +139,13 @@ + OLSR_PRINTF(3, "\nIP forwarding is enabled on this system\n"); + } else { + if ((proc_fwd = fopen(procfile, "w")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\n", procfile); + fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP forwarding is enabeled!\n\n"); + sleep(3); ++#endif + return 0; + } else { + syslog(LOG_INFO, "Writing \"1\" to %s\n", procfile); +@@ -154,11 +166,15 @@ + return -1; + + if ((proc_redirect = fopen(procfile, "r")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, + "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n", + procfile); + + sleep(3); ++#endif + return -1; + } + orig_global_redirect_state = fgetc(proc_redirect); +@@ -168,9 +184,13 @@ + return 0; + + if ((proc_redirect = fopen(procfile, "w")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\n", procfile); + fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n"); + sleep(3); ++#endif + return 0; + } + syslog(LOG_INFO, "Writing \"0\" to %s", procfile); +@@ -196,19 +216,27 @@ + snprintf(procfile, sizeof(procfile), REDIRECT_PROC, if_name); + + if ((proc_redirect = fopen(procfile, "r")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, + "WARNING! Could not open the %s file to check/disable ICMP redirects!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that ICMP redirects are disabled!\n\n", + procfile); + sleep(3); ++#endif + return 0; + } + iface->nic_state.redirect = fgetc(proc_redirect); + fclose(proc_redirect); + + if ((proc_redirect = fopen(procfile, "w")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\n", procfile); + fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that ICMP redirect is disabeled!\n\n"); + sleep(3); ++#endif + return 0; + } + syslog(LOG_INFO, "Writing \"0\" to %s", procfile); +@@ -234,20 +262,28 @@ + sprintf(procfile, SPOOF_PROC, if_name); + + if ((proc_spoof = fopen(procfile, "r")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, + "WARNING! Could not open the %s file to check/disable the IP spoof filter!\nAre you using the procfile filesystem?\nDoes your system support IPv4?\nI will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabled!\n\n", + procfile); + + sleep(3); ++#endif + return 0; + } + iface->nic_state.spoof = fgetc(proc_spoof); + fclose(proc_spoof); + + if ((proc_spoof = fopen(procfile, "w")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\n", procfile); + fprintf(stderr, "I will continue(in 3 sec) - but you should mannually ensure that IP spoof filtering is disabeled!\n\n"); + sleep(3); ++#endif + return 0; + } + syslog(LOG_INFO, "Writing \"0\" to %s", procfile); +@@ -272,7 +308,11 @@ + FILE *proc_fd; + + if ((proc_fd = fopen(procfile, "w")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile); ++#endif + } else { + syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_fwd_state); + fputc(orig_fwd_state, proc_fd); +@@ -287,7 +327,11 @@ + FILE *proc_fd; + + if ((proc_fd = fopen(procfile, "w")) == NULL) { ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile); ++#endif + } else { + syslog(LOG_INFO, "Resetting %s to %c\n", procfile, orig_global_redirect_state); + fputc(orig_global_redirect_state, proc_fd); +@@ -311,7 +355,11 @@ + snprintf(procfile, sizeof(procfile), REDIRECT_PROC, ifs->int_name); + + if ((proc_fd = fopen(procfile, "w")) == NULL) ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile); ++#endif + else { + syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.redirect); + +@@ -324,7 +372,11 @@ + /* Generate the procfile name */ + sprintf(procfile, SPOOF_PROC, ifs->int_name); + if ((proc_fd = fopen(procfile, "w")) == NULL) ++#ifdef SVEN_OLA_UNBLOAT_OLD ++ perror(procfile); ++#else + fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procfile); ++#endif + else { + syslog(LOG_INFO, "Resetting %s to %c\n", procfile, ifs->nic_state.spoof); + +@@ -372,6 +424,8 @@ + return sock; + } + ++#endif /* SVEN_OLA_UNBLOAT */ ++ + /** + *Creates a nonblocking broadcast socket. + *@param sa sockaddr struct. Used for bind(2). +diff -Nur olsrd-0.5.6-r3.orig/src/lq_plugin.c olsrd-0.5.6-r3/src/lq_plugin.c +--- olsrd-0.5.6-r3.orig/src/lq_plugin.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/lq_plugin.c 2008-12-03 10:01:07.000000000 +0100 +@@ -67,12 +67,18 @@ + init_lq_handler_tree(void) + { + avl_init(&lq_handler_tree, &avl_strcasecmp); ++#ifndef SVEN_OLA_UNBLOAT + register_lq_handler(&lq_etx_float_handler, LQ_ALGORITHM_ETX_FLOAT_NAME); + register_lq_handler(&lq_etx_fpm_handler, LQ_ALGORITHM_ETX_FPM_NAME); ++#endif /* SVEN_OLA_UNBLOAT */ + register_lq_handler(&lq_etx_ff_handler, LQ_ALGORITHM_ETX_FF_NAME); ++#ifndef SVEN_OLA_UNBLOAT + if (activate_lq_handler(olsr_cnf->lq_algorithm)) { + activate_lq_handler(LQ_ALGORITHM_ETX_FPM_NAME); + } ++#else /* SVEN_OLA_UNBLOAT */ ++ activate_lq_handler(LQ_ALGORITHM_ETX_FF_NAME); ++#endif /* SVEN_OLA_UNBLOAT */ + } + + /* +@@ -417,7 +423,11 @@ + * @return pointer to hello_neighbor + */ + struct hello_neighbor * ++#ifndef SVEN_OLA_UNBLOAT + olsr_malloc_hello_neighbor(const char *id) ++#else /* SVEN_OLA_UNBLOAT */ ++olsr_malloc_hello_neighbor(const char *id __attribute__ ((unused))) ++#endif /* SVEN_OLA_UNBLOAT */ + { + struct hello_neighbor *h; + +@@ -439,7 +449,11 @@ + * @return pointer to tc_mpr_addr + */ + struct tc_mpr_addr * ++#ifndef SVEN_OLA_UNBLOAT + olsr_malloc_tc_mpr_addr(const char *id) ++#else /* SVEN_OLA_UNBLOAT */ ++olsr_malloc_tc_mpr_addr(const char *id __attribute__ ((unused))) ++#endif /* SVEN_OLA_UNBLOAT */ + { + struct tc_mpr_addr *t; + +@@ -461,7 +475,11 @@ + * @return pointer to lq_hello_neighbor + */ + struct lq_hello_neighbor * ++#ifndef SVEN_OLA_UNBLOAT + olsr_malloc_lq_hello_neighbor(const char *id) ++#else /* SVEN_OLA_UNBLOAT */ ++olsr_malloc_lq_hello_neighbor(const char *id __attribute__ ((unused))) ++#endif /* SVEN_OLA_UNBLOAT */ + { + struct lq_hello_neighbor *h; + +@@ -483,7 +501,11 @@ + * @return pointer to link_entry + */ + struct link_entry * ++#ifndef SVEN_OLA_UNBLOAT + olsr_malloc_link_entry(const char *id) ++#else /* SVEN_OLA_UNBLOAT */ ++olsr_malloc_link_entry(const char *id __attribute__ ((unused))) ++#endif /* SVEN_OLA_UNBLOAT */ + { + struct link_entry *h; + +diff -Nur olsrd-0.5.6-r3.orig/src/lq_plugin_default_float.c olsrd-0.5.6-r3/src/lq_plugin_default_float.c +--- olsrd-0.5.6-r3.orig/src/lq_plugin_default_float.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/lq_plugin_default_float.c 2008-12-03 10:01:07.000000000 +0100 +@@ -39,6 +39,7 @@ + * + */ + ++#ifndef SVEN_OLA_UNBLOAT + #include "tc_set.h" + #include "link_set.h" + #include "olsr_spf.h" +@@ -223,6 +224,7 @@ + + return buffer->buf; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/lq_plugin_default_float.h olsrd-0.5.6-r3/src/lq_plugin_default_float.h +--- olsrd-0.5.6-r3.orig/src/lq_plugin_default_float.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/lq_plugin_default_float.h 2008-12-03 10:01:07.000000000 +0100 +@@ -39,6 +39,7 @@ + * + */ + ++#ifndef SVEN_OLA_UNBLOAT + #ifndef LQ_PLUGIN_DEFAULT_H_ + #define LQ_PLUGIN_DEFAULT_H_ + +@@ -77,6 +78,7 @@ + extern struct lq_handler lq_etx_float_handler; + + #endif /*LQ_PLUGIN_DEFAULT_H_ */ ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/lq_plugin_default_fpm.c olsrd-0.5.6-r3/src/lq_plugin_default_fpm.c +--- olsrd-0.5.6-r3.orig/src/lq_plugin_default_fpm.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/lq_plugin_default_fpm.c 2008-12-03 10:01:07.000000000 +0100 +@@ -39,6 +39,7 @@ + * + */ + ++#ifndef SVEN_OLA_UNBLOAT + #include "tc_set.h" + #include "link_set.h" + #include "lq_plugin.h" +@@ -235,6 +236,7 @@ + snprintf(buffer->buf, sizeof(buffer->buf), "%.3f", (float)(cost) / LQ_FPM_LINKCOST_MULTIPLIER); + return buffer->buf; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/lq_plugin_default_fpm.h olsrd-0.5.6-r3/src/lq_plugin_default_fpm.h +--- olsrd-0.5.6-r3.orig/src/lq_plugin_default_fpm.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/lq_plugin_default_fpm.h 2008-12-03 10:01:07.000000000 +0100 +@@ -39,6 +39,7 @@ + * + */ + ++#ifndef SVEN_OLA_UNBLOAT + #ifndef LQ_ETX_FPM_ + #define LQ_ETX_FPM_ + +@@ -83,6 +84,7 @@ + extern struct lq_handler lq_etx_fpm_handler; + + #endif /*LQ_ETX_FPM_ */ ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/main.c olsrd-0.5.6-r3/src/main.c +--- olsrd-0.5.6-r3.orig/src/main.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/main.c 2008-12-03 10:01:07.000000000 +0100 +@@ -243,13 +243,17 @@ + /* + * Print configuration + */ ++#ifndef SVEN_OLA_UNBLOAT + if (olsr_cnf->debug_level > 1) { + olsrd_print_cnf(olsr_cnf); + } ++#endif /* SVEN_OLA_UNBLOAT */ + #ifndef WIN32 ++#ifndef SVEN_OLA_UNBLOAT + /* Disable redirects globally */ + disable_redirects_global(olsr_cnf->ip_version); + #endif ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * socket for ioctl calls +@@ -285,7 +289,9 @@ + /* + *enable ip forwarding on host + */ ++#ifndef SVEN_OLA_UNBLOAT + enable_ip_forwarding(olsr_cnf->ip_version); ++#endif /* SVEN_OLA_UNBLOAT */ + + /* Initialize parser */ + olsr_init_parser(); +@@ -303,6 +309,7 @@ + *Set up willingness/APM + */ + if (olsr_cnf->willingness_auto) { ++#ifndef SVEN_OLA_UNBLOAT + if (apm_init() < 0) { + OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT); + +@@ -311,10 +318,13 @@ + olsr_cnf->willingness_auto = 0; + olsr_cnf->willingness = WILL_DEFAULT; + } else { ++#endif /* SVEN_OLA_UNBLOAT */ + olsr_cnf->willingness = olsr_calculate_willingness(); + + OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int); ++#ifndef SVEN_OLA_UNBLOAT + } ++#endif /* SVEN_OLA_UNBLOAT */ + } + + /* Initialize net */ +@@ -342,9 +352,11 @@ + + /* Initialize the IPC socket */ + ++#ifndef SVEN_OLA_UNBLOAT + if (olsr_cnf->ipc_connections > 0) { + ipc_init(); + } ++#endif /* SVEN_OLA_UNBLOAT */ + /* Initialisation of different tables to be used. */ + olsr_init_tables(); + +@@ -450,9 +462,11 @@ + OLSR_PRINTF(1, "Closing sockets...\n"); + + /* front-end IPC socket */ ++#ifndef SVEN_OLA_UNBLOAT + if (olsr_cnf->ipc_connections > 0) { + shutdown_ipc(); + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* OLSR sockets */ + for (ifn = ifnet; ifn; ifn = ifn->int_next) +@@ -462,7 +476,9 @@ + olsr_close_plugins(); + + /* Reset network settings */ ++#ifndef SVEN_OLA_UNBLOAT + restore_settings(olsr_cnf->ip_version); ++#endif /* SVEN_OLA_UNBLOAT */ + + /* ioctl socket */ + close(olsr_cnf->ioctl_s); +@@ -498,7 +514,11 @@ + "usage: olsrd [-f ] [ -i interface1 interface2 ... ]\n" + " [-d ] [-ipv6] [-multi ]\n" + " [-lql ] [-lqw ] [-lqnt ]\n" ++#ifdef SVEN_OLA_UNBLOAT ++ " [-bcast ] [-delgw] (Note: no -ipc,-dispin,-dispout)\n" ++#else /* SVEN_OLA_UNBLOAT */ + " [-bcast ] [-ipc] [-dispin] [-dispout] [-delgw]\n" ++#endif /* SVEN_OLA_UNBLOAT */ + " [-hint ] [-tcint ]\n" + " [-midint ] [-hnaint ]\n" + " [-T ] [-nofork] [-hemu ]\n" " [-lql ] [-lqa ]\n"); +@@ -662,12 +682,20 @@ + olsr_exit(__func__, EXIT_FAILURE); + } + printf("Queuing if %s\n", *argv); ++#ifdef SVEN_OLA_UNBLOAT ++ queue_if(*argv); ++#else /* SVEN_OLA_UNBLOAT */ + queue_if(*argv, OLSR_FALSE); ++#endif /* SVEN_OLA_UNBLOAT */ + + while ((argc - 1) && (argv[1][0] != '-')) { + NEXT_ARG; + printf("Queuing if %s\n", *argv); ++#ifdef SVEN_OLA_UNBLOAT ++ queue_if(*argv); ++#else /* SVEN_OLA_UNBLOAT */ + queue_if(*argv, OLSR_FALSE); ++#endif /* SVEN_OLA_UNBLOAT */ + } + + continue; +@@ -729,7 +757,7 @@ + sscanf(*argv, "%f", &cnf->pollrate); + continue; + } +- ++#ifndef SVEN_OLA_UNBLOAT + /* + * Should we display the contents of packages beeing sent? + */ +@@ -753,6 +781,7 @@ + cnf->ipc_connections = 1; + continue; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * IPv6 multicast addr +@@ -770,7 +799,7 @@ + + continue; + } +- ++#ifndef SVEN_OLA_UNBLOAT + /* + * Host emulation + */ +@@ -798,6 +827,7 @@ + + continue; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Delete possible default GWs +diff -Nur olsrd-0.5.6-r3.orig/src/neighbor_table.c olsrd-0.5.6-r3/src/neighbor_table.c +--- olsrd-0.5.6-r3.orig/src/neighbor_table.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/neighbor_table.c 2008-12-03 10:01:07.000000000 +0100 +@@ -362,6 +362,7 @@ + * + *@return nada + */ ++#ifndef SVEN_OLA_UNBLOAT + void + olsr_print_neighbor_table(void) + { +@@ -391,6 +392,7 @@ + } + #endif + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/net_olsr.c olsrd-0.5.6-r3/src/net_olsr.c +--- olsrd-0.5.6-r3.orig/src/net_olsr.c 2008-12-03 10:01:07.000000000 +0100 ++++ olsrd-0.5.6-r3/src/net_olsr.c 2008-12-03 10:01:07.000000000 +0100 +@@ -44,7 +44,9 @@ + #include "log.h" + #include "olsr.h" + #include "net_os.h" ++#ifndef SVEN_OLA_UNBLOAT + #include "print_packet.h" ++#endif /* SVEN_OLA_UNBLOAT */ + #include "link_set.h" + #include "lq_packet.h" + +@@ -385,8 +387,10 @@ + *if the -dispout option was given + *we print the content of the packets + */ ++#ifndef SVEN_OLA_UNBLOAT + if (disp_pack_out) + print_olsr_serialized_packet(stdout, (union olsr_packet *)ifp->netbuf.buff, ifp->netbuf.pending, &ifp->ip_addr); ++#endif /* SVEN_OLA_UNBLOAT */ + + if (olsr_cnf->ip_version == AF_INET) { + /* IP version 4 */ +@@ -400,12 +404,16 @@ + /* IP version 6 */ + if (olsr_sendto(ifp->olsr_socket, ifp->netbuf.buff, ifp->netbuf.pending, MSG_DONTROUTE, (struct sockaddr *)sin6, sizeof(*sin6)) + < 0) { ++#ifndef SVEN_OLA_UNBLOAT + struct ipaddr_str buf; ++#endif /* SVEN_OLA_UNBLOAT */ + perror("sendto(v6)"); + olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m"); ++#ifndef SVEN_OLA_UNBLOAT + fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_index); + fprintf(stderr, "To: %s (size: %u)\n", ip6_to_string(&buf, &sin6->sin6_addr), (unsigned int)sizeof(*sin6)); + fprintf(stderr, "Outputsize: %d\n", ifp->netbuf.pending); ++#endif /* SVEN_OLA_UNBLOAT */ + retval = -1; + } + } +diff -Nur olsrd-0.5.6-r3.orig/src/olsr.c olsrd-0.5.6-r3/src/olsr.c +--- olsrd-0.5.6-r3.orig/src/olsr.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/olsr.c 2008-12-03 10:01:07.000000000 +0100 +@@ -149,7 +149,9 @@ + return; + + if (olsr_cnf->debug_level > 0 && olsr_cnf->clear_screen && isatty(1)) { ++#ifndef SVEN_OLA_UNBLOAT + clear_console(); ++#endif /* SVEN_OLA_UNBLOAT */ + printf(" *** %s (%s on %s) ***\n", olsrd_version, build_date, build_host); + } + +@@ -165,7 +167,7 @@ + if (changes_neighborhood || changes_topology || changes_hna) { + olsr_calculate_routing_table(); + } +- ++#ifndef SVEN_OLA_UNBLOAT + if (olsr_cnf->debug_level > 0) { + if (olsr_cnf->debug_level > 2) { + olsr_print_mid_set(); +@@ -184,6 +186,7 @@ + olsr_print_tc_table(); + #endif + } ++#endif /* SVEN_OLA_UNBLOAT */ + + for (tmp_pc_list = pcf_list; tmp_pc_list != NULL; tmp_pc_list = tmp_pc_list->next) { + tmp_pc_list->function(changes_neighborhood, changes_topology, changes_hna); +@@ -415,12 +418,15 @@ + olsr_u8_t + olsr_calculate_willingness(void) + { ++#ifndef SVEN_OLA_UNBLOAT + struct olsr_apm_info ainfo; ++#endif /* SVEN_OLA_UNBLOAT */ + + /* If fixed willingness */ + if (!olsr_cnf->willingness_auto) + return olsr_cnf->willingness; + ++#ifndef SVEN_OLA_UNBLOAT + if (apm_read(&ainfo) < 1) + return WILL_DEFAULT; + +@@ -437,8 +443,12 @@ + * 26% > juice will: 1 + */ + return (ainfo.battery_percentage / 26); ++#else /* SVEN_OLA_UNBLOAT */ ++ return WILL_DEFAULT; ++#endif /* SVEN_OLA_UNBLOAT */ + } + ++#ifndef SVEN_OLA_UNBLOAT + const char * + olsr_msgtype_to_string(olsr_u8_t msgtype) + { +@@ -508,6 +518,7 @@ + snprintf(type, sizeof(type), "UNKNOWN(%d)", status); + return type; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + *Termination function to be called whenever a error occures +@@ -536,6 +547,7 @@ + * + * @return a void pointer to the memory allocated + */ ++#ifndef SVEN_OLA_UNBLOAT + void * + olsr_malloc(size_t size, const char *id) + { +@@ -560,6 +572,7 @@ + + return ptr; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + *Wrapper for printf that prints to a specific +diff -Nur olsrd-0.5.6-r3.orig/src/olsr_cfg.h olsrd-0.5.6-r3/src/olsr_cfg.h +--- olsrd-0.5.6-r3.orig/src/olsr_cfg.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/olsr_cfg.h 2008-12-03 10:01:07.000000000 +0100 +@@ -140,8 +140,10 @@ + char *name; + char *config; + olsr_bool configured; ++#ifndef SVEN_OLA_UNBLOAT + olsr_bool host_emul; + union olsr_ip_addr hemu_ip; ++#endif /* SVEN_OLA_UNBLOAT */ + struct interface *interf; + struct if_config_options *cnf; + struct olsr_if *next; +@@ -183,7 +185,9 @@ + struct olsrd_config { + int debug_level; + olsr_bool no_fork; ++#ifndef SVEN_OLA_UNBLOAT + olsr_bool host_emul; ++#endif /* SVEN_OLA_UNBLOAT */ + int ip_version; + olsr_bool allow_no_interfaces; + olsr_u16_t tos; +@@ -191,13 +195,17 @@ + olsr_u8_t rttable_default; + olsr_u8_t willingness; + olsr_bool willingness_auto; ++#ifndef SVEN_OLA_UNBLOAT + int ipc_connections; ++#endif /* SVEN_OLA_UNBLOAT */ + olsr_bool use_hysteresis; + olsr_fib_metric_options fib_metric; + struct hyst_param hysteresis_param; + struct plugin_entry *plugins; + struct ip_prefix_list *hna_entries; ++#ifndef SVEN_OLA_UNBLOAT + struct ip_prefix_list *ipc_nets; ++#endif /* SVEN_OLA_UNBLOAT */ + struct olsr_if *interfaces; + float pollrate; + float nic_chgs_pollrate; +@@ -257,7 +265,9 @@ + + void olsrd_free_cnf(struct olsrd_config *); + ++#ifndef SVEN_OLA_UNBLOAT + void olsrd_print_cnf(struct olsrd_config *); ++#endif /* SVEN_OLA_UNBLOAT */ + + int olsrd_write_cnf(struct olsrd_config *, const char *); + +diff -Nur olsrd-0.5.6-r3.orig/src/olsr.h olsrd-0.5.6-r3/src/olsr.h +--- olsrd-0.5.6-r3.orig/src/olsr.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/olsr.h 2008-12-03 10:01:07.000000000 +0100 +@@ -72,15 +72,21 @@ + + olsr_u8_t olsr_calculate_willingness(void); + ++#ifndef SVEN_OLA_UNBLOAT + const char *olsr_msgtype_to_string(olsr_u8_t); + + const char *olsr_link_to_string(olsr_u8_t); + + const char *olsr_status_to_string(olsr_u8_t); ++#endif /* SVEN_OLA_UNBLOAT */ + + void olsr_exit(const char *, int); + ++#ifdef SVEN_OLA_UNBLOAT ++#define olsr_malloc(size, msg) calloc(1, size) ++#else /* SVEN_OLA_UNBLOAT */ + void *olsr_malloc(size_t, const char *); ++#endif /* SVEN_OLA_UNBLOAT */ + + int olsr_printf(int, const char *, ...) __attribute__ ((format(printf, 2, 3))); + +diff -Nur olsrd-0.5.6-r3.orig/src/parser.c olsrd-0.5.6-r3/src/parser.c +--- olsrd-0.5.6-r3.orig/src/parser.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/parser.c 2008-12-03 10:01:07.000000000 +0100 +@@ -51,7 +51,9 @@ + #include "rebuild_packet.h" + #include "net_os.h" + #include "log.h" ++#ifndef SVEN_OLA_UNBLOAT + #include "print_packet.h" ++#endif /* SVEN_OLA_UNBLOAT */ + #include "net_olsr.h" + + #ifdef WIN32 +@@ -280,8 +282,10 @@ + //printf("Message from %s\n\n", olsr_ip_to_string(&buf, from_addr)); + + /* Display packet */ ++#ifndef SVEN_OLA_UNBLOAT + if (disp_pack_in) + print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr); ++#endif /* SVEN_OLA_UNBLOAT */ + + if (olsr_cnf->ip_version == AF_INET) + msgsize = ntohs(m->v4.olsr_msgsize); +diff -Nur olsrd-0.5.6-r3.orig/src/print_packet.c olsrd-0.5.6-r3/src/print_packet.c +--- olsrd-0.5.6-r3.orig/src/print_packet.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/print_packet.c 2008-12-03 10:01:07.000000000 +0100 +@@ -39,6 +39,7 @@ + * + */ + ++#ifndef SVEN_OLA_UNBLOAT + #include "print_packet.h" + #include "ipcalc.h" + #include "mantissa.h" +@@ -339,6 +340,7 @@ + remsize -= olsr_cnf->ipsize; + } + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/process_routes.c olsrd-0.5.6-r3/src/process_routes.c +--- olsrd-0.5.6-r3.orig/src/process_routes.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/process_routes.c 2008-12-03 10:01:07.000000000 +0100 +@@ -159,6 +159,7 @@ + static void + olsr_delete_kernel_route(struct rt_entry *rt) + { ++#ifndef SVEN_OLA_UNBLOAT + if (!olsr_cnf->host_emul) { + olsr_16_t error = olsr_cnf->ip_version == AF_INET ? olsr_delroute_function(rt) : olsr_delroute6_function(rt); + +@@ -170,6 +171,12 @@ + olsr_syslog(OLSR_LOG_ERR, "Delete route %s: %s", routestr, err_msg); + } + } ++#else /* SVEN_OLA_UNBLOAT */ ++ olsr_16_t error = olsr_cnf->ip_version == AF_INET ? olsr_delroute_function(rt) : olsr_delroute6_function(rt); ++ if (0 > error) { ++ olsr_syslog(OLSR_LOG_ERR, "Delete route: %s", strerror(errno)); ++ } ++#endif /* SVEN_OLA_UNBLOAT */ + } + + /** +@@ -181,6 +188,7 @@ + olsr_add_kernel_route(struct rt_entry *rt) + { + ++#ifndef SVEN_OLA_UNBLOAT + if (!olsr_cnf->host_emul) { + olsr_16_t error = (olsr_cnf->ip_version == AF_INET) ? olsr_addroute_function(rt) : olsr_addroute6_function(rt); + +@@ -199,6 +207,14 @@ + rt->rt_metric = rt->rt_best->rtp_metric; + } + } ++#else /* SVEN_OLA_UNBLOAT */ ++ olsr_16_t error = olsr_cnf->ip_version == AF_INET ? olsr_addroute_function(rt) : olsr_addroute6_function(rt); ++ if (0 > error) { ++ olsr_syslog(OLSR_LOG_ERR, "Add route: %s", strerror(errno)); ++ } else { ++ rt->rt_nexthop = rt->rt_best->rtp_nexthop; ++ } ++#endif /* SVEN_OLA_UNBLOAT */ + } + + /** +@@ -385,7 +401,7 @@ + /* route additions */ + olsr_add_kernel_routes(&add_kernel_list); + +-#if DEBUG ++#ifdef DEBUG + olsr_print_routing_table(&routingtree); + #endif + } +diff -Nur olsrd-0.5.6-r3.orig/src/rebuild_packet.c olsrd-0.5.6-r3/src/rebuild_packet.c +--- olsrd-0.5.6-r3.orig/src/rebuild_packet.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/rebuild_packet.c 2008-12-03 10:01:07.000000000 +0100 +@@ -60,7 +60,11 @@ + mid_chgestruct(struct mid_message *mmsg, const union olsr_message *m) + { + int i; ++#ifndef SVEN_OLA_UNBLOAT + struct mid_alias *alias, *alias_tmp; ++#else /* SVEN_OLA_UNBLOAT */ ++ struct mid_alias *alias; ++#endif /* SVEN_OLA_UNBLOAT */ + int no_aliases; + + /* Checking if everything is ok */ +@@ -100,6 +104,7 @@ + maddr++; + } + ++#ifndef SVEN_OLA_UNBLOAT + if (olsr_cnf->debug_level > 1) { + struct ipaddr_str buf; + OLSR_PRINTF(3, "Alias list for %s: ", olsr_ip_to_string(&buf, &mmsg->mid_origaddr)); +@@ -111,6 +116,7 @@ + } + OLSR_PRINTF(3, "\n"); + } ++#endif /* SVEN_OLA_UNBLOAT */ + } else { + /* IPv6 */ + const struct midaddr6 *maddr6 = m->v6.message.mid.mid_addr; +@@ -144,6 +150,7 @@ + maddr6++; + } + ++#ifndef SVEN_OLA_UNBLOAT + if (olsr_cnf->debug_level > 1) { + struct ipaddr_str buf; + OLSR_PRINTF(3, "Alias list for %s", ip6_to_string(&buf, &mmsg->mid_origaddr.v6)); +@@ -156,6 +163,7 @@ + } + OLSR_PRINTF(3, "\n"); + } ++#endif /* SVEN_OLA_UNBLOAT */ + } + + } +diff -Nur olsrd-0.5.6-r3.orig/src/routing_table.c olsrd-0.5.6-r3/src/routing_table.c +--- olsrd-0.5.6-r3.orig/src/routing_table.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/routing_table.c 2008-12-03 10:01:07.000000000 +0100 +@@ -623,6 +623,7 @@ + /** + * format a route entry into a buffer + */ ++#ifndef SVEN_OLA_UNBLOAT + char * + olsr_rt_to_string(const struct rt_entry *rt) + { +@@ -654,11 +655,13 @@ + + return buff; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + * Print the routingtree to STDOUT + * + */ ++#ifndef SVEN_OLA_UNBLOAT + void + olsr_print_routing_table(struct avl_tree *tree) + { +@@ -692,6 +695,7 @@ + #endif + tree = NULL; /* squelch compiler warnings */ + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/routing_table.h olsrd-0.5.6-r3/src/routing_table.h +--- olsrd-0.5.6-r3.orig/src/routing_table.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/routing_table.h 2008-12-03 10:01:07.000000000 +0100 +@@ -210,9 +210,11 @@ + olsr_bool olsr_cmp_rt(const struct rt_entry *, const struct rt_entry *); + olsr_u8_t olsr_fib_metric(const struct rt_metric *); + ++#ifndef SVEN_OLA_UNBLOAT + char *olsr_rt_to_string(const struct rt_entry *); + char *olsr_rtp_to_string(const struct rt_path *); + void olsr_print_routing_table(struct avl_tree *); ++#endif /* SVEN_OLA_UNBLOAT */ + + const struct rt_nexthop *olsr_get_nh(const struct rt_entry *); + +diff -Nur olsrd-0.5.6-r3.orig/src/tc_set.c olsrd-0.5.6-r3/src/tc_set.c +--- olsrd-0.5.6-r3.orig/src/tc_set.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/tc_set.c 2008-12-03 10:01:07.000000000 +0100 +@@ -336,6 +336,7 @@ + /** + * Format tc_edge contents into a buffer. + */ ++#ifndef SVEN_OLA_UNBLOAT + char * + olsr_tc_edge_to_string(struct tc_edge_entry *tc_edge) + { +@@ -350,6 +351,7 @@ + + return buf; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /** + * Wrapper for the timer callback. +@@ -685,6 +687,7 @@ + /** + * Print the topology table to stdout + */ ++#ifndef SVEN_OLA_UNBLOAT + void + olsr_print_tc_table(void) + { +@@ -710,6 +713,7 @@ + } OLSR_FOR_ALL_TC_ENTRIES_END(tc); + #endif + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * calculate the border IPs of a tc edge set according to the border flags +diff -Nur olsrd-0.5.6-r3.orig/src/tc_set.h olsrd-0.5.6-r3/src/tc_set.h +--- olsrd-0.5.6-r3.orig/src/tc_set.h 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/tc_set.h 2008-12-03 10:01:07.000000000 +0100 +@@ -157,7 +157,9 @@ + + /* tc_edge_entry manipulation */ + olsr_bool olsr_delete_outdated_tc_edges(struct tc_entry *); ++#ifndef SVEN_OLA_UNBLOAT + char *olsr_tc_edge_to_string(struct tc_edge_entry *); ++#endif /* SVEN_OLA_UNBLOAT */ + struct tc_edge_entry *olsr_lookup_tc_edge(struct tc_entry *, union olsr_ip_addr *); + struct tc_edge_entry *olsr_add_tc_edge_entry(struct tc_entry *, union olsr_ip_addr *, olsr_u16_t); + void olsr_delete_tc_entry(struct tc_entry *); +diff -Nur olsrd-0.5.6-r3.orig/src/two_hop_neighbor_table.c olsrd-0.5.6-r3/src/two_hop_neighbor_table.c +--- olsrd-0.5.6-r3.orig/src/two_hop_neighbor_table.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/two_hop_neighbor_table.c 2008-12-03 10:01:07.000000000 +0100 +@@ -203,6 +203,8 @@ + return NULL; + } + ++#ifndef SVEN_OLA_UNBLOAT ++ + /** + *Print the two hop neighbor table to STDOUT. + * +@@ -240,6 +242,7 @@ + } + #endif + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: +diff -Nur olsrd-0.5.6-r3.orig/src/unix/ifnet.c olsrd-0.5.6-r3/src/unix/ifnet.c +--- olsrd-0.5.6-r3.orig/src/unix/ifnet.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/unix/ifnet.c 2008-12-03 10:01:07.000000000 +0100 +@@ -70,6 +70,8 @@ + + #define BUFSPACE (127*1024) /* max. input buffer size to request */ + ++#ifndef SVEN_OLA_UNBLOAT ++ + int + set_flag(char *ifname, short flag __attribute__ ((unused))) + { +@@ -100,6 +102,8 @@ + + } + ++#endif /* SVEN_OLA_UNBLOAT */ ++ + void + check_interface_updates(void *foo __attribute__ ((unused))) + { +@@ -110,11 +114,13 @@ + #endif + + for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) { ++#ifndef SVEN_OLA_UNBLOAT + if (tmp_if->host_emul) + continue; + + if (olsr_cnf->host_emul) /* XXX: TEMPORARY! */ + continue; ++#endif /* SVEN_OLA_UNBLOAT */ + + if (!tmp_if->cnf->autodetect_chg) { + #ifdef DEBUG +@@ -154,8 +160,10 @@ + OLSR_PRINTF(3, "Checking if %s is set down or changed\n", iface->name); + #endif + ++#ifndef SVEN_OLA_UNBLOAT + if (iface->host_emul) + return -1; ++#endif /* SVEN_OLA_UNBLOAT */ + + ifp = iface->interf; + +@@ -279,7 +287,9 @@ + } else + /* IP version 4 */ + { ++#ifndef SVEN_OLA_UNBLOAT + struct ipaddr_str buf; ++#endif /* SVEN_OLA_UNBLOAT */ + /* Check interface address (IPv4) */ + if (ioctl(olsr_cnf->ioctl_s, SIOCGIFADDR, &ifr) < 0) { + OLSR_PRINTF(1, "\tCould not get address of interface - removing it\n"); +@@ -301,7 +311,9 @@ + + if (memcmp(&olsr_cnf->main_addr, &ifp->ip_addr, olsr_cnf->ipsize) == 0) { + OLSR_PRINTF(1, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr)); ++#ifndef SVEN_OLA_UNBLOAT + olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", sockaddr4_to_string(&buf, &ifr.ifr_addr)); ++#endif /* SVEN_OLA_UNBLOAT */ + memcpy(&olsr_cnf->main_addr, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr, olsr_cnf->ipsize); + } + +@@ -363,7 +375,9 @@ + + remove_interface: + OLSR_PRINTF(1, "Removing interface %s\n", iface->name); ++#ifndef SVEN_OLA_UNBLOAT + olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name); ++#endif /* SVEN_OLA_UNBLOAT */ + + olsr_delete_link_entry_by_ip(&ifp->ip_addr); + +@@ -393,10 +407,14 @@ + memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize); + OLSR_PRINTF(1, "No more interfaces...\n"); + } else { ++#if !defined(SVEN_OLA_UNBLOAT) + struct ipaddr_str buf; ++#endif /* SVEN_OLA_UNBLOAT */ + olsr_cnf->main_addr = ifnet->ip_addr; + OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); ++#ifndef SVEN_OLA_UNBLOAT + olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); ++#endif /* SVEN_OLA_UNBLOAT */ + } + } + +@@ -420,7 +438,9 @@ + + if ((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces)) { + OLSR_PRINTF(1, "No more active interfaces - exiting.\n"); ++#ifndef SVEN_OLA_UNBLOAT + olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n"); ++#endif /* SVEN_OLA_UNBLOAT */ + olsr_cnf->exit_value = EXIT_FAILURE; + kill(getpid(), SIGINT); + } +@@ -429,6 +449,8 @@ + + } + ++#ifndef SVEN_OLA_UNBLOAT ++ + /** + * Initializes the special interface used in + * host-client emulation +@@ -578,6 +600,7 @@ + + return 1; + } ++#endif /* SVEN_OLA_UNBLOAT */ + + static char basenamestr[32]; + static const char *if_basename(const char *name); +@@ -613,8 +636,10 @@ + int tos_bits = IPTOS_TOS(olsr_cnf->tos); + #endif + ++#ifndef SVEN_OLA_UNBLOAT + if (iface->host_emul) + return -1; ++#endif /* SVEN_OLA_UNBLOAT */ + + memset(&ifr, 0, sizeof(struct ifreq)); + memset(&ifs, 0, sizeof(struct interface)); +@@ -721,11 +746,13 @@ + ifs.int_broadaddr = *(struct sockaddr_in *)&ifr.ifr_broadaddr; + } + ++#ifndef SVEN_OLA_UNBLOAT + /* Deactivate IP spoof filter */ + deactivate_spoof(if_basename(ifr.ifr_name), &ifs, olsr_cnf->ip_version); + + /* Disable ICMP redirects */ + disable_redirects(if_basename(ifr.ifr_name), &ifs, olsr_cnf->ip_version); ++#endif /* SVEN_OLA_UNBLOAT */ + + } + +@@ -755,7 +782,9 @@ + + OLSR_PRINTF(1, "\tMTU - IPhdr: %d\n", ifs.int_mtu); + ++#ifndef SVEN_OLA_UNBLOAT + olsr_syslog(OLSR_LOG_INFO, "Adding interface %s\n", iface->name); ++#endif /* SVEN_OLA_UNBLOAT */ + OLSR_PRINTF(1, "\tIndex %d\n", ifs.if_index); + + if (olsr_cnf->ip_version == AF_INET) { +@@ -860,10 +889,14 @@ + */ + memset(&null_addr, 0, olsr_cnf->ipsize); + if (ipequal(&null_addr, &olsr_cnf->main_addr)) { ++#ifndef SVEN_OLA_UNBLOAT + struct ipaddr_str buf; ++#endif + olsr_cnf->main_addr = ifp->ip_addr; + OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); ++#ifndef SVEN_OLA_UNBLOAT + olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); ++#endif /* SVEN_OLA_UNBLOAT */ + } + + /* +diff -Nur olsrd-0.5.6-r3.orig/src/unix/misc.c olsrd-0.5.6-r3/src/unix/misc.c +--- olsrd-0.5.6-r3.orig/src/unix/misc.c 2008-12-02 11:50:01.000000000 +0100 ++++ olsrd-0.5.6-r3/src/unix/misc.c 2008-12-03 10:01:07.000000000 +0100 +@@ -44,6 +44,7 @@ + #include "misc.h" + #include "olsr_types.h" + ++#ifndef SVEN_OLA_UNBLOAT + void + clear_console(void) + { +@@ -69,6 +70,7 @@ + + fflush(stdout); + } ++#endif /* SVEN_OLA_UNBLOAT */ + + /* + * Local Variables: diff --git a/openwrt/packages/luci/contrib/package/xrelayd/Makefile b/openwrt/packages/luci/contrib/package/xrelayd/Makefile new file mode 100644 index 0000000..01a0244 --- /dev/null +++ b/openwrt/packages/luci/contrib/package/xrelayd/Makefile @@ -0,0 +1,59 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=xrelayd +PKG_VERSION:=0.2.1pre2 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=http://znerol.ch/files +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_MD5SUM:=05f242295fa864bb3b0b7f0712b4dfa3 + +PKG_CAT:=zcat +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install + +PKG_BUILD_DEPENDS:=libxyssl + +include $(INCLUDE_DIR)/package.mk + +define Package/xrelayd + SECTION:=net + CATEGORY:=Network + DEPENDS:=@BROKEN +libxyssl + TITLE:=stunnel replacement based on xyssl + URL:=http://znerol.ch/ +endef + +define Package/xrelayd/description + stunnel replacement based on xyssl +endef + +define Build/Configure +endef + +define Build/Compile + rm -rf $(PKG_INSTALL_DIR) + mkdir -p $(PKG_INSTALL_DIR) + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ + CC="$(TARGET_CC)" \ + LD="$(TARGET_CC)" \ + CFLAGS="$(strip $(TARGET_CFLAGS))" \ + CPPFLAGS="$$$$CPPFLAGS -I$(STAGING_DIR)/usr/include" \ + LDFLAGS="-L$(STAGING_DIR)/usr/lib" \ + prefix="$(PKG_INSTALL_DIR)/usr" + mkdir -p $(PKG_INSTALL_DIR)/usr/bin + $(CP) $(PKG_BUILD_DIR)/xrelayd $(PKG_INSTALL_DIR)/usr/bin +endef + +define Package/xrelayd/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/xrelayd $(1)/usr/bin + $(RSTRIP) $(1)/usr/bin/xrelayd +endef + +#mostlyclean: +# make -C $(PKG_BUILD_DIR) clean +# rm $(PKG_BUILD_DIR)/.built + +$(eval $(call BuildPackage,xrelayd)) diff --git a/openwrt/packages/luci/contrib/uci/.gitignore b/openwrt/packages/luci/contrib/uci/.gitignore new file mode 100644 index 0000000..692aa37 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/.gitignore @@ -0,0 +1,4 @@ +uci-* +uci.git +*.tar.gz +patches/series diff --git a/openwrt/packages/luci/contrib/uci/Makefile b/openwrt/packages/luci/contrib/uci/Makefile new file mode 100644 index 0000000..95d25ab --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/Makefile @@ -0,0 +1,41 @@ +include ../../build/config.mk +include ../../build/gccconfig.mk + +UCI_VERSION = 0.7.3 +UCI_SITE = http://mirror2.openwrt.org/sources +UCI_DIR = uci-$(UCI_VERSION) +UCI_FILE = $(UCI_DIR).tar.gz +UCI_URL = $(UCI_SITE)/$(UCI_FILE) +#UCI_GITREV = c79cc497e7b0caa0f9f6a2c978fa9a5f0f097463 +#UCI_SITE = http://nbd.name +#UCI_DIR = uci.git +#UCI_FILE = uci-$(UCI_VERSION)$(UCI_APPEND).tar.gz +#UCI_URL = $(UCI_SITE)/gitweb.cgi?p=uci.git;a=snapshot;h=$(UCI_GITREV) +UCI_PATCHDIR = patches + +all: compile + +include ../../build/module.mk + +$(UCI_FILE): + wget -O $@ "$(UCI_URL)" || rm -f $@ + +$(UCI_PATCHDIR)/series: + (cd $(UCI_PATCHDIR); ls *.patch | sort > series) + +$(UCI_DIR)/.prepared: $(UCI_FILE) + rm -rf $(UCI_DIR) + tar xvfz $(UCI_FILE) + touch $@ + +compile: $(UCI_DIR)/.prepared + $(MAKE) -C $(UCI_DIR) CC=$(CC) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" OS="$(OS)" + mkdir -p dist/usr/lib dist/usr/bin + $(MAKE) -C $(UCI_DIR) install DESTDIR=../dist prefix=/usr + $(MAKE) -C $(UCI_DIR)/lua CC=$(CC) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" OS="$(OS)" + $(MAKE) -C $(UCI_DIR)/lua install DESTDIR=../../dist luadir=$(LUA_LIBRARYDIR) + +compile-all: compile + +clean: + rm -rf $(UCI_DIR) $(UCI_FILE) diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/bin/uci b/openwrt/packages/luci/contrib/uci/hostfiles/bin/uci new file mode 100755 index 0000000..f6104c6 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/bin/uci @@ -0,0 +1,2 @@ +#!/bin/sh +$(dirname $0)/../usr/bin/uci -c $(dirname $0)/../etc/config "$@" diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/bin/uci-defaults b/openwrt/packages/luci/contrib/uci/hostfiles/bin/uci-defaults new file mode 100755 index 0000000..3b58d7b --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/bin/uci-defaults @@ -0,0 +1,7 @@ +#!/bin/sh +for i in $(find $(dirname $0)/../etc/uci-defaults -type f -not -name "$2") +do + [ -f $i ] && { + bash $i; rm $i + } +done diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/batmand b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/batmand new file mode 100644 index 0000000..95ec3fa --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/batmand @@ -0,0 +1,10 @@ +config batmand general + option interface ath0 + option announce + option gateway_class + option originator_interval + option preferred_gateway + option routing_class + option visualisation_srv + option policy_routing_script + diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ddns b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ddns new file mode 100644 index 0000000..7c3f3c1 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ddns @@ -0,0 +1,85 @@ +################################################################# +# In order to enable dynamic dns you need at least one section, +# and in that seciton the "enabled" option must be set to one +# +# Each section represents an update to a different service +# +# You specify your domain name, your username and your password +# with the optins "domain", "username" and "password" respectively +# +# Next you need to specify the name of the service you are +# connecting to "eg. dyndns.org". The format of the update +# urls for several different dynamic dns services is specified +# in the /usr/lib/ddns/services file. This list is hardly complete +# as there are many, many different dynamic dns services. If your +# service is on the list you can merely specify it with the +# "service_name" option. Otherwise you will need to determine +# the format of the url to update with. You can either add an +# entry to the /usr/lib/ddns/services file or specify this with +# the "update_url" option. +# +# We also need to specify the source of the ip address to associate with +# your domain. The "ip_source" option can be "network", "interface" +# or "web", with "network" as the default. +# +# If "ip_source" is "network" you specify a network section in your +# /etc/network config file (e.g. "wan", which is the default) with +# the "ip_network" option. If you specify "wan", you will update +# with whatever the ip for your wan is. +# +# If "ip_source" is "interface" you specify a hardware interface +# (e.g. "eth1") and whatever the current ip of this interface is +# will be associated with the domain when an update is performed. +# +# The last possibility is that "ip_source" is "web", which means +# that in order to obtain our ip address we will connect to a +# website, and the first valid ip address listed on that page +# will be assumed to be ours. If you are behind another firewall +# this is the best option since none of the local networks or +# interfaces will have the external ip. The website to connect +# to is specified by the "ip_url" option. You may specify multiple +# urls in the option, separated by whitespace. +# +# Finally we need to specify how often to check whether we need +# to check whether the ip address has changed (and if so update +# it) and how often we need to force an update ( many services +# will expire your domain if you don't connect and do an update +# every so often). Use the "check_interval" to specify how +# often to check whether an update is necessary, and the +# "force_interval" option to specify how often to force an +# update. Specify the units for these values with the "check_unit" +# and the "force_unit" options. Units can be "days", "hours", +# "minutes" or "seconds". The default force_unit is hours and the +# default check_unit is seconds. The default check_interval is +# 600 seconds, or ten minutes. The default force_interval is +# 72 hours or 3 days. +# +# +######################################################### + +config service "myddns" + option enabled "0" + + option service_name "dyndns.org" + option domain "mypersonaldomain.dyndns.org" + option username "myusername" + option password "mypassword" + + option ip_source "network" + option ip_network "wan" + + + option force_interval "72" + option force_unit "hours" + option check_interval "10" + option check_unit "minutes" + + #option ip_source "interface" + #option ip_interface "eth0.1" + + #option ip_source "web" + #option ip_url "http://www.whatismyip.com/automation/n09230945.asp" + + #option update_url "http://[USERNAME]:[PASSWORD]@members.dyndns.org/nic/update?hostname=[DOMAIN]&myip=[IP]" + + diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dhcp b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dhcp new file mode 100644 index 0000000..4904b02 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dhcp @@ -0,0 +1,23 @@ +config dnsmasq + option domainneeded 1 + option boguspriv 1 + option filterwin2k '0' #enable for dial on demand + option localise_queries 1 + option local '/lan/' + option domain 'lan' + option expandhosts 1 + option nonegcache 0 + option authoritative 1 + option readethers 1 + option leasefile '/tmp/dhcp.leases' + option resolvfile '/tmp/resolv.conf.auto' + +config dhcp + option interface lan + option start 100 + option limit 150 + option leasetime 12h + +config dhcp + option interface wan + option ignore 1 diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dropbear b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dropbear new file mode 100644 index 0000000..e660ac7 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/dropbear @@ -0,0 +1,3 @@ +config dropbear + option PasswordAuth 'on' + option Port '22' diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/firewall b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/firewall new file mode 100644 index 0000000..0731690 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/firewall @@ -0,0 +1,80 @@ +config defaults + option syn_flood 1 + option input DROP + option output ACCEPT + option forward DROP + +config zone + option name lan + option input ACCEPT + option output ACCEPT + option forward DROP + +config zone + option name wan + option input DROP + option output ACCEPT + option forward DROP + option masq 1 + +config forwarding + option src lan + option dest wan + + +### EXAMPLE CONFIG SECTIONS +# do not allow a specific ip to access wan +#config rule +# option src lan +# option src_ip 192.168.45.2 +# option dest wan +# option proto tcp +# option target REJECT + +# block a specific mac on wan +#config rule +# option dest wan +# option src_mac 00:11:22:33:44:66 +# option target REJECT + +# block incoming ICMP traffic on a zone +#config rule +# option src lan +# option proto ICMP +# option target DROP + +# port redirect port coming in on wan to lan +#config redirect +# option src wan +# option src_dport 80 +# option dest lan +# option dest_ip 192.168.16.235 +# option dest_port 80 +# option protocol tcp + +# include a file with users custom iptables rules +#config include +# option path /etc/firewall.user + + +### FULL CONFIG SECTIONS +#config rule +# option src lan +# option src_ip 192.168.45.2 +# option src_mac 00:11:22:33:44:55 +# option src_port 80 +# option dest wan +# option dest_ip 194.25.2.129 +# option dest_port 120 +# option proto tcp +# option target REJECT + +#config redirect +# option src lan +# option src_ip 192.168.45.2 +# option src_mac 00:11:22:33:44:55 +# option src_port 1024 +# option src_dport 80 +# option dest_ip 194.25.2.129 +# option dest_port 120 +# option proto tcp diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/fstab b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/fstab new file mode 100644 index 0000000..eccf0ce --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/fstab @@ -0,0 +1,10 @@ +config mount + option target /home + option device /dev/sda1 + option fstype ext3 + option options rw,sync + option enabled 0 + +config swap + option device /dev/sda2 + option enabled 0 diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/httpd b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/httpd new file mode 100644 index 0000000..2f8020f --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/httpd @@ -0,0 +1,5 @@ + +config 'httpd' + option 'port' '80' + option 'home' '/www' + diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/network b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/network new file mode 100644 index 0000000..6f499c9 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/network @@ -0,0 +1,27 @@ +#### VLAN configuration +config switch eth0 + option vlan0 "0 1 2 3 5*" + option vlan1 "4 5" + + +#### Loopback configuration +config interface loopback + option ifname "lo" + option proto static + option ipaddr 127.0.0.1 + option netmask 255.0.0.0 + + +#### LAN configuration +config interface lan + option type bridge + option ifname "eth0" + option proto static + option ipaddr 192.168.1.1 + option netmask 255.255.255.0 + + +#### WAN configuration +config interface wan + option ifname "wlan0" + option proto dhcp diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ntpclient b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ntpclient new file mode 100644 index 0000000..1b56f1b --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/ntpclient @@ -0,0 +1,22 @@ +config ntpserver + option hostname '0.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '1.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '2.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '3.openwrt.pool.ntp.org' + option port '123' + +config ntpdrift + option freq '0' + +config ntpclient + option interval 60 + #option count 10 diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/qos b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/qos new file mode 100644 index 0000000..51959b5 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/qos @@ -0,0 +1,89 @@ +# QoS configuration for OpenWrt + +# INTERFACES: +config interface wan + option classgroup "Default" + option enabled 1 + option overhead 1 + option upload 128 + option download 1024 + +# RULES: +config classify + option target "Bulk" + option ipp2p "all" +config classify + option target "Bulk" + option layer7 "edonkey" +config classify + option target "Bulk" + option layer7 "bittorrent" +config classify + option target "Priority" + option ports "22,53" +config classify + option target "Normal" + option proto "tcp" + option ports "20,21,25,80,110,443,993,995" +config classify + option target "Express" + option ports "5190" +config default + option target "Express" + option proto "udp" + option pktsize "-500" +config reclassify + option target "Priority" + option proto "icmp" +config default + option target "Bulk" + option portrange "1024-65535" +config reclassify + option target "Priority" + option proto "tcp" + option pktsize "-128" + option mark "!Bulk" + option tcpflags "SYN" +config reclassify + option target "Priority" + option proto "tcp" + option pktsize "-128" + option mark "!Bulk" + option tcpflags "ACK" + + +# Don't change the stuff below unless you +# really know what it means :) + +config classgroup "Default" + option classes "Priority Express Normal Bulk" + option default "Normal" + + +config class "Priority" + option packetsize 400 + option maxsize 400 + option avgrate 10 + option priority 20 +config class "Priority_down" + option packetsize 1000 + option avgrate 10 + + +config class "Express" + option packetsize 1000 + option maxsize 800 + option avgrate 50 + option priority 10 + +config class "Normal" + option packetsize 1500 + option packetdelay 100 + option avgrate 10 + option priority 5 +config class "Normal_down" + option avgrate 20 + +config class "Bulk" + option avgrate 1 + option packetdelay 200 diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/system b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/system new file mode 100644 index 0000000..b0726b7 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/system @@ -0,0 +1,3 @@ +config system + option hostname OpenWrt + option timezone UTC diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/upnpd b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/upnpd new file mode 100644 index 0000000..75dcb9a --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/upnpd @@ -0,0 +1,4 @@ +config upnpd config + option log_output 0 + option download 1024 + option upload 512 diff --git a/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/wireless b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/wireless new file mode 100644 index 0000000..4895797 --- /dev/null +++ b/openwrt/packages/luci/contrib/uci/hostfiles/etc/config/wireless @@ -0,0 +1,13 @@ +config wifi-device wifi0 + option type atheros + option channel auto + + # REMOVE THIS LINE TO ENABLE WIFI: + option disabled 1 + +config wifi-iface + option device wifi0 + option network lan + option mode ap + option ssid OpenWrt + option encryption none diff --git a/openwrt/packages/luci/host/bin/luadoc b/openwrt/packages/luci/host/bin/luadoc new file mode 100755 index 0000000..ba99a37 --- /dev/null +++ b/openwrt/packages/luci/host/bin/luadoc @@ -0,0 +1,121 @@ +#!/usr/bin/env lua +------------------------------------------------------------------------------- +-- LuaDoc launcher. +-- @release $Id: luadoc.lua.in,v 1.1 2008/02/17 06:42:51 jasonsantos Exp $ +------------------------------------------------------------------------------- + +require "luadoc" + +------------------------------------------------------------------------------- +-- Print version number. + +local function print_version () + print (string.format("%s\n%s\n%s", + luadoc._VERSION, + luadoc._DESCRIPTION, + luadoc._COPYRIGHT)) +end + +------------------------------------------------------------------------------- +-- Print usage message. + +local function print_help () + print ("Usage: "..arg[0]..[[ [options|files] +Generate documentation from files. Available options are: + -d path output directory path + -t path template directory path + -h, --help print this help and exit + --noindexpage do not generate global index page + --nofiles do not generate documentation for files + --nomodules do not generate documentation for modules + --doclet doclet_module doclet module to generate output + --taglet taglet_module taglet module to parse input code + -q, --quiet suppress all normal output + -v, --version print version information]]) +end + +local function off_messages (arg, i, options) + options.verbose = nil +end + +------------------------------------------------------------------------------- +-- Process options. TODO: use getopts. +-- @class table +-- @name OPTIONS + +local OPTIONS = { + d = function (arg, i, options) + local dir = arg[i+1] + if string.sub (dir, -2) ~= "/" then + dir = dir..'/' + end + options.output_dir = dir + return 1 + end, + t = function (arg, i, options) + local dir = arg[i+1] + if string.sub (dir, -2) ~= "/" then + dir = dir..'/' + end + options.template_dir = dir + return 1 + end, + h = print_help, + help = print_help, + q = off_messages, + quiet = off_messages, + v = print_version, + version = print_version, + doclet = function (arg, i, options) + options.doclet = arg[i+1] + return 1 + end, + taglet = function (arg, i, options) + options.taglet = arg[i+1] + return 1 + end, +} + +------------------------------------------------------------------------------- + +local function process_options (arg) + local files = {} + local options = require "luadoc.config" + local i = 1 + while i <= #arg do + local argi = arg[i] + if string.sub (argi, 1, 1) ~= '-' then + table.insert (files, argi) + else + local opt = string.sub (argi, 2) + if string.sub (opt, 1, 1) == '-' then + opt = string.gsub (opt, "%-", "") + end + if OPTIONS[opt] then + if OPTIONS[opt] (arg, i, options) then + i = i + 1 + end + else + options[opt] = 1 + end + end + i = i+1 + end + return files, options +end + +------------------------------------------------------------------------------- +-- Main function. Process command-line parameters and call luadoc processor. + +function main (arg) + -- Process options + local argc = #arg + if argc < 1 then + print_help () + return + end + local files, options = process_options (arg) + return luadoc.main(files, options) +end + +main(arg) diff --git a/openwrt/packages/luci/host/bin/uci b/openwrt/packages/luci/host/bin/uci new file mode 100755 index 0000000..f6104c6 --- /dev/null +++ b/openwrt/packages/luci/host/bin/uci @@ -0,0 +1,2 @@ +#!/bin/sh +$(dirname $0)/../usr/bin/uci -c $(dirname $0)/../etc/config "$@" diff --git a/openwrt/packages/luci/host/bin/uci-defaults b/openwrt/packages/luci/host/bin/uci-defaults new file mode 100755 index 0000000..3b58d7b --- /dev/null +++ b/openwrt/packages/luci/host/bin/uci-defaults @@ -0,0 +1,7 @@ +#!/bin/sh +for i in $(find $(dirname $0)/../etc/uci-defaults -type f -not -name "$2") +do + [ -f $i ] && { + bash $i; rm $i + } +done diff --git a/openwrt/packages/luci/host/etc/boa/boa.conf b/openwrt/packages/luci/host/etc/boa/boa.conf new file mode 100644 index 0000000..c152caa --- /dev/null +++ b/openwrt/packages/luci/host/etc/boa/boa.conf @@ -0,0 +1,17 @@ +Port 80 +ErrorLog /dev/stderr +AccessLog /dev/stderr +DocumentRoot /www +DirectoryMaker /usr/lib/boa/boa_indexer +KeepAliveMax 1000 +KeepAliveTimeout 10 +MimeTypes /etc/mime.types +DefaultType text/plain +ServerName localhost +CGIPath /bin:/usr/bin + +AddType application/x-httpd-cgi cgi +AddType application/x-httpd-cgi sh + +ScriptAlias /cgi-bin/ /www/cgi-bin +PluginRoot /usr/lib/boa diff --git a/openwrt/packages/luci/host/etc/config/batmand b/openwrt/packages/luci/host/etc/config/batmand new file mode 100644 index 0000000..95ec3fa --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/batmand @@ -0,0 +1,10 @@ +config batmand general + option interface ath0 + option announce + option gateway_class + option originator_interval + option preferred_gateway + option routing_class + option visualisation_srv + option policy_routing_script + diff --git a/openwrt/packages/luci/host/etc/config/ddns b/openwrt/packages/luci/host/etc/config/ddns new file mode 100644 index 0000000..7c3f3c1 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/ddns @@ -0,0 +1,85 @@ +################################################################# +# In order to enable dynamic dns you need at least one section, +# and in that seciton the "enabled" option must be set to one +# +# Each section represents an update to a different service +# +# You specify your domain name, your username and your password +# with the optins "domain", "username" and "password" respectively +# +# Next you need to specify the name of the service you are +# connecting to "eg. dyndns.org". The format of the update +# urls for several different dynamic dns services is specified +# in the /usr/lib/ddns/services file. This list is hardly complete +# as there are many, many different dynamic dns services. If your +# service is on the list you can merely specify it with the +# "service_name" option. Otherwise you will need to determine +# the format of the url to update with. You can either add an +# entry to the /usr/lib/ddns/services file or specify this with +# the "update_url" option. +# +# We also need to specify the source of the ip address to associate with +# your domain. The "ip_source" option can be "network", "interface" +# or "web", with "network" as the default. +# +# If "ip_source" is "network" you specify a network section in your +# /etc/network config file (e.g. "wan", which is the default) with +# the "ip_network" option. If you specify "wan", you will update +# with whatever the ip for your wan is. +# +# If "ip_source" is "interface" you specify a hardware interface +# (e.g. "eth1") and whatever the current ip of this interface is +# will be associated with the domain when an update is performed. +# +# The last possibility is that "ip_source" is "web", which means +# that in order to obtain our ip address we will connect to a +# website, and the first valid ip address listed on that page +# will be assumed to be ours. If you are behind another firewall +# this is the best option since none of the local networks or +# interfaces will have the external ip. The website to connect +# to is specified by the "ip_url" option. You may specify multiple +# urls in the option, separated by whitespace. +# +# Finally we need to specify how often to check whether we need +# to check whether the ip address has changed (and if so update +# it) and how often we need to force an update ( many services +# will expire your domain if you don't connect and do an update +# every so often). Use the "check_interval" to specify how +# often to check whether an update is necessary, and the +# "force_interval" option to specify how often to force an +# update. Specify the units for these values with the "check_unit" +# and the "force_unit" options. Units can be "days", "hours", +# "minutes" or "seconds". The default force_unit is hours and the +# default check_unit is seconds. The default check_interval is +# 600 seconds, or ten minutes. The default force_interval is +# 72 hours or 3 days. +# +# +######################################################### + +config service "myddns" + option enabled "0" + + option service_name "dyndns.org" + option domain "mypersonaldomain.dyndns.org" + option username "myusername" + option password "mypassword" + + option ip_source "network" + option ip_network "wan" + + + option force_interval "72" + option force_unit "hours" + option check_interval "10" + option check_unit "minutes" + + #option ip_source "interface" + #option ip_interface "eth0.1" + + #option ip_source "web" + #option ip_url "http://www.whatismyip.com/automation/n09230945.asp" + + #option update_url "http://[USERNAME]:[PASSWORD]@members.dyndns.org/nic/update?hostname=[DOMAIN]&myip=[IP]" + + diff --git a/openwrt/packages/luci/host/etc/config/dhcp b/openwrt/packages/luci/host/etc/config/dhcp new file mode 100644 index 0000000..4904b02 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/dhcp @@ -0,0 +1,23 @@ +config dnsmasq + option domainneeded 1 + option boguspriv 1 + option filterwin2k '0' #enable for dial on demand + option localise_queries 1 + option local '/lan/' + option domain 'lan' + option expandhosts 1 + option nonegcache 0 + option authoritative 1 + option readethers 1 + option leasefile '/tmp/dhcp.leases' + option resolvfile '/tmp/resolv.conf.auto' + +config dhcp + option interface lan + option start 100 + option limit 150 + option leasetime 12h + +config dhcp + option interface wan + option ignore 1 diff --git a/openwrt/packages/luci/host/etc/config/dropbear b/openwrt/packages/luci/host/etc/config/dropbear new file mode 100644 index 0000000..e660ac7 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/dropbear @@ -0,0 +1,3 @@ +config dropbear + option PasswordAuth 'on' + option Port '22' diff --git a/openwrt/packages/luci/host/etc/config/firewall b/openwrt/packages/luci/host/etc/config/firewall new file mode 100644 index 0000000..0731690 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/firewall @@ -0,0 +1,80 @@ +config defaults + option syn_flood 1 + option input DROP + option output ACCEPT + option forward DROP + +config zone + option name lan + option input ACCEPT + option output ACCEPT + option forward DROP + +config zone + option name wan + option input DROP + option output ACCEPT + option forward DROP + option masq 1 + +config forwarding + option src lan + option dest wan + + +### EXAMPLE CONFIG SECTIONS +# do not allow a specific ip to access wan +#config rule +# option src lan +# option src_ip 192.168.45.2 +# option dest wan +# option proto tcp +# option target REJECT + +# block a specific mac on wan +#config rule +# option dest wan +# option src_mac 00:11:22:33:44:66 +# option target REJECT + +# block incoming ICMP traffic on a zone +#config rule +# option src lan +# option proto ICMP +# option target DROP + +# port redirect port coming in on wan to lan +#config redirect +# option src wan +# option src_dport 80 +# option dest lan +# option dest_ip 192.168.16.235 +# option dest_port 80 +# option protocol tcp + +# include a file with users custom iptables rules +#config include +# option path /etc/firewall.user + + +### FULL CONFIG SECTIONS +#config rule +# option src lan +# option src_ip 192.168.45.2 +# option src_mac 00:11:22:33:44:55 +# option src_port 80 +# option dest wan +# option dest_ip 194.25.2.129 +# option dest_port 120 +# option proto tcp +# option target REJECT + +#config redirect +# option src lan +# option src_ip 192.168.45.2 +# option src_mac 00:11:22:33:44:55 +# option src_port 1024 +# option src_dport 80 +# option dest_ip 194.25.2.129 +# option dest_port 120 +# option proto tcp diff --git a/openwrt/packages/luci/host/etc/config/freifunk b/openwrt/packages/luci/host/etc/config/freifunk new file mode 100644 index 0000000..862c86d --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/freifunk @@ -0,0 +1,126 @@ +config settings wizard +config public contact + option nickname '' + option name '' + option mail '' + option phone '' + option location '' + option note '' + +config public community + option name 'Freifunk' + option homepage 'http://freifunk.net' + +config fw_rule icmp + option src freifunk + option target ACCEPT + option proto icmp + +config fw_rule http + option src freifunk + option target ACCEPT + option proto tcp + option dest_port 80 + +config fw_rule https + option src freifunk + option target ACCEPT + option proto tcp + option dest_port 443 + +config fw_rule ssh + option src freifunk + option target ACCEPT + option proto tcp + option dest_port 22 + +config fw_rule olsr + option src freifunk + option target ACCEPT + option proto udp + option dest_port 698 + +config fw_forwarding lan + option src lan + option dest freifunk + +config fw_forwarding fffwd + option src freifunk + option dest freifunk + + +config defaults wifi_device + option channel 1 + option diversity 1 + option disabled 0 + option txpower 10 + + +config defaults wifi_iface + option mode adhoc + option bssid 02:CA:FF:EE:BA:BE + option sw_merge 1 + + +config defaults interface + option netmask 255.0.0.0 + option dns "88.198.178.18 141.54.1.1 212.204.49.83 208.67.220.220 208.67.222.222" + + +config defaults alias + option netmask 255.255.255.0 + + +config defaults dhcp + option leasetime 30m + + +config defaults olsr_interface + option HelloInterval 6.0 + option HelloValidityTime 108.0 + option TcInterval 4.0 + option TcValidityTime 324.0 + option MidInterval 18.0 + option MidValidityTime 324.0 + option HnaInterval 18.0 + option HnaValidityTime 108.0 + + +config community leipzig + option name "Freifunk Leipzig" + option homepage http://leipzig.freifunk.net + option ssid "leipzig.freifunk.net" + option prefix "104.61" + +config community halle + option name "Freifunk Halle" + option homepage http://halle.freifunk.net + option ssid "halle.freifunk.net" + option prefix "104.62" + +config community l59 + option name "Freifunk L59" + option homepage http://freifunk.net + option ssid "start.freifunk.net" + option prefix "104.59" + +config community berlin + option name "Freifunk Berlin" + option homepage http://berlin.freifunk.net + option ssid "olsr.freifunk.net" + option prefix "104" + option external freifunk_berlin + +config community hannover + option name "Freifunk Hannover" + option homepage http://hannover.freifunk.net + option ssid "hannover.freifunk.net" + option prefix "10.2" + option external freifunk_hannover + +config community augsburg + option name "Freifunk Augsburg" + option homepage http://augsburg.freifunk.net + option ssid "augsburg.freifunk.net" + option prefix "191.161" + option external freifunk_augsburg diff --git a/openwrt/packages/luci/host/etc/config/freifunk_augsburg b/openwrt/packages/luci/host/etc/config/freifunk_augsburg new file mode 100644 index 0000000..f68600c --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/freifunk_augsburg @@ -0,0 +1,2 @@ +config defaults interface + option netmask 255.255.0.0 \ No newline at end of file diff --git a/openwrt/packages/luci/host/etc/config/freifunk_berlin b/openwrt/packages/luci/host/etc/config/freifunk_berlin new file mode 100644 index 0000000..65bde76 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/freifunk_berlin @@ -0,0 +1,2 @@ +config defaults wifi_device + option channel 10 \ No newline at end of file diff --git a/openwrt/packages/luci/host/etc/config/freifunk_hannover b/openwrt/packages/luci/host/etc/config/freifunk_hannover new file mode 100644 index 0000000..f797a93 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/freifunk_hannover @@ -0,0 +1,5 @@ +config defaults wifi_iface + option bssid CA:FF:EE:CA:FF:EE + +config defaults interface + option netmask 255.255.0.0 \ No newline at end of file diff --git a/openwrt/packages/luci/host/etc/config/fstab b/openwrt/packages/luci/host/etc/config/fstab new file mode 100644 index 0000000..eccf0ce --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/fstab @@ -0,0 +1,10 @@ +config mount + option target /home + option device /dev/sda1 + option fstype ext3 + option options rw,sync + option enabled 0 + +config swap + option device /dev/sda2 + option enabled 0 diff --git a/openwrt/packages/luci/host/etc/config/httpd b/openwrt/packages/luci/host/etc/config/httpd new file mode 100644 index 0000000..2f8020f --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/httpd @@ -0,0 +1,5 @@ + +config 'httpd' + option 'port' '80' + option 'home' '/www' + diff --git a/openwrt/packages/luci/host/etc/config/luci b/openwrt/packages/luci/host/etc/config/luci new file mode 100644 index 0000000..c890105 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/luci @@ -0,0 +1,43 @@ + +config 'core' 'main' + option 'lang' 'auto' + option 'resourcebase' '/luci-static/resources' + option 'mediaurlbase' '/luci-static/oxygen' + +config 'extern' 'flash_keep' + option 'uci' '/etc/config/' + option 'dropbear' '/etc/dropbear/' + option 'openvpn' '/etc/openvpn/' + option 'passwd' '/etc/passwd' + option 'opkg' '/etc/opkg.conf' + option 'firewall' '/etc/firewall.user' + option 'uploads' '/lib/uci/upload/' + +config 'internal' 'languages' + option 'ru' 'Russian' + option 'it' 'Italian' + option 'en' 'English' + option 'de' 'Deutsch' + option 'fr' 'Francais' + option 'pt_br' 'Portuguese (Brazilian)' + +config 'internal' 'sauth' + option 'sessionpath' '/tmp/luci-sessions' + option 'sessiontime' '3600' + +config 'internal' 'ccache' + option 'enable' '1' + +config 'internal' 'template' + option 'compiler_mode' 'file' + option 'compiledir' '/tmp/luci-templatecache' + +config 'internal' 'themes' + option 'OpenWrt_Light' '/luci-static/openwrt-light' + option 'Fledermaus' '/luci-static/fledermaus' + option 'Oxygen' '/luci-static/oxygen' + option 'OpenWrtOxygen' '/luci-static/openwrt.org-oxygen' + option 'OpenWrt' '/luci-static/openwrt.org' + option 'Freifunk' '/luci-static/freifunk' + option 'Freifunk_BNO' '/luci-static/freifunk-bno' + diff --git a/openwrt/packages/luci/host/etc/config/luci_ethers b/openwrt/packages/luci/host/etc/config/luci_ethers new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/luci_ethers @@ -0,0 +1 @@ + diff --git a/openwrt/packages/luci/host/etc/config/luci_hosts b/openwrt/packages/luci/host/etc/config/luci_hosts new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/luci_hosts @@ -0,0 +1 @@ + diff --git a/openwrt/packages/luci/host/etc/config/luci_splash b/openwrt/packages/luci/host/etc/config/luci_splash new file mode 100644 index 0000000..c4cfef5 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/luci_splash @@ -0,0 +1,2 @@ +config core general + option leasetime 1 \ No newline at end of file diff --git a/openwrt/packages/luci/host/etc/config/luci_statistics b/openwrt/packages/luci/host/etc/config/luci_statistics new file mode 100644 index 0000000..f6d870e --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/luci_statistics @@ -0,0 +1,132 @@ +config 'statistics' 'rrdtool' + option 'default_timespan' '1hour' + option 'image_width' '400' + option 'image_path' '/tmp/rrdimg' + +config 'statistics' 'collectd' + option 'BaseDir' '/var/run/collectd' + option 'Include' '/etc/collectd/conf.d' + option 'PIDFile' '/var/run/collectd.pid' + option 'PluginDir' '/usr/lib/collectd' + option 'TypesDB' '/usr/lib/collectd/types.db' + option 'Interval' '30' + option 'ReadThreads' '2' + +config 'statistics' 'collectd_ping' + option 'enable' '0' + option 'TTL' '127' + option 'Hosts' '127.0.0.1' + +config 'statistics' 'collectd_csv' + option 'enable' '0' + option 'StoreRates' '0' + option 'DataDir' '/tmp' + +config 'statistics' 'collectd_df' + option 'enable' '0' + option 'Devices' '/dev/mtdblock/4' + option 'MountPoints' '/jffs' + option 'FSTypes' 'tmpfs' + option 'IgnoreSelected' '0' + +config 'statistics' 'collectd_disk' + option 'enable' '0' + option 'Disks' 'hda1 hdb' + option 'IgnoreSelected' '0' + +config 'statistics' 'collectd_dns' + option 'enable' '0' + option 'Interfaces' 'ffdhcp ff br-lan' + option 'IgnoreSources' '127.0.0.1' + +config 'statistics' 'collectd_email' + option 'enable' '0' + option 'SocketFile' '/var/run/collectd/email.sock' + option 'SocketGroup' 'nogroup' + +config 'statistics' 'collectd_exec' + option 'enable' '1' + +config 'collectd_exec_input' + option 'cmdline' '/usr/bin/stat-input-olsr' + +config 'collectd_exec_notify' + option 'cmdline' '/usr/bin/stat-output-syslog' + +config 'statistics' 'collectd_interface' + option 'enable' '1' + option 'Interfaces' 'br-lan br-ff' + option 'IgnoreSelected' '0' + +config 'statistics' 'collectd_iptables' + option 'enable' '1' + +config 'collectd_iptables_match' + option 'table' 'nat' + option 'chain' 'luci_fw_postrouting' + option 'target' 'MASQUERADE' + option 'source' '192.168.1.0/24' + option 'outputif' 'br-ff' + option 'name' 'Verkehr LAN-Clients' + +config 'collectd_iptables_match' + option 'chain' 'luci_fw_postrouting' + option 'table' 'nat' + option 'target' 'MASQUERADE' + option 'source' '10.61.230.0/24' + option 'outputif' 'br-ff' + option 'name' 'Verkehr WLAN-Clients' + +config 'statistics' 'collectd_irq' + option 'enable' '0' + option 'Irqs' '2 3 4 7' + +config 'statistics' 'collectd_load' + option 'enable' '1' + +config 'statistics' 'collectd_logfile' + option 'enable' '0' + option 'LogLevel' 'notice' + option 'File' '/var/log/collectd.log' + option 'Timestamp' '1' + +config 'statistics' 'collectd_netlink' + option 'enable' '0' + option 'IgnoreSelected' '0' + option 'VerboseInterfaces' 'br-lan br-ff' + option 'QDiscs' 'br-lan br-ff' + +config 'statistics' 'collectd_network' + option 'enable' '0' + +config 'collectd_network_listen' + option 'host' '0.0.0.0' + +config 'collectd_network_server' + option 'host' '0.0.0.0' + +config 'statistics' 'collectd_processes' + option 'enable' '1' + +config 'statistics' 'collectd_tcpconns' + option 'enable' '1' + option 'ListeningPorts' '0' + option 'LocalPorts' '22 80' + +config 'statistics' 'collectd_unixsock' + option 'enable' '0' + option 'SocketFile' '/var/run/collectd/query.sock' + option 'SocketGroup' 'nogroup' + +config 'statistics' 'collectd_wireless' + option 'enable' '1' + +config 'statistics' 'collectd_cpu' + option 'enable' '1' + +config 'statistics' 'collectd_rrdtool' + option 'enable' '1' + option 'DataDir' '/tmp' + option 'RRARows' '100' + option 'RRASingle' '1' + option 'RRATimespans' '10min 1hour 1day 1week 1month 1year' diff --git a/openwrt/packages/luci/host/etc/config/lucittpd b/openwrt/packages/luci/host/etc/config/lucittpd new file mode 100644 index 0000000..803a6e5 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/lucittpd @@ -0,0 +1,6 @@ +config lucittpd lucittpd + option port 80 + option timeout 90 + option keepalive 0 + option path /usr/lib/lucittpd/plugins/ + option root /www diff --git a/openwrt/packages/luci/host/etc/config/network b/openwrt/packages/luci/host/etc/config/network new file mode 100644 index 0000000..6f499c9 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/network @@ -0,0 +1,27 @@ +#### VLAN configuration +config switch eth0 + option vlan0 "0 1 2 3 5*" + option vlan1 "4 5" + + +#### Loopback configuration +config interface loopback + option ifname "lo" + option proto static + option ipaddr 127.0.0.1 + option netmask 255.0.0.0 + + +#### LAN configuration +config interface lan + option type bridge + option ifname "eth0" + option proto static + option ipaddr 192.168.1.1 + option netmask 255.255.255.0 + + +#### WAN configuration +config interface wan + option ifname "wlan0" + option proto dhcp diff --git a/openwrt/packages/luci/host/etc/config/ntpclient b/openwrt/packages/luci/host/etc/config/ntpclient new file mode 100644 index 0000000..1b56f1b --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/ntpclient @@ -0,0 +1,22 @@ +config ntpserver + option hostname '0.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '1.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '2.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '3.openwrt.pool.ntp.org' + option port '123' + +config ntpdrift + option freq '0' + +config ntpclient + option interval 60 + #option count 10 diff --git a/openwrt/packages/luci/host/etc/config/qos b/openwrt/packages/luci/host/etc/config/qos new file mode 100644 index 0000000..51959b5 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/qos @@ -0,0 +1,89 @@ +# QoS configuration for OpenWrt + +# INTERFACES: +config interface wan + option classgroup "Default" + option enabled 1 + option overhead 1 + option upload 128 + option download 1024 + +# RULES: +config classify + option target "Bulk" + option ipp2p "all" +config classify + option target "Bulk" + option layer7 "edonkey" +config classify + option target "Bulk" + option layer7 "bittorrent" +config classify + option target "Priority" + option ports "22,53" +config classify + option target "Normal" + option proto "tcp" + option ports "20,21,25,80,110,443,993,995" +config classify + option target "Express" + option ports "5190" +config default + option target "Express" + option proto "udp" + option pktsize "-500" +config reclassify + option target "Priority" + option proto "icmp" +config default + option target "Bulk" + option portrange "1024-65535" +config reclassify + option target "Priority" + option proto "tcp" + option pktsize "-128" + option mark "!Bulk" + option tcpflags "SYN" +config reclassify + option target "Priority" + option proto "tcp" + option pktsize "-128" + option mark "!Bulk" + option tcpflags "ACK" + + +# Don't change the stuff below unless you +# really know what it means :) + +config classgroup "Default" + option classes "Priority Express Normal Bulk" + option default "Normal" + + +config class "Priority" + option packetsize 400 + option maxsize 400 + option avgrate 10 + option priority 20 +config class "Priority_down" + option packetsize 1000 + option avgrate 10 + + +config class "Express" + option packetsize 1000 + option maxsize 800 + option avgrate 50 + option priority 10 + +config class "Normal" + option packetsize 1500 + option packetdelay 100 + option avgrate 10 + option priority 5 +config class "Normal_down" + option avgrate 20 + +config class "Bulk" + option avgrate 1 + option packetdelay 200 diff --git a/openwrt/packages/luci/host/etc/config/siit b/openwrt/packages/luci/host/etc/config/siit new file mode 100644 index 0000000..0fce1ea --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/siit @@ -0,0 +1,10 @@ +config siit ipv6 + option ula_prefix "fd00::" + option ula_global "00ca:ffee:babe::" + option ula_subnet "0000:0000:0000:dada::" + option siit_prefix "::ffff:0000:0000" + +config siit wifi + option essid "6mesh.freifunk.net" + option bssid "02:ca:ff:ee:ba:be" + option channel "1" diff --git a/openwrt/packages/luci/host/etc/config/system b/openwrt/packages/luci/host/etc/config/system new file mode 100644 index 0000000..b0726b7 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/system @@ -0,0 +1,3 @@ +config system + option hostname OpenWrt + option timezone UTC diff --git a/openwrt/packages/luci/host/etc/config/ucitrack b/openwrt/packages/luci/host/etc/config/ucitrack new file mode 100644 index 0000000..422e82e --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/ucitrack @@ -0,0 +1,81 @@ + +config 'network' + option 'init' 'network' + list 'affects' 'dhcp' + +config 'wireless' + list 'affects' 'network' + +config 'firewall' + option 'init' 'firewall' + list 'affects' 'luci-splash' + list 'affects' 'qos' + +config 'olsr' + option 'init' 'olsrd' + +config 'dhcp' + option 'init' 'dnsmasq' + +config 'dropbear' + option 'init' 'dropbear' + +config 'httpd' + option 'init' 'httpd' + +config 'fstab' + option 'init' 'fstab' + +config 'qos' + option 'init' 'qos' + +config 'system' + option 'init' 'led' + +config 'luci_hosts' + option 'init' 'luci_hosts' + list 'affects' 'dhcp' + +config 'luci_ethers' + option 'init' 'luci_ethers' + list 'affects' 'dhcp' + +config 'luci_splash' + option 'init' 'luci_splash' + +config 'upnpd' + option 'init' 'miniupnpd' + +config 'ntpclient' + option 'init' 'ntpclient' + +config 'samba' + option 'init' 'samba' + +config 'tinyproxy' + option 'init' 'tinyproxy' + +config 'polipo' + option 'init' 'polipo' + +config 'ushare' + option 'init' 'ushare' + +config 'hd-idle' + option 'init' 'hd-idle' + +config 'olsrd' + option 'init' 'olsrd' + +config 'mmc_over_gpio' + option 'init' 'mmc_over_gpio' + +config 'p910nd' + option 'init' 'p910nd' + +config 'uvc-streamer' + option 'init' 'uvc-streamer' + +config 'luci_statistics' + option 'init' 'luci_statistics' + diff --git a/openwrt/packages/luci/host/etc/config/upnpd b/openwrt/packages/luci/host/etc/config/upnpd new file mode 100644 index 0000000..75dcb9a --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/upnpd @@ -0,0 +1,4 @@ +config upnpd config + option log_output 0 + option download 1024 + option upload 512 diff --git a/openwrt/packages/luci/host/etc/config/wireless b/openwrt/packages/luci/host/etc/config/wireless new file mode 100644 index 0000000..4895797 --- /dev/null +++ b/openwrt/packages/luci/host/etc/config/wireless @@ -0,0 +1,13 @@ +config wifi-device wifi0 + option type atheros + option channel auto + + # REMOVE THIS LINE TO ENABLE WIFI: + option disabled 1 + +config wifi-iface + option device wifi0 + option network lan + option mode ap + option ssid OpenWrt + option encryption none diff --git a/openwrt/packages/luci/host/etc/cron.minutely/luci_splash b/openwrt/packages/luci/host/etc/cron.minutely/luci_splash new file mode 100755 index 0000000..eae4294 --- /dev/null +++ b/openwrt/packages/luci/host/etc/cron.minutely/luci_splash @@ -0,0 +1,2 @@ +#!/bin/sh +[ "$(date +%M | cut -c2)" == "5" ] && luci-splash sync \ No newline at end of file diff --git a/openwrt/packages/luci/host/etc/firewall.freifunk b/openwrt/packages/luci/host/etc/firewall.freifunk new file mode 100644 index 0000000..3a33127 --- /dev/null +++ b/openwrt/packages/luci/host/etc/firewall.freifunk @@ -0,0 +1,53 @@ +#!/bin/sh +# Freifunk Firewall addons +# $Id: firewall.freifunk 4140 2009-01-25 19:38:41Z jow $ + + +# +# Apply advanced settings +# +apply_advanced() { + local tcp_ecn + local tcp_window_scaling + local accept_redirects + local accept_source_route + + config_get_bool tcp_ecn $1 tcp_ecn 1 + config_get_bool tcp_window_scaling $1 tcp_window_scaling 1 + config_get_bool accept_redirects $1 accept_redirects 0 + config_get_bool accept_source_route $1 accept_source_route 0 + + logger -t firewall.freifunk "tcp_ecn is $tcp_ecn" + logger -t firewall.freifunk "tcp_window_scaling is $tcp_window_scaling" + logger -t firewall.freifunk "accept_redirects is $accept_redirects" + logger -t firewall.freifunk "accept_source_route is $accept_source_route" + + sysctl -w net.ipv4.tcp_ecn=$tcp_ecn >/dev/null + sysctl -w net.ipv4.tcp_window_scaling=$tcp_window_scaling >/dev/null + + for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do + echo $accept_redirects > $f + done + + for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do + echo $accept_source_route > $f + done +} + +config_foreach apply_advanced advanced + + +# +# Apply fixes for masquerading rules +# +apply_nat_fix() { + local up + local ifname + config_get up $1 up + [ -n "$up" ] || return 0 + (ACTION="ifup" INTERFACE="$1" . /etc/hotplug.d/iface/22-firewall-nat-fix ) +} + +uci_set_state firewall core loaded 1 +config_foreach fw_addif interface +config_foreach apply_nat_fix interface diff --git a/openwrt/packages/luci/host/etc/hotplug.d/iface/22-firewall-nat-fix b/openwrt/packages/luci/host/etc/hotplug.d/iface/22-firewall-nat-fix new file mode 100644 index 0000000..634f432 --- /dev/null +++ b/openwrt/packages/luci/host/etc/hotplug.d/iface/22-firewall-nat-fix @@ -0,0 +1,61 @@ +. /lib/firewall/uci_firewall.sh +unset ZONE +config_get ifname $INTERFACE ifname +[ "$ifname" == "lo" ] && exit 0 + +load_zones() { + local name + local network + config_get name $1 name + config_get network $1 network + [ -z "$network" ] && network=$name + for n in $network; do + [ "$n" = "$INTERFACE" ] && ZONE="$ZONE $name" + done +} + +config_foreach load_zones zone + +[ -z "$ZONE" ] && exit 0 + +natfix_addr_add() { + local network=$1 + local iface=$2 + + config_get parent "$1" interface + [ "$network" != "$INTERFACE" -a "$parent" != "$INTERFACE" ] && return 0 + + config_get ipaddr "$network" ipaddr + [ -n "$ipaddr" ] || return 0 + config_get netmask "$network" netmask + [ -n "$netmask" ] || return 0 + eval "$(ipcalc.sh $ipaddr $netmask)" + + logger -t firewall.freifunk "adding nat rule for $iface($NETWORK/$PREFIX)" + iptables -t nat -A "natfix_$iface" -s "$NETWORK/$PREFIX" -d "$NETWORK/$PREFIX" -j ACCEPT +} + +[ ifup = "$ACTION" ] && { + iptables -t nat -N "natfix_$ifname" + natfix_addr_add "$INTERFACE" "$ifname" + config_foreach natfix_addr_add alias "$ifname" + + for z in $ZONE; do + local loaded + config_get loaded core loaded + [ -n "$loaded" ] && { + logger -t firewall.freifunk "applying nat rules on zone $z" + iptables -t nat -I "zone_${z}_nat" 1 -o "$ifname" -j "natfix_$ifname" + } + done +} + +[ ifdown = "$ACTION" ] && { + for z in $ZONE; do + local up + config_get up $z up + iptables -t nat -D "zone_${z}_nat" -o "$ifname" -j "natfix_$ifname" 2>/dev/null + done + iptables -t nat -F "natfix_$ifname" 2>/dev/null + iptables -t nat -X "natfix_$ifname" 2>/dev/null +} diff --git a/openwrt/packages/luci/host/etc/init.d/boa b/openwrt/packages/luci/host/etc/init.d/boa new file mode 100755 index 0000000..2a11ed7 --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/boa @@ -0,0 +1,57 @@ +#!/bin/sh /etc/rc.common +# +# Written by Miquel van Smoorenburg . +# Modified for Debian GNU/Linux +# by Ian Murdock . +# Modified for boa by Bill Allombert . +# Modified for OpenWrt by Steven Barth . + +### BEGIN INIT INFO +# Provides: boa +# Required-Start: $local_fs $remote_fs $network +# Required-Stop: $local_fs $remote_fs $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Boa: lightweight and high performance web server +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/boa +NAME=boa +DESC="HTTP server" +START=49 + +test -x $DAEMON || exit 0 + +set -e + +start() { + echo -n "Starting $DESC: $NAME" + start-stop-daemon -S -q -x $DAEMON + echo "." +} + +stop() { + echo -n "Stopping $DESC: $NAME" + start-stop-daemon -K -q -x $DAEMON + echo "." +} + +restart() { + echo -n "Restarting $DESC: $NAME... " + start-stop-daemon -K -s HUP -q -x $DAEMON + echo "done." +} + +reload() { + # + # If the daemon can reload its config files on the fly + # for example by sending it SIGHUP, do it here. + # + # If the daemon responds to changes in its config file + # directly anyway, make this a do-nothing entry. + # + echo -n "Reloading $DESC configuration... " + start-stop-daemon -K -s 1 -q -x $DAEMON + echo "done." +} diff --git a/openwrt/packages/luci/host/etc/init.d/freifunk b/openwrt/packages/luci/host/etc/init.d/freifunk new file mode 100755 index 0000000..60c0eb5 --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/freifunk @@ -0,0 +1,24 @@ +#!/bin/sh /etc/rc.common +# Freifunk Init +# $Id: freifunk 4214 2009-01-31 17:32:35Z jow $ + +START=99 + +boot() { + grep -q 'killall -HUP dnsmasq' /etc/crontabs/root || { + echo "*/5 * * * * killall -HUP dnsmasq" >> /etc/crontabs/root + } + + grep -q '/usr/sbin/ff_olsr_test_gw' /etc/crontabs/root || { + echo "* * * * * /usr/sbin/ff_olsr_test_gw" >> /etc/crontabs/root + } + + [ -f /etc/rc.local ] && . /etc/rc.local + [ -d /etc/rc.local.d ] && { + for file in /etc/rc.local.d/*; do + test -f "$file" && . "$file" + done + } + + killall -HUP crond 2>/dev/null || /etc/init.d/cron start +} diff --git a/openwrt/packages/luci/host/etc/init.d/luci_ethers b/openwrt/packages/luci/host/etc/init.d/luci_ethers new file mode 100755 index 0000000..fb1deb2 --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/luci_ethers @@ -0,0 +1,37 @@ +#!/bin/sh /etc/rc.common +START=59 + +apply_lease() { + local cfg="$1" + + config_get macaddr "$cfg" macaddr + config_get ipaddr "$cfg" ipaddr + + [ -n "$macaddr" -a -n "$ipaddr" ] || return 0 + + echo "$macaddr $ipaddr" >> /var/etc/ethers +} + +start() { + if [ ! -L /etc/ethers ]; then + test -f /etc/ethers && mv /etc/ethers /etc/ethers.local + ln -s /var/etc/ethers /etc/ethers + fi + + test -d /var/etc || mkdir -p /var/etc + + echo "# This file is autogenerated, use /etc/ethers.local instead" > /var/etc/ethers + + config_load luci_ethers + config_foreach apply_lease static_lease + + test -f /etc/ethers.local && cat /etc/ethers.local >> /var/etc/ethers + + return 0 +} + +stop() { + test -f /var/etc/ethers && rm -f /var/etc/ethers + + return 0 +} diff --git a/openwrt/packages/luci/host/etc/init.d/luci_fixtime b/openwrt/packages/luci/host/etc/init.d/luci_fixtime new file mode 100755 index 0000000..f300e45 --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/luci_fixtime @@ -0,0 +1,11 @@ +#!/bin/sh /etc/rc.common + +START=05 + +start() { + cat <<' EOF' | lua -l luci.fs -l luci.util - + if (os.time() < 1000000000) then + os.execute('date -s ' .. os.date('%m%d%H%M%Y', luci.fs.mtime("/etc/init.d/luci_fixtime"))) + end + EOF +} diff --git a/openwrt/packages/luci/host/etc/init.d/luci_hosts b/openwrt/packages/luci/host/etc/init.d/luci_hosts new file mode 100755 index 0000000..ae94714 --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/luci_hosts @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common +START=59 + +apply_host() { + local cfg="$1" + + config_get hostname "$cfg" hostname + config_get ipaddr "$cfg" ipaddr + + [ -n "$hostname" -a -n "$ipaddr" ] || return 0 + + echo "$ipaddr $hostname" >> /var/etc/hosts +} + +start() { + if [ ! -L /etc/hosts ]; then + test -f /etc/hosts && mv /etc/hosts /etc/hosts.local + ln -s /var/etc/hosts /etc/hosts + fi + + echo "# This file is autogenerated, use /etc/hosts.local instead" > /var/etc/hosts + + test -d /var/etc || mkdir -p /var/etc + test -f /etc/hosts.local && cat /etc/hosts.local >> /var/etc/hosts + + config_load luci_hosts + config_foreach apply_host host + + return 0 +} + +stop() { + test -f /var/etc/hosts && rm -f /var/etc/hosts + + return 0 +} diff --git a/openwrt/packages/luci/host/etc/init.d/luci_splash b/openwrt/packages/luci/host/etc/init.d/luci_splash new file mode 100755 index 0000000..85ea8ec --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/luci_splash @@ -0,0 +1,87 @@ +#!/bin/sh /etc/rc.common +START=70 + +iface_add() { + local cfg="$1" + + config_get zone "$cfg" zone + [ -n "$zone" ] || return 0 + + config_get net "$cfg" network + [ -n "$net" ] || return 0 + + config_get ipaddr "$net" ipaddr + [ -n "$ipaddr" ] || return 0 + + config_get netmask "$net" netmask + [ -n "$netmask" ] || return 0 + + eval "$(ipcalc.sh $ipaddr $netmask)" + + iptables -t nat -A zone_${zone}_prerouting -s "$NETWORK/$PREFIX" -p ! tcp -j luci_splash_portal + iptables -t nat -A zone_${zone}_prerouting -s "$NETWORK/$PREFIX" -d ! "$ipaddr" -j luci_splash_portal + iptables -t nat -A zone_${zone}_prerouting -s "$NETWORK/$PREFIX" -d "$ipaddr" -p tcp -m multiport ! --dport 22,80,443 -j luci_splash_portal +} + +blacklist_add() { + local cfg="$1" + + config_get mac "$cfg" mac + [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j DROP +} + +whitelist_add() { + local cfg="$1" + + config_get mac "$cfg" mac + [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j RETURN +} + +start() { + ### Read chains from config + include /lib/network + scan_interfaces + config_load luci_splash + + ### Create subchains + iptables -t nat -N luci_splash + iptables -t nat -N luci_splash_portal + iptables -t nat -N luci_splash_leases + + ### Build the main and portal rule + config_foreach blacklist_add blacklist + config_foreach whitelist_add whitelist + config_foreach iface_add iface + + ### Build the portal rule + iptables -t nat -A luci_splash_portal -p udp --dport 53 -j RETURN + iptables -t nat -A luci_splash_portal -j luci_splash_leases + + ### Build the leases rule + iptables -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082 + iptables -t nat -A luci_splash_leases -j DROP + + ### Add crontab entry + grep luci-splash /var/spool/cron/crontabs/root >/dev/null 2>&1 || { + echo '*/5 * * * * /usr/sbin/luci-splash sync' >> /var/spool/cron/crontabs/root + } + + ### Start the splash httpd + start-stop-daemon -S -b -q -x /usr/bin/luci-splashd +} + +stop() { + ### Clear subchains + iptables -t nat -F luci_splash_leases + iptables -t nat -F luci_splash_portal + iptables -t nat -F luci_splash + + ### Delete subchains + iptables -t nat -X luci_splash_leases + iptables -t nat -X luci_splash_portal + iptables -t nat -X luci_splash + + ### Stop the splash httpd + start-stop-daemon -K -q -x /usr/bin/luci-splashd +} + diff --git a/openwrt/packages/luci/host/etc/init.d/luci_statistics b/openwrt/packages/luci/host/etc/init.d/luci_statistics new file mode 100755 index 0000000..e4da1d5 --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/luci_statistics @@ -0,0 +1,31 @@ +#!/bin/sh /etc/rc.common +START=79 + +start() { + ### replace shipped config with symlink + if [ ! -L /etc/collectd.conf ]; then + test -f /etc/collectd.conf && mv /etc/collectd.conf /etc/collectd.conf.bak + ln -s /var/etc/collectd.conf /etc/collectd.conf + fi + + ### create config + mkdir -p /var/etc + /usr/bin/stat-genconfig > /var/etc/collectd.conf + + ### prepare rrdimg directory + if [ ! -L /www/rrdimg ]; then + imagepath="$(uci get luci_statistics.rrdtool.image_path)" + ln -s ${imagepath:-/tmp/rrdimg}/ /www/rrdimg + fi + + ### flush LuCI index cache + test -f /var/luci-indexcache && rm /var/luci-indexcache +} + +restart() { + ### regenerate config / prepare environment + start + + ### restart collectd + /etc/init.d/collectd restart +} diff --git a/openwrt/packages/luci/host/etc/init.d/lucittpd b/openwrt/packages/luci/host/etc/init.d/lucittpd new file mode 100755 index 0000000..a7f78e0 --- /dev/null +++ b/openwrt/packages/luci/host/etc/init.d/lucittpd @@ -0,0 +1,44 @@ +#!/bin/sh /etc/rc.common +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/lucittpd +NAME=lucittpd +DESC="HTTP server" +START=49 + +test -x $DAEMON || exit 0 +set -e + +start() { + echo -n "Starting $DESC: $NAME" + start-stop-daemon -b -S -q -x $DAEMON + echo "." +} + +stop() { + echo -n "Stopping $DESC: $NAME" + start-stop-daemon -K -q -x $DAEMON + echo "." +} + +restart() { + # echo -n "Restarting $DESC: $NAME... " + # start-stop-daemon -K -s HUP -q -x $DAEMON + # echo "done." + stop + sleep 3 + start +} + +reload() { + # + # If the daemon can reload its config files on the fly + # for example by sending it SIGHUP, do it here. + # + # If the daemon responds to changes in its config file + # directly anyway, make this a do-nothing entry. + # + # echo -n "Reloading $DESC configuration... " + # start-stop-daemon -K -s 1 -q -x $DAEMON + # echo "done." + restart +} diff --git a/openwrt/packages/luci/host/etc/lpk.conf b/openwrt/packages/luci/host/etc/lpk.conf new file mode 100644 index 0000000..7ff49f8 --- /dev/null +++ b/openwrt/packages/luci/host/etc/lpk.conf @@ -0,0 +1 @@ +backend.model = "ipkg" \ No newline at end of file diff --git a/openwrt/packages/luci/host/etc/mime.types b/openwrt/packages/luci/host/etc/mime.types new file mode 100644 index 0000000..ee11c1b --- /dev/null +++ b/openwrt/packages/luci/host/etc/mime.types @@ -0,0 +1,748 @@ +############################################################################### +# +# MIME-TYPES and the extensions that represent them +# +# This file is part of the "mime-support" package. Please send email (not a +# bug report) to mime-support@packages.debian.org if you would like new types +# and/or extensions to be added. +# +# The reason that all types are managed by the mime-support package instead +# allowing individual packages to install types in much the same way as they +# add entries in to the mailcap file is so these types can be referenced by +# other programs (such as a web server) even if the specific support package +# for that type is not installed. +# +# Users can add their own types if they wish by creating a ".mime.types" +# file in their home directory. Definitions included there will take +# precedence over those listed here. +# +# Note: Compression schemes like "gzip", "bzip", and "compress" are not +# actually "mime-types". They are "encodings" and hence must _not_ have +# entries in this file to map their extensions. The "mime-type" of an +# encoded file refers to the type of data that has been encoded, not the +# type of encoding. +# +############################################################################### + + +application/activemessage +application/andrew-inset ez +application/applefile +application/atom atom +application/atomcat+xml atomcat +application/atomserv+xml atomsrv +application/atomicmail +application/batch-SMTP +application/beep+xml +application/cals-1840 +application/cap cap pcap +application/commonground +application/cu-seeme cu +application/cybercash +application/dca-rft +application/dec-dx +application/docbook+xml +application/dsptype tsp +application/dvcs +application/edi-consent +application/edi-x12 +application/edifact +application/eshop +application/font-tdpfr +application/futuresplash spl +application/ghostview +application/hta hta +application/http +application/hyperstudio +application/iges +application/index +application/index.cmd +application/index.obj +application/index.response +application/index.vnd +application/iotp +application/ipp +application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/macwriteii +application/marc +application/mathematica nb +application/mathematica-old +application/ms-tnef +application/msaccess mdb +application/msword doc dot +application/news-message-id +application/news-transmission +application/ocsp-request +application/ocsp-response +application/octet-stream bin +application/oda oda +application/ogg ogg +application/parityfec +application/pdf pdf +application/pgp-encrypted +application/pgp-keys key +application/pgp-signature pgp +application/pics-rules prf +application/pkcs10 +application/pkcs7-mime +application/pkcs7-signature +application/pkix-cert +application/pkix-crl +application/pkixcmp +application/postscript ps ai eps +application/prs.alvestrand.titrax-sheet +application/prs.cww +application/prs.nprend +application/qsig +application/rar rar +application/rdf+xml rdf +application/remote-printing +application/riscos +application/rss+xml rss +application/rtf rtf +application/sdp +application/set-payment +application/set-payment-initiation +application/set-registration +application/set-registration-initiation +application/sgml +application/sgml-open-catalog +application/sieve +application/slate +application/smil smi smil +application/timestamp-query +application/timestamp-reply +application/vemmi +application/whoispp-query +application/whoispp-response +application/wita +application/wordperfect wpd +application/wordperfect5.1 wp5 +application/x400-bp +application/xhtml+xml xhtml xht +application/xml xml xsl +application/xml-dtd +application/xml-external-parsed-entity +application/zip zip +application/vnd.3M.Post-it-Notes +application/vnd.accpac.simply.aso +application/vnd.accpac.simply.imp +application/vnd.acucobol +application/vnd.aether.imp +application/vnd.anser-web-certificate-issue-initiation +application/vnd.anser-web-funds-transfer-initiation +application/vnd.audiograph +application/vnd.bmi +application/vnd.businessobjects +application/vnd.canon-cpdl +application/vnd.canon-lips +application/vnd.cinderella cdy +application/vnd.claymore +application/vnd.commerce-battelle +application/vnd.commonspace +application/vnd.comsocaller +application/vnd.contact.cmsg +application/vnd.cosmocaller +application/vnd.ctc-posml +application/vnd.cups-postscript +application/vnd.cups-raster +application/vnd.cups-raw +application/vnd.cybank +application/vnd.dna +application/vnd.dpgraph +application/vnd.dxr +application/vnd.ecdis-update +application/vnd.ecowin.chart +application/vnd.ecowin.filerequest +application/vnd.ecowin.fileupdate +application/vnd.ecowin.series +application/vnd.ecowin.seriesrequest +application/vnd.ecowin.seriesupdate +application/vnd.enliven +application/vnd.epson.esf +application/vnd.epson.msf +application/vnd.epson.quickanime +application/vnd.epson.salt +application/vnd.epson.ssf +application/vnd.ericsson.quickcall +application/vnd.eudora.data +application/vnd.fdf +application/vnd.ffsns +application/vnd.flographit +application/vnd.framemaker +application/vnd.fsc.weblaunch +application/vnd.fujitsu.oasys +application/vnd.fujitsu.oasys2 +application/vnd.fujitsu.oasys3 +application/vnd.fujitsu.oasysgp +application/vnd.fujitsu.oasysprs +application/vnd.fujixerox.ddd +application/vnd.fujixerox.docuworks +application/vnd.fujixerox.docuworks.binder +application/vnd.fut-misnet +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq +application/vnd.groove-account +application/vnd.groove-identity-message +application/vnd.groove-injector +application/vnd.groove-tool-message +application/vnd.groove-tool-template +application/vnd.groove-vcard +application/vnd.hhe.lesson-player +application/vnd.hp-HPGL +application/vnd.hp-PCL +application/vnd.hp-PCLXL +application/vnd.hp-hpid +application/vnd.hp-hps +application/vnd.httphone +application/vnd.hzn-3d-crossword +application/vnd.ibm.MiniPay +application/vnd.ibm.afplinedata +application/vnd.ibm.modcap +application/vnd.informix-visionary +application/vnd.intercon.formnet +application/vnd.intertrust.digibox +application/vnd.intertrust.nncp +application/vnd.intu.qbo +application/vnd.intu.qfx +application/vnd.irepository.package+xml +application/vnd.is-xpr +application/vnd.japannet-directory-service +application/vnd.japannet-jpnstore-wakeup +application/vnd.japannet-payment-wakeup +application/vnd.japannet-registration +application/vnd.japannet-registration-wakeup +application/vnd.japannet-setstore-wakeup +application/vnd.japannet-verification +application/vnd.japannet-verification-wakeup +application/vnd.koan +application/vnd.lotus-1-2-3 +application/vnd.lotus-approach +application/vnd.lotus-freelance +application/vnd.lotus-notes +application/vnd.lotus-organizer +application/vnd.lotus-screencam +application/vnd.lotus-wordpro +application/vnd.mcd +application/vnd.mediastation.cdkey +application/vnd.meridian-slingshot +application/vnd.mif +application/vnd.minisoft-hp3000-save +application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf +application/vnd.mobius.dis +application/vnd.mobius.msl +application/vnd.mobius.plc +application/vnd.mobius.txf +application/vnd.motorola.flexsuite +application/vnd.motorola.flexsuite.adsi +application/vnd.motorola.flexsuite.fis +application/vnd.motorola.flexsuite.gotap +application/vnd.motorola.flexsuite.kmr +application/vnd.motorola.flexsuite.ttc +application/vnd.motorola.flexsuite.wem +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry +application/vnd.ms-asf +application/vnd.ms-excel xls xlb xlt +application/vnd.ms-lrm +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +application/vnd.ms-powerpoint ppt pps +application/vnd.ms-project +application/vnd.ms-tnef +application/vnd.ms-works +application/vnd.mseq +application/vnd.msign +application/vnd.music-niff +application/vnd.musician +application/vnd.netfpx +application/vnd.noblenet-directory +application/vnd.noblenet-sealer +application/vnd.noblenet-web +application/vnd.novadigm.EDM +application/vnd.novadigm.EDX +application/vnd.novadigm.EXT +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +application/vnd.osa.netdeploy +application/vnd.palm +application/vnd.pg.format +application/vnd.pg.osasli +application/vnd.powerbuilder6 +application/vnd.powerbuilder6-s +application/vnd.powerbuilder7 +application/vnd.powerbuilder7-s +application/vnd.powerbuilder75 +application/vnd.powerbuilder75-s +application/vnd.previewsystems.box +application/vnd.publishare-delta-tree +application/vnd.pvi.ptid1 +application/vnd.pwg-xhtml-print+xml +application/vnd.rapid +application/vnd.rim.cod cod +application/vnd.s3sms +application/vnd.seemail +application/vnd.shana.informed.formdata +application/vnd.shana.informed.formtemplate +application/vnd.shana.informed.interchange +application/vnd.shana.informed.package +application/vnd.smaf mmf +application/vnd.sss-cod +application/vnd.sss-dtf +application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.chart sds +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math sdf +application/vnd.stardivision.writer sdw +application/vnd.stardivision.writer-global sgl +application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +application/vnd.svd +application/vnd.swiftview-ics +application/vnd.symbian.install sis +application/vnd.triscape.mxs +application/vnd.trueapp +application/vnd.truedoc +application/vnd.tve-trigger +application/vnd.ufdl +application/vnd.uplanet.alert +application/vnd.uplanet.alert-wbxml +application/vnd.uplanet.bearer-choice +application/vnd.uplanet.bearer-choice-wbxml +application/vnd.uplanet.cacheop +application/vnd.uplanet.cacheop-wbxml +application/vnd.uplanet.channel +application/vnd.uplanet.channel-wbxml +application/vnd.uplanet.list +application/vnd.uplanet.list-wbxml +application/vnd.uplanet.listcmd +application/vnd.uplanet.listcmd-wbxml +application/vnd.uplanet.signal +application/vnd.vcx +application/vnd.vectorworks +application/vnd.vidsoft.vidconference +application/vnd.visio vsd +application/vnd.vividence.scriptfile +application/vnd.wap.sic +application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo +application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf +application/vnd.xara +application/vnd.xfdl +application/vnd.yellowriver-custom-menu +application/x-123 wk +application/x-7z-compressed 7z +application/x-abiword abw +application/x-apple-diskimage dmg +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-cab cab +application/x-cbr cbr +application/x-cbz cbz +application/x-cdf cdf +application/x-cdlink vcd +application/x-chess-pgn pgn +application/x-core +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dcr dir dxr +application/x-dms dms +application/x-doom wad +application/x-dvi dvi +application/x-httpd-eruby rhtml +application/x-executable +application/x-flac flac +application/x-font pfa pfb gsf pcf pcf.Z +application/x-freemind mm +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-go-sgf sgf +application/x-graphing-calculator gcf +application/x-gtar gtar tgz taz +application/x-hdf hdf +application/x-httpd-php phtml pht php +application/x-httpd-php-source phps +application/x-httpd-php3 php3 +application/x-httpd-php3-preprocessed php3p +application/x-httpd-php4 php4 +application/x-ica ica +application/x-internet-signup ins isp +application/x-iphone iii +application/x-iso9660-image iso +application/x-java-applet +application/x-java-bean +application/x-java-jnlp-file jnlp +application/x-javascript js +application/x-jmol jmz +application/x-kchart chrt +application/x-kdelnk +application/x-killustrator kil +application/x-koan skp skd skt skm +application/x-kpresenter kpr kpt +application/x-kspread ksp +application/x-kword kwd kwt +application/x-latex latex +application/x-lha lha +application/x-lyx lyx +application/x-lzh lzh +application/x-lzx lzx +application/x-maker frm maker frame fm fb book fbdoc +application/x-mif mif +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-msdos-program com exe bat dll +application/x-msi msi +application/x-netcdf nc +application/x-ns-proxy-autoconfig pac +application/x-nwc nwc +application/x-object o +application/x-oz-application oza +application/x-pkcs7-certreqresp p7r +application/x-pkcs7-crl crl +application/x-python-code pyc pyo +application/x-quicktimeplayer qtl +application/x-redhat-package-manager rpm +application/x-rx +application/x-sh sh +application/x-shar shar +application/x-shellscript +application/x-shockwave-flash swf swfl +application/x-stuffit sit sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex-gf gf +application/x-tex-pk pk +application/x-texinfo texinfo texi +application/x-trash ~ % bak old sik +application/x-troff t tr roff +application/x-troff-man man +application/x-troff-me me +application/x-troff-ms ms +application/x-ustar ustar +application/x-videolan +application/x-wais-source src +application/x-wingz wz +application/x-x509-ca-cert crt +application/x-xcf xcf +application/x-xfig fig +application/x-xpinstall xpi + +audio/32kadpcm +audio/3gpp +audio/basic au snd +audio/g.722.1 +audio/l16 +audio/midi mid midi kar +audio/mp4a-latm +audio/mpa-robust +audio/mpeg mpga mpega mp2 mp3 m4a +audio/mpegurl m3u +audio/parityfec +audio/prs.sid sid +audio/telephone-event +audio/tone +audio/vnd.cisco.nse +audio/vnd.cns.anp1 +audio/vnd.cns.inf1 +audio/vnd.digital-winds +audio/vnd.everad.plj +audio/vnd.lucent.voice +audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 +audio/vnd.nuera.ecelp7470 +audio/vnd.nuera.ecelp9600 +audio/vnd.octel.sbc +audio/vnd.qcelp +audio/vnd.rhetorex.32kadpcm +audio/vnd.vmx.cvsd +audio/x-aiff aif aiff aifc +audio/x-gsm gsm +audio/x-mpegurl m3u +audio/x-ms-wma wma +audio/x-ms-wax wax +audio/x-pn-realaudio-plugin +audio/x-pn-realaudio ra rm ram +audio/x-realaudio ra +audio/x-scpls pls +audio/x-sd2 sd2 +audio/x-wav wav + +chemical/x-alchemy alc +chemical/x-cache cac cache +chemical/x-cache-csf csf +chemical/x-cactvs-binary cbin cascii ctab +chemical/x-cdx cdx +chemical/x-cerius cer +chemical/x-chem3d c3d +chemical/x-chemdraw chm +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-compass cpa +chemical/x-crossfire bsd +chemical/x-csml csml csm +chemical/x-ctx ctx +chemical/x-cxf cxf cef +#chemical/x-daylight-smiles smi +chemical/x-embl-dl-nucleotide emb embl +chemical/x-galactic-spc spc +chemical/x-gamess-input inp gam gamin +chemical/x-gaussian-checkpoint fch fchk +chemical/x-gaussian-cube cub +chemical/x-gaussian-input gau gjc gjf +chemical/x-gaussian-log gal +chemical/x-gcg8-sequence gcg +chemical/x-genbank gen +chemical/x-hin hin +chemical/x-isostar istr ist +chemical/x-jcamp-dx jdx dx +chemical/x-kinemage kin +chemical/x-macmolecule mcm +chemical/x-macromodel-input mmd mmod +chemical/x-mdl-molfile mol +chemical/x-mdl-rdfile rd +chemical/x-mdl-rxnfile rxn +chemical/x-mdl-sdfile sd sdf +chemical/x-mdl-tgf tgf +#chemical/x-mif mif +chemical/x-mmcif mcif +chemical/x-mol2 mol2 +chemical/x-molconn-Z b +chemical/x-mopac-graph gpt +chemical/x-mopac-input mop mopcrt mpc dat zmt +chemical/x-mopac-out moo +chemical/x-mopac-vib mvb +chemical/x-ncbi-asn1 asn +chemical/x-ncbi-asn1-ascii prt ent +chemical/x-ncbi-asn1-binary val aso +chemical/x-ncbi-asn1-spec asn +chemical/x-pdb pdb ent +chemical/x-rosdal ros +chemical/x-swissprot sw +chemical/x-vamas-iso14976 vms +chemical/x-vmd vmd +chemical/x-xtel xtel +chemical/x-xyz xyz + +image/cgm +image/g3fax +image/gif gif +image/ief ief +image/jpeg jpeg jpg jpe +image/naplps +image/pcx pcx +image/png png +image/prs.btif +image/prs.pti +image/svg+xml svg svgz +image/tiff tiff tif +image/vnd.cns.inf2 +image/vnd.djvu djvu djv +image/vnd.dwg +image/vnd.dxf +image/vnd.fastbidsheet +image/vnd.fpx +image/vnd.fst +image/vnd.fujixerox.edmics-mmr +image/vnd.fujixerox.edmics-rlc +image/vnd.mix +image/vnd.net-fpx +image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff +image/x-cmu-raster ras +image/x-coreldraw cdr +image/x-coreldrawpattern pat +image/x-coreldrawtemplate cdt +image/x-corelphotopaint cpt +image/x-icon ico +image/x-jg art +image/x-jng jng +image/x-ms-bmp bmp +image/x-photoshop psd +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd + +inode/chardevice +inode/blockdevice +inode/directory-locked +inode/directory +inode/fifo +inode/socket + +message/delivery-status +message/disposition-notification +message/external-body +message/http +message/s-http +message/news +message/partial +message/rfc822 eml + +model/iges igs iges +model/mesh msh mesh silo +model/vnd.dwf +model/vnd.flatland.3dml +model/vnd.gdl +model/vnd.gs-gdl +model/vnd.gtw +model/vnd.mts +model/vnd.vtu +model/vrml wrl vrml + +multipart/alternative +multipart/appledouble +multipart/byteranges +multipart/digest +multipart/encrypted +multipart/form-data +multipart/header-set +multipart/mixed +multipart/parallel +multipart/related +multipart/report +multipart/signed +multipart/voice-message + +text/calendar ics icz +text/css css +text/csv csv +text/directory +text/english +text/enriched +text/h323 323 +text/html html htm shtml +text/iuls uls +text/mathml mml +text/parityfec +text/plain asc txt text pot +text/prs.lines.tag +text/rfc822-headers +text/richtext rtx +text/rtf +text/scriptlet sct wsc +text/t140 +text/texmacs tm ts +text/tab-separated-values tsv +text/uri-list +text/vnd.abc +text/vnd.curl +text/vnd.DMClientScript +text/vnd.flatland.3dml +text/vnd.fly +text/vnd.fmi.flexstor +text/vnd.in3d.3dml +text/vnd.in3d.spot +text/vnd.IPTC.NewsML +text/vnd.IPTC.NITF +text/vnd.latex-z +text/vnd.motorola.reflex +text/vnd.ms-mediapackage +text/vnd.sun.j2me.app-descriptor jad +text/vnd.wap.si +text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-bibtex bib +text/x-boo boo +text/x-c++hdr h++ hpp hxx hh +text/x-c++src c++ cpp cxx cc +text/x-chdr h +text/x-component htc +text/x-crontab +text/x-csh csh +text/x-csrc c +text/x-dsrc d +text/x-diff diff patch +text/x-haskell hs +text/x-java java +text/x-literate-haskell lhs +text/x-makefile +text/x-moc moc +text/x-pascal p pas +text/x-pcs-gcd gcd +text/x-perl pl pm +text/x-python py +text/x-server-parsed-html +text/x-setext etx +text/x-sh sh +text/x-tcl tcl tk +text/x-tex tex ltx sty cls +text/x-vcalendar vcs +text/x-vcard vcf + +video/3gpp 3gp +video/dl dl +video/dv dif dv +video/fli fli +video/gl gl +video/mpeg mpeg mpg mpe +video/mp4 mp4 +video/quicktime qt mov +video/mp4v-es +video/parityfec +video/pointer +video/vnd.fvt +video/vnd.motorola.video +video/vnd.motorola.videop +video/vnd.mpegurl mxu +video/vnd.mts +video/vnd.nokia.interleaved-multimedia +video/vnd.vivo +video/x-la-asf lsf lsx +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie + +x-conference/x-cooltalk ice + +x-epoc/x-sisx-app sisx +x-world/x-vrml vrm vrml wrl diff --git a/openwrt/packages/luci/host/etc/rc.local b/openwrt/packages/luci/host/etc/rc.local new file mode 100644 index 0000000..58e44e4 --- /dev/null +++ b/openwrt/packages/luci/host/etc/rc.local @@ -0,0 +1,2 @@ +# /etc/rc.local +# Only executed on boot, put your custom startup commands here diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/ddns b/openwrt/packages/luci/host/lib/uci/schema/default/ddns new file mode 100644 index 0000000..f947aff --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/ddns @@ -0,0 +1,147 @@ +package ddns + +config package + option title 'Dynamic DNS configuration' + +config section + option name 'service' + option title 'DynDNS service entry' + option package 'ddns' + option named true + option required true + +config variable + option name 'enabled' + option title 'Enable this service entry' + option section 'ddns.service' + option datatype 'boolean' + +config variable + option name 'service_name' + option title 'Name of the DynDNS provider' + option section 'ddns.service' + option datatype 'string' + +config variable + option name 'domain' + option title 'Own DynDNS domain' + option section 'ddns.service' + option required true + +config variable + option name 'username' + option title 'Account username' + option section 'ddns.service' + option required true + +config variable + option name 'password' + option title 'Account password' + option section 'ddns.service' + option required true + +config variable + option name 'ip_source' + option title 'Method to determine current IP address' + option section 'ddns.service' + option type 'enum' + option required true + +config enum + option variable 'ddns.service.ip_source' + option value 'network' + option title 'Read ip address from /etc/config/network' + +config enum + option variable 'ddns.service.ip_source' + option value 'interface' + option title 'Determine ip address from given hardware interface' + +config enum + option variable 'ddns.service.ip_source' + option value 'web' + option title 'Determine own IP using a remote web page' + +config variable + option name 'ip_network' + option title 'Configured network to use IP from' + option section 'ddns.service' + option depends 'ip_source=network' + option valueof 'network.interface' + +config variable + option name 'ip_interface' + option title 'Physical network interface to read IP from' + option section 'ddns.service' + option depends 'ip_source=interface' + +config variable + option name 'ip_url' + option title 'Web page used to determine IP address' + option section 'ddns.service' + option depends 'ip_source=web' + +config variable + option name 'update_url' + option title 'URL format to use for updating DNS information (for yet-unknown providers)' + option section 'ddns.service' + +config variable + option name 'check_interval' + option title 'Update check interval' + option section 'ddns.service' + option datatype 'integer' + option required true + +config variable + option name 'check_unit' + option title 'Unit for update check interval' + option section 'ddns.service' + option type 'enum' + option required true + +config enum + option variable 'ddns.service.check_unit' + option value 'seconds' + +config enum + option variable 'ddns.service.check_unit' + option value 'minutes' + +config enum + option variable 'ddns.service.check_unit' + option value 'hours' + +config enum + option variable 'ddns.service.check_unit' + option value 'days' + +config variable + option name 'force_interval' + option title 'Forced update interval' + option section 'ddns.service' + option datatype 'integer' + option required true + +config variable + option name 'force_unit' + option title 'Unit of forced update interval' + option section 'ddns.service' + option type 'enum' + option required true + +config enum + option variable 'ddns.service.force_unit' + option value 'seconds' + +config enum + option variable 'ddns.service.force_unit' + option value 'minutes' + +config enum + option variable 'ddns.service.force_unit' + option value 'hours' + +config enum + option variable 'ddns.service.force_unit' + option value 'days' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/dhcp b/openwrt/packages/luci/host/lib/uci/schema/default/dhcp new file mode 100644 index 0000000..86a5a47 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/dhcp @@ -0,0 +1,240 @@ +package dhcp + +config package + option title 'Dnsmasq DHCPd configuration' + +config section + option name 'dnsmasq' + option package 'dhcp' + option title 'General Settings' + option unique true + option required true + option dynamic true + +config variable + option name 'domainneeded' + option section 'dhcp.dnsmasq' + option title 'Domain required' + option description "Don't forward DNS-Requests without DNS-Name" + option datatype boolean + +config variable + option name 'authoritative' + option section 'dhcp.dnsmasq' + option title 'Authoritative' + option description 'This is the only DHCP in the local network' + option datatype boolean + +config variable + option name 'boguspriv' + option section 'dhcp.dnsmasq' + option title 'Filter private' + option description "Don't forward reverse lookups for local networks" + option datatype boolean + +config variable + option name 'filterwin2k' + option section 'dhcp.dnsmasq' + option title 'Filter useless' + option description 'Filter useless DNS-queries of Windows-systems' + option datatype boolean + +config variable + option name 'localise_queries' + option section 'dhcp.dnsmasq' + option title 'Localise queries' + option description 'Localises the hostname depending on its subnet' + option datatype boolean + +config variable + option name 'local' + option section 'dhcp.dnsmasq' + option title 'Local Server' + +config variable + option name 'domain' + option section 'dhcp.dnsmasq' + option title 'Local Domain' + +config variable + option name 'expandhosts' + option section 'dhcp.dnsmasq' + option title 'Expand Hosts' + option description 'adds domain names to hostentries in the resolv file' + option datatype boolean + +config variable + option name 'nonegcache' + option section 'dhcp.dnsmasq' + option title "don't cache unknown" + option description 'prevents caching of negative DNS-replies' + option datatype boolean + +config variable + option name 'readethers' + option section 'dhcp.dnsmasq' + option title 'Use /etc/ethers' + option description 'Read /etc/ethers to configure the DHCP-Server' + option datatype boolean + +config variable + option name 'leasefile' + option section 'dhcp.dnsmasq' + option title 'Leasefile' + option description 'file where given DHCP-leases will be stored' + +config variable + option name 'resolvfile' + option section 'dhcp.dnsmasq' + option title 'Resolvfile' + option description 'local DNS file' + +config variable + option name 'nohosts' + option section 'dhcp.dnsmasq' + option title 'Ignore /etc/hosts ' + option datatype boolean + +config variable + option name 'strictorder' + option section 'dhcp.dnsmasq' + option title 'Strict order' + option description 'DNS-Server will be queried in the order of the resolvfile' + option datatype boolean + +config variable + option name 'logqueries' + option section 'dhcp.dnsmasq' + option title 'Log queries' + option datatype boolean + +config variable + option name 'noresolv' + option section 'dhcp.dnsmasq' + option title 'Ignore resolve file' + option datatype boolean + +config variable + option name 'dnsforwardmax' + option section 'dhcp.dnsmasq' + option title 'concurrent queries' + option datatype uint + +config variable + option name 'port' + option section 'dhcp.dnsmasq' + option title 'DNS-Port' + option datatype port + +config variable + option name 'ednspacket_max' + option section 'dhcp.dnsmasq' + option title 'ednspacket_max' + option datatype uint + +config variable + option name 'dhcpleasemax' + option section 'dhcp.dnsmasq' + option title 'max. DHCP -Leases' + option datatype uint + +config variable + option name 'addnhosts' + option section 'dhcp.dnsmasq' + option title 'additional hostfile' + option datatype file + +config variable + option name 'queryport' + option section 'dhcp.dnsmasq' + option title 'query port' + option datatype port + +config variable + option name 'enable_tftp' + option section 'dhcp.dnsmasq' + option title 'Enable builtin TFTP-Server' + option datatype boolean + +config variable + option name 'tftp_root' + option section 'dhcp.dnsmasq' + option title 'TFTP-Server root directory' + option datatype directory + +config variable + option name 'dhcp_boot' + option section 'dhcp.dnsmasq' + option title 'DHCP Boot image' + + +config section + option name 'dhcp' + option package 'dhcp' + option title 'DHCP interface configuration' + option dynamic true + +config variable + option name 'interface' + option section 'dhcp.dhcp' + option title 'Interface' + option required true + option type reference + list valueof network.interface + list valueof network.alias + +config variable + option name 'start' + option section 'dhcp.dhcp' + option title 'Start' + option description 'first address (last octet)' + option datatype uint + +config variable + option name 'limit' + option section 'dhcp.dhcp' + option title 'Limit' + option description 'number of leased addresses -1' + option datatype uint + +config variable + option name 'leasetime' + option section 'dhcp.dhcp' + option title 'Leasetime' + +config variable + option name 'dynamicdhcp' + option section 'dhcp.dhcp' + option title 'Dynamic DHCP ' + option datatype boolean + +config variable + option name 'name' + option section 'dhcp.dhcp' + option title 'Name' + +config variable + option name 'ignore' + option section 'dhcp.dhcp' + option title 'Ignore interface' + option description 'disable DHCP for this interface' + option datatype boolean + +config variable + option name 'netmask' + option section 'dhcp.dhcp' + option title 'IPv4-Netmask' + option datatype ip4addr + +config variable + option name 'force' + option section 'dhcp.dhcp' + option title 'Force' + option datatype boolean + +config variable + option name 'dhcp_option' + option section 'dhcp.dhcp' + option title 'DHCP-Options' + option description 'See "dnsmasq --help dhcp" for a list of available options.' + option type lazylist diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/dropbear b/openwrt/packages/luci/host/lib/uci/schema/default/dropbear new file mode 100644 index 0000000..ba490a7 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/dropbear @@ -0,0 +1,24 @@ +package dropbear + +config package + option title 'Dropbear SSHd configuration' + +config section + option name 'dropbear' + option title 'General SSH daemon settings' + option package 'dropbear' + option required true + option unique true + +config variable + option name 'PasswordAuth' + option title 'Permit password authentication' + option section 'dropbear.dropbear' + option datatype 'boolean' + +config variable + option name 'Port' + option title 'Listening port' + option section 'dropbear.dropbear' + option datatype 'integer' + option required true diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/firewall b/openwrt/packages/luci/host/lib/uci/schema/default/firewall new file mode 100644 index 0000000..35ff056 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/firewall @@ -0,0 +1,255 @@ +package firewall + +config package + option title 'Firewall configuration' + +config section + option name 'zone' + option title 'Firewall zones' + option package 'firewall' + +config variable + option name 'name' + option title 'Name' + option section 'firewall.zone' + option required true + +config variable + option name 'network' + option title 'Networks belonging to this zone' + option section 'firewall.zone' + option valueof 'network.interface' + option multival true + +config variable + option name 'forward' + option title 'Zone specific action for forwarded traffic' + option section 'firewall.zone' + option required true + +config variable + option name 'input' + option title 'Zone specific action for incoming traffic' + option section 'firewall.zone' + option required true + +config variable + option name 'output' + option title 'Zone specific action for outgoing traffic' + option section 'firewall.zone' + option required true + +config variable + option name 'masq' + option title 'Enable masquerading for outgoing zone traffic' + option section 'firewall.zone' + option datatype 'boolean' + + + +config section + option name 'defaults' + option title 'Global firewall defaults' + option package 'firewall' + option unique true + option required true + +config variable + option name 'forward' + option title 'Action for forwarded traffic' + option section 'firewall.defaults' + option required true + +config variable + option name 'input' + option title 'Action for incoming traffic' + option section 'firewall.defaults' + option required true + +config variable + option name 'output' + option title 'Action for outgoing traffic' + option section 'firewall.defaults' + option required true + +config variable + option name 'syn_flood' + option title 'Enable syn-flood protection' + option section 'firewall.defaults' + option datatype 'boolean' + +config variable + option name 'drop_invalid' + option title 'Do not drop packages with state invalid' + option section 'firewall.defaults' + option datatype 'boolean' + + + +config section + option name 'forwarding' + option title 'Forwarding rules' + option package 'firewall' + +config variable + option name 'src' + option title 'Source zone' + option section 'firewall.forwarding' + option valueof 'firewall.zone.name' + option required true + +config variable + option name 'dest' + option title 'Destination zone' + option section 'firewall.forwarding' + option valueof 'firewall.zone.name' + option required true + +config variable + option name 'mtu_fix' + option title 'Fixup MTU of outgoing packages' + option section 'firewall.forwarding' + option datatype 'boolean' + + + +config section + option name 'rule' + option title 'Custom rules' + option package 'firewall' + list depends 'target, src' + list depends 'target, dest' + list depends 'target, src_ip' + list depends 'target, src_port' + list depends 'target, src_mac' + list depends 'target, dest_ip' + list depends 'target, dest_port' + list depends 'target, proto' + +config variable + option name 'src' + option title 'Source zone' + option section 'firewall.rule' + option valueof 'firewall.zone.name' + +config variable + option name 'src_ip' + option title 'Source IP address' + option section 'firewall.rule' + option datatype 'ipaddr' + +config variable + option name 'src_port' + option title 'Source port' + option section 'firewall.rule' + option datatype 'portrange' + +config variable + option name 'src_mac' + option title 'Source MAC address' + option section 'firewall.rule' + option datatype 'macaddr' + +config variable + option name 'dest' + option title 'Destination zone' + option section 'firewall.rule' + option valueof 'firewall.zone.name' + +config variable + option name 'dest_ip' + option title 'Destination IP address' + option section 'firewall.rule' + option datatype 'ipaddr' + +config variable + option name 'dest_port' + option title 'Destination port' + option section 'firewall.rule' + option datatype 'portrange' + +config variable + option name 'proto' + option title 'Protocol' + option section 'firewall.rule' + option datatype 'string' + +config variable + option name 'target' + option title 'Option target' + option section 'firewall.rule' + option datatype 'string' + + + +config section + option name 'redirect' + option title 'Redirection rules' + option package 'firewall' + +config variable + option name 'src' + option title 'Source zone' + option section 'firewall.redirect' + option valueof 'firewall.zone.name' + +config variable + option name 'src_ip' + option title 'Source IP address' + option section 'firewall.redirect' + option datatype 'ipaddr' + +config variable + option name 'src_port' + option title 'Source port' + option section 'firewall.redirect' + option datatype 'portrange' + +config variable + option name 'src_dport' + option title 'Source destination port' + option section 'firewall.redirect' + option datatype 'portrange' + +config variable + option name 'src_mac' + option title 'Option src_mac' + option section 'firewall.redirect' + option datatype 'macaddr' + +config variable + option name 'dest' + option title 'Destination zone' + option section 'firewall.redirect' + option valueof 'firewall.zone.name' + +config variable + option name 'dest_ip' + option title 'Destination IP address' + option section 'firewall.redirect' + option datatype 'ipaddr' + +config variable + option name 'dest_port' + option title 'Destination port' + option section 'firewall.redirect' + option datatype 'portrange' + +config variable + option name 'proto' + option title 'Protocol' + option section 'firewall.redirect' + option datatype 'string' + + + +config section + option name 'include' + option title 'User defined config includes' + option package 'firewall' + +config variable + option name 'path' + option title 'Path to the include file' + option section 'firewall.include' + option datatype 'file' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/fstab b/openwrt/packages/luci/host/lib/uci/schema/default/fstab new file mode 100644 index 0000000..58dff58 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/fstab @@ -0,0 +1,54 @@ +package fstab + +config package + option title 'Filesystem configuration' + +config section + option name 'mount' + option title 'Filesystem entry' + option package 'fstab' + +config variable + option name 'device' + option title 'Device node' + option section 'fstab.mount' + +config variable + option name 'enabled' + option title 'Enable this mount point' + option section 'fstab.mount' + option datatype 'boolean' + option required 'true' + +config variable + option name 'fstype' + option title 'Filesystem type' + option section 'fstab.mount' + +config variable + option name 'options' + option title 'Mount options' + option section 'fstab.mount' + +config variable + option name 'target' + option title 'Mount point' + option section 'fstab.mount' + option datatype 'directory' + + +config section + option name 'swap' + option title 'Swap entry' + option package 'fstab' + +config variable + option name 'device' + option title 'Swap file or Partition' + option section 'fstab.swap' + +config variable + option name 'enabled' + option title 'Enable this swap' + option section 'fstab.swap' + option datatype 'boolean' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/httpd b/openwrt/packages/luci/host/lib/uci/schema/default/httpd new file mode 100644 index 0000000..8dcf095 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/httpd @@ -0,0 +1,37 @@ +package httpd + +config package + option title 'Busybox HTTPd configuration' + +config section + option name 'httpd' + option title 'General httpd settings' + option package 'httpd' + option required true + +config variable + option name 'home' + option title 'Document root' + option section 'httpd.httpd' + option datatype 'directory' + option required true + +config variable + option name 'port' + option title 'Listening port' + option section 'httpd.httpd' + option datatype 'integer' + option required true + +config variable + option name 'c_file' + option title 'Configuration file' + option section 'httpd.httpd' + option datatype 'file' + +config variable + option name 'realm' + option title 'Authentication Realm' + option description 'Realm shown on login prompt' + option section 'httpd.httpd' + diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/luci_hosts b/openwrt/packages/luci/host/lib/uci/schema/default/luci_hosts new file mode 100644 index 0000000..e2597f4 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/luci_hosts @@ -0,0 +1,21 @@ +package luci_hosts + +config section + option name 'host' + option title 'Host entry definition' + option package 'luci_hosts' + +config variable + option name 'hostname' + option title 'Hostname' + option section 'luci_hosts.host' + option datatype 'hostname' + option required true + +config variable + option name 'ipaddr' + option title 'IP address' + option section 'luci_hosts.host' + option datatype 'ipaddr' + option required true + diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/luci_splash b/openwrt/packages/luci/host/lib/uci/schema/default/luci_splash new file mode 100644 index 0000000..f320141 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/luci_splash @@ -0,0 +1,14 @@ +package luci_splash + +config section + option name 'core' + option title 'Common DHCP splash settings' + option package 'luci_splash' + option unique true + option required true + +config variable + option name 'leasetime' + option title 'Lease time in hours' + option section 'luci_splash.core' + option datatype 'float' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/network b/openwrt/packages/luci/host/lib/uci/schema/default/network new file mode 100644 index 0000000..0ea439d --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/network @@ -0,0 +1,495 @@ +package network + +config package + option title 'Network configuration' + +config section + option name 'interface' + option title 'Network interface' + option package 'network' + list depends 'proto=static, ipaddr, netmask' + list depends 'proto=static, ip6addr' + list depends 'proto=pppoe, username, password' + list depends 'proto=pppoa, username, password, encaps, vpi, vci' + list depends 'proto=ppp, device' + list depends 'proto=3g, device' + list depends 'proto=pptp, username, password, server' + list depends 'proto=dhcp' + list depends 'proto=none' + option named 'true' + option required 'true' + +config variable + option name 'ifname' + option title 'Physical interface' + option section 'network.interface' + +config variable + option name 'macaddr' + option title 'Interface MAC address' + option section 'network.interface' + option datatype 'macaddr' + +config variable + option name 'mtu' + option title 'MTU' + option section 'network.interface' + option datatype 'uint' + +config variable + option name 'ipaddr' + option title 'IPv4 host address' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'netmask' + option title 'IPv4 network mask' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'gateway' + option title 'IPv4 gateway' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'bcast' + option title 'IPv4 broadcast address' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'ip6addr' + option title 'IPv6 address (CIDR)' + option section 'network.interface' + option datatype 'ip6addr' + +config variable + option name 'ip6gw' + option title 'IPv6 gateway' + option section 'network.interface' + option datatype 'ip6addr' + +config variable + option name 'dns' + option title 'DNS server (IPv4 or IPv6)' + option section 'network.interface' + option datatype 'ipaddr' + option multival 'true' + +config variable + option name 'keepalive' + option title 'keep-alive' + option description 'Number of connection failures before reconnect' + option section 'network.interface' + option datatype 'string' + list depends 'proto=pppoe' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + list depends 'proto=pppoa' + +config variable + option name 'demand' + option title 'Dial on-demand' + option description 'Number of seconds to wait before closing the connection due to inactivity' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'username' + option title 'Username' + option section 'network.interface' + option datatype 'string' + list depends 'proto=pppoa' + list depends 'proto=pppoe' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'password' + option title 'Password' + option section 'network.interface' + option datatype 'string' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'encaps' + option title 'PPPoA encapsulation mode' + option section 'network.interface' + option type 'enum' + list depends 'proto=pppoa' + +config enum + option variable 'network.interface.encaps' + option value 'vc' + option title 'VC' + +config enum + option variable 'network.interface.encaps' + option value 'llc' + option title 'LLC' + +config variable + option name 'vpi' + option title 'PPPoA VPI' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=pppoa' + +config variable + option name 'vci' + option title 'PPPoA VCI' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=pppoa' + +config variable + option name 'server' + option title 'PPTP server' + option section 'network.interface' + option datatype 'host' + list depends 'proto=pptp' + +config variable + option name 'device' + option title 'Modem device' + option section 'network.interface' + option datatype 'device' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'defaultroute' + option title 'Replace default route' + option section 'network.interface' + option datatype 'boolean' + list depends 'proto=ppp' + list depends 'proto=pppoa' + list depends 'proto=pppoe' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'peerdns' + option title 'Use peer DNS' + option section 'network.interface' + option datatype 'boolean' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'ipv6' + option title 'Enable IPv6 on PPP link' + option section 'network.interface' + option datatype 'boolean' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'connect' + option title 'PPP connect script' + option section 'network.interface' + option datatype 'file' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'disconnect' + option title 'PPP disconnect script' + option section 'network.interface' + option datatype 'file' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'pppd_options' + option title 'Additional PPP daemon options' + option section 'network.interface' + option datatype 'string' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'maxwait' + option title 'Setup wait time' + option description 'Number of seconds to wait for the device to become ready' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=3g' + +config variable + option name 'apn' + option title 'Access point (APN)' + option section 'network.interface' + option datatype 'string' + list depends 'proto=3g' + +config variable + option name 'pincode' + option title 'PIN code' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=3g' + +config variable + option name 'service' + option title 'Service type' + option section 'network.interface' + option type 'enum' + list depends 'proto=3g' + +config enum + option variable 'network.interface.service' + option value 'umts' + option title 'UMTS/GPRS' + +config enum + option variable 'network.interface.service' + option value 'cdma' + option title 'CDMA' + +config enum + option variable 'network.interface.service' + option value 'evdo' + option title 'EV-DO' + +config variable + option name 'proto' + option title 'Protocol' + option section 'network.interface' + option type 'enum' + option required 'true' + +config enum + option variable 'network.interface.proto' + option value 'none' + option title 'Disabled' + +config enum + option variable 'network.interface.proto' + option value 'dhcp' + option title 'Retrieve IP address via DHCP' + option default 'true' + +config enum + option variable 'network.interface.proto' + option value 'pptp' + option title 'Interface is a PPTP tunnel endpoint' + +config enum + option variable 'network.interface.proto' + option value 'static' + option title 'Interface has static network configuration' + +config enum + option variable 'network.interface.proto' + option value 'pppoe' + option title 'Interface is a PPPoE connection' + +config enum + option variable 'network.interface.proto' + option value 'pppoa' + option title 'Interface is a PPPoA connection' + +config enum + option variable 'network.interface.proto' + option value 'ppp' + option title 'Interface is a PPP connection' + +config enum + option variable 'network.interface.proto' + option value '3g' + option title '3G UMTS/GPRS connection' + +config variable + option name 'type' + option title 'Option type' + option section 'network.interface' + option type 'enum' + +config enum + option variable 'network.interface.type' + option value 'bridge' + option title 'This is a bridge interface' + + + +config section + option name 'alias' + option title 'Alias interface definition' + option package 'network' + list depends 'proto=static, ipaddr, netmask' + list depends 'proto=static, ip6addr' + option named 'true' + +config variable + option name 'interface' + option title 'Parent interface' + option section 'network.alias' + option valueof 'network.interface' + option required 'true' + +config variable + option name 'ipaddr' + option title 'IPv4 host address' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'netmask' + option title 'IPv4 network mask' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'gateway' + option title 'IPv4 gateway' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'bcast' + option title 'IPv4 broadcast address' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'ip6addr' + option title 'IPv6 address (CIDR)' + option section 'network.alias' + option datatype 'ip6addr' + +config variable + option name 'ip6gw' + option title 'IPv6 gateway' + option section 'network.alias' + option datatype 'ip6addr' + +config variable + option name 'dns' + option title 'DNS server (IPv4 or IPv6)' + option section 'network.alias' + option datatype 'ipaddr' + +config variable + option name 'proto' + option title 'Protocol' + option section 'network.alias' + option type 'enum' + option required 'true' + +config enum + option variable 'network.alias.proto' + option value 'static' + option title 'Interface has static network configuration' + + + +config section + option name 'route' + option title 'Static route definition' + option package 'network' + +config variable + option name 'interface' + option title 'Interface' + option section 'network.route' + option valueof 'network.interface' + option required 'true' + +config variable + option name 'target' + option title 'Target IPv4 host or network' + option section 'network.route' + option datatype 'ip4addr' + option required 'true' + +config variable + option name 'netmask' + option title 'Target IPv4 netmask' + option section 'network.route' + option datatype 'ip4addr' + +config variable + option name 'gateway' + option title 'IPv4 gateway' + option section 'network.route' + option datatype 'ip4addr' + +config variable + option name 'metric' + option title 'Metric' + option section 'network.route6' + option datatype 'uint' + + + +config section + option name 'route6' + option title 'Static IPv6 route definition' + option package 'network' + +config variable + option name 'interface' + option title 'Interface' + option section 'network.route6' + option valueof 'network.interface' + option required 'true' + +config variable + option name 'target' + option title 'Target IPv6 host or network (CIDR)' + option section 'network.route6' + option datatype 'ip6addr' + option required 'true' + +config variable + option name 'gateway' + option title 'IPv6 gateway' + option section 'network.route6' + option datatype 'ip6addr' + option required 'false' + +config variable + option name 'metric' + option title 'Metric' + option section 'network.route6' + option datatype 'uint' + + + +config section + option name 'switch' + option title 'Section switch' + option package 'network' + option named 'true' + option dynamic 'true' + option required 'true' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/ntpclient b/openwrt/packages/luci/host/lib/uci/schema/default/ntpclient new file mode 100644 index 0000000..0b7b5a5 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/ntpclient @@ -0,0 +1,53 @@ +package ntpclient + +config package + option title 'Time Synchronisation' + +config section + option name 'ntpclient' + option package 'ntpclient' + option title 'General' + option unique true + option required true + +config variable + option name 'interval' + option section 'ntpclient.ntpclient' + option title 'Update Interval (in s)' + option datatype uint + +config variable + option name 'count' + option section 'ntpclient.ntpclient' + option title 'Count of Time Measurements' + option datatype uint + +config section + option name 'ntpdrift' + option package 'ntpclient' + option title 'Clock Adjustment' + option unique true + +config variable + option name 'freq' + option section 'ntpclient.ntpdrift' + option title 'Offset Frequency' + option datatype float + +config section + option name 'ntpserver' + option package 'ntpclient' + option title 'Time Server' + +config variable + option name 'hostname' + option section 'ntpclient.ntpserver' + option title 'Hostname' + option required true + option datatype host + +config variable + option name 'port' + option section 'ntpclient.ntpserver' + option title 'Port' + option datatype port diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/qos b/openwrt/packages/luci/host/lib/uci/schema/default/qos new file mode 100644 index 0000000..24f8e0d --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/qos @@ -0,0 +1,200 @@ +package qos + +config package + option title 'Network quality of service' + +config section + option name 'interface' + option title 'QoS interface section' + option package 'qos' + option named true + option required true + +config variable + option name 'enabled' + option title 'Enable QoS on this interface' + option section 'qos.interface' + +config variable + option name 'overhead' + option title 'Calculate overhead bandwidth' + option section 'qos.interface' + option datatype 'boolean' + +config variable + option name 'classgroup' + option title 'QoS classification' + option section 'qos.interface' + option valueof 'qos.classgroup' + +config variable + option name 'download' + option title 'Maximum download speed in kBits/s' + option section 'qos.interface' + option datatype 'integer' + +config variable + option name 'upload' + option title 'Maximum upload speed in kBits/s' + option section 'qos.interface' + option datatype 'integer' + + +config section + option name 'class' + option title 'QoS traffic class definition' + option package 'qos' + option named true + option required true + +config variable + option name 'avgrate' + option title 'Average rate' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'maxsize' + option title 'Maximum size' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'packetdelay' + option title 'Packet delay' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'packetsize' + option title 'Packet size' + option section 'qos.class' + option datatype 'integer' + +config variable + option name 'priority' + option title 'QoS priority' + option section 'qos.class' + option datatype 'integer' + + +config section + option name 'classgroup' + option title 'QoS classification group' + option package 'qos' + option named true + +config variable + option name 'classes' + option title 'Defined QoS classes in group' + option section 'qos.classgroup' + +config variable + option name 'default' + option title 'Default QoS class in group' + option section 'qos.classgroup' + option valueof 'qos.class' + + +config section + option name 'default' + option title 'QoS default classification' + option package 'qos' + list depends 'target, pktsize' + list depends 'target, portrange' + list depends 'target, proto' + +config variable + option name 'pktsize' + option title 'Match by packet size' + option section 'qos.default' + option datatype 'integer' + +config variable + option name 'portrange' + option title 'Match by port range' + option section 'qos.default' + +config variable + option name 'proto' + option title 'Match by layer 3 protocol' + option section 'qos.default' + +config variable + option name 'target' + option title 'Option target' + option section 'qos.default' + option valueof 'qos.class' + option required true + + +config section + option name 'classify' + option title 'QoS classification rule' + option package 'qos' + +config variable + option name 'ipp2p' + option title 'Match by ipp2p' + option section 'qos.classify' + +config variable + option name 'layer7' + option title 'Match by layer 7 protocol' + option section 'qos.classify' + +config variable + option name 'ports' + option title 'Match by ports' + option section 'qos.classify' + +config variable + option name 'proto' + option title 'Match by layer 3 protocol' + option section 'qos.classify' + +config variable + option name 'tcpflags' + option title 'Match by TCP flags' + option section 'qos.classify' + +config variable + option name 'target' + option title 'QoS target class' + option section 'qos.classify' + option valueof 'qos.class' + option required true + + +config section + option name 'reclassify' + option title 'QoS reclassification rule' + option package 'qos' + +config variable + option name 'mark' + option title 'Match by classification mark' + option section 'qos.reclassify' + +config variable + option name 'pktsize' + option title 'Match by packet size' + option section 'qos.reclassify' + option datatype 'integer' + +config variable + option name 'proto' + option title 'Match by layer 3 protocol' + option section 'qos.reclassify' + +config variable + option name 'tcpflags' + option title 'Match by TCP flags' + option section 'qos.reclassify' + +config variable + option name 'target' + option title 'QoS classification target' + option section 'qos.reclassify' + option valueof 'qos.class' + option required true diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/samba b/openwrt/packages/luci/host/lib/uci/schema/default/samba new file mode 100644 index 0000000..d4c7d8c --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/samba @@ -0,0 +1,76 @@ +package samba + +config package + option title 'Samba CIFS/SMB Daemon' + +config section + option name 'samba' + option package 'samba' + option title 'General Settings' + option unique true + option required true + +config variable + option name 'name' + option section 'samba.samba' + option title 'Hostname' + option datatype host + option required true + +config variable + option name 'description' + option section 'samba.samba' + option title 'Description' + +config variable + option name 'workgroup' + option section 'samba.samba' + option title 'Workgroup' + option required true + +config variable + option name 'homes' + option section 'samba.samba' + option title 'Share home-directories' + option description 'System users can reach their home directories via network shares.' + option datatype boolean + +config section + option name 'sambashare' + option package 'samba' + option title 'Shared Directories' + +config variable + option name 'name' + option section 'samba.sambashare' + option title 'Name' + option required true + +config variable + option name 'users' + option section 'samba.sambashare' + option title 'Allowed Users' + +config variable + option name 'read_only' + option section 'samba.sambashare' + option title 'Read Only' + option datatype boolean + +config variable + option name 'guest_ok' + option section 'samba.sambashare' + option title 'Allow Guests' + option datatype boolean + +config variable + option name 'create_mask' + option section 'samba.sambashare' + option title 'Create Mask' + option description 'Mask for new files' + +config variable + option name 'dir_mask' + option section 'samba.sambashare' + option title 'Directory Mask' + option description 'Mask for new directories' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/system b/openwrt/packages/luci/host/lib/uci/schema/default/system new file mode 100644 index 0000000..28fee1c --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/system @@ -0,0 +1,103 @@ +package system + +config package + option title 'System configuration' + +config section + option name 'system' + option title 'General system configuration' + option package 'system' + option unique true + option required true + +config variable + option name 'hostname' + option title 'Local hostname' + option section 'system.system' + option datatype 'hostname' + option required true + +config variable + option name 'zonename' + option title 'Option zonename' + option section 'system.system' + +config variable + option name 'timezone' + option title 'Option timezone' + option section 'system.system' + option required true + +config variable + option name 'log_size' + option section 'system.system' + option title 'System log buffer size (kiB)' + option datatype uint + +config variable + option name 'log_ip' + option section 'system.system' + option title 'External system log server' + option datatype ipaddr + +config variable + option name 'conloglevel' + option section 'system.system' + option title 'Log output level' + option description 'Level of log messages on the console' + option datatype integer + +config section + option name 'led' + option package 'system' + option title 'LED Configuration' + +config variable + option name 'name' + option section 'system.led' + option title 'LED Name' + option required true + +config variable + option name 'sysfs' + option section 'system.led' + option title 'LED Device' + option required true + +config variable + option name 'default' + option section 'system.led' + option title 'Default state' + option datatype boolean + +config variable + option name 'trigger' + option section 'system.led' + option title 'Trigger' + option required true + +config variable + option name 'delayon' + option section 'system.led' + option title 'On-State Delay' + option description 'Time (in ms) the LED is on' + list depends 'trigger=timer' + +config variable + option name 'delayoff' + option section 'system.led' + option title 'Off-State Delay' + option description 'Time (in ms) the LED is off' + list depends 'trigger=timer' + +config variable + option name 'dev' + option section 'system.led' + option title 'Device' + list depends 'trigger=netdev' + +config variable + option name 'mode' + option section 'system.led' + option title 'Trigger Mode' + list depends 'trigger=netdev' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/upnpd b/openwrt/packages/luci/host/lib/uci/schema/default/upnpd new file mode 100644 index 0000000..8574d03 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/upnpd @@ -0,0 +1,28 @@ +package upnpd + +config package + option title 'Miniupnpd UPNP daemon' + +config section + option name 'upnpd' + option title 'Settings' + option package 'upnpd' + option unique true + +config variable + option name 'download' + option title 'Download bandwidth in kBit/s' + option section 'upnpd.upnpd' + option datatype 'integer' + +config variable + option name 'upload' + option title 'Upload bandwidth in kBit/s' + option section 'upnpd.upnpd' + option datatype 'integer' + +config variable + option name 'log_output' + option title 'Enable log messages' + option section 'upnpd.upnpd' + option datatype 'boolean' diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/uvc-streamer b/openwrt/packages/luci/host/lib/uci/schema/default/uvc-streamer new file mode 100644 index 0000000..9ea255c --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/uvc-streamer @@ -0,0 +1,41 @@ +#package uvc-streamer + +config package + option title 'UVC-Streamer webcam streaming configuration' + +config section + option name 'uvc-streamer' + option package 'uvc-streamer' + option title 'Settings' + option unique true + option required true + +config variable + option name 'enabled' + option section 'uvc-streamer.uvc-streamer' + option title 'Enable' + option required true + option datatype boolean + +config variable + option name 'device' + option section 'uvc-streamer.uvc-streamer' + option title 'Device' + +config variable + option name 'resolution' + option section 'uvc-streamer.uvc-streamer' + option title 'Resolution' + option required true + +config variable + option name 'framespersecond' + option section 'uvc-streamer.uvc-streamer' + option title 'Frames per second' + option datatype uint + +config variable + option name 'port' + option section 'uvc-streamer.uvc-streamer' + option title 'Port' + option datatype port diff --git a/openwrt/packages/luci/host/lib/uci/schema/default/wireless b/openwrt/packages/luci/host/lib/uci/schema/default/wireless new file mode 100644 index 0000000..85532a1 --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/default/wireless @@ -0,0 +1,523 @@ +package wireless + +config package + option title 'Wireless LAN' + +config section + option name 'wifi-device' + option package 'wireless' + option title 'Devices' + option named true + +config variable + option name 'disabled' + option section 'wireless.wifi-device' + option title 'disabled' + option datatype boolean + +config variable + option name 'type' + option section 'wireless.wifi-device' + option title 'Type' + option required true + +config variable + option name 'channel' + option section 'wireless.wifi-device' + option title 'Channel' + +config variable + option name 'hwmode' + option section 'wireless.wifi-device' + option title 'Mode (atheros)' + option type enum + list depends type=atheros + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '' + option title 'auto' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11b' + option title '802.11b' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11g' + option title '802.11g' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11a' + option title '802.11a' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11bg' + option title '802.11b+g' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11gdt' + option title '802.11adt' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11adt' + option title '802.11adt' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value 'fh' + option title 'Frequency Hopping' + +config variable + option name 'diversity' + option section 'wireless.wifi-device' + option title 'Diversity (atheros)' + option datatype boolean + list depends type=atheros + +config variable + option name 'txpower' + option section 'wireless.wifi-device' + option title 'Transmit Power' + option description 'dbm' + option datatype uint + +config variable + option name 'txantenna' + option section 'wireless.wifi-device' + option title 'Transmitter Antenna' + option datatype uint + list depends type=atheros + list depends type=broadcom + +config variable + option name 'rxantenna' + option section 'wireless.wifi-device' + option title 'Receiver Antenna' + option datatype uint + list depends type=atheros + list depends type=broadcom + +config variable + option name 'distance' + option section 'wireless.wifi-device' + option title 'Distance Optimization (atheros, broadcom)' + option description 'Distance to farthest network member in meters.' + option datatype uint + list depends type=atheros + list depends type=broadcom + +config variable + option name 'macfilter' + option section 'wireless.wifi-device' + option title 'MAC-Address Filter (broadcom)' + option type enum + list depends type=broadcom + +config enum + option variable 'wireless.wifi-device.macfilter' + option value 'deny' + option title 'Allow listed only' + +config enum + option variable 'wireless.wifi-device.macfilter' + option value 'allow' + option title 'Allow all except listed' + +config variable + option name 'maclist' + option section 'wireless.wifi-device' + option title 'MAC-List (broadcom)' + list depends 'type=broadcom, macfilter=allow' + list depends 'type=broadcom, macfilter=deny' + option type lazylist + option datatype macaddr + +config variable + option name 'frameburst' + option section 'wireless.wifi-device' + option title 'Frame Bursting (broadcom)' + option datatype boolean + list depends 'type=broadcom' + +config variable + option name 'country' + option section 'wireless.wifi-device' + option title 'Country Code (broadcom)' + list depends 'type=broadcom' + +config variable + option name 'maxassoc' + option section 'wireless.wifi-device' + option title 'Connection Limit (broadcom)' + option datatype uint + list depends 'type=broadcom' + + +config section + option name 'wifi-iface' + option package 'wireless' + option title 'Interfaces' + +config variable + option name 'device' + option section 'wireless.wifi-iface' + option title 'Wifi Device' + option valueof 'wireless.wifi-device' + +config variable + option name 'ssid' + option section 'wireless.wifi-iface' + option title 'ESSID' + +config variable + option name 'network' + option section 'wireless.wifi-iface' + option title 'Network' + option description 'Add the Wifi network to physical network' + option type reference + list valueof network.interface + +config variable + option name 'mode' + option section 'wireless.wifi-iface' + option title 'Mode' + option required true + option type enum + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'ap' + option title 'Access Point' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'adhoc' + option title 'Ad-Hoc' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'sta' + option title 'Client' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'monitor' + option title 'Monitor' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'ahdemo' + option title 'Pseudo Ad-Hoc (ahdemo)' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'wds' + option title 'WDS' + +config variable + option name 'bssid' + option section 'wireless.wifi-iface' + option title 'BSSID' + +config variable + option name 'txpower' + option section 'wireless.wifi-iface' + option title 'Transmit Power' + option description 'dbm' + option datatype uint + +config variable + option name 'frag' + option section 'wireless.wifi-iface' + option title 'Fragmentation Threshold (mac80211, atheros)' + option datatype uint + +config variable + option name 'rts' + option section 'wireless.wifi-iface' + option title 'RTS/CTS Threshold (mac80211, atheros)' + option datatype uint + +config variable + option name 'wds' + option section 'wireless.wifi-iface' + option title 'WDS (atheros)' + option datatype boolean + list depends 'mode=ap' + list depends 'mode=sta' + +config variable + option name 'wdssep' + option section 'wireless.wifi-iface' + option title 'Separate WDS (atheros)' + option datatype boolean + list depends 'wds=1,mode=ap' + +config variable + option name 'doth' + option section 'wireless.wifi-iface' + option title '802.11h (atheros)' + option datatype boolean + +config variable + option name 'hidden' + option section 'wireless.wifi-iface' + option title 'Hide ESSID (atheros, broadcom)' + option datatype boolean + list depends 'mode=ap' + list depends 'mode=adhoc' + list depends 'mode=wds' + +config variable + option name 'isolate' + option section 'wireless.wifi-iface' + option title 'isolate (atheros, broadcom)' + option datatype boolean + list depends 'mode=ap' + +config variable + option name 'bgscan' + option section 'wireless.wifi-iface' + option title 'Background Scan (atheros)' + option datatype boolean + +config variable + option name 'sw_merge' + option section 'wireless.wifi-iface' + option title 'Disable Ad-Hoc HW beacon timer (atheros)' + option datatype boolean + +config variable + option name 'nosbeacon' + option section 'wireless.wifi-iface' + option title 'Disable station HW beacon timer (atheros)' + option datatype boolean + +config variable + option name 'probereq' + option section 'wireless.wifi-iface' + option title 'Disable probe responses (atheros)' + option datatype boolean + +config variable + option name 'macpolicy' + option section 'wireless.wifi-iface' + option title 'MAC-Address Filter (atheros)' + option type enum + +config enum + option variable 'wireless.wifi-iface.macpolicy' + option value 'deny' + option title 'Allow listed only' + +config enum + option variable 'wireless.wifi-iface.macpolicy' + option value 'allow' + option title 'Allow all except listed' + +config variable + option name 'maclist' + option section 'wireless.wifi-iface' + option title 'MAC-List (atheros)' + list depends 'macpolicy=allow' + list depends 'macpolicy=deny' + option type lazylist + option datatype macaddr + +config variable + option name 'rate' + option section 'wireless.wifi-iface' + option title 'Transmission Rate (atheros)' + +config variable + option name 'mcast_rate' + option section 'wireless.wifi-iface' + option title 'Multicast Rate (atheros)' + +config variable + option name 'minrate' + option section 'wireless.wifi-iface' + option title 'Minimum Rate (atheros)' + +config variable + option name 'maxrate' + option section 'wireless.wifi-iface' + option title 'Maximum Rate (atheros)' + +config variable + option name 'compression' + option section 'wireless.wifi-iface' + option title 'Compression (atheros)' + option datatype boolean + +config variable + option name 'bursting' + option section 'wireless.wifi-iface' + option title 'Frame Bursting (atheros)' + option datatype boolean + +config variable + option name 'turbo' + option section 'wireless.wifi-iface' + option title 'Turbo Mode (atheros)' + option datatype boolean + +config variable + option name 'ff' + option section 'wireless.wifi-iface' + option title 'Fast Frames (atheros)' + +config variable + option name 'wmm' + option section 'wireless.wifi-iface' + option title 'WMM Mode (atheros)' + option datatype boolean + +config variable + option name 'xr' + option section 'wireless.wifi-iface' + option title 'XR Support (atheros)' + option datatype boolean + +config variable + option name 'ar' + option section 'wireless.wifi-iface' + option title 'AR Support (atheros)' + option datatype boolean + +config variable + option name 'encryption' + option section 'wireless.wifi-iface' + option title 'Encryption' + option description 'WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP and ad-hoc mode) to be installed.' + option type enum + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'none' + option title 'No Encryption' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'wep' + option title 'WEP' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'psk' + option title 'WPA-PSK' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'psk2' + option title 'WPA2-PSK' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'wpa' + option title 'WPA-EAP' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'wpa2i' + option title 'WPA2-EAP' + +config variable + option name 'server' + option section 'wireless.wifi-iface' + option title 'RadiusServer' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=wpa2i,mode=ap' + option datatype host + +config variable + option name 'port' + option section 'wireless.wifi-iface' + option title 'Radius-Port' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=wpa2i,mode=ap' + option datatype port + +config variable + option name 'key' + option section 'wireless.wifi-iface' + option title 'Key' + list depends 'encryption=wep' + list depends 'encryption=psk' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=psk2' + list depends 'encryption=wpa2i,mode=ap' + +config variable + option name 'nasid' + option section 'wireless.wifi-iface' + option title 'NAS ID' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=wpa2i,mode=ap' + +config variable + option name 'eap_type' + option section 'wireless.wifi-iface' + option title 'EAP-Method' + option type enum + list depends 'encryption=wpa,mode=sta' + list depends 'encryption=wpa2i,mode=sta' + +config enum + option variable 'wireless.wifi-iface.eap_type' + option value 'TLS' + +config enum + option variable 'wireless.wifi-iface.eap_type' + option value 'PEAP' + +config variable + option name 'ca_cert' + option section 'wireless.wifi-iface' + option title 'Path to CA-Certificate' + list depends 'encryption=wpa,mode=sta' + list depends 'encryption=wpa2i,mode=sta' + option datatype file + +config variable + option name 'priv_key' + option section 'wireless.wifi-iface' + option title 'Path to Private Key' + list depends 'mode=sta,encryption=wpa2i,eap_type=TLS' + list depends 'mode=sta,encryption=wpa,eap_type=TLS' + option datatype file + + +config variable + option name 'priv_key_pwd' + option section 'wireless.wifi-iface' + option title 'Password of Private Key' + list depends 'mode=sta,encryption=wpa2i,eap_type=TLS' + list depends 'mode=sta,encryption=wpa,eap_type=TLS' + +config variable + option name 'auth' + option section 'wireless.wifi-iface' + option title 'PEAP-Authentication' + list depends 'mode=sta,encryption=wpa2i,eap_type=PEAP' + list depends 'mode=sta,encryption=wpa,eap_type=PEAP' + +config variable + option name 'identity' + option section 'wireless.wifi-iface' + option title 'PEAP-Identity' + list depends 'mode=sta,encryption=wpa2i,eap_type=PEAP' + list depends 'mode=sta,encryption=wpa,eap_type=PEAP' + +config variable + option name 'password' + option section 'wireless.wifi-iface' + option title 'PEAP-Password' + list depends 'mode=sta,encryption=wpa2i,eap_type=PEAP' + list depends 'mode=sta,encryption=wpa,eap_type=PEAP' diff --git a/openwrt/packages/luci/host/lib/uci/schema/meta/schema b/openwrt/packages/luci/host/lib/uci/schema/meta/schema new file mode 100644 index 0000000..a2f29aa --- /dev/null +++ b/openwrt/packages/luci/host/lib/uci/schema/meta/schema @@ -0,0 +1,403 @@ +# UVL - Reference-Spec +# This is a meta scheme defining the format of uci schemes. +# $Id: schema 3709 2008-11-04 21:28:07Z jow $ + +package schema + +#------------------------------------------------------------------------------- +# Central package definition +# +# config package +# option ... +#------------------------------------------------------------------------------- + +# Section definition (schema.@package) +config section + option name 'package' + option title 'Definition of uci package' + option package 'schema' + option required false + option named false + option unique true + option dynamic false + +# Section title (schema.@package.title) +config variable + option name 'title' + option title 'Title of the defined package' + option section 'schema.package' + option type 'variable' + option datatype 'string' + option required false + +# Section description (schema.@package.description) +config variable + option name 'description' + option title 'Description of the defined package' + option section 'schema.package' + option type 'lazylist' + option datatype 'string' + option required false + + +#------------------------------------------------------------------------------- +# Central section definition +# +# config section +# option ... +#------------------------------------------------------------------------------- + +# Section definition (schema.@section) +config section + option name 'section' + option title 'Definition of uci section' + option package 'schema' + option required false + option named false + option unique false + option dynamic false + +# Section name (schema.@section.name) +config variable + option name 'name' + option title 'Name of the defined section' + option section 'schema.section' + option type 'variable' + option datatype 'string' + option required true + +# Section package (schema.@section.package) +config variable + option name 'package' + option title 'Parent package of the defined section' + option section 'schema.section' + option type 'variable' + option datatype 'string' + option required true + +# Section title (schema.@section.title) +config variable + option name 'title' + option title 'Title of the defined section' + option section 'schema.section' + option type 'variable' + option datatype 'string' + option required false + +# Section description (schema.@section.description) +config variable + option name 'description' + option title 'Description of the defined section' + option section 'schema.section' + option type 'lazylist' + option datatype 'string' + option required false + +# Section dependencies (schema.@section.depends) +config variable + option name 'depends' + option title 'List of dependencies within and between defined sections' + option section 'schema.section' + option type 'lazylist' + option datatype 'string' + option required false + +# Section required flag (schema.@section.required) +config variable + option name 'required' + option title 'Specify whether at least one instance of this section type must be defined in config' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + +# Section unique flag (schema.@section.unique) +config variable + option name 'unique' + option title 'Specify whether only one instance of this section type is allowed in config' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + +# Section named flag (schema.@section.named) +config variable + option name 'named' + option title 'Specify whether sections of this type must have a name set (are not anonymous)' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + +# Section dynamic flag (schema.@section.dynamic) +config variable + option name 'dynamic' + option title 'Specify whether sections of this type may contain arbitary, not specified options' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + + +#------------------------------------------------------------------------------- +# Central variable definition +# +# config variable +# option ... +#------------------------------------------------------------------------------- + +# Variable definition (schema.@variable) +config section + option name 'variable' + option title 'Definition of uci variable' + option package 'schema' + option required false + option named false + option unique false + option dynamic false + +# Variable name (schema.@variable.name) +config variable + option name 'name' + option title 'Name of the defined variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required true + +# Variable section (schema.@variable.section) +config variable + option name 'section' + option title 'Parent section of the defined variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required true + +# Variable title (schema.@variable.title) +config variable + option name 'title' + option title 'Title of the defined variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required false + +# Variable description (schema.@variable.description) +config variable + option name 'description' + option title 'Description of the defined variable' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + +# Variable dependencies (schema.@variable.depends) +config variable + option name 'depends' + option title 'List of dependencies between defined variables' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + +# Variable required flag (schema.@variable.required) +config variable + option name 'required' + option title 'Specify whether this variable must be set in config' + option section 'schema.variable' + option type 'variable' + option datatype 'boolean' + option required false + +# Variable multiple values flag (schema.@variable.multival) +config variable + option name 'multival' + option title 'Specify whether this variable may contain multiple values separated by space' + option section 'schema.variable' + option type 'variable' + option datatype 'boolean' + option required false + +# Variable type (schema.@variable.type) +config variable + option name 'type' + option title 'Type of this variable' + option section 'schema.variable' + option type 'enum' + option datatype 'string' + option required false + +# Plain variable type (schema.@variable.type=variable) +config enum + option value 'variable' + option title 'This is a plain variable' + option variable 'schema.variable.type' + +# Enum variable type (schema.@variable.type=enum) +config enum + option value 'enum' + option title 'This is a enum variable' + option variable 'schema.variable.type' + +# List variable type (schema.@variable.type=list) +config enum + option value 'list' + option title 'This is a list variable' + option variable 'schema.variable.type' + +# List-or-Option variable type (schema.@variable.type=lazylist) +config enum + option value 'lazylist' + option title 'This is a list or option variable' + option variable 'schema.variable.type' + +# Reference variable type (schema.@variable.type=reference) +config enum + option value 'reference' + option title 'This is a reference (valueof) variable' + option variable 'schema.variable.type' + +# Variable datatype (schema.@variable.datatype) +config variable + option name 'datatype' + option title 'Datatype of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required false + +# Variable default value (schema.@variable.default) +config variable + option name 'default' + option title 'Default value of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required false + +# Variable minimum length (schema.@variable.minlength) +config variable + option name 'minlength' + option title 'Minimum length of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'uint' + option required false + +# Variable maximum length (schema.@variable.minlength) +config variable + option name 'maxlength' + option title 'Maximum length of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'uint' + option required false + +# Variable minimum value (schema.@variable.minlength) +config variable + option name 'minimum' + option title 'Minimum value of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'integer' + option required false + +# Variable maximum value (schema.@variable.minlength) +config variable + option name 'maximum' + option title 'Maximum value of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'integer' + option required false + +# Variable validators (schema.@variable.validator) +config variable + option name 'validator' + option title 'Datatype of this variable' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + +# Variable value references (schema.@variable.valueof) +config variable + option name 'valueof' + option title 'Reference to section or option to read values from' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + + +#------------------------------------------------------------------------------- +# Central enum definition +# +# config enum +# option ... +#------------------------------------------------------------------------------- + +# Enum definition (schema.@enum) +config section + option name 'enum' + option title 'Definition of uci enum value' + option package 'schema' + option required false + option named false + option unique false + option dynamic false + +# Enum value (schema.@enum.value) +config variable + option name 'value' + option title 'Value of the defined enum value' + option section 'schema.enum' + option type 'variable' + option datatype 'string' + option required true + +# Enum variable (schema.@enum.variable) +config variable + option name 'variable' + option title 'Parent variable of the defined enum value' + option section 'schema.enum' + option type 'variable' + option datatype 'string' + option required true + +# Enum value title (schema.@enum.title) +config variable + option name 'title' + option title 'Title of the defined enum value' + option section 'schema.enum' + option type 'variable' + option datatype 'string' + option required false + +# Enum value description (schema.@enum.description) +config variable + option name 'description' + option title 'Description of the defined enum value' + option section 'schema.enum' + option type 'lazylist' + option datatype 'string' + option required false + +# Enum value dependencies (schema.@enum.depends) +config variable + option name 'depends' + option title 'List of dependencies on defined variables' + option section 'schema.enum' + option type 'lazylist' + option datatype 'string' + option required false + +# Enum value default flag (schema.@enum.default) +config variable + option name 'default' + option title 'Specify whether this value is the default value of the parent enum' + option section 'schema.enum' + option type 'variable' + option datatype 'boolean' + option required false diff --git a/openwrt/packages/luci/host/luci b/openwrt/packages/luci/host/luci new file mode 120000 index 0000000..1844fff --- /dev/null +++ b/openwrt/packages/luci/host/luci @@ -0,0 +1 @@ +./usr/lib/lua/luci \ No newline at end of file diff --git a/openwrt/packages/luci/host/sbin/luci-flash b/openwrt/packages/luci/host/sbin/luci-flash new file mode 100755 index 0000000..819be40 --- /dev/null +++ b/openwrt/packages/luci/host/sbin/luci-flash @@ -0,0 +1,89 @@ +#!/bin/sh +. /etc/functions.sh + +# initialize defaults +RAMFS_COPY_BIN="/usr/bin/awk" # extra programs for temporary ramfs root +RAMFS_COPY_DATA="" # extra data files +export KEEP_PATTERN="" +export VERBOSE=0 + +# parse options +while [ -n "$1" ]; do + case "$1" in + -k) + shift + export SAVE_CONFIG=1 + 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 < + +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' diff --git a/openwrt/packages/luci/host/sbin/luci-reload b/openwrt/packages/luci/host/sbin/luci-reload new file mode 100755 index 0000000..b6b1ff6 --- /dev/null +++ b/openwrt/packages/luci/host/sbin/luci-reload @@ -0,0 +1,34 @@ +#!/bin/sh +. /etc/functions.sh + +apply_config() { + config_get init "$1" init + config_get exec "$1" exec + config_get test "$1" test + + [ -n "$init" ] && reload_init "$2" "$init" "$test" + [ -n "$exec" ] && reload_exec "$2" "$exec" "$test" +} + +reload_exec() { + [ -x $2 ] && { + echo "Reloading $1... " + $2 >/dev/null 2>&1 + [ -n "$3" -a "$?" != "$3" ] && echo '!!! Failed to reload' $1 '!!!' + } +} + +reload_init() { + [ -x /etc/init.d/$2 ] && /etc/init.d/$2 enabled && { + echo "Reloading $1... " + /etc/init.d/$2 reload >/dev/null 2>&1 + [ -n "$3" -a "$?" != "$3" ] && echo '!!! Failed to reload' $1 '!!!' + } +} + +config_load ucitrack + +for i in $* +do + config_foreach apply_config $i $i +done diff --git a/openwrt/packages/luci/host/tmp/.uci/luci b/openwrt/packages/luci/host/tmp/.uci/luci new file mode 100644 index 0000000..e69de29 diff --git a/openwrt/packages/luci/host/usr/bin/boa b/openwrt/packages/luci/host/usr/bin/boa new file mode 100755 index 0000000000000000000000000000000000000000..271e5a167b3281cfbbdd96a34f99f75e0fe37ed9 GIT binary patch literal 82281 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ξ6?fJkOfxesyhb04B6(=(>@vN-{`ms-wOccxBgAM%z*6zg6y2cC( zt3u}f)%GabcJ&r=OFFQ#T{4J&FpD~8g$AOLh-76=w?A9jRk2~z(hl;! z2W8+R*F#~F38J9QL}!7dR-1O9R%3TPmYdqI1Nv+rOHOI&AU7h!u7c^}f*#6+4zd+i zrEY5(keS?_SZ+No1*}d#)?Glq;W1qP5EfcwqEv~>qj!vv0!8iuY`50cht;YlP%Rlw z7Yp{J^F!0qTW;9h$TmW0u7=m)dCvaN!cYE728m|xuhB(4}-|W1TDSZ`&SHoK!(>VB=v5 zb+ZUwid)rQX;H#`nlpJQk3fKOh3sI(LOaD>nAL7E8ILP7-Z0JbkPEvl+8dm$Fj|Ad zgsE0t%0{FR{a|^V9~DY&U4|@W|A_j4J>HwWvftzJ_~Q|Xep$1&dV{%&4~ogxi;foM zz7I`qEGNTt;OsddgRzygJ=*HT5c?Z)O>YGG5RBP1Cx0kc%B8hioCcxKevv8+myli7 z7q$Dzgetj|R;XlGF4I2hNOEf#b!dRyIa>#aMRvX;{j!m;+akg_tj*B^I|Xt`wv4i7 zO1`85q>ja5YntR4C9*cio!X?LkK$&7kA@Yxv|)C+&J-K^1pIN2;w2#^5<20!qQzyc zV_Ml`fP@H&YXjZy)reX|$A9*C?x{rxgO(5TB8 z+TAK4DEF=ILY$DLkO)}nZKuHzFI613$%s46=^pM}4`n5?8EqVPNyjc_5Gbfwel`|% zFQh1yLR94r9qRm5y*qTPpa3dCovt_3IaJIQ7t(Jj*JQ0l_J@7QU|+UiL1V%yYY$zQ zH+v$c@niXN;79KFtb0GQ9?IM%XUP_Z4V|q^!x9NgcT(Si1KzoyGZS1D2Z5wm&F*Yb z12Mr%k$?@~GOp5%uM#&XPW0FyfLI!+lv#u-6Tojo|utd9G}V|j|Y0#&qPu* zOG7>=brQXGo-u*aVox`x)kaqkXMVBk!<><|Q?|3J-z;sbsSU^-uI)im*yie~szsNb z61h2>onA&w@*u=Id`DgGKCZLc)0ZnR(mTzml7!o|#;!&OR0jq%!KhOxSGmSkGX&M$ zwC2e)vXPU0Bx)qt-Au`C*_@{2t~yW6$Y$A9myNpa@Py*nAJ3jx@G#}7RGMTH#_ppW z>fpd3BHNb?L))-B!Kq)|yB~HaxIQnB0Wm2`*AZ#q8Es;|AsO^qfhuG0oI%$7D zj$V=@vuIA`0G-_jl%Y3^N0CRP@Cir0u_HFQ2xm;$JuqR(UO|;qM{uMQk3XRt)1zY) zb`T(7ce$iGyOoh+117NuUc|%4H!XNi|GIc&b5_M?EoWVpwbcM*BaWrc=>Wou=vI(r z#U83rc8NoB2YZmr99_of-l{<`s+>)5>!Q$w<%w*@{{Oi#V5`7m0PQiz?M*WvH7Jg* zuvQJ&cVN;ebdG6wK%aJ3VsLzw= i#qN*gU0@EigF8pPF(L?gjkW5a$tiJ;CkQnL_3sEm*C1`~uC=_I_tfItWjMF#Kq5Osgw?U@PQaIu*)Q)ps@m?El0 zl_*CN^JaEH2J|-Kq%x2jBd0z4yF&)3GHt+lbxv{*Er z+3HIteACTmQMJ^4`RWbwS?a-OJfLx)^FUS@jR@O3-bw(sWY0x>tV;KSqbV}5{Id;c zo@p=e5g_U^3RD3a0~!gUPV5V|n}IT{%X+p_lcter2d;j%`~Hr(5z5)aPZf9qoNZzG zR?rZ+&;sDZcPe~6IOQK!cmygZen#OZpak(N3cm|Ze4oP06wWC86NSSH&r>+7@O*{y z3SXe`PKBu_%ipc=ovQw871qF+->Go5!fO@&k&=%qJWJ)TQ2089sn>xYxjnS`IN=qK zgD=8Zx4$3?v29w)Fdmt7|1VuU+h|AnqG7?B9QU;3N3I)lji&C~d5RHqrl&*{A zt5z;)^iTKA9EjDSrSvrZf6>o1km^8;R0~5B z{9f=8=#%~Azz4`-^n>J>NS-3cfa@a1069#Kf!a-u!EuBf1Lh@i4Axi4;oQf`F+hJw z4o%)9$6);pIR@+7TJb>rPV4Vn=7`%jljrQ91v zS<#2o;y*&|;(O5H`i;kWO0)hRPnK#P!9SlV)v#p|Mn8NTkCkfJ!U*#|JT5U?8lky9 z?3S1Ji1EfJ|B?vR)kiOeNVN=(Z{77^bfF)b8XLEJ1c zEfr}dUL-Ls7U6LJuufuHE^-U8CNV7-VS_%bl$e%`B#DK@v}j~2asTH?sG(&e9mH=- zObbVL5FeMAmX7Qq?gp;^!_A%VWZ&y=Zdn)UzZW?IgKzD%kz~Q`DgF-xPVO2K&_CG| zo{j~lQHn4s`Yy_LyB|FTPu3WqNvljTi>NcL3u=1E<@gtnbat4VGY zd3+bN-Uh9YS&x;fb2A@sd%6xnuwYCUeXnATd6LMmo+mor>@$GD{qp!Dci276b*WJH&dk?*sJvFkoyr!_)@x6<)|K%+# znUgJz+~Fv!C4SdiXq;0>Id(Yv3No|K%Dn4cnOWEOPH#E1smLCw*m$#lQxA;#N2=wn zF23{`hDQ-wFT93Ej4lI`R8%3s6Q%vb~u^-qC;k7-tTpa>=Ae8OB*-!^g1W^E^!2UmpI#dm$;I>OWapvUo7kE zGSkCIH;|4rci&#x-%O9$(|1DkbCv32Ox0iT=5B@NsHDCdmGHsA{zw1ZePSo(r2M7| zeGeDp&ZhqQZuATrpT}f@!o1tB!_r;I^`9!0jxMdP;2Hw%Y5sw97&^<#aEapSPfMlF z+)hZzhi2iS>~n;ld$(T!;5}6KD&*$7yxaF+ntZnMK0M!2UD0_HobD#+bR9@4x>0Su zzz1{3y!UoNwEm;QbALi=pBLSK#na64Zhr~d=A}}F2X`YS?>>mqJkSPpiNf`xS!Qt# zl!7`&Z$7slLN%gahy`Mi5SgbsFRCu?Kz5<*RrRlAYG5m1~2x6gHZw@*Oblxk(m z?zH7g(|Wg`gohS#Z?f_qAHhGgquqj*_)XQ7Q0D~O3A+_?vL04Y1qs!T++6eyq^|!P zG`$n)M{~PS6q+FVuC*7=l1C!H@F0sR6lf4Mv679Z@+jl-`^}n)FMLue?aIo69C_I# z^Ca+YKMIwV)e6#T53;trdl!lrZo5zaY})S7aN8MsX_Zx|L|JU0Y3||&P>Z&E6Ahr$ zWJnbrl*+aYTJUW&gi=pHN;RdTy7&nzJmu=_@!so%RSHi{=|^c@?9bEB|2yZW7yh)* zoBIIWW7gQa{bEW8+U7YtY<5HM_Og>Sp=mwly^cIn3Dwy*RZozvhem_D(LL;`{p^Dr zWaWGge|-&gKKlxtwh_Z%4Z8iqCj3E^o2ufoXj>N)E#)`#>od;f_{mJY`v?b=oJg#0 zeS)ef;*Pzzav-VDw#zILW84nbvAKz$TzxK&0#v@rjzXC`%okKf085Xr;01w*;Bj( zDZNWw=qhuh?}n=uFF;~_clL;O!^Ta8!08?qjPhB6ABFerLA!YpE3Sp5x@hRWH;}}2 zp}24$>3Oy2p%q+il7-Bp)?9Y7zMC@@ch2DMW-MQwGpmdDe2n5)3TB4vDJ^q~LY2Vv zZ&8dDp&BkZ#q%LLFrQDD(U$$>t}PdJ9`Ag;?S*0)7Afz)c0UVuEdAoeDsz#-yq^8E zIrB!o>7+iROuEE~?2+Wgn>Y0oe~7{cS7_+_1@m!n4fMFXr+^b2md@gwk5K>5xLqk^ z`9JmO3ngc+WK`FGgjEOD@?cGpog(M#(gROY3cfJ!sjh4cI5rU%6LaozU8%F+HtC zhH z=qW7~h--rff-RFrY{^-lOEMjtKtoQ#23t1*bteq&}wB=PeT}KwMK}4ls!W}phZ%8+k#0xU+tuY&4Cn5IcTPa+JNop zQQ`~rT}dO;f;FhlQoGh{(kQ9F)*6O}iPVBgm$u0;35{Jbec_NNfnk9FEY9W*wrxu^ zWJDHBnpsyf&!uLzp2Di-zM1Qqge4K%Uv`;mNU(*1FB0Wh|rMTy>^h zCdXUT$t!F^XNu6&%jn(1jBM+dFVmf>Q*+JM9*l-b3#Z_J>Nne_uhQX*&GdDw2m95k zj%$ddw0I&N353v#X7`5mxSqmL3BfJo{fp(2iyj7qNailLv z1hnh)*0i45j3L^XNN$r|s!eH}s@2b%S3hlfUEOpoVi?K!wY6KeZ1J@w0=`5ltWBE+ z7pfgLOumOb=o6r4K;59DiXI1Fyrgky)3W6&R$g`Ws%uuSXKFY$U##xv7{~>wy zEjs(!Stdd?$SDf=r}vruI0>BoNI$WHDR%+f#FV=eeaYBf<+qkx6(aOQ>>NQE(6ASQ z%<2T0LT(4QU5F_j?Ik8a&bB~y9vU)N{c@vqlj5@m9Wq5lioSw3O zW};`rPhr zm~RrNP4~?)6Q&t>kysm@F?TlJxVHvtgXv6dFl9u2>(A!7!NTyIfG=x{*K5;#^>cl7 z!qH(`W)oC!JJ=ZQFH|P}O(^3S=cpNb&S=-z3&)OgjCWLG9&%QT(W4h4307B8bQZS3 zOofeS3fI{Aqpujf@|-IxoS3i5CySNrBF8vUS-zp%<+;#P<2i>D+nFhsBGoBmFF8IP zJ4WC$4`(HiLqy|I!xsb+;vNw8mH2lI7yG*1CWPuY)+5TCoQz##9aXhe3vR3mhihw{ zWvB!h91X51D#KZh#I4`37VI#k1&5Yvq@${;%IPqx=OA-U7)VJ+uyw_jIgPyz7FGJb znZ($z;TB6^^DO^{$PWPQY*W$;8^2;oJqz0ob#2vUg9=c)fpw9lPJw9Ihe7NB25a4< z5jsF@`hHu!@TIr4W2*sfq)Z;MVyHk*C511ZFm&JIB`c>HfiR93@r)1O1|q^2+7`#d zCO1-M4)z!6Xd*rY_>q^=W0W@|$(SL0Y>)66`d0k60U#?83K#+5(@ zC9J$aYimm1Y$1I9g9>ILFo_ja#hK}!GaQ{-{La&o4e{C0^9 z4RI@&D}@lVkia2NIqq*(KyI%}0~`3x$(bD|*#zad|2YAp|QzG0uHc z2juDyx7Q0O!l02L%5mRy5OQ>It2{u7li-#d_i0_o;Qozr+#6bQIFibCu^x__W(cre zD^QLB!)ri}W2Xahi>yW>k8-5DY;yc=-i?A^9TFW$23#YWZ2L)Jk2$4ZWU$M+EYwr*2zKyI&1?jYn2eu>;a z+2pz)*Yzd!9)uii%zEXwddR)0(!gZB)Z-Zt+e^6z9&>vhz(#y{JBWX7ljHt;H{|F; zR-g>&D99?WA9DSWWB*&hD*H7guzuFd?>(m>2Nef`CHDqWY~3y>*KA9$qHhh8YsP`0 zd7!jGoBw{8+#`^yvB_EGeKJh$-yrw6m1)Z>N182J#J(j&;tR^-oeaC&TacS-OR%Dv zlC#Ey8xz>ihLuOz?M?ylG<78#q6j7?S}4 z=Rp(G)6MzL#GJ{6oYzb&#pL{DVz$COPnwvgQFA^rF=u2vpR>w0J(%;0nLkG6a~?4< zwvY(c+U~;L0|w3u=n$X1DK~-=re%L70Nn?y41+v_@tamU=Sd19Fn`# z?H7(W6Z5oejw=&Sl-T-n2{@lExWolE#PZ-ww%{5vQ!<|$+ri)x-yQ^rxx^*Iur}al z%y5f8mZYLeirBs;6SG9iUJkqg;2LJx%YoY>^MNgUIk2KH2ky5{TeyY8V~6~X4DJvU zMGX9uvX29A6VkvM-kE^G@5c<;6R>`+D+g46u>PIE^4t#2`u`T(>R$)?_iiGK@j^{>Nuo;V3?*+V$Ti82f{JDvz^`HRCjK~w=-{-B|~ zmjfT%;r2X@a>hfSE18dP_8dvXYk-f#9;}zR71;83;wUf!&!O~I-r=!=hDd%Gei)eJ zfg_i9arOaQ<7GT#8MTtisi&lR@rD!s0-byw-Xfe+Zq`wTeQ>Gqt&R6+g5sLAVH zRo=zG{9enlng1PN%N~`m#~dZUOv$fQ_$LZ)1U{+!Wt{VT5n(>+zfqO9Rmsm&@;_9V ze#tujPGOEL;sd~oVDEhrj}gx^e;@XHVB_GQuQ4C~%aKF*-vK9~|IHGQ5r3dO0!JqE zKLe(JGp!Q-GE&XK*4?TL71oeX`8mLqs1H#o-=OlVRsI@PSV#69^8(IKSepWLq1eet%=jnsxqF zE7!O1a+ZJT5Oh_eEi07phhvG>K+G>sD*ixbtH3EF8PoBS);DYJ%o!p{R*ySVID7a* znfCT=Rs~I~mkyS1fo1C!U(@8b5G%9dgLTQnk*rI8l=0(B5Y*Ojg)6C3|K+RJELptD zzh>F8^-V4Qmc>g}HL)FREe=Jgz&5`g=S4DGg1m|*{7Y|Gz4)4yje>_N^TwCp7ZSf& zHgBHc+YO$SH^T7R#V^lqe0@AzL=|Y>AzQS_x-C|Rhrjafo4+mTk8BZU;pW{ndkN~Q znmy@^J8DBRhhCr?u$lSwOx|X*i>LJ%a!@%wM?hPfDa;#lLuBRsI(rHpNGJUG$`y*~ zc0T;f4Jjg3~LlSs5&z>M(p!wsv9!e`4i=ilB-Pp4~l|~Qy5G(zM@QH#TnOn%BRGfrk8sA$qj zTBh6a<`g-#t+m+NYOBYhXse<&5=x{$Hl_BIRu9IjtvgLhqf*ULO78o9d+o_iz+3yA zKF@ugyWz{)?^@sb*0;X(zxJASm$$MaBO^oEPo~OJL{(pPxo5&%?6pE>Dvvrz6{>0K zTs0P644c^u9#9Y7Nn=1RP!=c;Lh@Q%Zqg~hB!*EoNgl*iAoB{PNQ|#?t#I-C8Nxup zOr`Q6fax+EP^l|HKSz8}4_-+OXBwnJBvOd9NgiO59d_LxV>N)sJ$C%!V8goNV9mwB zhETkzs4-l0i4_+~i|&h-u9CRagK^xT1)y6%p9P%{vY$!%g)xdi}~4WLD!>7Z*t z7l5t|05=ZpL_zI9PO9w z2+Mc8+pnL)%LEXrfjY9=#?eg-ry9b&z(9`Gr! z9I0#iRpsfIo8X?U-{)!fD!8*jmuY+^+>1f1XQyeuv*2C`ngW^(ngil<9*Av^OL?|2&%a?jg*O>MozL18-6N5kT3)(2G8^mih-lB1(=3fk#;Tv=~ zZ9&X7!H0Gu9;ee|SrGqG^Rt~0FVx|*De)97|3_M%Z|U$SbvSKoKOVd|>j?2Tb^I>8 zQ(jWXuhaTotMP|A{IJ$%pT=u+{4Z<#u@1NOyFg>MdCCuK{@ofsZtJVl`=#c8R^wca zmuvo68b>sqr{izbm}SoAX%N#pr1`rwz8fwd);EU#PU~Zrcczxda$)#hjo;GvHZ6~R z2g9f6@HUNi+4-!x|XV|u^P`q}kutHw|2@GCUGo&F3R{wn+#zd(lfG6?{uAhREK|{;}5_k{|!3awqJ+FH*5Z%YX0{%&eGWK zKOWKPHE4NDb$q*i9z#4n&w-d;Cjp){AmYOWc$R~R=V*DmHGTvxpL!6(g9Lck5fVSF z(_5+WZ?%3L#~J>N#vf^XKU_Yiff)W*ogT+r;=fSdAjs&#Kpi>8b6p1;bIzmO^>gr&)F&?!dHwI$04S`^dLe6}_ zaCm(@;)}$h0ug4p{*3|K!`BE<(_k^wMgsv~br|_;vN-+0V7PjO4`dM6+EIdGzm=B1 zrp8wfQ-`CQeGz}GUJ|GdZ`c4sQ_%hA>oS2}S*z>W~e-rVR#T5(uFNG*VV2 zOy#c`wz@A;jjT&55N;WiNj5YN^XS^)ERAR&67*LiwT5-otX7vP-;!mhjx`M-U%W9; zqZ-52>!E$12}Ws*pq|BQ6(okLH$>=0tLvkv#CWTTM^wZr_QpV{rnUi=5XQ)6RU3}3 zM-r&jA^OF_LDjgqF&M5R3epoXlw=Qnb;0mD$b_s=7`d$W#~Q*RwXOjyuoP6PkH>1l zn?h=1W60Jh5Tl~uNK9>z8UVpH5TK|=D6ASA>ipFrW|O}m7HNQxn5bT>1^BD01BmSN zHPPM@iVXUEw2N+?8~hC+(T#OZ^6al(kM_3SSL;WM@dc#O`F!gd8?6}dg39&&P)#rp z^(|StGX1__apgj_sB%g90^cP?Gt+OS>9-R0ADJ?f)E%7QtPws8XQ;(ty<5oXGyFcx zZ~NKY#FiiXJ?CS^ampSJwdHZPKk^@avebPLnXB3J8XC~~xzuvPr78D-3Snw3k#p0`wZnjbv(S^n(bfL#gx=?%;T}*uD(8YjKM)wrVgXv+hAR=NdPbI_fJF^ukKm1?JZzEbznEyVneE*8J{)5QX32VD$K z57E6?sYmD*DfJj#EPQv;MQwbFE*3n`(7i;d=jmdw>!6Ft!d|+UD)lnm%TO$IFITFY zE(Xh2>0+=vNcRe*UZ;ymL=Rm|*50OzNs38#F3OoM7Hk7_%al4ocfL}CbjwlxbQhrf zF?OG{5amzTi}I(7$x$}lMJRu|i&6e`u_(`{do{|R?lmZXx|Jw@y4Rxo=`Kb2)5Rja zgl-kepDq>+v*<2I`O{s2@~4Z*$wIoTlv5bqG2OI%3YE;x@EC8~Ox1?LlUI@22wJcYQ7c&%U$@nYgC!3D&y zi0Um9Tu8i{xJ2+p#A}H?f=h^*q264nU ziQ9=g1TQAOk9eoxO5z>FI|Nq|KSJCtcqQ>p;%33CiJu{k2>u*#2k~0LYl&Ybt`b~B z+)Z32xSseRaf#p{aSyRaaD><-&J`RZ9w1hNn}`RA2ma3d-$9K26Zse1OzbA^7Tijl zOWYxND{(&YPQiB*dx&=kZYM4zZWnwnaS3s=;QNTV{OFAczMr^^c&*?a#EXfm1V2Pv zMO-HM5#rUvC4wI#UQ6r|ypy<|I9Kpf#1Ud8_!;6R;(?>g|MSGn#65yLh_@1V3*JlI zPTV2*W#apYcMARm@ebl0g1dC?6?}wvfLIA0BpxIl_?Y=WO3cx?w?{C0xOz8nw_x^k z_1uQ&?GVf!uRfo6r(pJc^&a9Kg4qMs7ZSG%W=~jOLfkBvJz_n#F?u6{*)!Ic5w8`@ z9`Ch*#7Z!G)cPjkfsds9 z6E_q02xbpkzm>RKFnikicH$0Tv>SO!|8h(6&BWUSRV$a*@BA@1I`HSZ>+3z=#9sDE zF!Yi35fA$5M8CWFs{8lhPuJye87Lh^()M;VrtRSIR*n{qCY#iu)vkt#j2g0Sz!JFvjVt@ zeR<|G4E)Bndl8WMvny5Znmv%*c0W)~YcBq#cJJsP8cOYAc=C<{myuv=NV*Elc`$&H zAZHguQziPAV%lK&8fC78=}HO*@;7@R{*x0Y^L<23?S2%=j7;Frf1fCUZp=^qK?14r zqqE<$5{@lO?SASw$*m`pyz&1gIk7kU=39JgIxXASDD@OZQW4%j+-^bY(WUbBGRzfF2j4!7Md1`s0$0S%{QS*+feLMDMCx-J85O_0L5u_ zgYZf0o%0NHE7sKZ(|JrmHFN8Sh^6}WrxGt&c5~^_a}bKi60dK9v$|XDBR{$32+}bh z#6-KLGY8YfWPC8W6eRbV=OC=@gUvIvuIwMpk3XO? zjvV{|W)bxbBo-euwj53Nujxb-N@W>P=HHM__UWqc_o*Mj;k+!-KMVSqE>SL8BFY(Y zx22zK_@pJEd1kR(VLCBxTDCcdRcB^FI!9gRbF?vv4J{MC*-T7|5Ly&l%&1CIpaZn) znj@muu;vc^Z2S39Q(8KIh3WUO{p_4QN*i?~_uUz1K0kxRfx2>9Q%F}E!8WxAfyo$Z z6I3H}8PaFeyKaZM&96`!s}6q^GD|z!K8Tk&>|BoUtQ1@99+HPj>CGQhAdcPa*|rhFYh`s3Wv-F*PZ$_V!flvno|t;6iskbn8*wlU|Ei zb4%xLEKRO!>F0FJm~AX^1s=qjOC`Pir5#;uD=~af1o~t;sa+pXfz)Dno6jS9SK=Z1 z<3S0UUq)8}YwSrTxYwK0x*mU1i6KVGlLjTGi=iQwp-_?4+$zSTJ>i*5#Dw4V7x1Il z4Us}C@6p^?q&m2pgnQg^-1mYznc#HA*hYzM2Xb0J1J}F;3MYm#b6Ven979qwABM4v z1Vwdud*H2VUwYYH+vR;dQ`IKDhoGaIzIL&|4s2y+KAKQsa45M?k0)X%W=MJ}D9?!G zv?J0y+fX2hj*Ohv4-t^^vfFd#;*~Xo;WH?d;qU5*80o~WpFd&+w0*>giCN4t%<>kz zb-|dYvuBfhv}0-8CE2IBdIvEhw%UWSoyBI9yUZs?F!vq>3*=zQtju$u0|wz4U8*?V z80{)^@e6WSnY%a`ukI?#ZivMqU1hm7#gSlFSzf%ZAynH{mfu*suk1|NoYwB$&IA*a zw2t!}IyNHzsf0&|Oml?Xh!9%fR#f#=;zG@l<>0uSaoawJ3?$ns@i(=7HUB2&k$3w- z@t=dghP)fX)73_vW@HPp(__H3kjkR#ik)J_jAY-)QScqd|} zcCjv*zoj-PVb%v!S1Dn(lynJ0#uJb?ng=@Gl#;-w;S?Jqw`;!hDHl?Z;K#HV33Bf%M5O6GaV?OZ&Mn4ERTu1W2Z8iMX+*j_ge zFy`nv-nA&q6HdXdY@^`#ZWt7avEfag02jr*2U$SFL4hgr-=VHCrNA*|MK9aZU&ttH z2F*7iqNQ`$bbN-<{p*p^j+8e$**1XoBHbOj^!U-#(?{4EQO1fft)bGKEgC-pAJo?K z*;yi4_73K^{)%M1M*=g(ur9_=HP#FoaT&hb*`Rj5i%R^4)&9+o!6E~}^Vq$z_EpR! zqSucLIlIfV2D@~JN2X+gsiqRr?<4EKf+mT*c{i_-`8%eEZV|8%0$Tbz$l4Z!PnVa= zan^g0#vTqDvqLm?q4OC^K20w32}nz|_0R%O^KVyM4ZKefGY5WVLacxp4EPR$8-BTV z3XnbtIN7!m0V(;*M9pQ0)3TR}-F(ZMPRkG}Xa2$7()nW;1o@{ha7uH9!%+{34VgDV zNL$BUJv!sV^WzofIElYW;=59bJ6K&|ChkKZHiejXpq6lAC-bF3V-=?)=C3jHZRwnc zc$km09l(q!7ESHq8o0FM=(E!CfB62R1}ez5Bk)WnO#C&xxyb}4#fCR8nc#xgDzR+5 z4cnSSDO7kGsvtOcNAD!w!6 z-9de}95uGkQm!(vvVwZ=r(WLs?20{5+F^L}S*25nt+WTMYQDp=^WFzda?w?B-G(X4 z{VXEGyMyW;g2gbewkz_45qg?slXZRl8j8QAliRSYuZf+=xg|taAsJ{5Rw1P}TJuvF zd(f!HEY)1*-BPVYk~BA$`P^aJDcz8q<$Z>T`VvH8OOl3y>V17o z)rB@Ox_%}4rLf<|#J8n$xunm@yRpS>ei5^xHcTL5+4fxWA^5<+c8#{$zRUazlwmn0 z2S%8LML{E0cuGH@1yYIa%n;ORMQVM&t{q-Km^G6A0aQn8^2_wcBDLhcRN_f(2KE-; z#(OI9g2N{QgQjdNTeDv9-E?A=kdYJVa|Bc2zE`17X$Myfg{WIn!OdSHpr!LlORb}@ zi`4*kjJZuO>OID&HJ4+(XPa3twuM~WBf4-&6JVrC4}-na3RXmYz^6B2u;$P8YVheo1D0`f9qCnKP=!}5*fCpz+H?~C=P z5^T&^8TA!OduCl2fDd{ch8b0S4hLNs7l6p4*1?MUp+y%}32b~zok%E_p5CqBxGossy+6@Sgx z#u7sJcXeLd{`f0Kd4Au1qs-H{*Y02O9Rq`Gp7|ThW?MSvLt8Z6Y<8d0AIf%??o`gk zz=O)^&Bs@ceD(<(6X3ewD9%q$?M?S}dcS5weT_&GhdfeWjregk;V{DIpKDy&DmT6( z#k0al9E2F7DL2uPJG(1Bsc*janI|5xON>PxyB}MHUJ@1SkTo{Aj78b7@6alA;v&O} z5q||WTk7=*`ipO3ZPL;?-t$TI?H{$m6BV-_8MprFxcW8?4fFW==Ip;Fh(5Pty@hV| z1oi)apwHkRkJBdrn~&57`=QC-U7y^y!c1WH-O~9kb}7+0ZN2s#))TG~Sc4~^2KRm) zC2e^7n`af}wDQ~(r-5X`peqZn`yjk|%llZfpUnc*oLAu8$+d?ncug6w^vrY~YN3egI#pfw|U@ zIoXkltS?}T4CK6@`fT;S-}@e7CO@#pCyu6^UvNK)?_v@$d%%w^WnjJ{bxZY)8Tr77bbB&7pt_tZ{x+>Dc<6h`$R7_zVdKRx# z{|S0I_Xza>@e@epd1X!k_Vk9fvv6H2LhhOOd^zF%R#{$8TAM<=kYCCpE zTKa!ML9(mRC3_J(cahw_5+bK>{~Z3N61iC8Wb8?9UkhZ2Uout2_Y{4SZHt9#zdgm` z#&mXp+3>%~En(j7WZOcrVqieU5L>Z=R4{3D`$Z@MRP3#90~_9M*74utwe-O7+Np1o zj5mgCN?Br2c+z^%f14LseM_kMj=4j{Ijv72cB-w(N>Y{zm=AD=-ArK7iXQuP!@G5w z!g}s1)y!SJ-!cOFkAy7NGK}pth&y{#_r{fm_f=!2tUKK>>ugCM8>x3k!C)A)d@9j{ zxg+zIO8m+)f;*KM#2fOMI|j9r&CSSQ(ZnF5@9RcNtN|m{Am=T6Sp?R^M@qmD>uc-6 zTq)OSFertXc~IZ5j4wrIu_j*1FwaFZvaGYOHH#&tdW)%IYBm2_5|`v=yqDY_gh$){ zWGVtTr}a1N8|B@YJ^R07HHOGdbmS%5=76EkedP;ejNO#F;i!>fTucFy+w1X?#O5nA zwah9$`9xw!EMs0$HW)B|cFb;*_-7ijyJg&#*Y_WmQi+%Hk|}OOplk}Duek{|2Gv;h zxpG=3(r|4|$9RE%xrW4EtitqEuwjLX)I^ty^S~x|GIw8D9#?SY&tPdI#fT6&KR>5+ zC*m5ikf+X%GFWnf;PNRst<4B#os>Qs3@7(6W-MzT%_CaOpV9|ZL?&#x%ce=-4Kl@h zb>32y)E4HsE#Huxo8)|V@;X;?mR$;#oa|(Iu2G(SrS}=b`%KRL<)WP_j{J1uJ8W9Lms6Ck9xQz+OcnytmD2_2c!v91 z>EEWXf18AA+|qd$J~$egsoktYY+tFw8?4mFSpV4TKJj0Wj!y5RL|Jx*k(t=zN^KoF zcI?=P-BVv`d9xW$toOs0nw#0I9%SY6y4C)~AF@jKPk+z61FJS9Wt8V7_T(j3_0R4` zPkEL-3e~nZ-*u{rUobn~kCowRv3HXH3FcJOQDaf=mF3x6-jsCB-|-8QlgYAIx_`D64MEZ5p1v1k{XJY?-o)$| z`+wLBHZn0zW3c+L8wHTgy{<58k@M31$$cn1qiPBU>eG==Y?{cfuOxw5wf;57)CKr< zXqOlqo72{gd_IE;J#-;92k`k1Ld^#dNE<+7`6~1{QW$L`W0kOTaL7S0TKT^CBviEI zfb_I_{{s?jbt#bAn9Y#RWQ>FuORW4nL<~oUnO@XsV-HJIx)2O~JGeiA9TR?-O7F*U zq5WgbyIVS^VXqQX33KT8D3{&x5hKCB)4N_8%EY9mp!9bLT(HOQ;SugYjYrP;#=>DwFuX~hy)B&X;fYur9>#YVeuSw}a=bbc#%bzU!-haO zjuWb6yWi99L&ZkVEw)++JNKH8i-CdNS{LX zZ}M;UYzlbl!Y8X~HL5taAyQlfIci#C@w7%yL!)N{PD$egy(b*?REML{cqDeRD&FXi z7F&m}hhK};1w}Yj&EwMe$mEX%`BkZ?nvzsJv_6DW$sT?59jCKlyql*ruJJVbVcpFh zIhwCc<7o(arZpB$tC>EPYh}g5+<~a)Do<@ZBnOo}g*f|N7rRId9P)1nOh0)XjI;sg z#O0*89elgTho1)21ey@nx5%>vY&-*A1EGzDwHJ9r2Z$V3TZq4bU}FI9l0ig=N2umxlHy5e+Z?{eYWzw- zKWun>wOzjFK8G_kaBZ5W-|s`$$1a_}r@%)G`5gs^z{U72>EDhGgk3Qc?A!mQZ9tXV$dIfX{bQp9DH1S@<2Ni+lf|i1A z0fj(!g6;u50D2tsBIp&+A<$vaG0?>Ahz}|P%>^w5-2w`M?gZTfdI0n|=ta;gphKX; zpkttk|Bm>eBG6pWQqV1+5a>?OJ)j3bkAq$Wy#hJ}It)4nnuy;=pA9Mk%>~(oas(Zp zTC`xn6`n%;OnACyW)Tk7dkR;ri-%%y3te0q7gUPxTK{U!8J}9_|9_nSZ|%v{@f3hE z6%WC%$FTa4bK&y0SZv$&WAUAdrfu=L(5Cp-s(@iqo$KNnuG zx_(7r;TtG@VdI%9YvL8-uN=SRlzG{i7~aNyRxM!>WlU1JV^@vMa-Zd%=01gk(eXa# z!8cQWu%40e@x%!V*F10}0cFTE3)2NYUjSvwodd_Q{j-)*N|zhcQDZVWfM!k1m|8sb zs+*?P)fE?Kj)4{kU~9-K)B%}e;o0;r)`A75wP4fA8kaG3>eNj9I*7@$k!9tjeH!aA zA@syU_;FSUGfCEc%ZqQLnp-f8>6!c)!Jh`z_5P^T!Ug}J>;DwC9a*(GGe(gOD?shi z^BJ1@BM>cn7l;MG$DZ%d2yPIwzSR+~iW)a>z(fu%eh()uf5s_qNFWf6sG?9f7ATru zzU1PVzfKj^h2ll^{>FM$RI@pR$d-%WNlFOj(vAF;oD=vE77YZ+Z@olSl6w?4=-(myFj3i6$1O% zuUedC>reBS=fzkr*moJXXbF@^Svk->omi`)Ix^;m0{F`8coT-cJvhIM1bSl*Re&0uV$9ALqe? z<8UVg1NB2*J{$))howBuU(ZEP_dMS1bm>o84dR@a@0|DcfUgYi&U67)9SBKD9L}3P zIOO61w&hU;R{jXc=HooO41An_laF(In{PATsVmcA8#;&yc?sU_$IcR(TAGjTh!gfQ zJ5hv@k93!Vk9X))VWK}}Dm?W=+wo}w+3B*)24{g!LaaY_x`yVXUD$57g6~EG{n&il zfGLkbZ)08a_7#>snoV@$`!_-4W7%=d&U<#!odx`Cc@H`G2EaG)34D(_`1k{a!B0qc zr-Sb(_>O)8-wWVlSx`T@-v<@42e0(wL;a}lK9HRc{zkJ0e70>7Bz)xkxr2}EumSL` zW<>pvhx97QmbVzcwOD+WRZlcq+Ae>92h*p1{7uG6@a=FU?14X@H$aYL6!``n9`>s_ zimwWb&?*Yhk6kuA{c6Wy&<^lT(>!$SF#ZYLZd;h~z^r6I(Z9S^cqvt(4jC zTG&c~{i}tUy48kd`adgN*kpge!j{79&nzrkHtBmGvh=M@ z?4PV~_H?j=UIApujY!s7#0p0zi^rZ1WGQr#c-Vi?&C)H3{e*>CD%guiWA0j@UZ=4& zlCgc$Kg+)TNbfn|SJw1aY_D{)^esnhmlo!(2*xqAD+}ifW;?Smez5F#vecOlM0sb8 z!pm37JxVJ+T(_F;Pv7DGG*!Ii7&d)`_w*4}2 zGY7iCwEZ$L6IcY?Y_Hf*UTc7vf7Z_o+*lQa%io2;0nS&AaCbWRN2h-m!uxf3F#WrM zWsgGQPgY-pYnOKh%KKqpyF97SF5ogfU(AF)qw~8T;r7G)b_4W4p9UyQe)g9U=*yCz z{)gb+4a}B7+yl4jYcBV#ntuSe`|B?E*Woh$-{D5SF^o?JU+(=b_jt|EUrn_`9`&L; zp2P?`53=r?E0rNC#g3_VL5K2+h0cJsp{_t=YwGqwG*G%(8by9(S!PS zrtWOnk{Es&@Q#OF?(YenpvrZ)eGk~x8qd`HYc$@X@#i(Bohk2j;I&U-UkxtrwfQpK zT*$vi%fDCibMu1y4{Cgq#yf%eyG!=8jNbvg_WLe(yT-rP{A`De{}!;_Ka&5?I=n)M zAJh0MjVJ3t#J*Q-s>V<1@R^Q5#sj|vqcHD5YX6bTeU9XJf~o~(|I6~5g!0^=`Mb2d zCXMT~eZH(Q=L6KA_nLA3h*#i=>bp9e^CN~oqw$wD{+Y&heqPu3IvxIJ;zzOHDR_b! zL&flLET=r)lfmantxBqL+}LEpu;0Ne3Ql-HU5&uPiy>D zjk`7ezQ*k7DgRlG?fSY8xEuQ0<$VD7Ziju})cn`#`0s1{md07u5G{8gN`5tN)8U00 z@7DRB0c^LAT(ple9sYpkzgpw#HTG#7)%aG8?ea)yOtsj?w`=@E&HpfP?)NZ16+A)l z5{I52y4*DycK}Bm_dNYV$6ui1zYg4v_;+glKHy69SAc3#X1*HK{C0Va#}tJ>VYb@W z1a%fLpV=VV=VFcR_BTu8Cw2I>8r%6>qcPW?j9&}fgZgo?@J~=1b+~ZPM7T|INT9 zC{HZ=B!4L#&T)(BeM4ireScTu+qC>$8dqriBJf(2|9M*8&vkfIhrdSbxRd@C^bEf5SmUTp&Avk=7cvUhs9+s0is>>y%~wlNm3t;MU)w_xS6<-W=# zD^~K-H{Ze$=;{TIpqj9c_hI>iKG}`)`QuFrn`;r?M^;mG>8zPERD@2clD#`$O?<y>PO`fKos7az^5V@N@FOX0Bl7^NXbeV2}`i`T-JU%h?4qM0*GXQ~b1ns_iE_o?BF zy>C(Fvhw+rzGW2^E4(XxE9aM2dRay+N$g`r{hQ@luMr+{eV_6zym9ILYnLqG!3kVC zR#s-;@Ku5g#r*cAV52TJbFv|mO}MKreFGi7#M_syIoXgUU;2_a#KE?$;}*P885Wtc z>C0%&>)@Ps2kM*7@GZx>Zct+Jg1p9nb#Iz=Uz<}4ogcdj3~gVJO1%?Ssc%C+Cz3Wq2c<(~AY>yc{rHD7fbioBgPg za;>1_VnDXCQ4&U6329x>H;O~*0Y5s}S42W*t075(`WnPhA7r2|uJLn9VkLB9F_WBm zu`e9d7yLPyXd->NqR;1OCCs{Yqhb2$K4&!RJdo4JI!83ZM{WQd>BGwgoj#I5-Y3b6 z6LlXVZN+(OpJc>w+oD90?m&(;LGQ+}&x)Y*^@7ec98F6^TQ?3mIha}6JRFg#eB8a1 zJPGCGr_n^|wEAp|I0nU$!pSIBOy5^2+~_xOkEC3Mh`v_0VL3PDjHs_gbb5`7EtSuC z*`b}5eNCu!52I58uZeVCnJ9NVT31%4FUB0copdz!u%wwREE;V1mP`8@OIn5{HS(rK zuven%c3eto9TcM&RAN+ReSIoUmdUl9lGke9c8W_a*})Abjw@S%#uu}d*sacjc(R;I6^v~R{7Es?jERx|hd z_Ep_Gr0vge+aOF7`AXlnDrVHD+tOFf+WiJ{fGa_r$=SDpI{kQ!s1u8U(Eg=FnKtj9 y#n5`$tjmg6QzO;BSUnEb6|HN+7uY)A@O7WKB-WZ6G~(1DF6NZ+S;Xl3R{szC|Hh&K literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/usr/bin/stat-genconfig b/openwrt/packages/luci/host/usr/bin/stat-genconfig new file mode 100755 index 0000000..5313869 --- /dev/null +++ b/openwrt/packages/luci/host/usr/bin/stat-genconfig @@ -0,0 +1,381 @@ +#!/usr/bin/lua + +--[[ + +Luci statistics - collectd configuration generator +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: stat-genconfig 3642 2008-10-29 05:08:03Z jow $ + +]]-- + + +require("luci.model.uci") +require("luci.sys.iptparser") +require("luci.util") + +local ipt = luci.sys.iptparser.IptParser() +local uci = luci.model.uci.cursor() +local sections = uci:get_all( "luci_statistics" ) + + +function section( plugin ) + + local config = sections[ "collectd_" .. plugin ] or sections["collectd"] + + if type(config) == "table" and ( plugin == "collectd" or config.enable == "1" ) then + + local params = "" + + if type( plugins[plugin] ) == "function" then + params = plugins[plugin]( config ) + else + params = config_generic( config, plugins[plugin][1], plugins[plugin][2], plugins[plugin][3], plugin == "collectd" ) + end + + + if plugin ~= "collectd" then + print( "LoadPlugin " .. plugin ) + + if params:len() > 0 then + print( "\n" .. params .. "\n" ) + else + print( "" ) + end + else + print( params .. "\n" ) + end + end +end + +function config_generic( c, singles, bools, lists, nopad ) + local str = "" + + if type(c) == "table" then + + if type(singles) == "table" then + for i, key in ipairs( singles ) do + if preprocess[key] then + c[key] = preprocess[key](c[key]) + end + + str = str .. _string( c[key], key, nopad ) + end + end + + if type(bools) == "table" then + for i, key in ipairs( bools ) do + if preprocess[key] then + c[key] = preprocess[key](c[key]) + end + + str = str .. _bool( c[key], key, nopad ) + end + end + + if type(lists) == "table" then + str = str .. _list_expand( c, lists, nopad ) + end + end + + return str +end + +function config_exec( c ) + local str = "" + + for s in pairs(sections) do + for key, type in pairs({ Exec="collectd_exec_input", NotificationExec="collectd_exec_notify" }) do + if sections[s][".type"] == type then + + cmd = sections[s].cmdline + + if cmd then + cmd = cmd:gsub("^%s+", ""):gsub("%s+$", "") + user = sections[s].cmduser or "nobody" + group = sections[s].cmdgroup + + str = str .. "\t" .. key .. ' "' .. + user .. ( group and ":" .. group or "" ) .. '" "' .. + cmd:gsub('%s+', '" "') .. '"\n' + end + end + end + end + + return str +end + +function config_iptables( c ) + local str = "" + + for s in pairs(sections) do + if sections[s][".type"] == "collectd_iptables_match" then + + search = { } + + for i, k in ipairs( { + "table", "chain", "target", "protocol", "source", "destination", + "inputif", "outputif", "options" + } ) do + v = sections[s][k] + + if type(v) == "string" then + if k == "options" then v = luci.util.split( v, "%s+", nil, true ) end + search[k] = v + end + end + + for i, rule in ipairs( ipt:find( search ) ) do + + name = sections[s].name:gsub( "%s+", "_" ) + if i > 1 then name = name .. "_(" .. i .. ")" end + + str = str .. "\tChain " .. rule.table .. " " .. rule.chain .. " " .. rule.index .. ' "' .. name .. "\"\n" + end + end + end + + return str +end + +function config_network( c ) + local str = "" + + for s in pairs(sections) do + for key, type in pairs({ Listen="collectd_network_listen", Server="collectd_network_server" }) do + if sections[s][".type"] == type then + + host = sections[s].host + port = sections[s].port + + if host then + if port then + str = str .. "\t" .. key .. " " .. host .. " " .. port .. "\n" + else + str = str .. "\t" .. key .. " " .. host .. "\n" + end + end + end + end + end + + return str .. _string( c["TimeToLive"], "TimeToLive" ) + .. _string( c["CacheFlush"], "CacheFlush" ) + .. _bool( c["Forward"], "Forward" ) +end + + +function _list_expand( c, l, nopad ) + local str = "" + + for i, n in ipairs(l) do + if c[n] then + if preprocess[n] then + c[n] = preprocess[n](c[n]) + end + + if n:find("(%w+)ses") then + k = n:gsub("(%w+)ses", "%1s") + else + k = n:gsub("(%w+)s", "%1") + end + + str = str .. _expand( c[n], k, nopad ) + end + end + + return str +end + +function _expand( s, n, nopad ) + if type(s) == "string" then + local str = "" + + for i, v in ipairs( luci.util.split( s, "%s+", nil, true ) ) do + str = str .. _string( v, n, nopad ) + end + + return str + end +end + +function _bool( s, n, nopad ) + + local str = "" + local pad = "" + if not nopad then pad = "\t" end + + if s and s == "1" then + str = pad .. n .. " true" + else + str = pad .. n .. " false" + end + + return str .. "\n" +end + +function _string( s, n, nopad ) + + local str = "" + local pad = "" + if not nopad then pad = "\t" end + + if s then + if s:find("[^%d]") then + if not s:find("[^%w]") then + str = pad .. n .. " " .. luci.util.trim(s) + else + str = pad .. n .. ' "' .. luci.util.trim(s) .. '"' + end + else + str = pad .. n .. " " .. luci.util.trim(s) + end + + str = str .. "\n" + end + + return str +end + + +plugins = { + collectd = { + { "BaseDir", "Include", "PIDFile", "PluginDir", "TypesDB", "Interval", "ReadThreads", "Hostname" }, + { }, + { } + }, + + cpu = { + { }, + { }, + { } + }, + + csv = { + { "DataDir" }, + { "StoreRates" }, + { } + }, + + df = { + { }, + { "IgnoreSelected" }, + { "Devices", "MountPoints", "FSTypes" } + }, + + disk = { + { }, + { "IgnoreSelected" }, + { "Disks" } + }, + + dns = { + { }, + { }, + { "Interfaces", "IgnoreSources" } + }, + + email = { + { "SocketFile", "SocketGroup", "SocketPerms", "MaxConns" }, + { }, + { } + }, + + exec = config_exec, + + interface = { + { }, + { "IgnoreSelected" }, + { "Interfaces" } + }, + + iptables = config_iptables, + + irq = { + { }, + { "IgnoreSelected" }, + { "Irqs" } + }, + + load = { + { }, + { }, + { } + }, + + logfile = { + { "LogLevel", "File" }, + { "Timestamp" }, + { } + }, + + netlink = { + { }, + { "IgnoreSelected" }, + { "Interfaces", "VerboseInterfaces", "QDiscs", "Classes", "Filters" } + }, + + network = config_network, + + ping = { + { "TTL" }, + { }, + { "Hosts" } + }, + + processes = { + { }, + { }, + { "Processes" } + }, + + rrdtool = { + { "DataDir", "StepSize", "HeartBeat", "RRARows", "XFF", "CacheFlush", "CacheTimeout" }, + { "RRASingle" }, + { "RRATimespans" } + }, + + tcpconns = { + { }, + { "ListeningPorts" }, + { "LocalPorts", "RemotePorts" } + }, + + unixsock = { + { "SocketFile", "SocketGroup", "SocketPerms" }, + { }, + { } + }, + + wireless = { + { }, + { }, + { } + }, +} + +preprocess = { + RRATimespans = function(val) + local rv = { } + for time in val:gmatch("[^%s]+") do + table.insert( rv, luci.util.parse_units(time) ) + end + return table.concat(rv, " ") + end +} + + +section("collectd") + +for plugin in pairs(plugins) do + if plugin ~= "collectd" then + section( plugin ) + end +end diff --git a/openwrt/packages/luci/host/usr/bin/uci b/openwrt/packages/luci/host/usr/bin/uci new file mode 100755 index 0000000000000000000000000000000000000000..567994755c06e692b34b82f206db02651605cd7e GIT binary patch literal 16410 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 M?)BkPo~oz+15iON_y7O^ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/usr/bin/uvl b/openwrt/packages/luci/host/usr/bin/uvl new file mode 100755 index 0000000..2eb6c31 --- /dev/null +++ b/openwrt/packages/luci/host/usr/bin/uvl @@ -0,0 +1,241 @@ +#!/usr/bin/lua +--[[ + +UCI Validation Layer - Command Line Utility +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: uvl 4085 2009-01-17 23:51:28Z jow $ + +]]-- + +require("luci.uvl") +require("luci.util") + + +function getopt( arg, options ) + options = options or "" + local tab = {} + local args = {} + for k, v in ipairs(arg) do + if v:sub(1, 2) == "--" then + local x = v:find( "=", 1, true ) + if x then + tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 ) + else + tab[ v:sub( 3 ) ] = true + end + elseif v:sub( 1, 1 ) == "-" then + local y = 2 + local l = #v + local jopt + while ( y <= l ) do + jopt = v:sub( y, y ) + if options:find( jopt, 1, true ) then + if y < l then + tab[ jopt ] = v:sub( y+1 ) + y = l + else + tab[ jopt ] = arg[ k + 1 ] + arg[ k + 1 ] = "" + end + else + tab[ jopt ] = true + end + y = y + 1 + end + elseif #v > 0 then + table.insert(args, v) + end + end + return tab, args +end + +function genspec(conf) + require("luci.model.uci") + require("luci.uvl.datatypes") + + local uci = luci.model.uci.cursor() + local ok, err = uci:load(conf) + + if not ok then + print("Can not load config:", err) + os.exit(1) + else + local function _guess_datatype(v) + if type(v) == "table" then v = v[1] end + + for _, type in ipairs({ + "boolean", "integer", "float", "ip4addr", "ip6addr", + "macaddr", "directory", "file" + }) do + if luci.uvl.datatypes[type](v) then + return type + end + end + return "string" + end + + + local co = uci:get_all(conf) + local ct = { } + local ca = { } + local so = { } + local to = { } + + -- count section types + for _, section in pairs(co) do + ct[section['.type']] = ( ct[section['.type']] or 0 ) + 1 + ca[section['.type']] = section['.anonymous'] + so[section['.type']] = so[section['.type']] or { } + to[section['.type']] = to[section['.type']] or { } + + for option, value in pairs(section) do + if option:sub(1,1) ~= "." then + so[section['.type']][option] = _guess_datatype(value) + to[section['.type']][option] = ( type(value) == "table" and "list" or "variable" ) + end + end + end + + -- package name + print( "package %s" % conf ) + + -- write section schemes + for type, count in luci.util.kspairs(ct) do + print( "\nconfig section" ) + print( "\toption name '%s'" % type ) + print( "\toption title 'Section %s'" % type ) + print( "\toption package '%s'"% conf ) + print( "\toption named %s" % ( ca[type] and 'false' or 'true' ) ) + print( "\toption unique %s" % ( ct[type] > 1 and 'false' or ( ca[type] and 'false' or 'true' ) ) ) + print( "\toption dynamic false" ) + print( "\toption required false" ) + + -- write option schemes + for opt, val in luci.util.kspairs(so[type]) do + print( "\nconfig variable" ) + print( "\toption name '%s'" % opt ) + print( "\toption title 'Option %s'" % opt ) + print( "\toption section '%s.%s'" %{ conf, type } ) + print( "\toption datatype '%s'" % so[type][opt] ) + + if to[type][opt] ~= "variable" then + print( "\toption type '%s'" % to[type][opt] ) + end + end + + print("") + end + + end +end + + +local options, arguments = getopt( arg ) + +if #arguments ~= 2 or options.help then + print([=[ + +uvl - UCI Validation Layer +$Id: uvl 4085 2009-01-17 23:51:28Z jow $ +(c) 2008 Jo-Philipp Wich, Steven Barth + +Usage: + uvl --help + uvl [--silent] [--schemedir=DIR] [--configdir=DIR] [--no-strict-sections] \ + [--no-strict-options] [--no-strict-validators] [--no-strict-lists] \ + {verify|verify-scheme|genspec} config[.section[.option]] + +Options: + --help + Display this help message. + + --silent + Don't produce any output. + + --schemedir=DIR + Use DIR as scheme directory. + + --configdir=DIR + Use DIR as config directory. + + --no-strict-sections + Don't treat sections found in config but not in scheme as error. + + --no-strict-options + Don't treat options found in config but not in scheme as error. + + --no-strict-validators + Don't invalidate config if an external validator fails. + + --no-strict-lists + Don't invalidate lists that are stored options. + +Actions: + verify + Validate given configuration, section or option. + + verify-scheme + Validate given scheme against the reference meta scheme. + + genspec + Generate a scheme skeleton from given configuration. + ]=]) + os.exit(255) +elseif arguments[1] == "verify" or arguments[1] == "verify-scheme" then + luci.uvl.STRICT_UNKNOWN_SECTIONS = + ( not options['no-strict-sections'] and true or false ) + luci.uvl.STRICT_UNKNOWN_OPTIONS = + ( not options['no-strict-options'] and true or false ) + luci.uvl.STRICT_EXTERNAL_VALIDATORS = + ( not options['no-strict-validators'] and true or false ) + luci.uvl.STRICT_LIST_TYPE = + ( not options['no-strict-lists'] and true or false ) + + local uvl = luci.uvl.UVL( + type(options.schemedir) == "string" and options.schemedir, + type(options.configdir) == "string" and options.configdir + ) + + local cso = luci.util.split( arguments[2], "." ) + local ok, err + + if arguments[1] == "verify-scheme" then + uvl:read_scheme( 'schema', cso[1] ) + + local uci = uvl.uci.cursor( + type(options.configdir) == "string" + and options.configdir or uvl.schemedir .. '/default' + ) + + ok, err = uvl:validate_config( cso[1], uci:get_all(cso[1]) ) + if err then err.code = luci.uvl.errors.ERR_SCHEME end + else + ok, err = uvl:validate( unpack(cso) ) + end + + if ok then + if not options.silent then + print( string.format( + '%s "%s" validates fine!', + ( arguments[1] == "verify-scheme" and "Scheme" or + ( #cso == 1 and "Config" or + ( #cso == 2 and "Section" or "Option" ) ) ), + table.concat(cso, ".") + ) ) + end + os.exit( 0 ) + else + if not options.silent then print( err and err:string() or "Unknown error" ) end + os.exit( 1 ) + end +else + genspec( arguments[2] ) +end diff --git a/openwrt/packages/luci/host/usr/bin/uvlc b/openwrt/packages/luci/host/usr/bin/uvlc new file mode 100755 index 0000000..c07cc54 --- /dev/null +++ b/openwrt/packages/luci/host/usr/bin/uvlc @@ -0,0 +1,22 @@ +#!/usr/bin/lua + + +if arg[1] then + require("luci.util") + require("luci.uvl") + require("luci.fs") + + local uvl = luci.uvl.UVL() + local scheme, err = uvl:get_scheme( arg[1] ) + + if scheme then + luci.fs.writefile( + "%s/bytecode/%s.lua" %{ uvl.schemedir, arg[1] }, + luci.util.get_bytecode(scheme) + ) + else + print("Error:", err:string()) + end +else + print( "Usage: uvlc " ) +end diff --git a/openwrt/packages/luci/host/usr/include/uci.h b/openwrt/packages/luci/host/usr/include/uci.h new file mode 100644 index 0000000..2ae02b7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/include/uci.h @@ -0,0 +1,545 @@ +/* + * libuci - Library for the Unified Configuration Interface + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LIBUCI_H +#define __LIBUCI_H + +#include "uci_config.h" + +/* + * you can use these defines to enable debugging behavior for + * apps compiled against libuci: + * + * #define UCI_DEBUG_TYPECAST: + * enable uci_element typecast checking at run time + * + */ + +#include +#include +#include + +#define UCI_CONFDIR "/etc/config" +#define UCI_SAVEDIR "/tmp/.uci" +#define UCI_DIRMODE 0700 +#define UCI_FILEMODE 0600 + +enum +{ + UCI_OK = 0, + UCI_ERR_MEM, + UCI_ERR_INVAL, + UCI_ERR_NOTFOUND, + UCI_ERR_IO, + UCI_ERR_PARSE, + UCI_ERR_DUPLICATE, + UCI_ERR_UNKNOWN, + UCI_ERR_LAST +}; + +struct uci_list; +struct uci_list +{ + struct uci_list *next; + struct uci_list *prev; +}; + +struct uci_ptr; +struct uci_element; +struct uci_package; +struct uci_section; +struct uci_option; +struct uci_history; +struct uci_context; +struct uci_backend; +struct uci_parse_context; + + +/** + * uci_alloc_context: Allocate a new uci context + */ +extern struct uci_context *uci_alloc_context(void); + +/** + * uci_free_context: Free the uci context including all of its data + */ +extern void uci_free_context(struct uci_context *ctx); + +/** + * uci_perror: Print the last uci error that occured + * @ctx: uci context + * @str: string to print before the error message + */ +extern void uci_perror(struct uci_context *ctx, const char *str); + +/** + * uci_geterror: Get an error string for the last uci error + * @ctx: uci context + * @dest: target pointer for the string + * @str: prefix for the error message + * + * Note: string must be freed by the caller + */ +extern void uci_get_errorstr(struct uci_context *ctx, char **dest, const char *str); + +/** + * uci_import: Import uci config data from a stream + * @ctx: uci context + * @stream: file stream to import from + * @name: (optional) assume the config has the given name + * @package: (optional) store the last parsed config package in this variable + * @single: ignore the 'package' keyword and parse everything into a single package + * + * the name parameter is for config files that don't explicitly use the 'package <...>' keyword + * if 'package' points to a non-null struct pointer, enable history tracking and merge + */ +extern int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct uci_package **package, bool single); + +/** + * uci_export: Export one or all uci config packages + * @ctx: uci context + * @stream: output stream + * @package: (optional) uci config package to export + * @header: include the package header + */ +extern int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *package, bool header); + +/** + * uci_load: Parse an uci config file and store it in the uci context + * + * @ctx: uci context + * @name: name of the config file (relative to the config directory) + * @package: store the loaded config package in this variable + */ +extern int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package); + +/** + * uci_unload: Unload a config file from the uci context + * + * @ctx: uci context + * @package: pointer to the uci_package struct + */ +extern int uci_unload(struct uci_context *ctx, struct uci_package *p); + +/** + * uci_lookup_ptr: Split an uci tuple string and look up an element tree + * @ctx: uci context + * @ptr: lookup result struct + * @str: uci tuple string to look up + * @extended: allow extended syntax lookup + * + * if extended is set to true, uci_lookup_ptr supports the following + * extended syntax: + * + * Examples: + * network.@interface[0].ifname ('ifname' option of the first interface section) + * network.@interface[-1] (last interface section) + * Note: uci_lookup_ext will automatically load a config package if necessary + */ +extern int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended); + +/** + * uci_add_section: Add an unnamed section + * @ctx: uci context + * @p: package to add the section to + * @type: section type + * @res: pointer to store a reference to the new section in + */ +extern int uci_add_section(struct uci_context *ctx, struct uci_package *p, const char *type, struct uci_section **res); + +/** + * uci_set: Set an element's value; create the element if necessary + * @ctx: uci context + * @ptr: uci pointer + * + * The updated/created element is stored in ptr->last + */ +extern int uci_set(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_add_list: Append a string to an element list + * @ctx: uci context + * @ptr: uci pointer (with value) + * + * Note: if the given option already contains a string value, + * it will be converted to an 1-element-list before appending the next element + */ +extern int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_rename: Rename an element + * @ctx: uci context + * @ptr: uci pointer (with value) + */ +extern int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_delete: Delete a section or option + * @ctx: uci context + * @ptr: uci pointer + */ +extern int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_save: save change history for a package + * @ctx: uci context + * @p: uci_package struct + */ +extern int uci_save(struct uci_context *ctx, struct uci_package *p); + +/** + * uci_commit: commit changes to a package + * @ctx: uci context + * @p: uci_package struct pointer + * @overwrite: overwrite existing config data and flush history + * + * committing may reload the whole uci_package data, + * the supplied pointer is updated accordingly + */ +extern int uci_commit(struct uci_context *ctx, struct uci_package **p, bool overwrite); + +/** + * uci_list_configs: List available uci config files + * @ctx: uci context + * + * caller is responsible for freeing the allocated memory behind list + */ +extern int uci_list_configs(struct uci_context *ctx, char ***list); + +/** + * uci_set_savedir: override the default history save directory + * @ctx: uci context + * @dir: directory name + */ +extern int uci_set_savedir(struct uci_context *ctx, const char *dir); + +/** + * uci_set_savedir: override the default config storage directory + * @ctx: uci context + * @dir: directory name + */ +extern int uci_set_confdir(struct uci_context *ctx, const char *dir); + +/** + * uci_add_history_path: add a directory to the search path for change history files + * @ctx: uci context + * @dir: directory name + * + * This function allows you to add directories, which contain 'overlays' + * for the active config, that will never be committed. + */ +extern int uci_add_history_path(struct uci_context *ctx, const char *dir); + +/** + * uci_revert: revert all changes to a config item + * @ctx: uci context + * @ptr: uci pointer + */ +extern int uci_revert(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_parse_argument: parse a shell-style argument, with an arbitrary quoting style + * @ctx: uci context + * @stream: input stream + * @str: pointer to the current line (use NULL for parsing the next line) + * @result: pointer for the result + */ +extern int uci_parse_argument(struct uci_context *ctx, FILE *stream, char **str, char **result); + +/** + * uci_set_backend: change the default backend + * @ctx: uci context + * @name: name of the backend + * + * The default backend is "file", which uses /etc/config for config storage + */ +extern int uci_set_backend(struct uci_context *ctx, const char *name); + +/** + * uci_validate_text: validate a value string for uci options + * @str: value + * + * this function checks whether a given string is acceptable as value + * for uci options + */ +extern bool uci_validate_text(const char *str); + +/* UCI data structures */ +enum uci_type { + UCI_TYPE_UNSPEC = 0, + UCI_TYPE_HISTORY = 1, + UCI_TYPE_PACKAGE = 2, + UCI_TYPE_SECTION = 3, + UCI_TYPE_OPTION = 4, + UCI_TYPE_PATH = 5, + UCI_TYPE_BACKEND = 6, + UCI_TYPE_ITEM = 7, +}; + +enum uci_option_type { + UCI_TYPE_STRING = 0, + UCI_TYPE_LIST = 1, +}; + +enum uci_flags { + UCI_FLAG_STRICT = (1 << 0), /* strict mode for the parser */ + UCI_FLAG_PERROR = (1 << 1), /* print parser error messages */ + UCI_FLAG_EXPORT_NAME = (1 << 2), /* when exporting, name unnamed sections */ + UCI_FLAG_SAVED_HISTORY = (1 << 3), /* store the saved history in memory as well */ +}; + +struct uci_element +{ + struct uci_list list; + enum uci_type type; + char *name; +}; + +struct uci_backend +{ + struct uci_element e; + char **(*list_configs)(struct uci_context *ctx); + struct uci_package *(*load)(struct uci_context *ctx, const char *name); + void (*commit)(struct uci_context *ctx, struct uci_package **p, bool overwrite); + + /* private: */ + const void *ptr; + void *priv; +}; + +struct uci_context +{ + /* list of config packages */ + struct uci_list root; + + /* parser context, use for error handling only */ + struct uci_parse_context *pctx; + + /* backend for import and export */ + struct uci_backend *backend; + struct uci_list backends; + + /* uci runtime flags */ + enum uci_flags flags; + + char *confdir; + char *savedir; + + /* search path for history files */ + struct uci_list history_path; + + /* private: */ + int err; + const char *func; + jmp_buf trap; + bool internal, nested; + char *buf; + int bufsz; +}; + +struct uci_package +{ + struct uci_element e; + struct uci_list sections; + struct uci_context *ctx; + bool has_history; + char *path; + + /* private: */ + struct uci_backend *backend; + void *priv; + int n_section; + struct uci_list history; + struct uci_list saved_history; +}; + +struct uci_section +{ + struct uci_element e; + struct uci_list options; + struct uci_package *package; + bool anonymous; + char *type; +}; + +struct uci_option +{ + struct uci_element e; + struct uci_section *section; + enum uci_option_type type; + union { + struct uci_list list; + char *string; + } v; +}; + +enum uci_command { + UCI_CMD_ADD, + UCI_CMD_REMOVE, + UCI_CMD_CHANGE, + UCI_CMD_RENAME, + UCI_CMD_LIST_ADD, +}; + +struct uci_history +{ + struct uci_element e; + enum uci_command cmd; + char *section; + char *value; +}; + +struct uci_ptr +{ + enum uci_type target; + enum { + UCI_LOOKUP_DONE = (1 << 0), + UCI_LOOKUP_COMPLETE = (1 << 1), + UCI_LOOKUP_EXTENDED = (1 << 2), + } flags; + + struct uci_package *p; + struct uci_section *s; + struct uci_option *o; + struct uci_element *last; + + const char *package; + const char *section; + const char *option; + const char *value; +}; + + +/* linked list handling */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + */ +#ifndef container_of +#define container_of(ptr, type, member) \ + ((type *) ((char *)ptr - offsetof(type,member))) +#endif + + +/** + * uci_list_entry: casts an uci_list pointer to the containing struct. + * @_type: config, section or option + * @_ptr: pointer to the uci_list struct + */ +#define list_to_element(ptr) \ + container_of(ptr, struct uci_element, list) + +/** + * uci_foreach_entry: loop through a list of uci elements + * @_list: pointer to the uci_list struct + * @_ptr: iteration variable, struct uci_element + * + * use like a for loop, e.g: + * uci_foreach(&list, p) { + * ... + * } + */ +#define uci_foreach_element(_list, _ptr) \ + for(_ptr = list_to_element((_list)->next); \ + &_ptr->list != (_list); \ + _ptr = list_to_element(_ptr->list.next)) + +/** + * uci_foreach_entry_safe: like uci_foreach_safe, but safe for deletion + * @_list: pointer to the uci_list struct + * @_tmp: temporary variable, struct uci_element * + * @_ptr: iteration variable, struct uci_element * + * + * use like a for loop, e.g: + * uci_foreach(&list, p) { + * ... + * } + */ +#define uci_foreach_element_safe(_list, _tmp, _ptr) \ + for(_ptr = list_to_element((_list)->next), \ + _tmp = list_to_element(_ptr->list.next); \ + &_ptr->list != (_list); \ + _ptr = _tmp, _tmp = list_to_element(_ptr->list.next)) + +/** + * uci_list_empty: returns true if a list is empty + * @list: list head + */ +#define uci_list_empty(list) ((list)->next == (list)) + +/* wrappers for dynamic type handling */ +#define uci_type_backend UCI_TYPE_BACKEND +#define uci_type_history UCI_TYPE_HISTORY +#define uci_type_package UCI_TYPE_PACKAGE +#define uci_type_section UCI_TYPE_SECTION +#define uci_type_option UCI_TYPE_OPTION + +/* element typecasting */ +#ifdef UCI_DEBUG_TYPECAST +static const char *uci_typestr[] = { + [uci_type_backend] = "backend", + [uci_type_history] = "history", + [uci_type_package] = "package", + [uci_type_section] = "section", + [uci_type_option] = "option", +}; + +static void uci_typecast_error(int from, int to) +{ + fprintf(stderr, "Invalid typecast from '%s' to '%s'\n", uci_typestr[from], uci_typestr[to]); +} + +#define BUILD_CAST(_type) \ + static inline struct uci_ ## _type *uci_to_ ## _type (struct uci_element *e) \ + { \ + if (e->type != uci_type_ ## _type) { \ + uci_typecast_error(e->type, uci_type_ ## _type); \ + } \ + return (struct uci_ ## _type *) e; \ + } + +BUILD_CAST(backend) +BUILD_CAST(history) +BUILD_CAST(package) +BUILD_CAST(section) +BUILD_CAST(option) + +#else +#define uci_to_backend(ptr) container_of(ptr, struct uci_backend, e) +#define uci_to_history(ptr) container_of(ptr, struct uci_history, e) +#define uci_to_package(ptr) container_of(ptr, struct uci_package, e) +#define uci_to_section(ptr) container_of(ptr, struct uci_section, e) +#define uci_to_option(ptr) container_of(ptr, struct uci_option, e) +#endif + +/** + * uci_alloc_element: allocate a generic uci_element, reserve a buffer and typecast + * @ctx: uci context + * @type: {package,section,option} + * @name: string containing the name of the element + * @datasize: additional buffer size to reserve at the end of the struct + */ +#define uci_alloc_element(ctx, type, name, datasize) \ + uci_to_ ## type (uci_alloc_generic(ctx, uci_type_ ## type, name, sizeof(struct uci_ ## type) + datasize)) + +#define uci_dataptr(ptr) \ + (((char *) ptr) + sizeof(*ptr)) + +#endif diff --git a/openwrt/packages/luci/host/usr/include/uci_config.h b/openwrt/packages/luci/host/usr/include/uci_config.h new file mode 100644 index 0000000..0dd76cc --- /dev/null +++ b/openwrt/packages/luci/host/usr/include/uci_config.h @@ -0,0 +1,3 @@ +#define UCI_PLUGIN_SUPPORT 1 +#undef UCI_DEBUG +#undef UCI_DEBUG_TYPECAST diff --git a/openwrt/packages/luci/host/usr/include/uci_list.h b/openwrt/packages/luci/host/usr/include/uci_list.h new file mode 100644 index 0000000..2959a06 --- /dev/null +++ b/openwrt/packages/luci/host/usr/include/uci_list.h @@ -0,0 +1,601 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#include +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#ifndef container_of +#define container_of(ptr, type, member) ( \ + (type *)( (char *)ptr - offsetof(type,member) )) +#endif + + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = NULL; + entry->prev = NULL; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = NULL; + n->pprev = NULL; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos; pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after current point + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from current point + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +#endif diff --git a/openwrt/packages/luci/host/usr/include/ucimap.h b/openwrt/packages/luci/host/usr/include/ucimap.h new file mode 100644 index 0000000..43f54e0 --- /dev/null +++ b/openwrt/packages/luci/host/usr/include/ucimap.h @@ -0,0 +1,125 @@ +/* + * ucimap - library for mapping uci sections into data structures + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include "uci_list.h" +#include "uci.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#define BITFIELD_SIZE(_fields) (((_fields) / 8) + 1) + +#define CLR_BIT(_name, _bit) do { \ + _name[(_bit) / 8] &= ~(1 << ((_bit) % 8)); \ +} while (0) + +#define SET_BIT(_name, _bit) do { \ + _name[(_bit) / 8] |= (1 << ((_bit) % 8)); \ +} while (0) + +#define TEST_BIT(_name, _bit) \ + (_name[(_bit) / 8] & (1 << ((_bit) % 8))) + +#define OPTMAP_OPTION(_maptype, _type, _field, ...) \ + { \ + .type = _maptype, \ + .name = #_field, \ + .offset = offsetof(_type, _field), \ + __VA_ARGS__ \ + } + +struct uci_sectmap; +struct uci_optmap; + +struct uci_map { + struct uci_sectmap **sections; + unsigned int n_sections; + struct list_head sdata; + struct list_head fixup; + + void *priv; /* user data */ +}; + +enum ucimap_type { + /* types */ + UCIMAP_SIMPLE = 0x00, + UCIMAP_LIST = 0x10, + UCIMAP_TYPE = 0xf0, /* type mask */ + + /* subtypes */ + UCIMAP_STRING = 0x0, + UCIMAP_BOOL = 0x1, + UCIMAP_INT = 0x2, + UCIMAP_SECTION = 0x3, + UCIMAP_SUBTYPE = 0xf, /* subtype mask */ +}; + +union uci_datamap { + int i; + bool b; + const char *s; + void *section; + struct list_head list; +}; + +struct uci_listmap { + struct list_head list; + union uci_datamap data; +}; + +struct uci_sectmap { + /* type string for the uci section */ + const char *type; + + /* length of the struct to map into */ + unsigned int alloc_len; + + /* give the caller time to initialize the preallocated struct */ + int (*init_section)(struct uci_map *map, void *section, struct uci_section *s); + + /* pass the fully processed struct to the callback after the section end */ + int (*add_section)(struct uci_map *map, void *section); + + /* let the callback clean up its own stuff in the section */ + int (*free_section)(struct uci_map *map, void *section); + + /* list of option mappings for this section */ + struct uci_optmap *options; + unsigned int n_options; +}; + +struct uci_optmap { + unsigned int offset; + const char *name; + enum ucimap_type type; + union { + struct { + int base; + int min; + int max; + } i; + struct { + int maxlen; + } s; + struct uci_sectmap *sm; + } data; +}; + +extern int ucimap_init(struct uci_map *map); +extern void ucimap_cleanup(struct uci_map *map); +extern void ucimap_set_changed(void *section, void *field); +extern int ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section); +extern void ucimap_parse(struct uci_map *map, struct uci_package *pkg); + diff --git a/openwrt/packages/luci/host/usr/lib/boa/luci.lua b/openwrt/packages/luci/host/usr/lib/boa/luci.lua new file mode 100644 index 0000000..2bb9313 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/boa/luci.lua @@ -0,0 +1,66 @@ +module("luci-plugin", package.seeall) + +function normalize(path) + local newpath + while newpath ~= path do + if (newpath) then + path = newpath + end + newpath = string.gsub(path, "/[^/]+/../", "/") + end + return newpath +end + +function init(path) + -- NB: path points to ROOT/usr/lib/boa, change it to /usr/lib/lua + root = normalize(path .. '/../../../') + path = normalize(path .. '/../lua/') + package.cpath = path..'?.so;'..package.cpath + package.path = path..'?.lua;'..package.path + + require("luci.dispatcher") + require("luci.sgi.webuci") + require("luci.model.uci") + + if (root ~= '/') then + -- Entering dummy mode + luci.model.uci.cursor = function(config, ...) + return uci.cursor(config or root .. "/etc/config", ...) + end + + luci.sys.hostname = function() return "" end + luci.sys.loadavg = function() return 0,0,0,0,0 end + luci.sys.reboot = function() return end + luci.sys.sysinfo = function() return "","","" end + luci.sys.syslog = function() return "" end + + luci.sys.net.arptable = function() return {} end + luci.sys.net.devices = function() return {} end + luci.sys.net.routes = function() return {} end + luci.sys.wifi.getiwconfig = function() return {} end + luci.sys.wifi.iwscan = function() return {} end + + luci.sys.user.checkpasswd = function() return true end + end +end + +function prepare_req(uri) + luci.dispatcher.createindex() + env = {} + env.REQUEST_URI = uri + -- TODO: setting luci-plugin.reload = true allows this function to trigger a context reload +end + +function handle_req(context) + env.SERVER_PROTOCOL = context.server_proto + env.REMOTE_ADDR = context.remote_addr + env.REQUEST_METHOD = context.request_method + env.PATH_INFO = context.uri + env.REMOTE_PORT = context.remote_port + env.SERVER_ADDR = context.server_addr + env.HTTP_COOKIE = context.cookie + env.HTTP_ACCEPT = context.http_accept + env.SCRIPT_NAME = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO) + + luci.sgi.webuci.run(env, vars) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/ltn12.lua b/openwrt/packages/luci/host/usr/lib/lua/ltn12.lua new file mode 100644 index 0000000..b42689a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/ltn12.lua @@ -0,0 +1,292 @@ +----------------------------------------------------------------------------- +-- LTN12 - Filters, sources, sinks and pumps. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: ltn12.lua,v 1.31 2006/04/03 04:45:42 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module +----------------------------------------------------------------------------- +local string = require("string") +local table = require("table") +local base = _G +module("ltn12") + +filter = {} +source = {} +sink = {} +pump = {} + +-- 2048 seems to be better in windows... +BLOCKSIZE = 2048 +_VERSION = "LTN12 1.0.1" + +----------------------------------------------------------------------------- +-- Filter stuff +----------------------------------------------------------------------------- +-- returns a high level filter that cycles a low-level filter +function filter.cycle(low, ctx, extra) + base.assert(low) + return function(chunk) + local ret + ret, ctx = low(ctx, chunk, extra) + return ret + end +end + +-- chains a bunch of filters together +-- (thanks to Wim Couwenberg) +function filter.chain(...) + local n = table.getn(arg) + local top, index = 1, 1 + local retry = "" + return function(chunk) + retry = chunk and retry + while true do + if index == top then + chunk = arg[index](chunk) + if chunk == "" or top == n then return chunk + elseif chunk then index = index + 1 + else + top = top+1 + index = top + end + else + chunk = arg[index](chunk or "") + if chunk == "" then + index = index - 1 + chunk = retry + elseif chunk then + if index == n then return chunk + else index = index + 1 end + else base.error("filter returned inappropriate nil") end + end + end + end +end + +----------------------------------------------------------------------------- +-- Source stuff +----------------------------------------------------------------------------- +-- create an empty source +local function empty() + return nil +end + +function source.empty() + return empty +end + +-- returns a source that just outputs an error +function source.error(err) + return function() + return nil, err + end +end + +-- creates a file source +function source.file(handle, io_err) + if handle then + return function() + local chunk = handle:read(BLOCKSIZE) + if not chunk then handle:close() end + return chunk + end + else return source.error(io_err or "unable to open file") end +end + +-- turns a fancy source into a simple source +function source.simplify(src) + base.assert(src) + return function() + local chunk, err_or_new = src() + src = err_or_new or src + if not chunk then return nil, err_or_new + else return chunk end + end +end + +-- creates string source +function source.string(s) + if s then + local i = 1 + return function() + local chunk = string.sub(s, i, i+BLOCKSIZE-1) + i = i + BLOCKSIZE + if chunk ~= "" then return chunk + else return nil end + end + else return source.empty() end +end + +-- creates rewindable source +function source.rewind(src) + base.assert(src) + local t = {} + return function(chunk) + if not chunk then + chunk = table.remove(t) + if not chunk then return src() + else return chunk end + else + table.insert(t, chunk) + end + end +end + +function source.chain(src, f) + base.assert(src and f) + local last_in, last_out = "", "" + local state = "feeding" + local err + return function() + if not last_out then + base.error('source is empty!', 2) + end + while true do + if state == "feeding" then + last_in, err = src() + if err then return nil, err end + last_out = f(last_in) + if not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + elseif last_out ~= "" then + state = "eating" + if last_in then last_in = "" end + return last_out + end + else + last_out = f(last_in) + if last_out == "" then + if last_in == "" then + state = "feeding" + else + base.error('filter returned ""') + end + elseif not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + else + return last_out + end + end + end + end +end + +-- creates a source that produces contents of several sources, one after the +-- other, as if they were concatenated +-- (thanks to Wim Couwenberg) +function source.cat(...) + local src = table.remove(arg, 1) + return function() + while src do + local chunk, err = src() + if chunk then return chunk end + if err then return nil, err end + src = table.remove(arg, 1) + end + end +end + +----------------------------------------------------------------------------- +-- Sink stuff +----------------------------------------------------------------------------- +-- creates a sink that stores into a table +function sink.table(t) + t = t or {} + local f = function(chunk, err) + if chunk then table.insert(t, chunk) end + return 1 + end + return f, t +end + +-- turns a fancy sink into a simple sink +function sink.simplify(snk) + base.assert(snk) + return function(chunk, err) + local ret, err_or_new = snk(chunk, err) + if not ret then return nil, err_or_new end + snk = err_or_new or snk + return 1 + end +end + +-- creates a file sink +function sink.file(handle, io_err) + if handle then + return function(chunk, err) + if not chunk then + handle:close() + return 1 + else return handle:write(chunk) end + end + else return sink.error(io_err or "unable to open file") end +end + +-- creates a sink that discards data +local function null() + return 1 +end + +function sink.null() + return null +end + +-- creates a sink that just returns an error +function sink.error(err) + return function() + return nil, err + end +end + +-- chains a sink with a filter +function sink.chain(f, snk) + base.assert(f and snk) + return function(chunk, err) + if chunk ~= "" then + local filtered = f(chunk) + local done = chunk and "" + while true do + local ret, snkerr = snk(filtered, err) + if not ret then return nil, snkerr end + if filtered == done then return 1 end + filtered = f(done) + end + else return 1 end + end +end + +----------------------------------------------------------------------------- +-- Pump stuff +----------------------------------------------------------------------------- +-- pumps one chunk from the source to the sink +function pump.step(src, snk) + local chunk, src_err = src() + local ret, snk_err = snk(chunk, src_err) + if chunk and ret then return 1 + else return nil, src_err or snk_err end +end + +-- pumps all data from a source to a sink, using a step function +function pump.all(src, snk, step) + base.assert(src and snk) + step = step or pump.step + while true do + local ret, err = step(src, snk) + if not ret then + if err then return nil, err + else return 1 end + end + end +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/config.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/config.lua new file mode 100644 index 0000000..2738cf5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/config.lua @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +-- LuaDoc configuration file. This file contains the default options for +-- luadoc operation. These options can be overriden by the command line tool +-- @see luadoc.print_help +-- @release $Id: config.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +module "luadoc.config" + +------------------------------------------------------------------------------- +-- Default options +-- @class table +-- @name default_options +-- @field output_dir default output directory for generated documentation, used +-- by several doclets +-- @field taglet parser used to analyze source code input +-- @field doclet documentation generator +-- @field template_dir directory with documentation templates, used by the html +-- doclet +-- @field verbose command line tool configuration to output processing +-- information + +local default_options = { + output_dir = "", + taglet = "luadoc.taglet.standard", + doclet = "luadoc.doclet.html", + -- TODO: find a way to define doclet specific options + template_dir = "luadoc/doclet/html/", + nomodules = false, + nofiles = false, + verbose = true, +} + +return default_options diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/debug.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/debug.lua new file mode 100644 index 0000000..33966cb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/debug.lua @@ -0,0 +1,46 @@ +----------------------------------------------------------------- +-- LuaDoc debugging facilities. +-- @release $Id: debug.lua 3941 2008-12-23 21:39:38Z jow $ +----------------------------------------------------------------- + +module "luadoc.doclet.debug" + +function printline() + print(string.rep('-', 79)) +end + +----------------------------------------------------------------- +-- Print debug information about document +-- @param doc Table with the structured documentation. + +function start (doc) + print("Files:") + for _, filepath in ipairs(doc.files) do + print('\t', filepath) + end + printline() + + print("Modules:") + for _, modulename in ipairs(doc.modules) do + print('\t', modulename) + end + printline() + + for i, v in pairs(doc.files) do + print('\t', i, v) + end + printline() + for i, v in pairs(doc.files[doc.files[1]]) do + print(i, v) + end + + printline() + for i, v in pairs(doc.files[doc.files[1]].doc[1]) do + print(i, v) + end + printline() + print("Params") + for i, v in pairs(doc.files[doc.files[1]].doc[1].param) do + print(i, v) + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/formatter.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/formatter.lua new file mode 100644 index 0000000..40a7ce0 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/formatter.lua @@ -0,0 +1,84 @@ +------------------------------------------------------------------------------- +-- Doclet to format source code according to LuaDoc standard tags. This doclet +-- (re)write .lua files adding missing standard tags. Texts are formatted to +-- 80 columns and function parameters are added based on code analysis. +-- +-- @release $Id: formatter.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local util = require "luadoc.util" +local assert, ipairs, pairs, type = assert, ipairs, pairs, type +local string = require"string" +local table = require"table" + +module "luadoc.doclet.formatter" + +options = { + output_dir = "./", +} + +------------------------------------------------------------------------------- +-- Assembly the output filename for an input file. +-- TODO: change the name of this function +function out_file (filename) + local h = filename + h = options.output_dir..h + return h +end + +------------------------------------------------------------------------------- +-- Generate a new lua file for each input lua file. If the user does not +-- specify a different output directory input files will be rewritten. +-- @param doc documentation table + +function start (doc) + local todo = "" + + -- Process files + for i, file_doc in ipairs(doc.files) do + -- assembly the filename + local filename = out_file(file_doc.name) + luadoc.logger:info(string.format("generating file `%s'", filename)) + + -- TODO: confirm file overwrite + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + + for _, block in ipairs(file_doc.doc) do + + -- write reorganized comments + f:write(string.rep("-", 80).."\n") + + -- description + f:write(util.comment(util.wrap(block.description, 77))) + f:write("\n") + + if block.class == "function" then + -- parameters + table.foreachi(block.param, function (_, param_name) + f:write(util.comment(util.wrap(string.format("@param %s %s", param_name, block.param[param_name] or todo), 77))) + f:write("\n") + end) + + -- return + if type(block.ret) == "table" then + table.foreachi(block.ret, function (_, ret) + f:write(util.comment(util.wrap(string.format("@return %s", ret), 77)).."\n") + end) + else + f:write(util.comment(util.wrap(string.format("@return %s", block.ret or todo), 77)).."\n") + end + end + + -- TODO: usage + -- TODO: see + + -- write code + for _, line in ipairs(block.code) do + f:write(line.."\n") + end + end + + f:close() + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html.lua new file mode 100644 index 0000000..cd55e2e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html.lua @@ -0,0 +1,275 @@ +------------------------------------------------------------------------------- +-- Doclet that generates HTML output. This doclet generates a set of html files +-- based on a group of templates. The main templates are: +--
    +--
  • index.lp: index of modules and files;
  • +--
  • file.lp: documentation for a lua file;
  • +--
  • module.lp: documentation for a lua module;
  • +--
  • function.lp: documentation for a lua function. This is a +-- sub-template used by the others.
  • +--
+-- +-- @release $Id: html.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local assert, getfenv, ipairs, loadstring, pairs, setfenv, tostring, tonumber, type = assert, getfenv, ipairs, loadstring, pairs, setfenv, tostring, tonumber, type +local io = require"io" +local posix = require "posix" +local lp = require "luadoc.lp" +local luadoc = require"luadoc" +local package = package +local string = require"string" +local table = require"table" + +module "luadoc.doclet.html" + +------------------------------------------------------------------------------- +-- Looks for a file `name' in given path. Removed from compat-5.1 +-- @param path String with the path. +-- @param name String with the name to look for. +-- @return String with the complete path of the file found +-- or nil in case the file is not found. + +local function search (path, name) + for c in string.gfind(path, "[^;]+") do + c = string.gsub(c, "%?", name) + local f = io.open(c) + if f then -- file exist? + f:close() + return c + end + end + return nil -- file not found +end + +------------------------------------------------------------------------------- +-- Include the result of a lp template into the current stream. + +function include (template, env) + -- template_dir is relative to package.path + local templatepath = options.template_dir .. template + + -- search using package.path (modified to search .lp instead of .lua + local search_path = string.gsub(package.path, "%.lua", "") + local templatepath = search(search_path, templatepath) + assert(templatepath, string.format("template `%s' not found", template)) + + env = env or {} + env.table = table + env.io = io + env.lp = lp + env.ipairs = ipairs + env.tonumber = tonumber + env.tostring = tostring + env.type = type + env.luadoc = luadoc + env.options = options + + return lp.include(templatepath, env) +end + +------------------------------------------------------------------------------- +-- Returns a link to a html file, appending "../" to the link to make it right. +-- @param html Name of the html file to link to +-- @return link to the html file + +function link (html, from) + local h = html + from = from or "" + string.gsub(from, "/", function () h = "../" .. h end) + return h +end + +------------------------------------------------------------------------------- +-- Returns the name of the html file to be generated from a module. +-- Files with "lua" or "luadoc" extensions are replaced by "html" extension. +-- @param modulename Name of the module to be processed, may be a .lua file or +-- a .luadoc file. +-- @return name of the generated html file for the module + +function module_link (modulename, doc, from) + -- TODO: replace "." by "/" to create directories? + -- TODO: how to deal with module names with "/"? + assert(modulename) + assert(doc) + from = from or "" + + if doc.modules[modulename] == nil then +-- logger:error(string.format("unresolved reference to module `%s'", modulename)) + return + end + + local href = "modules/" .. modulename .. ".html" + string.gsub(from, "/", function () href = "../" .. href end) + return href +end + +------------------------------------------------------------------------------- +-- Returns the name of the html file to be generated from a lua(doc) file. +-- Files with "lua" or "luadoc" extensions are replaced by "html" extension. +-- @param to Name of the file to be processed, may be a .lua file or +-- a .luadoc file. +-- @param from path of where am I, based on this we append ..'s to the +-- beginning of path +-- @return name of the generated html file + +function file_link (to, from) + assert(to) + from = from or "" + + local href = to + href = string.gsub(href, "lua$", "html") + href = string.gsub(href, "luadoc$", "html") + href = "files/" .. href + string.gsub(from, "/", function () href = "../" .. href end) + return href +end + +------------------------------------------------------------------------------- +-- Returns a link to a function or to a table +-- @param fname name of the function or table to link to. +-- @param doc documentation table +-- @param kind String specying the kinf of element to link ("functions" or "tables"). + +function link_to (fname, doc, module_doc, file_doc, from, kind) + assert(fname) + assert(doc) + from = from or "" + kind = kind or "functions" + + if file_doc then + for _, func_name in pairs(file_doc[kind]) do + if func_name == fname then + return file_link(file_doc.name, from) .. "#" .. fname + end + end + end + + if module_doc and module_doc[kind] then + for func_name, tbl in pairs(module_doc[kind]) do + if func_name == fname then + return "#" .. fname + end + end + end + + local _, _, modulename, fname = string.find(fname, "^(.-)[%.%:]?([^%.%:]*)$") + assert(fname) + + -- if fname does not specify a module, use the module_doc + if string.len(modulename) == 0 and module_doc then + modulename = module_doc.name + end + + local module_doc = doc.modules[modulename] + if not module_doc then +-- logger:error(string.format("unresolved reference to function `%s': module `%s' not found", fname, modulename)) + return + end + + for _, func_name in pairs(module_doc[kind]) do + if func_name == fname then + return module_link(modulename, doc, from) .. "#" .. fname + end + end + +-- logger:error(string.format("unresolved reference to function `%s' of module `%s'", fname, modulename)) +end + +------------------------------------------------------------------------------- +-- Make a link to a file, module or function + +function symbol_link (symbol, doc, module_doc, file_doc, from) + assert(symbol) + assert(doc) + + local href = +-- file_link(symbol, from) or + module_link(symbol, doc, from) or + link_to(symbol, doc, module_doc, file_doc, from, "functions") or + link_to(symbol, doc, module_doc, file_doc, from, "tables") + + if not href then + logger:error(string.format("unresolved reference to symbol `%s'", symbol)) + end + + return href or "" +end + +------------------------------------------------------------------------------- +-- Assembly the output filename for an input file. +-- TODO: change the name of this function +function out_file (filename) + local h = filename + h = string.gsub(h, "lua$", "html") + h = string.gsub(h, "luadoc$", "html") + h = "files/" .. h +-- h = options.output_dir .. string.gsub (h, "^.-([%w_]+%.html)$", "%1") + h = options.output_dir .. h + return h +end + +------------------------------------------------------------------------------- +-- Assembly the output filename for a module. +-- TODO: change the name of this function +function out_module (modulename) + local h = modulename .. ".html" + h = "modules/" .. h + h = options.output_dir .. h + return h +end + +----------------------------------------------------------------- +-- Generate the output. +-- @param doc Table with the structured documentation. + +function start (doc) + -- Generate index file + if (#doc.files > 0 or #doc.modules > 0) and (not options.noindexpage) then + local filename = options.output_dir.."index.html" + logger:info(string.format("generating file `%s'", filename)) + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + io.output(f) + include("index.lp", { doc = doc }) + f:close() + end + + -- Process modules + if not options.nomodules then + for _, modulename in ipairs(doc.modules) do + local module_doc = doc.modules[modulename] + -- assembly the filename + local filename = out_module(modulename) + logger:info(string.format("generating file `%s'", filename)) + + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + io.output(f) + include("module.lp", { doc = doc, module_doc = module_doc }) + f:close() + end + end + + -- Process files + if not options.nofiles then + for _, filepath in ipairs(doc.files) do + local file_doc = doc.files[filepath] + -- assembly the filename + local filename = out_file(file_doc.name) + logger:info(string.format("generating file `%s'", filename)) + + local f = posix.open(filename, "w") + assert(f, string.format("could not open `%s' for writing", filename)) + io.output(f) + include("file.lp", { doc = doc, file_doc = file_doc} ) + f:close() + end + end + + -- copy extra files + local f = posix.open(options.output_dir.."luadoc.css", "w") + io.output(f) + include("luadoc.css") + f:close() +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/constant.lp b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/constant.lp new file mode 100644 index 0000000..2e35392 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/constant.lp @@ -0,0 +1,28 @@ +<% +if module_doc then + from = "modules/"..module_doc.name +elseif file_doc then + from = "files/.."..file_doc.name +else + from = "" +end +%> + +
<%=const.private and "local " or ""%><%=const.name:gsub(".+%.","")%>
+
+<%=const.description or ""%> + +<%if type(const.see) == "string" then %> +

See also:

+ <%=const.see%> +<%elseif type(const.see) == "table" and #const.see > 0 then %> +

See also:

+ +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/file.lp b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/file.lp new file mode 100644 index 0000000..67926b4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/file.lp @@ -0,0 +1,112 @@ + + + + Reference + + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ +

File <%=file_doc.name%>

+ +<%if file_doc.description then%> +

<%=file_doc.description%>

+<%end%> +<%if file_doc.author then%> +

<%= #file_doc.author>1 and "Authors" or "Author" %>: + +<%for _, author in ipairs(file_doc.author) do%> + +<%end%> +
<%= author %>
+

+<%end%> +<%if file_doc.copyright then%> +

Copyright ©<%=file_doc.copyright%>

+<%end%> +<%if file_doc.release then%> +

Release: <%=file_doc.release%>

+<%end%> + +<%if #file_doc.functions > 0 then%> +

Functions

+ +<%for _, func_name in ipairs(file_doc.functions) do + local func_data = file_doc.functions[func_name]%> + + + + +<%end%> +
<%=func_data.private and "local " or ""%><%=func_name%> (<%=table.concat(func_data.param, ", ")%>)<%=func_data.summary%>
+<%end%> + + +<%if #file_doc.tables > 0 then%> +

Tables

+ +<%for _, tab_name in ipairs(file_doc.tables) do%> + + + + +<%end%> +
<%=tab_name%><%=file_doc.tables[tab_name].summary%>
+<%end%> + + +
+
+ + + +<%if #file_doc.functions > 0 then%> +

Functions

+
+<%for _, func_name in ipairs(file_doc.functions) do%> +<%=luadoc.doclet.html.include("function.lp", { doc=doc, file_doc=file_doc, func=file_doc.functions[func_name] })%> +<%end%> +
+<%end%> + + +<%if #file_doc.tables > 0 then%> +

Tables

+
+<%for _, tab_name in ipairs(file_doc.tables) do%> +<%=luadoc.doclet.html.include("table.lp", { doc=doc, file_doc=file_doc, tab=file_doc.tables[tab_name] })%> +<%end%> +
+<%end%> + + + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/function.lp b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/function.lp new file mode 100644 index 0000000..a870ff8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/function.lp @@ -0,0 +1,64 @@ +<% +if module_doc then + from = "modules/"..module_doc.name +elseif file_doc then + from = "files/.."..file_doc.name +else + from = "" +end +%> + +
<%=func.private and "local " or ""%><%=(oop and func.name:gsub("%.",":") or func.name:gsub(".+%.",""))%> (<%=table.concat(func.param or {}, ", ")%>)
+
+<%=func.description or ""%> + +<%if type(func.param) == "table" and #func.param > 0 then%> +

Parameters

+
    + <%for p = 1, #func.param do%> +
  • + <%=func.param[p]%>: <%=func.param[func.param[p]] or ""%> +
  • + <%end%> +
+<%end%> + + +<%if type(func.usage) == "string" then%> +

Usage:

+<%=func.usage%> +<%elseif type(func.usage) == "table" then%> +

Usage

+
    + <%for _, usage in ipairs(func.usage) do%> +
  • <%= usage %> + <%end%> +
+<%end%> + +<%if type(func.ret) == "string" then%> +

Return value:

+<%=func.ret%> +<%elseif type(func.ret) == "table" then%> +

Return values:

+
    + <%for _, ret in ipairs(func.ret) do%> +
  1. <%= ret %> + <%end%> +
+<%end%> + +<%if type(func.see) == "string" then %> +

See also:

+ <%=func.see%> +<%elseif type(func.see) == "table" and #func.see > 0 then %> +

See also:

+ +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/index.lp b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/index.lp new file mode 100644 index 0000000..b4b9f5c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/index.lp @@ -0,0 +1,67 @@ + + + + Reference + " type="text/css" /> + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ + +<%if not options.nomodules and #doc.modules > 0 then%> +

Modules

+ + +<%for _, modulename in ipairs(doc.modules) do%> + + + + +<%end%> +
<%=modulename%><%=doc.modules[modulename].summary%>
+<%end%> + + + +<%if not options.nofiles and #doc.files > 0 then%> +

Files

+ + +<%for _, filepath in ipairs(doc.files) do%> + + + + +<%end%> +
<%=filepath%>
+<%end%> + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/luadoc.css b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/luadoc.css new file mode 100644 index 0000000..bc0f98a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/luadoc.css @@ -0,0 +1,286 @@ +body { + margin-left: 1em; + margin-right: 1em; + font-family: arial, helvetica, geneva, sans-serif; + background-color:#ffffff; margin:0px; +} + +code { + font-family: "Andale Mono", monospace; +} + +tt { + font-family: "Andale Mono", monospace; +} + +body, td, th { font-size: 11pt; } + +h1, h2, h3, h4 { margin-left: 0em; } + +textarea, pre, tt { font-size:10pt; } +body, td, th { color:#000000; } +small { font-size:0.85em; } +h1 { font-size:1.5em; } +h2 { font-size:1.25em; } +h3 { font-size:1.15em; } +h4 { font-size:1.06em; } + +a:link { font-weight:bold; color: #004080; text-decoration: none; } +a:visited { font-weight:bold; color: #006699; text-decoration: none; } +a:link:hover { text-decoration:underline; } +hr { color:#cccccc } +img { border-width: 0px; } + + +h3 { padding-top: 1em; } + +p { margin-left: 1em; } + +p.name { + font-family: "Andale Mono", monospace; + padding-top: 1em; + margin-left: 0em; +} + +blockquote { margin-left: 3em; } + +pre.example { + background-color: rgb(245, 245, 245); + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-color: silver; + border-right-color: silver; + border-bottom-color: silver; + border-left-color: silver; + padding: 1em; + margin-left: 1em; + margin-right: 1em; + font-family: "Andale Mono", monospace; + font-size: smaller; +} + + +hr { + margin-left: 0em; + background: #00007f; + border: 0px; + height: 1px; +} + +ul { list-style-type: disc; } + +table.index { border: 1px #00007f; } +table.index td { text-align: left; vertical-align: top; } +table.index ul { padding-top: 0em; margin-top: 0em; } + +table { + border: 1px solid black; + border-collapse: collapse; + margin-left: auto; + margin-right: auto; +} +th { + border: 1px solid black; + padding: 0.5em; +} +td { + border: 1px solid black; + padding: 0.5em; +} +div.header, div.footer { margin-left: 0em; } + +#container +{ + margin-left: 1em; + margin-right: 1em; + background-color: #f0f0f0; +} + +#product +{ + text-align: center; + border-bottom: 1px solid #cccccc; + background-color: #ffffff; +} + +#product big { + font-size: 2em; +} + +#product_logo +{ +} + +#product_name +{ +} + +#product_description +{ +} + +#main +{ + background-color: #f0f0f0; + border-left: 2px solid #cccccc; +} + +#navigation +{ + float: left; + width: 18em; + margin: 0; + vertical-align: top; + background-color: #f0f0f0; + overflow:visible; +} + +#navigation h1 { + background-color:#e7e7e7; + font-size:1.1em; + color:#000000; + text-align:left; + margin:0px; + padding:0.2em; + border-top:1px solid #dddddd; + border-bottom:1px solid #dddddd; +} + +#navigation ul +{ + font-size:1em; + list-style-type: none; + padding: 0; + margin: 1px; +} + +#navigation li +{ + text-indent: -1em; + margin: 0em 0em 0em 0.5em; + display: block; + padding: 3px 0px 0px 12px; +} + +#navigation li li a +{ + padding: 0px 3px 0px -1em; +} + +#content +{ + margin-left: 18em; + padding: 1em; + border-left: 2px solid #cccccc; + border-right: 2px solid #cccccc; + background-color: #ffffff; +} + +#about +{ + clear: both; + margin: 0; + padding: 5px; + border-top: 2px solid #cccccc; + background-color: #ffffff; +} + +@media print { + body { + font: 12pt "Times New Roman", "TimeNR", Times, serif; + } + a { font-weight:bold; color: #004080; text-decoration: underline; } + + #main { background-color: #ffffff; border-left: 0px; } + #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } + + #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } + + #navigation { display: none; + } + pre.example { + font-family: "Andale Mono", monospace; + font-size: 10pt; + page-break-inside: avoid; + } +} + +table.module_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.module_list td.name { background-color: #f0f0f0; } +table.module_list td.summary { width: 100%; } + +table.file_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.file_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.file_list td.name { background-color: #f0f0f0; } +table.file_list td.summary { width: 100%; } + + +table.function_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.function_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.function_list td.name { background-color: #f0f0f0; } +table.function_list td.summary { width: 100%; } + + +table.table_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.table_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.table_list td.name { background-color: #f0f0f0; } +table.table_list td.summary { width: 100%; } + +dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} +dl.function dd {padding-bottom: 1em;} +dl.function h3 {padding: 0; margin: 0; font-size: medium;} + +dl.table dt {border-top: 1px solid #ccc; padding-top: 1em;} +dl.table dd {padding-bottom: 1em;} +dl.table h3 {padding: 0; margin: 0; font-size: medium;} + +#TODO: make module_list, file_list, function_list, table_list inherit from a list + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/menu.lp b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/menu.lp new file mode 100644 index 0000000..0fe3652 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/menu.lp @@ -0,0 +1,55 @@ +<% +if module_doc then + from = "modules/"..module_doc.name +elseif file_doc then + from = "files/.."..file_doc.name +else + from = "" +end +%> + +

LuaDoc

+
    + <%if not module_doc and not file_doc then%> +
  • Index
  • + <%else%> +
  • ">Index
  • + <%end%> +
+ + + +<%if not options.nomodules and #doc.modules > 0 then%> +

Modules

+
    +<%for _, modulename in ipairs(doc.modules) do + if module_doc and module_doc.name == modulename then%> +
  • <%=modulename%>
  • + <%else%> +
  • + <%=modulename%> +
  • +<% end +end%> +
+<%end%> + + + +<%if not options.nofiles and #doc.files > 0 then%> +

Files

+
    +<%for _, filepath in ipairs(doc.files) do + if file_doc and file_doc.name == filepath then%> +
  • <%=filepath%>
  • + <%else%> +
  • + <%=filepath%> +
  • +<% end +end%> +
+<%end%> + + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/module.lp b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/module.lp new file mode 100644 index 0000000..daa7086 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/module.lp @@ -0,0 +1,120 @@ + + + + Reference + + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ +

<%=( oop and "Object Instance" or "Class" )%> <%=module_doc.name%>

+ +

<%=module_doc.description%>

+<%if module_doc.author then%> +

<%= #module_doc.author>1 and "Authors" or "Author" %>: + +<%for _, author in ipairs(module_doc.author) do%> + +<%end%> +
<%= author %>
+

+<%end%> +<%if module_doc.copyright then%> +

Copyright© <%=module_doc.copyright%>

+<%end%> +<%if module_doc.release then%> +

Release: <%=module_doc.release%>

+<%end%> + +<%if #module_doc.constants > 0 then %> +

Constants

+ +<%for _, const_name in ipairs(module_doc.constants) do + local const_data = module_doc.constants[const_name]%> + + + + +<%end%> +
<%=const_data.private and "local " or ""%><%=(const_name:gsub(".+%.",""))%><%=const_data.summary%>
+<%end%> + +<%if #module_doc.functions > 0 then %> +

Functions

+ +<%for _, func_name in ipairs(module_doc.functions) do + local func_data = module_doc.functions[func_name]%> + + + + +<%end%> +
<%=func_data.private and "local " or ""%><%=(oop and func_name:gsub("%.",":") or func_name:gsub(".+%.",""))%> (<%=table.concat(module_doc.functions[func_name].param or {}, ", ")%>)<%=module_doc.functions[func_name].summary%>
+<%end%> + + +<%if #module_doc.tables > 0 then%> +

Tables

+ +<%for _, tab_name in ipairs(module_doc.tables) do%> + + + + +<%end%> +
<%=tab_name%><%=module_doc.tables[tab_name].summary%>
+<%end%> + + +
+
+ +<%if #module_doc.functions > 0 then%> +

Functions

+
+<%for _, func_name in ipairs(module_doc.functions) do%> +<%=luadoc.doclet.html.include("function.lp", { doc=doc, module_doc=module_doc, func=module_doc.functions[func_name], oop=oop })%> +<%end%> +
+<%end%> + +<%if #module_doc.tables > 0 then%> +

Tables

+
+<%for _, tab_name in ipairs(module_doc.tables) do%> +<%=luadoc.doclet.html.include("table.lp", { doc=doc, module_doc=module_doc, tab=module_doc.tables[tab_name] })%> +<%end%> +
+<%end%> + + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/table.lp b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/table.lp new file mode 100644 index 0000000..5cd0239 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/html/table.lp @@ -0,0 +1,15 @@ +
<%=tab.name%>
+
<%=tab.description%> + +<%if type(tab.field) == "table" and #tab.field > 0 then%> +Fields +
    + <%for p = 1, #tab.field do%> +
  • + <%=tab.field[p]%>: <%=tab.field[tab.field[p]] or ""%> +
  • + <%end%> +
+<%end%> + +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/raw.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/raw.lua new file mode 100644 index 0000000..6c8ba6f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/doclet/raw.lua @@ -0,0 +1,12 @@ +----------------------------------------------------------------- +-- @release $Id: raw.lua 3941 2008-12-23 21:39:38Z jow $ +----------------------------------------------------------------- + +module "luadoc.doclet.raw" + +----------------------------------------------------------------- +-- Generate the output. +-- @param doc Table with the structured documentation. + +function start (doc) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/init.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/init.lua new file mode 100644 index 0000000..dedf379 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/init.lua @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------- +-- LuaDoc main function. +-- @release $Id: init.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local require = require + +local util = require "luadoc.util" + +logger = {} + +module ("luadoc") + +------------------------------------------------------------------------------- +-- LuaDoc version number. + +_COPYRIGHT = "Copyright (c) 2003-2007 The Kepler Project" +_DESCRIPTION = "Documentation Generator Tool for the Lua language" +_VERSION = "LuaDoc 3.0.1" + +------------------------------------------------------------------------------- +-- Main function +-- @see luadoc.doclet.html, luadoc.doclet.formatter, luadoc.doclet.raw +-- @see luadoc.taglet.standard + +function main (files, options) + logger = util.loadlogengine(options) + + -- load config file + if options.config ~= nil then + -- load specified config file + dofile(options.config) + else + -- load default config file + require("luadoc.config") + end + + local taglet = require(options.taglet) + local doclet = require(options.doclet) + + -- analyze input + taglet.options = options + taglet.logger = logger + local doc = taglet.start(files) + + -- generate output + doclet.options = options + doclet.logger = logger + doclet.start(doc) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/lp.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/lp.lua new file mode 100644 index 0000000..f880ab7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/lp.lua @@ -0,0 +1,130 @@ +---------------------------------------------------------------------------- +-- Lua Pages Template Preprocessor. +-- +-- @release $Id: lp.lua 3941 2008-12-23 21:39:38Z jow $ +---------------------------------------------------------------------------- + +local assert, error, getfenv, loadstring, setfenv = assert, error, getfenv, loadstring, setfenv +local find, format, gsub, strsub = string.find, string.format, string.gsub, string.sub +local concat, tinsert = table.concat, table.insert +local open = io.open + +module (...) + +---------------------------------------------------------------------------- +-- function to do output +local outfunc = "io.write" +-- accepts the old expression field: `$| |$' +local compatmode = true + +-- +-- Builds a piece of Lua code which outputs the (part of the) given string. +-- @param s String. +-- @param i Number with the initial position in the string. +-- @param f Number with the final position in the string (default == -1). +-- @return String with the correspondent Lua code which outputs the part of the string. +-- +local function out (s, i, f) + s = strsub(s, i, f or -1) + if s == "" then return s end + -- we could use `%q' here, but this way we have better control + s = gsub(s, "([\\\n\'])", "\\%1") + -- substitute '\r' by '\'+'r' and let `loadstring' reconstruct it + s = gsub(s, "\r", "\\r") + return format(" %s('%s'); ", outfunc, s) +end + + +---------------------------------------------------------------------------- +-- Translate the template to Lua code. +-- @param s String to translate. +-- @return String with translated code. +---------------------------------------------------------------------------- +function translate (s) + if compatmode then + s = gsub(s, "$|(.-)|%$", "") + s = gsub(s, "", "") + end + s = gsub(s, "<%%(.-)%%>", "") + local res = {} + local start = 1 -- start of untranslated part in `s' + while true do + local ip, fp, target, exp, code = find(s, "<%?(%w*)[ \t]*(=?)(.-)%?>", start) + if not ip then break end + tinsert(res, out(s, start, ip-1)) + if target ~= "" and target ~= "lua" then + -- not for Lua; pass whole instruction to the output + tinsert(res, out(s, ip, fp)) + else + if exp == "=" then -- expression? + tinsert(res, format(" %s(%s);", outfunc, code)) + else -- command + tinsert(res, format(" %s ", code)) + end + end + start = fp + 1 + end + tinsert(res, out(s, start)) + return concat(res) +end + + +---------------------------------------------------------------------------- +-- Defines the name of the output function. +-- @param f String with the name of the function which produces output. + +function setoutfunc (f) + outfunc = f +end + +---------------------------------------------------------------------------- +-- Turns on or off the compatibility with old CGILua 3.X behavior. +-- @param c Boolean indicating if the compatibility mode should be used. + +function setcompatmode (c) + compatmode = c +end + +---------------------------------------------------------------------------- +-- Internal compilation cache. + +local cache = {} + +---------------------------------------------------------------------------- +-- Translates a template into a Lua function. +-- Does NOT execute the resulting function. +-- Uses a cache of templates. +-- @param string String with the template to be translated. +-- @param chunkname String with the name of the chunk, for debugging purposes. +-- @return Function with the resulting translation. + +function compile (string, chunkname) + local f, err = cache[string] + if f then return f end + f, err = loadstring (translate (string), chunkname) + if not f then error (err, 3) end + cache[string] = f + return f +end + +---------------------------------------------------------------------------- +-- Translates and executes a template in a given file. +-- The translation creates a Lua function which will be executed in an +-- optionally given environment. +-- @param filename String with the name of the file containing the template. +-- @param env Table with the environment to run the resulting function. + +function include (filename, env) + -- read the whole contents of the file + local fh = assert (open (filename)) + local src = fh:read("*a") + fh:close() + -- translates the file into a function + local prog = compile (src, '@'..filename) + local _env + if env then + _env = getfenv (prog) + setfenv (prog, env) + end + prog () +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard.lua new file mode 100644 index 0000000..d4654b7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard.lua @@ -0,0 +1,565 @@ +------------------------------------------------------------------------------- +-- @release $Id: standard.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local assert, pairs, tostring, type = assert, pairs, tostring, type +local io = require "io" +local posix = require "posix" +local luadoc = require "luadoc" +local util = require "luadoc.util" +local tags = require "luadoc.taglet.standard.tags" +local string = require "string" +local table = require "table" + +module 'luadoc.taglet.standard' + +------------------------------------------------------------------------------- +-- Creates an iterator for an array base on a class type. +-- @param t array to iterate over +-- @param class name of the class to iterate over + +function class_iterator (t, class) + return function () + local i = 1 + return function () + while t[i] and t[i].class ~= class do + i = i + 1 + end + local v = t[i] + i = i + 1 + return v + end + end +end + +-- Patterns for function recognition +local identifiers_list_pattern = "%s*(.-)%s*" +local identifier_pattern = "[^%(%s]+" +local function_patterns = { + "^()%s*function%s*("..identifier_pattern..")%s*%("..identifiers_list_pattern.."%)", + "^%s*(local%s)%s*function%s*("..identifier_pattern..")%s*%("..identifiers_list_pattern.."%)", + "^()%s*("..identifier_pattern..")%s*%=%s*function%s*%("..identifiers_list_pattern.."%)", +} + +------------------------------------------------------------------------------- +-- Checks if the line contains a function definition +-- @param line string with line text +-- @return function information or nil if no function definition found + +local function check_function (line) + line = util.trim(line) + + local info = table.foreachi(function_patterns, function (_, pattern) + local r, _, l, id, param = string.find(line, pattern) + if r ~= nil then + return { + name = id, + private = (l == "local"), + param = { } --util.split("%s*,%s*", param), + } + end + end) + + -- TODO: remove these assert's? + if info ~= nil then + assert(info.name, "function name undefined") + assert(info.param, string.format("undefined parameter list for function `%s'", info.name)) + end + + return info +end + +------------------------------------------------------------------------------- +-- Checks if the line contains a module definition. +-- @param line string with line text +-- @param currentmodule module already found, if any +-- @return the name of the defined module, or nil if there is no module +-- definition + +local function check_module (line, currentmodule) + line = util.trim(line) + + -- module"x.y" + -- module'x.y' + -- module[[x.y]] + -- module("x.y") + -- module('x.y') + -- module([[x.y]]) + -- module(...) + + local r, _, modulename = string.find(line, "^module%s*[%s\"'(%[]+([^,\"')%]]+)") + if r then + -- found module definition + logger:debug(string.format("found module `%s'", modulename)) + return modulename + end + return currentmodule +end + +-- Patterns for constant recognition +local constant_patterns = { + "^()%s*([A-Z][A-Z0-9_]*)%s*=", + "^%s*(local%s)%s*([A-Z][A-Z0-9_]*)%s*=", +} + +------------------------------------------------------------------------------- +-- Checks if the line contains a constant definition +-- @param line string with line text +-- @return constant information or nil if no constant definition found + +local function check_constant (line) + line = util.trim(line) + + local info = table.foreachi(constant_patterns, function (_, pattern) + local r, _, l, id = string.find(line, pattern) + if r ~= nil then + return { + name = id, + private = (l == "local"), + } + end + end) + + -- TODO: remove these assert's? + if info ~= nil then + assert(info.name, "constant name undefined") + end + + return info +end + +------------------------------------------------------------------------------- +-- Extracts summary information from a description. The first sentence of each +-- doc comment should be a summary sentence, containing a concise but complete +-- description of the item. It is important to write crisp and informative +-- initial sentences that can stand on their own +-- @param description text with item description +-- @return summary string or nil if description is nil + +local function parse_summary (description) + -- summary is never nil... + description = description or "" + + -- append an " " at the end to make the pattern work in all cases + description = description.." " + + -- read until the first period followed by a space or tab + local summary = string.match(description, "(.-%.)[%s\t]") + + -- if pattern did not find the first sentence, summary is the whole description + summary = summary or description + + return summary +end + +------------------------------------------------------------------------------- +-- @param f file handle +-- @param line current line being parsed +-- @param modulename module already found, if any +-- @return current line +-- @return code block +-- @return modulename if found + +local function parse_code (f, line, modulename) + local code = {} + while line ~= nil do + if string.find(line, "^[\t ]*%-%-%-") then + -- reached another luadoc block, end this parsing + return line, code, modulename + else + -- look for a module definition + modulename = check_module(line, modulename) + + table.insert(code, line) + line = f:read() + end + end + -- reached end of file + return line, code, modulename +end + +------------------------------------------------------------------------------- +-- Parses the information inside a block comment +-- @param block block with comment field +-- @return block parameter + +local function parse_comment (block, first_line, modulename) + + -- get the first non-empty line of code + local code = table.foreachi(block.code, function(_, line) + if not util.line_empty(line) then + -- `local' declarations are ignored in two cases: + -- when the `nolocals' option is turned on; and + -- when the first block of a file is parsed (this is + -- necessary to avoid confusion between the top + -- local declarations and the `module' definition. + if (options.nolocals or first_line) and line:find"^%s*local" then + return + end + return line + end + end) + + -- parse first line of code + if code ~= nil then + local func_info = check_function(code) + local module_name = check_module(code) + local const_info = check_constant(code) + if func_info then + block.class = "function" + block.name = func_info.name + block.param = func_info.param + block.private = func_info.private + elseif const_info then + block.class = "constant" + block.name = const_info.name + block.private = const_info.private + elseif module_name then + block.class = "module" + block.name = module_name + block.param = {} + else + block.param = {} + end + else + -- TODO: comment without any code. Does this means we are dealing + -- with a file comment? + end + + -- parse @ tags + local currenttag = "description" + local currenttext + + table.foreachi(block.comment, function (_, line) + line = util.trim_comment(line) + + local r, _, tag, text = string.find(line, "@([_%w%.]+)%s+(.*)") + if r ~= nil then + -- found new tag, add previous one, and start a new one + -- TODO: what to do with invalid tags? issue an error? or log a warning? + tags.handle(currenttag, block, currenttext) + + currenttag = tag + currenttext = text + else + currenttext = util.concat(currenttext, line) + assert(string.sub(currenttext, 1, 1) ~= " ", string.format("`%s', `%s'", currenttext, line)) + end + end) + tags.handle(currenttag, block, currenttext) + + -- extracts summary information from the description + block.summary = parse_summary(block.description) + assert(string.sub(block.description, 1, 1) ~= " ", string.format("`%s'", block.description)) + + if block.name and block.class == "module" then + modulename = block.name + end + + return block, modulename +end + +------------------------------------------------------------------------------- +-- Parses a block of comment, started with ---. Read until the next block of +-- comment. +-- @param f file handle +-- @param line being parsed +-- @param modulename module already found, if any +-- @return line +-- @return block parsed +-- @return modulename if found + +local function parse_block (f, line, modulename, first) + local block = { + comment = {}, + code = {}, + } + + while line ~= nil do + if string.find(line, "^[\t ]*%-%-") == nil then + -- reached end of comment, read the code below it + -- TODO: allow empty lines + line, block.code, modulename = parse_code(f, line, modulename) + + -- parse information in block comment + block, modulename = parse_comment(block, first, modulename) + + return line, block, modulename + else + table.insert(block.comment, line) + line = f:read() + end + end + -- reached end of file + + -- parse information in block comment + block, modulename = parse_comment(block, first, modulename) + + return line, block, modulename +end + +------------------------------------------------------------------------------- +-- Parses a file documented following luadoc format. +-- @param filepath full path of file to parse +-- @param doc table with documentation +-- @return table with documentation + +function parse_file (filepath, doc, handle, prev_line, prev_block, prev_modname) + local blocks = { prev_block } + local modulename = prev_modname + + -- read each line + local f = handle or io.open(filepath, "r") + local i = 1 + local line = prev_line or f:read() + local first = true + while line ~= nil do + + if string.find(line, "^[\t ]*%-%-%-") then + -- reached a luadoc block + local block, newmodname + line, block, newmodname = parse_block(f, line, modulename, first) + + if modulename and newmodname and newmodname ~= modulename then + doc = parse_file( nil, doc, f, line, block, newmodname ) + else + table.insert(blocks, block) + modulename = newmodname + end + else + -- look for a module definition + local newmodname = check_module(line, modulename) + + if modulename and newmodname and newmodname ~= modulename then + parse_file( nil, doc, f ) + else + modulename = newmodname + end + + -- TODO: keep beginning of file somewhere + + line = f:read() + end + first = false + i = i + 1 + end + + if not handle then + f:close() + end + + if filepath then + -- store blocks in file hierarchy + assert(doc.files[filepath] == nil, string.format("doc for file `%s' already defined", filepath)) + table.insert(doc.files, filepath) + doc.files[filepath] = { + type = "file", + name = filepath, + doc = blocks, + -- functions = class_iterator(blocks, "function"), + -- tables = class_iterator(blocks, "table"), + } + -- + local first = doc.files[filepath].doc[1] + if first and modulename then + doc.files[filepath].author = first.author + doc.files[filepath].copyright = first.copyright + doc.files[filepath].description = first.description + doc.files[filepath].release = first.release + doc.files[filepath].summary = first.summary + end + end + + -- if module definition is found, store in module hierarchy + if modulename ~= nil then + if modulename == "..." then + assert( filepath, "Can't determine name for virtual module from filepatch" ) + modulename = string.gsub (filepath, "%.lua$", "") + modulename = string.gsub (modulename, "/", ".") + end + if doc.modules[modulename] ~= nil then + -- module is already defined, just add the blocks + table.foreachi(blocks, function (_, v) + table.insert(doc.modules[modulename].doc, v) + end) + else + -- TODO: put this in a different module + table.insert(doc.modules, modulename) + doc.modules[modulename] = { + type = "module", + name = modulename, + doc = blocks, +-- functions = class_iterator(blocks, "function"), +-- tables = class_iterator(blocks, "table"), + author = first and first.author, + copyright = first and first.copyright, + description = "", + release = first and first.release, + summary = "", + } + + -- find module description + for m in class_iterator(blocks, "module")() do + doc.modules[modulename].description = util.concat( + doc.modules[modulename].description, + m.description) + doc.modules[modulename].summary = util.concat( + doc.modules[modulename].summary, + m.summary) + if m.author then + doc.modules[modulename].author = m.author + end + if m.copyright then + doc.modules[modulename].copyright = m.copyright + end + if m.release then + doc.modules[modulename].release = m.release + end + if m.name then + doc.modules[modulename].name = m.name + end + end + doc.modules[modulename].description = doc.modules[modulename].description or (first and first.description) or "" + doc.modules[modulename].summary = doc.modules[modulename].summary or (first and first.summary) or "" + end + + -- make functions table + doc.modules[modulename].functions = {} + for f in class_iterator(blocks, "function")() do + if f and f.name then + table.insert(doc.modules[modulename].functions, f.name) + doc.modules[modulename].functions[f.name] = f + end + end + + -- make tables table + doc.modules[modulename].tables = {} + for t in class_iterator(blocks, "table")() do + if t and t.name then + table.insert(doc.modules[modulename].tables, t.name) + doc.modules[modulename].tables[t.name] = t + end + end + + -- make constants table + doc.modules[modulename].constants = {} + for c in class_iterator(blocks, "constant")() do + if c and c.name then + table.insert(doc.modules[modulename].constants, c.name) + doc.modules[modulename].constants[c.name] = c + end + end + end + + if filepath then + -- make functions table + doc.files[filepath].functions = {} + for f in class_iterator(blocks, "function")() do + if f and f.name then + table.insert(doc.files[filepath].functions, f.name) + doc.files[filepath].functions[f.name] = f + end + end + + -- make tables table + doc.files[filepath].tables = {} + for t in class_iterator(blocks, "table")() do + if t and t.name then + table.insert(doc.files[filepath].tables, t.name) + doc.files[filepath].tables[t.name] = t + end + end + end + + return doc +end + +------------------------------------------------------------------------------- +-- Checks if the file is terminated by ".lua" or ".luadoc" and calls the +-- function that does the actual parsing +-- @param filepath full path of the file to parse +-- @param doc table with documentation +-- @return table with documentation +-- @see parse_file + +function file (filepath, doc) + local patterns = { "%.lua$", "%.luadoc$" } + local valid = table.foreachi(patterns, function (_, pattern) + if string.find(filepath, pattern) ~= nil then + return true + end + end) + + if valid then + logger:info(string.format("processing file `%s'", filepath)) + doc = parse_file(filepath, doc) + end + + return doc +end + +------------------------------------------------------------------------------- +-- Recursively iterates through a directory, parsing each file +-- @param path directory to search +-- @param doc table with documentation +-- @return table with documentation + +function directory (path, doc) + for f in posix.files(path) do + local fullpath = path .. "/" .. f + local attr = posix.stat(fullpath) + assert(attr, string.format("error stating file `%s'", fullpath)) + + if attr.type == "regular" then + doc = file(fullpath, doc) + elseif attr.type == "directory" and f ~= "." and f ~= ".." then + doc = directory(fullpath, doc) + end + end + return doc +end + +-- Recursively sorts the documentation table +local function recsort (tab) + table.sort (tab) + -- sort list of functions by name alphabetically + for f, doc in pairs(tab) do + if doc.functions then + table.sort(doc.functions) + end + if doc.tables then + table.sort(doc.tables) + end + end +end + +------------------------------------------------------------------------------- + +function start (files, doc) + assert(files, "file list not specified") + + -- Create an empty document, or use the given one + doc = doc or { + files = {}, + modules = {}, + } + assert(doc.files, "undefined `files' field") + assert(doc.modules, "undefined `modules' field") + + table.foreachi(files, function (_, path) + local attr = posix.stat(path) + assert(attr, string.format("error stating path `%s'", path)) + + if attr.type == "regular" then + doc = file(path, doc) + elseif attr.type == "directory" then + doc = directory(path, doc) + end + end) + + -- order arrays alphabetically + recsort(doc.files) + recsort(doc.modules) + + return doc +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard/tags.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard/tags.lua new file mode 100644 index 0000000..293e186 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/taglet/standard/tags.lua @@ -0,0 +1,178 @@ +------------------------------------------------------------------------------- +-- Handlers for several tags +-- @release $Id: tags.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local luadoc = require "luadoc" +local util = require "luadoc.util" +local string = require "string" +local table = require "table" +local assert, type, tostring = assert, type, tostring + +module "luadoc.taglet.standard.tags" + +------------------------------------------------------------------------------- + +local function author (tag, block, text) + block[tag] = block[tag] or {} + if not text then + luadoc.logger:warn("author `name' not defined [["..text.."]]: skipping") + return + end + table.insert (block[tag], text) +end + +------------------------------------------------------------------------------- +-- Set the class of a comment block. Classes can be "module", "function", +-- "table". The first two classes are automatic, extracted from the source code + +local function class (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function cstyle (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function copyright (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function description (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function field (tag, block, text) + if block["class"] ~= "table" then + luadoc.logger:warn("documenting `field' for block that is not a `table'") + end + block[tag] = block[tag] or {} + + local _, _, name, desc = string.find(text, "^([_%w%.]+)%s+(.*)") + assert(name, "field name not defined") + + table.insert(block[tag], name) + block[tag][name] = desc +end + +------------------------------------------------------------------------------- +-- Set the name of the comment block. If the block already has a name, issue +-- an error and do not change the previous value + +local function name (tag, block, text) + if block[tag] and block[tag] ~= text then + luadoc.logger:error(string.format("block name conflict: `%s' -> `%s'", block[tag], text)) + end + + block[tag] = text +end + +------------------------------------------------------------------------------- +-- Processes a parameter documentation. +-- @param tag String with the name of the tag (it must be "param" always). +-- @param block Table with previous information about the block. +-- @param text String with the current line beeing processed. + +local function param (tag, block, text) + block[tag] = block[tag] or {} + -- TODO: make this pattern more flexible, accepting empty descriptions + local _, _, name, desc = string.find(text, "^([_%w%.]+)%s+(.*)") + if not name then + luadoc.logger:warn("parameter `name' not defined [["..text.."]]: skipping") + return + end + local i = table.foreachi(block[tag], function (i, v) + if v == name then + return i + end + end) + if i == nil then + luadoc.logger:warn(string.format("documenting undefined parameter `%s'", name)) + table.insert(block[tag], name) + end + block[tag][name] = desc +end + +------------------------------------------------------------------------------- + +local function release (tag, block, text) + block[tag] = text +end + +------------------------------------------------------------------------------- + +local function ret (tag, block, text) + tag = "ret" + if type(block[tag]) == "string" then + block[tag] = { block[tag], text } + elseif type(block[tag]) == "table" then + table.insert(block[tag], text) + else + block[tag] = text + end +end + +------------------------------------------------------------------------------- +-- @see ret + +local function see (tag, block, text) + -- see is always an array + block[tag] = block[tag] or {} + + -- remove trailing "." + text = string.gsub(text, "(.*)%.$", "%1") + + local s = util.split("%s*,%s*", text) + + table.foreachi(s, function (_, v) + table.insert(block[tag], v) + end) +end + +------------------------------------------------------------------------------- +-- @see ret + +local function usage (tag, block, text) + if type(block[tag]) == "string" then + block[tag] = { block[tag], text } + elseif type(block[tag]) == "table" then + table.insert(block[tag], text) + else + block[tag] = text + end +end + +------------------------------------------------------------------------------- + +local handlers = {} +handlers["author"] = author +handlers["class"] = class +handlers["cstyle"] = cstyle +handlers["copyright"] = copyright +handlers["description"] = description +handlers["field"] = field +handlers["name"] = name +handlers["param"] = param +handlers["release"] = release +handlers["return"] = ret +handlers["see"] = see +handlers["usage"] = usage + +------------------------------------------------------------------------------- + +function handle (tag, block, text) + if not handlers[tag] then + luadoc.logger:error(string.format("undefined handler for tag `%s'", tag)) + return + end +-- assert(handlers[tag], string.format("undefined handler for tag `%s'", tag)) + return handlers[tag](tag, block, text) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luadoc/util.lua b/openwrt/packages/luci/host/usr/lib/lua/luadoc/util.lua new file mode 100644 index 0000000..21470f5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luadoc/util.lua @@ -0,0 +1,201 @@ +------------------------------------------------------------------------------- +-- General utilities. +-- @release $Id: util.lua 3941 2008-12-23 21:39:38Z jow $ +------------------------------------------------------------------------------- + +local posix = require "posix" +local type, table, string, io, assert, tostring, setmetatable, pcall = type, table, string, io, assert, tostring, setmetatable, pcall + +------------------------------------------------------------------------------- +-- Module with several utilities that could not fit in a specific module + +module "luadoc.util" + +------------------------------------------------------------------------------- +-- Removes spaces from the begining and end of a given string +-- @param s string to be trimmed +-- @return trimmed string + +function trim (s) + return (string.gsub(s, "^%s*(.-)%s*$", "%1")) +end + +------------------------------------------------------------------------------- +-- Removes spaces from the begining and end of a given string, considering the +-- string is inside a lua comment. +-- @param s string to be trimmed +-- @return trimmed string +-- @see trim +-- @see string.gsub + +function trim_comment (s) + s = string.gsub(s, "%-%-+(.*)$", "%1") + return trim(s) +end + +------------------------------------------------------------------------------- +-- Checks if a given line is empty +-- @param line string with a line +-- @return true if line is empty, false otherwise + +function line_empty (line) + return (string.len(trim(line)) == 0) +end + +------------------------------------------------------------------------------- +-- Appends two string, but if the first one is nil, use to second one +-- @param str1 first string, can be nil +-- @param str2 second string +-- @return str1 .. " " .. str2, or str2 if str1 is nil + +function concat (str1, str2) + if str1 == nil or string.len(str1) == 0 then + return str2 + else + return str1 .. " " .. str2 + end +end + +------------------------------------------------------------------------------- +-- Split text into a list consisting of the strings in text, +-- separated by strings matching delim (which may be a pattern). +-- @param delim if delim is "" then action is the same as %s+ except that +-- field 1 may be preceeded by leading whitespace +-- @usage split(",%s*", "Anna, Bob, Charlie,Dolores") +-- @usage split(""," x y") gives {"x","y"} +-- @usage split("%s+"," x y") gives {"", "x","y"} +-- @return array with strings +-- @see table.concat + +function split(delim, text) + local list = {} + if string.len(text) > 0 then + delim = delim or "" + local pos = 1 + -- if delim matches empty string then it would give an endless loop + if string.find("", delim, 1) and delim ~= "" then + error("delim matches empty string!") + end + local first, last + while 1 do + if delim ~= "" then + first, last = string.find(text, delim, pos) + else + first, last = string.find(text, "%s+", pos) + if first == 1 then + pos = last+1 + first, last = string.find(text, "%s+", pos) + end + end + if first then -- found? + table.insert(list, string.sub(text, pos, first-1)) + pos = last+1 + else + table.insert(list, string.sub(text, pos)) + break + end + end + end + return list +end + +------------------------------------------------------------------------------- +-- Comments a paragraph. +-- @param text text to comment with "--", may contain several lines +-- @return commented text + +function comment (text) + text = string.gsub(text, "\n", "\n-- ") + return "-- " .. text +end + +------------------------------------------------------------------------------- +-- Wrap a string into a paragraph. +-- @param s string to wrap +-- @param w width to wrap to [80] +-- @param i1 indent of first line [0] +-- @param i2 indent of subsequent lines [0] +-- @return wrapped paragraph + +function wrap(s, w, i1, i2) + w = w or 80 + i1 = i1 or 0 + i2 = i2 or 0 + assert(i1 < w and i2 < w, "the indents must be less than the line width") + s = string.rep(" ", i1) .. s + local lstart, len = 1, string.len(s) + while len - lstart > w do + local i = lstart + w + while i > lstart and string.sub(s, i, i) ~= " " do i = i - 1 end + local j = i + while j > lstart and string.sub(s, j, j) == " " do j = j - 1 end + s = string.sub(s, 1, j) .. "\n" .. string.rep(" ", i2) .. + string.sub(s, i + 1, -1) + local change = i2 + 1 - (i - j) + lstart = j + change + len = len + change + end + return s +end + +------------------------------------------------------------------------------- +-- Opens a file, creating the directories if necessary +-- @param filename full path of the file to open (or create) +-- @param mode mode of opening +-- @return file handle + +function posix.open (filename, mode) + local f = io.open(filename, mode) + if f == nil then + filename = string.gsub(filename, "\\", "/") + local dir = "" + for d in string.gfind(filename, ".-/") do + dir = dir .. d + posix.mkdir(dir) + end + f = io.open(filename, mode) + end + return f +end + + +---------------------------------------------------------------------------------- +-- Creates a Logger with LuaLogging, if present. Otherwise, creates a mock logger. +-- @param options a table with options for the logging mechanism +-- @return logger object that will implement log methods + +function loadlogengine(options) + local logenabled = pcall(function() + require "logging" + require "logging.console" + end) + + local logging = logenabled and logging + + if logenabled then + if options.filelog then + logger = logging.file("luadoc.log") -- use this to get a file log + else + logger = logging.console("[%level] %message\n") + end + + if options.verbose then + logger:setLevel(logging.INFO) + else + logger:setLevel(logging.WARN) + end + + else + noop = {__index=function(...) + return function(...) + -- noop + end + end} + + logger = {} + setmetatable(logger, noop) + end + + return logger +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/cacheloader.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/cacheloader.lua new file mode 100644 index 0000000..1cdf534 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/cacheloader.lua @@ -0,0 +1,23 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: cacheloader.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local config = require "luci.config" +local ccache = require "luci.ccache" + +module "luci.cacheloader" + +if config.ccache and config.ccache.enable == "1" then + ccache.cache_ondemand() +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/cbi.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/cbi.lua new file mode 100644 index 0000000..d332603 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/cbi.lua @@ -0,0 +1,1621 @@ +--[[ +LuCI - Configuration Bind Interface + +Description: +Offers an interface for binding configuration values to certain +data types. Supports value and range validation and basic dependencies. + +FileId: +$Id: cbi.lua 4102 2009-01-20 00:54:28Z jow $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.cbi", package.seeall) + +require("luci.template") +local util = require("luci.util") +require("luci.http") +require("luci.uvl") +require("luci.fs") + +--local event = require "luci.sys.event" +local uci = require("luci.model.uci") +local class = util.class +local instanceof = util.instanceof + +FORM_NODATA = 0 +FORM_PROCEED = 0 +FORM_VALID = 1 +FORM_INVALID = -1 +FORM_CHANGED = 2 + +AUTO = true + +CREATE_PREFIX = "cbi.cts." +REMOVE_PREFIX = "cbi.rts." + +-- Loads a CBI map from given file, creating an environment and returns it +function load(cbimap, ...) + require("luci.fs") + local i18n = require "luci.i18n" + require("luci.config") + require("luci.util") + + local upldir = "/lib/uci/upload/" + local cbidir = luci.util.libpath() .. "/model/cbi/" + + assert(luci.fs.stat(cbimap) or luci.fs.stat(cbidir..cbimap..".lua"), + "Model not found!") + + local func, err = loadfile(cbimap) + if not func then + func, err = loadfile(cbidir..cbimap..".lua") + end + assert(func, err) + + luci.i18n.loadc("cbi") + luci.i18n.loadc("uvl") + + local env = { + translate=i18n.translate, + translatef=i18n.translatef, + arg={...} + } + + setfenv(func, setmetatable(env, {__index = + function(tbl, key) + return rawget(tbl, key) or _M[key] or _G[key] + end})) + + local maps = { func() } + local uploads = { } + local has_upload = false + + for i, map in ipairs(maps) do + if not instanceof(map, Node) then + error("CBI map returns no valid map object!") + return nil + else + map:prepare() + if map.upload_fields then + has_upload = true + for _, field in ipairs(map.upload_fields) do + uploads[ + field.config .. '.' .. + field.section.sectiontype .. '.' .. + field.option + ] = true + end + end + end + end + + if has_upload then + local uci = luci.model.uci.cursor() + local prm = luci.http.context.request.message.params + local fd, cbid + + luci.http.setfilehandler( + function( field, chunk, eof ) + if not field then return end + if field.name and not cbid then + local c, s, o = field.name:gmatch( + "cbid%.([^%.]+)%.([^%.]+)%.([^%.]+)" + )() + + if c and s and o then + local t = uci:get( c, s ) + if t and uploads[c.."."..t.."."..o] then + local path = upldir .. field.name + fd = io.open(path, "w") + if fd then + cbid = field.name + prm[cbid] = path + end + end + end + end + + if field.name == cbid and fd then + fd:write(chunk) + end + + if eof and fd then + fd:close() + fd = nil + cbid = nil + end + end + ) + end + + return maps +end + +local function _uvl_validate_section(node, name) + local co = node.map:get() + + luci.uvl.STRICT_UNKNOWN_OPTIONS = false + luci.uvl.STRICT_UNKNOWN_SECTIONS = false + + local function tag_fields(e) + if e.option and node.fields[e.option] then + if node.fields[e.option].error then + node.fields[e.option].error[name] = e + else + node.fields[e.option].error = { [name] = e } + end + elseif e.childs then + for _, c in ipairs(e.childs) do tag_fields(c) end + end + end + + local function tag_section(e) + local s = { } + for _, c in ipairs(e.childs) do + if c.childs and not c:is(luci.uvl.errors.ERR_DEPENDENCY) then + table.insert( s, c.childs[1]:string() ) + else + table.insert( s, c:string() ) + end + end + if #s > 0 then + if node.error then + node.error[name] = s + else + node.error = { [name] = s } + end + end + end + + local stat, err = node.map.validator:validate_section(node.config, name, co) + if err then + node.map.save = false + tag_fields(err) + tag_section(err) + end + +end + +local function _uvl_strip_remote_dependencies(deps) + local clean = {} + + for k, v in pairs(deps) do + k = k:gsub("%$config%.%$section%.", "") + if k:match("^[%w_]+$") and type(v) == "string" then + clean[k] = v + end + end + + return clean +end + + +-- Node pseudo abstract class +Node = class() + +function Node.__init__(self, title, description) + self.children = {} + self.title = title or "" + self.description = description or "" + self.template = "cbi/node" +end + +-- i18n helper +function Node._i18n(self, config, section, option, title, description) + + -- i18n loaded? + if type(luci.i18n) == "table" then + + local key = config and config:gsub("[^%w]+", "") or "" + + if section then key = key .. "_" .. section:lower():gsub("[^%w]+", "") end + if option then key = key .. "_" .. tostring(option):lower():gsub("[^%w]+", "") end + + self.title = title or luci.i18n.translate( key, option or section or config ) + self.description = description or luci.i18n.translate( key .. "_desc", "" ) + end +end + +-- Prepare nodes +function Node.prepare(self, ...) + for k, child in ipairs(self.children) do + child:prepare(...) + end +end + +-- Append child nodes +function Node.append(self, obj) + table.insert(self.children, obj) +end + +-- Parse this node and its children +function Node.parse(self, ...) + for k, child in ipairs(self.children) do + child:parse(...) + end +end + +-- Render this node +function Node.render(self, scope) + scope = scope or {} + scope.self = self + + luci.template.render(self.template, scope) +end + +-- Render the children +function Node.render_children(self, ...) + for k, node in ipairs(self.children) do + node:render(...) + end +end + + +--[[ +A simple template element +]]-- +Template = class(Node) + +function Template.__init__(self, template) + Node.__init__(self) + self.template = template +end + +function Template.render(self) + luci.template.render(self.template, {self=self}) +end + + +--[[ +Map - A map describing a configuration file +]]-- +Map = class(Node) + +function Map.__init__(self, config, ...) + Node.__init__(self, ...) + Node._i18n(self, config, nil, nil, ...) + + self.config = config + self.parsechain = {self.config} + self.template = "cbi/map" + self.apply_on_parse = nil + self.readinput = true + + self.uci = uci.cursor() + self.save = true + + self.changed = false + + if not self.uci:load(self.config) then + error("Unable to read UCI data: " .. self.config) + end + + self.validator = luci.uvl.UVL() + self.scheme = self.validator:get_scheme(self.config) + +end + +function Map.formvalue(self, key) + return self.readinput and luci.http.formvalue(key) +end + +function Map.formvaluetable(self, key) + return self.readinput and luci.http.formvaluetable(key) +end + +function Map.get_scheme(self, sectiontype, option) + if not option then + return self.scheme and self.scheme.sections[sectiontype] + else + return self.scheme and self.scheme.variables[sectiontype] + and self.scheme.variables[sectiontype][option] + end +end + +function Map.submitstate(self) + return self:formvalue("cbi.submit") +end + +-- Chain foreign config +function Map.chain(self, config) + table.insert(self.parsechain, config) +end + +function Map.state_handler(self, state) + return state +end + +-- Use optimized UCI writing +function Map.parse(self, readinput, ...) + self.readinput = (readinput ~= false) + Node.parse(self, ...) + + if self.save then + for i, config in ipairs(self.parsechain) do + self.uci:save(config) + end + if self:submitstate() and (self.autoapply or luci.http.formvalue("cbi.apply")) then + for i, config in ipairs(self.parsechain) do + self.uci:commit(config) + + -- Refresh data because commit changes section names + self.uci:load(config) + end + if self.apply_on_parse then + self.uci:apply(self.parsechain) + else + self._apply = function() + local cmd = self.uci:apply(self.parsechain, true) + return io.popen(cmd) + end + end + + -- Reparse sections + Node.parse(self, true) + + end + for i, config in ipairs(self.parsechain) do + self.uci:unload(config) + end + if type(self.commit_handler) == "function" then + self:commit_handler(self:submitstate()) + end + end + + if self:submitstate() then + if self.save then + self.state = self.changed and FORM_CHANGED or FORM_VALID + else + self.state = FORM_INVALID + end + else + self.state = FORM_NODATA + end + + return self:state_handler(self.state) +end + +function Map.render(self, ...) + Node.render(self, ...) + if self._apply then + local fp = self._apply() + fp:read("*a") + fp:close() + end +end + +-- Creates a child section +function Map.section(self, class, ...) + if instanceof(class, AbstractSection) then + local obj = class(self, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractSection") + end +end + +-- UCI add +function Map.add(self, sectiontype) + return self.uci:add(self.config, sectiontype) +end + +-- UCI set +function Map.set(self, section, option, value) + if option then + return self.uci:set(self.config, section, option, value) + else + return self.uci:set(self.config, section, value) + end +end + +-- UCI del +function Map.del(self, section, option) + if option then + return self.uci:delete(self.config, section, option) + else + return self.uci:delete(self.config, section) + end +end + +-- UCI get +function Map.get(self, section, option) + if not section then + return self.uci:get_all(self.config) + elseif option then + return self.uci:get(self.config, section, option) + else + return self.uci:get_all(self.config, section) + end +end + +--[[ +Compound - Container +]]-- +Compound = class(Node) + +function Compound.__init__(self, ...) + Node.__init__(self) + self.children = {...} +end + +function Compound.parse(self, ...) + local cstate, state = 0, 0 + + for k, child in ipairs(self.children) do + cstate = child:parse(...) + state = (not state or cstate < state) and cstate or state + end + + return state +end + + +--[[ +Delegator - Node controller +]]-- +Delegator = class(Node) +function Delegator.__init__(self, ...) + Node.__init__(self, ...) + self.nodes = {} + self.template = "cbi/delegator" +end + +function Delegator.state(self, name, node, transitor) + transitor = transitor or self.transistor_linear + local state = {node=node, name=name, transitor=transitor} + + assert(instanceof(node, Node), "Invalid node") + assert(not self.nodes[name], "Duplicate entry") + + self.nodes[name] = state + self:append(state) + + return state +end + +function Delegator.get(self, name) + return self.nodes[name] +end + +function Delegator.transistor_linear(self, state, cstate) + if cstate > 0 then + for i, child in ipairs(self.children) do + if state == child then + return self.children[i+1] + end + end + else + return state + end +end + +function Delegator.parse(self, ...) + local active = self:getactive() + assert(active, "Invalid state") + + local cstate = active.node:parse() + self.active = active.transistor(self, active.node, cstate) + + if not self.active then + return FORM_DONE + else + self.active:parse(false) + return FROM_PROCEED + end +end + +function Delegator.render(self, ...) + self.active.node:render(...) +end + +function Delegator.getactive(self) + return self:get(Map.formvalue(self, "cbi.delegated") + or (self.children[1] and self.children[1].name)) +end + +--[[ +Page - A simple node +]]-- + +Page = class(Node) +Page.__init__ = Node.__init__ +Page.parse = function() end + + +--[[ +SimpleForm - A Simple non-UCI form +]]-- +SimpleForm = class(Node) + +function SimpleForm.__init__(self, config, title, description, data) + Node.__init__(self, title, description) + self.config = config + self.data = data or {} + self.template = "cbi/simpleform" + self.dorender = true + self.pageaction = false + self.readinput = true +end + +SimpleForm.formvalue = Map.formvalue +SimpleForm.formvaluetable = Map.formvaluetable + +function SimpleForm.parse(self, readinput, ...) + self.readinput = (readinput ~= false) + if self:submitstate() then + Node.parse(self, 1, ...) + end + + local valid = true + for k, j in ipairs(self.children) do + for i, v in ipairs(j.children) do + valid = valid + and (not v.tag_missing or not v.tag_missing[1]) + and (not v.tag_invalid or not v.tag_invalid[1]) + and (not v.error) + end + end + + local state = + not self:submitstate() and FORM_NODATA + or valid and FORM_VALID + or FORM_INVALID + + self.dorender = not self.handle or self:handle(state, self.data) ~= false + return state +end + +function SimpleForm.render(self, ...) + if self.dorender then + Node.render(self, ...) + end +end + +function SimpleForm.submitstate(self) + return self:formvalue("cbi.submit") +end + +function SimpleForm.section(self, class, ...) + if instanceof(class, AbstractSection) then + local obj = class(self, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractSection") + end +end + +-- Creates a child field +function SimpleForm.field(self, class, ...) + local section + for k, v in ipairs(self.children) do + if instanceof(v, SimpleSection) then + section = v + break + end + end + if not section then + section = self:section(SimpleSection) + end + + if instanceof(class, AbstractValue) then + local obj = class(self, section, ...) + obj.track_missing = true + section:append(obj) + return obj + else + error("class must be a descendent of AbstractValue") + end +end + +function SimpleForm.set(self, section, option, value) + self.data[option] = value +end + + +function SimpleForm.del(self, section, option) + self.data[option] = nil +end + + +function SimpleForm.get(self, section, option) + return self.data[option] +end + + +function SimpleForm.get_scheme() + return nil +end + + + +--[[ +AbstractSection +]]-- +AbstractSection = class(Node) + +function AbstractSection.__init__(self, map, sectiontype, ...) + Node.__init__(self, ...) + self.sectiontype = sectiontype + self.map = map + self.config = map.config + self.optionals = {} + self.defaults = {} + self.fields = {} + self.tag_error = {} + self.tag_invalid = {} + self.tag_deperror = {} + self.changed = false + + self.optional = true + self.addremove = false + self.dynamic = false +end + +-- Appends a new option +function AbstractSection.option(self, class, option, ...) + -- Autodetect from UVL + if class == true and self.map:get_scheme(self.sectiontype, option) then + local vs = self.map:get_scheme(self.sectiontype, option) + if vs.type == "boolean" then + class = Flag + elseif vs.type == "list" then + class = DynamicList + elseif vs.type == "enum" or vs.type == "reference" then + class = ListValue + else + class = Value + end + end + + if instanceof(class, AbstractValue) then + local obj = class(self.map, self, option, ...) + + Node._i18n(obj, self.config, self.section or self.sectiontype, option, ...) + + self:append(obj) + self.fields[option] = obj + return obj + elseif class == true then + error("No valid class was given and autodetection failed.") + else + error("class must be a descendant of AbstractValue") + end +end + +-- Parse optional options +function AbstractSection.parse_optionals(self, section) + if not self.optional then + return + end + + self.optionals[section] = {} + + local field = self.map:formvalue("cbi.opt."..self.config.."."..section) + for k,v in ipairs(self.children) do + if v.optional and not v:cfgvalue(section) then + if field == v.option then + field = nil + else + table.insert(self.optionals[section], v) + end + end + end + + if field and #field > 0 and self.dynamic then + self:add_dynamic(field) + end +end + +-- Add a dynamic option +function AbstractSection.add_dynamic(self, field, optional) + local o = self:option(Value, field, field) + o.optional = optional +end + +-- Parse all dynamic options +function AbstractSection.parse_dynamic(self, section) + if not self.dynamic then + return + end + + local arr = luci.util.clone(self:cfgvalue(section)) + local form = self.map:formvaluetable("cbid."..self.config.."."..section) + for k, v in pairs(form) do + arr[k] = v + end + + for key,val in pairs(arr) do + local create = true + + for i,c in ipairs(self.children) do + if c.option == key then + create = false + end + end + + if create and key:sub(1, 1) ~= "." then + self:add_dynamic(key, true) + end + end +end + +-- Returns the section's UCI table +function AbstractSection.cfgvalue(self, section) + return self.map:get(section) +end + +-- Push events +function AbstractSection.push_events(self) + --luci.util.append(self.map.events, self.events) + self.map.changed = true +end + +-- Removes the section +function AbstractSection.remove(self, section) + self.map.autoapply = false + return self.map:del(section) +end + +-- Creates the section +function AbstractSection.create(self, section) + local stat + + if section then + stat = section:match("^%w+$") and self.map:set(section, nil, self.sectiontype) + else + section = self.map:add(self.sectiontype) + stat = section + end + + if stat then + for k,v in pairs(self.children) do + if v.default then + self.map:set(section, v.option, v.default) + end + end + + for k,v in pairs(self.defaults) do + self.map:set(section, k, v) + end + end + + self.map.autoapply = false + + return stat +end + + +SimpleSection = class(AbstractSection) + +function SimpleSection.__init__(self, form, ...) + AbstractSection.__init__(self, form, nil, ...) + self.template = "cbi/nullsection" +end + + +Table = class(AbstractSection) + +function Table.__init__(self, form, data, ...) + local datasource = {} + datasource.config = "table" + self.data = data + + datasource.formvalue = Map.formvalue + datasource.formvaluetable = Map.formvaluetable + datasource.readinput = true + + function datasource.get(self, section, option) + return data[section] and data[section][option] + end + + function datasource.submitstate(self) + return Map.formvalue(self, "cbi.submit") + end + + function datasource.del(...) + return true + end + + function datasource.get_scheme() + return nil + end + + AbstractSection.__init__(self, datasource, "table", ...) + self.template = "cbi/tblsection" + self.rowcolors = true + self.anonymous = true +end + +function Table.parse(self, readinput) + self.map.readinput = (readinput ~= false) + for i, k in ipairs(self:cfgsections()) do + if self.map:submitstate() then + Node.parse(self, k) + end + end +end + +function Table.cfgsections(self) + local sections = {} + + for i, v in luci.util.kspairs(self.data) do + table.insert(sections, i) + end + + return sections +end + + + +--[[ +NamedSection - A fixed configuration section defined by its name +]]-- +NamedSection = class(AbstractSection) + +function NamedSection.__init__(self, map, section, stype, ...) + AbstractSection.__init__(self, map, stype, ...) + Node._i18n(self, map.config, section, nil, ...) + + -- Defaults + self.addremove = false + + -- Use defaults from UVL + if not self.override_scheme and self.map:get_scheme(self.sectiontype) then + local vs = self.map:get_scheme(self.sectiontype) + self.addremove = not vs.unique and not vs.required + self.dynamic = vs.dynamic + self.title = self.title or vs.title + self.description = self.description or vs.descr + end + + self.template = "cbi/nsection" + self.section = section +end + +function NamedSection.parse(self, novld) + local s = self.section + local active = self:cfgvalue(s) + + if self.addremove then + local path = self.config.."."..s + if active then -- Remove the section + if self.map:formvalue("cbi.rns."..path) and self:remove(s) then + self:push_events() + return + end + else -- Create and apply default values + if self.map:formvalue("cbi.cns."..path) then + self:create(s) + return + end + end + end + + if active then + AbstractSection.parse_dynamic(self, s) + if self.map:submitstate() then + Node.parse(self, s) + + if not novld and not self.override_scheme and self.map.scheme then + _uvl_validate_section(self, s) + end + end + AbstractSection.parse_optionals(self, s) + + if self.changed then + self:push_events() + end + end +end + + +--[[ +TypedSection - A (set of) configuration section(s) defined by the type + addremove: Defines whether the user can add/remove sections of this type + anonymous: Allow creating anonymous sections + validate: a validation function returning nil if the section is invalid +]]-- +TypedSection = class(AbstractSection) + +function TypedSection.__init__(self, map, type, ...) + AbstractSection.__init__(self, map, type, ...) + Node._i18n(self, map.config, type, nil, ...) + + self.template = "cbi/tsection" + self.deps = {} + self.anonymous = false + + -- Use defaults from UVL + if not self.override_scheme and self.map:get_scheme(self.sectiontype) then + local vs = self.map:get_scheme(self.sectiontype) + self.addremove = not vs.unique and not vs.required + self.dynamic = vs.dynamic + self.anonymous = not vs.named + self.title = self.title or vs.title + self.description = self.description or vs.descr + end +end + +-- Return all matching UCI sections for this TypedSection +function TypedSection.cfgsections(self) + local sections = {} + self.map.uci:foreach(self.map.config, self.sectiontype, + function (section) + if self:checkscope(section[".name"]) then + table.insert(sections, section[".name"]) + end + end) + + return sections +end + +-- Limits scope to sections that have certain option => value pairs +function TypedSection.depends(self, option, value) + table.insert(self.deps, {option=option, value=value}) +end + +function TypedSection.parse(self, novld) + if self.addremove then + -- Remove + local crval = REMOVE_PREFIX .. self.config + local name = self.map:formvaluetable(crval) + for k,v in pairs(name) do + if k:sub(-2) == ".x" then + k = k:sub(1, #k - 2) + end + if self:cfgvalue(k) and self:checkscope(k) then + self:remove(k) + end + end + end + + local co + for i, k in ipairs(self:cfgsections()) do + AbstractSection.parse_dynamic(self, k) + if self.map:submitstate() then + Node.parse(self, k, novld) + + if not novld and not self.override_scheme and self.map.scheme then + _uvl_validate_section(self, k) + end + end + AbstractSection.parse_optionals(self, k) + end + + if self.addremove then + -- Create + local created + local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype + local name = self.map:formvalue(crval) + if self.anonymous then + if name then + created = self:create() + end + else + if name then + -- Ignore if it already exists + if self:cfgvalue(name) then + name = nil; + end + + name = self:checkscope(name) + + if not name then + self.err_invalid = true + end + + if name and #name > 0 then + created = self:create(name) and name + if not created then + self.invalid_cts = true + end + end + end + end + + if created then + AbstractSection.parse_optionals(self, created) + end + end + + if created or self.changed then + self:push_events() + end +end + +-- Verifies scope of sections +function TypedSection.checkscope(self, section) + -- Check if we are not excluded + if self.filter and not self:filter(section) then + return nil + end + + -- Check if at least one dependency is met + if #self.deps > 0 and self:cfgvalue(section) then + local stat = false + + for k, v in ipairs(self.deps) do + if self:cfgvalue(section)[v.option] == v.value then + stat = true + end + end + + if not stat then + return nil + end + end + + return self:validate(section) +end + + +-- Dummy validate function +function TypedSection.validate(self, section) + return section +end + + +--[[ +AbstractValue - An abstract Value Type + null: Value can be empty + valid: A function returning the value if it is valid otherwise nil + depends: A table of option => value pairs of which one must be true + default: The default value + size: The size of the input fields + rmempty: Unset value if empty + optional: This value is optional (see AbstractSection.optionals) +]]-- +AbstractValue = class(Node) + +function AbstractValue.__init__(self, map, section, option, ...) + Node.__init__(self, ...) + self.section = section + self.option = option + self.map = map + self.config = map.config + self.tag_invalid = {} + self.tag_missing = {} + self.tag_reqerror = {} + self.tag_error = {} + self.deps = {} + --self.cast = "string" + + self.track_missing = false + self.rmempty = true + self.default = nil + self.size = nil + self.optional = false +end + +function AbstractValue.prepare(self) + -- Use defaults from UVL + if not self.override_scheme + and self.map:get_scheme(self.section.sectiontype, self.option) then + local vs = self.map:get_scheme(self.section.sectiontype, self.option) + if self.cast == nil then + self.cast = (vs.type == "list") and "list" or "string" + end + self.title = self.title or vs.title + self.description = self.description or vs.descr + if self.default == nil then + self.default = vs.default + end + + if vs.depends and not self.override_dependencies then + for i, deps in ipairs(vs.depends) do + deps = _uvl_strip_remote_dependencies(deps) + if next(deps) then + self:depends(deps) + end + end + end + end + + self.cast = self.cast or "string" +end + +-- Add a dependencie to another section field +function AbstractValue.depends(self, field, value) + local deps + if type(field) == "string" then + deps = {} + deps[field] = value + else + deps = field + end + + table.insert(self.deps, {deps=deps, add=""}) +end + +-- Generates the unique CBID +function AbstractValue.cbid(self, section) + return "cbid."..self.map.config.."."..section.."."..self.option +end + +-- Return whether this object should be created +function AbstractValue.formcreated(self, section) + local key = "cbi.opt."..self.config.."."..section + return (self.map:formvalue(key) == self.option) +end + +-- Returns the formvalue for this object +function AbstractValue.formvalue(self, section) + return self.map:formvalue(self:cbid(section)) +end + +function AbstractValue.additional(self, value) + self.optional = value +end + +function AbstractValue.mandatory(self, value) + self.rmempty = not value +end + +function AbstractValue.parse(self, section, novld) + local fvalue = self:formvalue(section) + local cvalue = self:cfgvalue(section) + + if fvalue and #fvalue > 0 then -- If we have a form value, write it to UCI + fvalue = self:transform(self:validate(fvalue, section)) + if not fvalue and not novld then + if self.error then + self.error[section] = "invalid" + else + self.error = { [section] = "invalid" } + end + self.map.save = false + end + if fvalue and not (fvalue == cvalue) then + if self:write(section, fvalue) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end + end + else -- Unset the UCI or error + if self.rmempty or self.optional then + if self:remove(section) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end + elseif cvalue ~= fvalue and not novld then + self:write(section, fvalue or "") + if self.error then + self.error[section] = "missing" + else + self.error = { [section] = "missing" } + end + self.map.save = false + end + end +end + +-- Render if this value exists or if it is mandatory +function AbstractValue.render(self, s, scope) + if not self.optional or self:cfgvalue(s) or self:formcreated(s) then + scope = scope or {} + scope.section = s + scope.cbid = self:cbid(s) + scope.striptags = luci.util.striptags + + scope.ifattr = function(cond,key,val) + if cond then + return string.format( + ' %s="%s"', tostring(key), + luci.util.pcdata(tostring( val + or scope[key] + or (type(self[key]) ~= "function" and self[key]) + or "" )) + ) + else + return '' + end + end + + scope.attr = function(...) + return scope.ifattr( true, ... ) + end + + Node.render(self, scope) + end +end + +-- Return the UCI value of this object +function AbstractValue.cfgvalue(self, section) + local value = self.map:get(section, self.option) + if not value then + return nil + elseif not self.cast or self.cast == type(value) then + return value + elseif self.cast == "string" then + if type(value) == "table" then + return value[1] + end + elseif self.cast == "table" then + return luci.util.split(value, "%s+", nil, true) + end +end + +-- Validate the form value +function AbstractValue.validate(self, value) + return value +end + +AbstractValue.transform = AbstractValue.validate + + +-- Write to UCI +function AbstractValue.write(self, section, value) + return self.map:set(section, self.option, value) +end + +-- Remove from UCI +function AbstractValue.remove(self, section) + return self.map:del(section, self.option) +end + + + + +--[[ +Value - A one-line value + maxlength: The maximum length +]]-- +Value = class(AbstractValue) + +function Value.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/value" + self.keylist = {} + self.vallist = {} +end + +function Value.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + + +-- DummyValue - This does nothing except being there +DummyValue = class(AbstractValue) + +function DummyValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/dvalue" + self.value = nil +end + +function DummyValue.cfgvalue(self, section) + local value + if self.value then + if type(self.value) == "function" then + value = self:value(section) + else + value = self.value + end + else + value = AbstractValue.cfgvalue(self, section) + end + return value +end + +function DummyValue.parse(self) + +end + + +--[[ +Flag - A flag being enabled or disabled +]]-- +Flag = class(AbstractValue) + +function Flag.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/fvalue" + + self.enabled = "1" + self.disabled = "0" +end + +-- A flag can only have two states: set or unset +function Flag.parse(self, section) + local fvalue = self:formvalue(section) + + if fvalue then + fvalue = self.enabled + else + fvalue = self.disabled + end + + if fvalue == self.enabled or (not self.optional and not self.rmempty) then + if not(fvalue == self:cfgvalue(section)) then + self:write(section, fvalue) + end + else + self:remove(section) + end +end + + + +--[[ +ListValue - A one-line value predefined in a list + widget: The widget that will be used (select, radio) +]]-- +ListValue = class(AbstractValue) + +function ListValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/lvalue" + + self.keylist = {} + self.vallist = {} + self.size = 1 + self.widget = "select" +end + +function ListValue.prepare(self, ...) + AbstractValue.prepare(self, ...) + if not self.override_scheme + and self.map:get_scheme(self.section.sectiontype, self.option) then + local vs = self.map:get_scheme(self.section.sectiontype, self.option) + if self.value and vs.valuelist and not self.override_values then + for k, v in ipairs(vs.valuelist) do + local deps = {} + if not self.override_dependencies + and vs.enum_depends and vs.enum_depends[v.value] then + for i, dep in ipairs(vs.enum_depends[v.value]) do + table.insert(deps, _uvl_strip_remote_dependencies(dep)) + end + end + self:value(v.value, v.title or v.value, unpack(deps)) + end + end + end +end + +function ListValue.value(self, key, val, ...) + if luci.util.contains(self.keylist, key) then + return + end + + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) + + for i, deps in ipairs({...}) do + table.insert(self.deps, {add = "-"..key, deps=deps}) + end +end + +function ListValue.validate(self, val) + if luci.util.contains(self.keylist, val) then + return val + else + return nil + end +end + + + +--[[ +MultiValue - Multiple delimited values + widget: The widget that will be used (select, checkbox) + delimiter: The delimiter that will separate the values (default: " ") +]]-- +MultiValue = class(AbstractValue) + +function MultiValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/mvalue" + + self.keylist = {} + self.vallist = {} + + self.widget = "checkbox" + self.delimiter = " " +end + +function MultiValue.render(self, ...) + if self.widget == "select" and not self.size then + self.size = #self.vallist + end + + AbstractValue.render(self, ...) +end + +function MultiValue.value(self, key, val) + if luci.util.contains(self.keylist, key) then + return + end + + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function MultiValue.valuelist(self, section) + local val = self:cfgvalue(section) + + if not(type(val) == "string") then + return {} + end + + return luci.util.split(val, self.delimiter) +end + +function MultiValue.validate(self, val) + val = (type(val) == "table") and val or {val} + + local result + + for i, value in ipairs(val) do + if luci.util.contains(self.keylist, value) then + result = result and (result .. self.delimiter .. value) or value + end + end + + return result +end + + +StaticList = class(MultiValue) + +function StaticList.__init__(self, ...) + MultiValue.__init__(self, ...) + self.cast = "table" + self.valuelist = self.cfgvalue + + if not self.override_scheme + and self.map:get_scheme(self.section.sectiontype, self.option) then + local vs = self.map:get_scheme(self.section.sectiontype, self.option) + if self.value and vs.values and not self.override_values then + for k, v in pairs(vs.values) do + self:value(k, v) + end + end + end +end + +function StaticList.validate(self, value) + value = (type(value) == "table") and value or {value} + + local valid = {} + for i, v in ipairs(value) do + if luci.util.contains(self.keylist, v) then + table.insert(valid, v) + end + end + return valid +end + + +DynamicList = class(AbstractValue) + +function DynamicList.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/dynlist" + self.cast = "table" + self.keylist = {} + self.vallist = {} +end + +function DynamicList.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function DynamicList.formvalue(self, section) + local value = AbstractValue.formvalue(self, section) + value = (type(value) == "table") and value or {value} + + local valid = {} + for i, v in ipairs(value) do + if v and #v > 0 + and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i) + and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i..".x") then + table.insert(valid, v) + end + end + + return valid +end + + +--[[ +TextValue - A multi-line value + rows: Rows +]]-- +TextValue = class(AbstractValue) + +function TextValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/tvalue" +end + +--[[ +Button +]]-- +Button = class(AbstractValue) + +function Button.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/button" + self.inputstyle = nil + self.rmempty = true +end + + +FileUpload = class(AbstractValue) + +function FileUpload.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/upload" + if not self.map.upload_fields then + self.map.upload_fields = { self } + else + self.map.upload_fields[#self.map.upload_fields+1] = self + end +end + +function FileUpload.formcreated(self, section) + return AbstractValue.formcreated(self, section) or + self.map:formvalue("cbi.rlf."..section.."."..self.option) or + self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") +end + +function FileUpload.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val and luci.fs.access(val) then + return val + end + return nil +end + +function FileUpload.formvalue(self, section) + local val = AbstractValue.formvalue(self, section) + if val then + if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and + not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") + then + return val + end + luci.fs.unlink(val) + self.value = nil + end + return nil +end + +function FileUpload.remove(self, section) + local val = AbstractValue.formvalue(self, section) + if val and luci.fs.access(val) then luci.fs.unlink(val) end + return AbstractValue.remove(self, section) +end + + +FileBrowser = class(AbstractValue) + +function FileBrowser.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/browser" +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/ccache.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/ccache.lua new file mode 100644 index 0000000..4db3b39 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/ccache.lua @@ -0,0 +1,86 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ccache.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local io = require "io" +local util = require "luci.util" +local posix = require "posix" +local debug = require "debug" +local string = require "string" +local package = require "package" + +local type, loadfile = type, loadfile + + +module "luci.ccache" + +function cache_ondemand(...) + if debug.getinfo(1, 'S').source ~= "=?" then + cache_enable(...) + end +end + +function cache_enable(cachepath, mode) + cachepath = cachepath or "/tmp/luci-modulecache" + mode = mode or "r--r--r--" + + local loader = package.loaders[2] + local uid = posix.getpid("uid") + + if not posix.stat(cachepath) then + posix.mkdir(cachepath) + end + + local function _encode_filename(name) + local encoded = "" + for i=1, #name do + encoded = encoded .. ("%2X" % string.byte(name, i)) + end + return encoded + end + + local function _load_sane(file) + local stat = posix.stat(file) + if stat and stat.uid == uid and stat.mode == mode then + return loadfile(file) + end + end + + local function _write_sane(file, func) + if posix.getpid("uid") == uid then + local fp = io.open(file, "w") + if fp then + fp:write(util.get_bytecode(func)) + fp:close() + posix.chmod(file, mode) + end + end + end + + package.loaders[2] = function(mod) + local encoded = cachepath .. "/" .. _encode_filename(mod) + local modcons = _load_sane(encoded) + + if modcons then + return modcons + end + + -- No cachefile + modcons = loader(mod) + if type(modcons) == "function" then + _write_sane(encoded, modcons) + end + return modcons + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/config.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/config.lua new file mode 100644 index 0000000..58e182e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/config.lua @@ -0,0 +1,42 @@ +--[[ +LuCI - Configuration + +Description: +Some LuCI configuration values read from uci file "luci" + + +FileId: +$Id: config.lua 3857 2008-12-05 15:37:39Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local util = require "luci.util" +module("luci.config", + function(m) + if pcall(require, "luci.model.uci") then + local config = util.threadlocal() + setmetatable(m, { + __index = function(tbl, key) + if not config[key] then + config[key] = luci.model.uci.cursor():get_all("luci", key) + end + return config[key] + end + }) + end + end) diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/filebrowser.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/filebrowser.lua new file mode 100644 index 0000000..4c19b46 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/filebrowser.lua @@ -0,0 +1,20 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: filebrowser.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +module("luci.controller.admin.filebrowser", package.seeall) + +function index() + entry( {"admin", "filebrowser"}, template("cbi/filebrowser") ).leaf = true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/index.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/index.lua new file mode 100644 index 0000000..41f423c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/index.lua @@ -0,0 +1,67 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: index.lua 4041 2009-01-16 12:39:50Z Cyrus $ +]]-- +module("luci.controller.admin.index", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + local root = node() + if not root.target then + root.target = alias("admin") + root.index = true + end + + entry({"about"}, template("about")).i18n = "admin-core" + + local page = node("admin") + page.target = alias("admin", "index") + page.title = i18n("administration", "Administration") + page.order = 10 + page.i18n = "admin-core" + page.sysauth = "root" + page.sysauth_authenticator = "htmlauth" + page.ucidata = true + page.index = true + + local page = node("admin", "index") + page.target = template("admin_index/index") + page.title = i18n("overview", "Übersicht") + page.order = 10 + page.index = true + + local page = node("admin", "index", "luci") + page.target = cbi("admin_index/luci") + page.title = i18n("a_i_ui", "Oberfläche") + page.order = 10 + + entry({"admin", "index", "components"}, call("redir_components"), i18n("luci_components", "LuCI Components"), 20) + entry({"admin", "index", "logout"}, call("action_logout"), i18n("logout"), 90) +end + +function redir_components() + luci.http.redirect(luci.dispatcher.build_url("admin", "system", "packages")..'?update=1&query=luci') +end + +function action_logout() + local dsp = require "luci.dispatcher" + local sauth = require "luci.sauth" + if dsp.context.authsession then + sauth.kill(dsp.context.authsession) + dsp.context.urltoken.stok = nil + end + + luci.http.header("Set-Cookie", "sysauth=; path=" .. dsp.build_url()) + luci.http.redirect(luci.dispatcher.build_url()) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/network.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/network.lua new file mode 100644 index 0000000..6d12abb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/network.lua @@ -0,0 +1,97 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: network.lua 3995 2009-01-04 15:47:53Z Cyrus $ +]]-- +module("luci.controller.admin.network", package.seeall) + +function index() + require("luci.i18n") + local uci = require("luci.model.uci").cursor() + local i18n = luci.i18n.translate + + local page = node("admin", "network") + page.target = alias("admin", "network", "network") + page.title = i18n("network") + page.order = 50 + page.index = true + + local page = node("admin", "network", "vlan") + page.target = cbi("admin_network/vlan") + page.title = i18n("a_n_switch") + page.order = 20 + + local page = entry({"admin", "network", "wireless"}, arcombine(cbi("admin_network/wireless"), cbi("admin_network/wifi")), i18n("wifi"), 15) + page.i18n = "wifi" + page.leaf = true + page.subindex = true + + uci:foreach("wireless", "wifi-device", + function (section) + local ifc = section[".name"] + entry({"admin", "network", "wireless", ifc}, + true, + ifc:upper()).i18n = "wifi" + end + ) + + local page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), i18n("interfaces", "Schnittstellen"), 10) + page.leaf = true + page.subindex = true + + uci:foreach("network", "interface", + function (section) + local ifc = section[".name"] + if ifc ~= "loopback" then + entry({"admin", "network", "network", ifc}, + true, + ifc:upper()) + end + end + ) + + local page = node("admin", "network", "dhcp") + page.target = cbi("admin_network/dhcp") + page.title = "DHCP" + page.order = 30 + page.subindex = true + + entry( + {"admin", "network", "dhcp", "leases"}, + cbi("admin_network/dhcpleases"), + i18n("dhcp_leases") + ) + + local page = node("admin", "network", "hosts") + page.target = cbi("admin_network/hosts") + page.title = i18n("hostnames", "Hostnames") + page.order = 40 + + local page = node("admin", "network", "routes") + page.target = cbi("admin_network/routes") + page.title = i18n("a_n_routes") + page.order = 50 + page.leaf = true + + entry( + {"admin", "network", "routes", "static"}, + function() end, + i18n("a_n_routes_static") + ) + + entry( + {"admin", "network", "conntrack"}, + form("admin_network/conntrack"), + i18n("a_n_conntrack"), + 60 + ) + +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/services.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/services.lua new file mode 100644 index 0000000..6f4fa77 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/services.lua @@ -0,0 +1,54 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: services.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +module("luci.controller.admin.services", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + local page = node("admin", "services", "crontab") + page.target = form("admin_services/crontab") + page.title = i18n("a_s_crontab") + page.order = 50 + + local page = node("admin", "services") + page.target = template("admin_services/index") + page.title = i18n("services", "Dienste") + page.order = 40 + page.index = true + + if luci.fs.access("/etc/config/lucittpd") then + local page = node("admin", "services", "lucittpd") + page.target = cbi("admin_services/lucittpd") + page.title = "LuCIttpd" + page.order = 10 + end + + if luci.fs.access("/etc/config/httpd") then + local page = node("admin", "services", "httpd") + page.target = cbi("admin_services/httpd") + page.title = "Busybox HTTPd" + page.order = 11 + end + + local page = node("admin", "services", "dropbear") + page.target = cbi("admin_services/dropbear") + page.title = "Dropbear SSHd" + page.order = 20 + + local page = node("admin", "services", "dnsmasq") + page.target = cbi("admin_services/dnsmasq") + page.title = "Dnsmasq" + page.order = 30 +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/status.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/status.lua new file mode 100644 index 0000000..8133013 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/status.lua @@ -0,0 +1,33 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: status.lua 3792 2008-11-16 22:46:25Z jow $ +]]-- +module("luci.controller.admin.status", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + entry({"admin", "status"}, template("admin_status/index"), i18n("status", "Status"), 20).index = true + entry({"admin", "status", "syslog"}, call("action_syslog"), i18n("syslog", "Systemprotokoll"), 1) + entry({"admin", "status", "dmesg"}, call("action_dmesg"), i18n("dmesg", "Kernelprotokoll"), 2) +end + +function action_syslog() + local syslog = luci.sys.syslog() + luci.template.render("admin_status/syslog", {syslog=syslog}) +end + +function action_dmesg() + local dmesg = luci.sys.dmesg() + luci.template.render("admin_status/dmesg", {dmesg=dmesg}) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/system.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/system.lua new file mode 100644 index 0000000..9d4422d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/system.lua @@ -0,0 +1,235 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: system.lua 4065 2009-01-17 13:21:50Z Cyrus $ +]]-- +module("luci.controller.admin.system", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + entry({"admin", "system"}, alias("admin", "system", "system"), i18n("system"), 30).index = true + entry({"admin", "system", "system"}, cbi("admin_system/system"), i18n("system"), 1) + entry({"admin", "system", "packages"}, call("action_packages"), i18n("a_s_packages"), 10) + entry({"admin", "system", "packages", "ipkg"}, form("admin_system/ipkg")) + entry({"admin", "system", "passwd"}, form("admin_system/passwd"), i18n("a_s_changepw"), 20) + entry({"admin", "system", "sshkeys"}, form("admin_system/sshkeys"), i18n("a_s_sshkeys"), 30) + entry({"admin", "system", "processes"}, form("admin_system/processes"), i18n("process_head"), 45) + entry({"admin", "system", "fstab"}, cbi("admin_system/fstab"), i18n("a_s_fstab"), 50) + + if luci.fs.isdirectory("/sys/class/leds") then + entry({"admin", "system", "leds"}, cbi("admin_system/leds"), i18n("leds", "LEDs"), 60) + end + + entry({"admin", "system", "backup"}, call("action_backup"), i18n("a_s_backup"), 70) + entry({"admin", "system", "upgrade"}, call("action_upgrade"), i18n("a_s_flash"), 80) + entry({"admin", "system", "reboot"}, call("action_reboot"), i18n("reboot"), 90) +end + +function action_packages() + local ipkg = require("luci.model.ipkg") + local void = nil + local submit = luci.http.formvalue("submit") + + + -- Search query + local query = luci.http.formvalue("query") + query = (query ~= '') and query or nil + + + -- Packets to be installed + local install = submit and luci.http.formvaluetable("install") + + -- Install from URL + local url = luci.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 = submit and luci.http.formvaluetable("remove") + if remove then + for k, v in pairs(remove) do + void, remove[k] = ipkg.remove(k) + end + end + + + -- Update all packets + local update = luci.http.formvalue("update") + if update then + void, update = ipkg.update() + end + + + -- Upgrade all packets + local upgrade = luci.http.formvalue("upgrade") + if upgrade then + void, upgrade = ipkg.upgrade() + end + + + -- Package info + local info = luci.model.ipkg.info(query and "*"..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 + + luci.template.render("admin_system/packages", {pkgs=pkgs, query=query, + install=install, remove=remove, update=update, upgrade=upgrade}) +end + +function action_backup() + local reset_avail = os.execute([[grep '"rootfs_data"' /proc/mtd >/dev/null 2>&1]]) == 0 + local restore_cmd = "gunzip | tar -xC/ >/dev/null 2>&1" + local backup_cmd = "tar -c %s | gzip 2>/dev/null" + + local restore_fpi + luci.http.setfilehandler( + function(meta, chunk, eof) + if not restore_fpi then + restore_fpi = io.popen(restore_cmd, "w") + end + if chunk then + restore_fpi:write(chunk) + end + if eof then + restore_fpi:close() + end + end + ) + + local upload = luci.http.formvalue("archive") + local backup = luci.http.formvalue("backup") + local reset = reset_avail and luci.http.formvalue("reset") + + if upload and #upload > 0 then + luci.template.render("admin_system/applyreboot") + luci.sys.reboot() + elseif backup then + luci.util.perror(backup_cmd:format(_keep_pattern())) + local backup_fpi = io.popen(backup_cmd:format(_keep_pattern()), "r") + luci.http.header('Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % { + luci.sys.hostname(), os.date("%Y-%m-%d")}) + luci.http.prepare_content("application/x-targz") + luci.ltn12.pump.all(luci.ltn12.source.file(backup_fpi), luci.http.write) + elseif reset then + luci.template.render("admin_system/applyreboot") + luci.util.exec("mtd -r erase rootfs_data") + else + luci.template.render("admin_system/backup", {reset_avail = reset_avail}) + end +end + +function action_passwd() + local p1 = luci.http.formvalue("pwd1") + local p2 = luci.http.formvalue("pwd2") + local stat = nil + + if p1 or p2 then + if p1 == p2 then + stat = luci.sys.user.setpasswd("root", p1) + else + stat = 10 + end + end + + luci.template.render("admin_system/passwd", {stat=stat}) +end + +function action_reboot() + local reboot = luci.http.formvalue("reboot") + luci.template.render("admin_system/reboot", {reboot=reboot}) + if reboot then + luci.sys.reboot() + end +end + +function action_upgrade() + require("luci.model.uci") + + local ret + local plat = luci.fs.mtime("/lib/upgrade/platform.sh") + local tmpfile = "/tmp/firmware.img" + local keep_avail = true + + local file + luci.http.setfilehandler( + function(meta, chunk, eof) + if not file then + file = io.open(tmpfile, "w") + end + if chunk then + file:write(chunk) + end + if eof then + file:close() + end + end + ) + + local fname = luci.http.formvalue("image") + local keepcfg = keep_avail and luci.http.formvalue("keepcfg") + + if plat and fname then + ret = function() + return luci.sys.flash(tmpfile, keepcfg and _keep_pattern()) + end + end + + luci.http.prepare_content("text/html") + luci.template.render("admin_system/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail}) +end + +function _keep_pattern() + local kpattern = "" + local files = luci.model.uci.cursor():get_all("luci", "flash_keep") + if files then + kpattern = "" + for k, v in pairs(files) do + if k:sub(1,1) ~= "." and luci.fs.glob(v) then + kpattern = kpattern .. " " .. v + end + end + end + return kpattern +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/uci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/uci.lua new file mode 100644 index 0000000..ddecd9b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/admin/uci.lua @@ -0,0 +1,90 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: uci.lua 3650 2008-10-29 19:40:40Z jow $ +]]-- +module("luci.controller.admin.uci", package.seeall) + +function index() + local i18n = luci.i18n.translate + local redir = luci.http.formvalue("redir", true) or + luci.dispatcher.build_url(unpack(luci.dispatcher.context.request)) + + entry({"admin", "uci"}, nil, i18n("config")) + entry({"admin", "uci", "changes"}, call("action_changes"), i18n("changes"), 40).query = {redir=redir} + entry({"admin", "uci", "revert"}, call("action_revert"), i18n("revert"), 30).query = {redir=redir} + entry({"admin", "uci", "apply"}, call("action_apply"), i18n("apply"), 20).query = {redir=redir} + entry({"admin", "uci", "saveapply"}, call("action_apply"), i18n("saveapply"), 10).query = {redir=redir} +end + +function convert_changes(changes) + local util = require "luci.util" + + local ret + for r, tbl in pairs(changes) do + for s, os in pairs(tbl) do + for o, v in pairs(os) do + ret = (ret and ret.."\n" or "") .. "%s%s.%s%s%s" % { + v == "" and "-" or "", + r, + s, + o ~= ".type" and "."..o or "", + v ~= "" and "="..util.pcdata(v) or "" + } + end + end + end + return ret +end + +function action_changes() + local changes = convert_changes(luci.model.uci.cursor():changes()) + luci.template.render("admin_uci/changes", {changes=changes}) +end + +function action_apply() + local path = luci.dispatcher.context.path + local uci = luci.model.uci.cursor() + local changes = uci:changes() + local reload = {} + + -- Collect files to be applied and commit changes + for r, tbl in pairs(changes) do + table.insert(reload, r) + if path[#path] ~= "apply" then + uci:load(r) + uci:commit(r) + uci:unload(r) + end + end + + local function _reload() + local cmd = uci:apply(reload, true) + return io.popen(cmd) + end + + luci.template.render("admin_uci/apply", {changes=convert_changes(changes), reload=_reload}) +end + + +function action_revert() + local uci = luci.model.uci.cursor() + local changes = uci:changes() + + -- Collect files to be reverted + for r, tbl in pairs(changes) do + uci:load(r) + uci:revert(r) + uci:unload(r) + end + + luci.template.render("admin_uci/revert", {changes=convert_changes(changes)}) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ddns.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ddns.lua new file mode 100644 index 0000000..e964c5e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ddns.lua @@ -0,0 +1,32 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ddns.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.ddns", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("ddns") + if not luci.fs.access("/etc/config/ddns") then + return + end + + local page = entry({"admin", "services", "ddns"}, cbi("ddns/ddns"), luci.i18n.translate("ddns"), 60) + page.i18n = "ddns" + page.dependent = true + + + local page = entry({"mini", "network", "ddns"}, cbi("ddns/ddnsmini", {autoapply=true}), luci.i18n.translate("ddns"), 60) + page.i18n = "ddns" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ffwizard.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ffwizard.lua new file mode 100644 index 0000000..f0e700d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ffwizard.lua @@ -0,0 +1,21 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ffwizard.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +module "luci.controller.ffwizard" + +function index() + entry({"admin", "freifunk", "ffwizard"}, form("ffwizard"), "Freifunkassistent", 50) +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/freifunk/freifunk.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/freifunk/freifunk.lua new file mode 100644 index 0000000..5bd7821 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/freifunk/freifunk.lua @@ -0,0 +1,192 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: freifunk.lua 4152 2009-01-26 10:21:20Z Cyrus $ +]]-- +module("luci.controller.freifunk.freifunk", package.seeall) + +function index() + local i18n = luci.i18n.translate + + local page = node() + page.lock = true + page.target = alias("freifunk") + page.subindex = true + page.index = false + + local page = node("freifunk") + page.title = "Freifunk" + page.target = alias("freifunk", "index") + page.order = 5 + page.setuser = "nobody" + page.setgroup = "nogroup" + page.i18n = "freifunk" + page.index = true + + local page = node("freifunk", "index") + page.target = template("freifunk/index") + page.title = "Übersicht" + page.order = 10 + page.indexignore = true + + local page = node("freifunk", "index", "contact") + page.target = template("freifunk/contact") + page.title = "Kontakt" + + + local page = node("freifunk", "status") + page.target = form("freifunk/public_status") + page.title = "Status" + page.order = 20 + page.i18n = "admin-core" + page.setuser = false + page.setgroup = false + + entry({"freifunk", "status.json"}, call("jsonstatus")) + + assign({"freifunk", "olsr"}, {"admin", "status", "olsr"}, "OLSR", 30) + + if luci.fs.access("/etc/config/luci_statistics") then + assign({"freifunk", "graph"}, {"admin", "statistics", "graph"}, i18n("stat_statistics", "Statistiken"), 40) + end + + assign({"mini", "freifunk"}, {"admin", "freifunk"}, "Freifunk", 15) + entry({"admin", "freifunk"}, alias("admin", "freifunk", "index"), "Freifunk", 15) + local page = node("admin", "freifunk", "index") + page.target = cbi("freifunk/freifunk") + page.title = "Freifunk" + page.order = 30 + + local page = node("admin", "freifunk", "contact") + page.target = cbi("freifunk/contact") + page.title = "Kontakt" + page.order = 40 +end + +local function fetch_olsrd() + local sys = require "luci.sys" + local util = require "luci.util" + local table = require "table" + local rawdata = sys.httpget("http://127.0.0.1:2006/") + + if #rawdata == 0 then + if luci.fs.access("/proc/net/ipv6_route", "r") then + rawdata = sys.httpget("http://[::1]:2006/") + if #rawdata == 0 then + return nil + end + else + return nil + end + end + + local data = {} + + local tables = util.split(util.trim(rawdata), "\r?\n\r?\n", nil, true) + + + for i, tbl in ipairs(tables) do + local lines = util.split(tbl, "\r?\n", nil, true) + local name = table.remove(lines, 1):sub(8) + local keys = util.split(table.remove(lines, 1), "\t") + local split = #keys - 1 + + data[name] = {} + + for j, line in ipairs(lines) do + local fields = util.split(line, "\t", split) + data[name][j] = {} + for k, key in pairs(keys) do + data[name][j][key] = fields[k] + end + + if data[name][j].Linkcost then + data[name][j].LinkQuality, + data[name][j].NLQ, + data[name][j].ETX = + data[name][j].Linkcost:match("([%w.]+)/([%w.]+)[%s]+([%w.]+)") + end + end + end + + return data +end + +function jsonstatus() + local root = {} + local sys = require "luci.sys" + local uci = require "luci.model.uci" + local util = require "luci.util" + local http = require "luci.http" + local json = require "luci.json" + local ltn12 = require "luci.ltn12" + local version = require "luci.version" + local webadmin = require "luci.tools.webadmin" + + local cursor = uci.cursor_state() + + local ffzone = webadmin.firewall_find_zone("freifunk") + local ffznet = ffzone and cursor:get("firewall", ffzone, "network") + local ffwifs = ffznet and util.split(ffznet, " ") or {} + + + root.protocol = 1 + + root.system = { + uptime = {sys.uptime()}, + loadavg = {sys.loadavg()}, + sysinfo = {sys.sysinfo()}, + hostname = sys.hostname() + } + + root.firmware = { + luciname=version.luciname, + luciversion=version.luciversion, + distname=version.distname, + distversion=version.distversion + } + + root.freifunk = {} + cursor:foreach("freifunk", "public", function(s) + root.freifunk[s[".name"]] = s + end) + + cursor:foreach("system", "system", function(s) + root.geo = { + latitude = s.latitude, + longitude = s.longitude + } + end) + + root.network = {} + root.wireless = {devices = {}, interfaces = {}, status = {}} + local wifs = root.wireless.interfaces + local wifidata = luci.sys.wifi.getiwconfig() or {} + local netdata = luci.sys.net.deviceinfo() or {} + + for _, vif in ipairs(ffwifs) do + root.network[vif] = cursor:get_all("network", vif) + root.wireless.devices[vif] = cursor:get_all("wireless", vif) + cursor:foreach("wireless", "wifi-iface", function(s) + if s.device == vif and s.network == vif then + wifs[#wifs+1] = s + if s.ifname then + root.wireless.status[s.ifname] = wifidata[s.ifname] + end + end + end) + end + + root.olsrd = fetch_olsrd() + + http.prepare_content("application/json") + ltn12.pump.all(json.Encoder(root):source(), http.write) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/hd_idle.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/hd_idle.lua new file mode 100644 index 0000000..10a3963 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/hd_idle.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI hd-idle +(c) 2008 Yanira + +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: hd_idle.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.hd_idle", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("hd_idle") + if not luci.fs.access("/etc/config/hd-idle") then + return + end + + local page = entry({"admin", "services", "hd_idle"}, cbi("hd_idle"), luci.i18n.translate("hd_idle", "hd-idle"), 60) + page.i18n = "hd_idle" + page.dependent = true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/init.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/init.lua new file mode 100644 index 0000000..caae2ba --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/init.lua @@ -0,0 +1,29 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: init.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.init", package.seeall) + +function index() + if not luci.fs.access("/etc/rc.common") then + return + end + + require("luci.i18n") + luci.i18n.loadc("initmgr") + + entry( + {"admin", "system", "init"}, form("init/init"), + luci.i18n.translate("initmgr", "Init Scripts") + ).i18n = "initmgr" +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/livestats.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/livestats.lua new file mode 100644 index 0000000..cb7a6a3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/livestats.lua @@ -0,0 +1,29 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: livestats.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +module("luci.controller.livestats", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("livestats") + + entry( {"admin", "status", "wifistat"}, template("livestats/wireless"), luci.i18n.translate("livestats_stat_wireless"), 90 ).i18n = "livestats" + entry( {"admin", "status", "trafstat"}, template("livestats/traffic"), luci.i18n.translate("livestats_stat_traffic"), 91 ).i18n = "livestats" + entry( {"admin", "status", "loadavg"}, template("livestats/loadavg"), luci.i18n.translate("livestats_stat_loadavg"), 92 ).i18n = "livestats" + + entry( {"mini", "network", "wifistat"}, template("livestats/wireless"), luci.i18n.translate("livestats_stat_wireless"), 90 ).i18n = "livestats" + entry( {"mini", "network", "trafstat"}, template("livestats/traffic"), luci.i18n.translate("livestats_stat_traffic"), 91 ).i18n = "livestats" + entry( {"mini", "system", "loadavg"}, template("livestats/loadavg"), luci.i18n.translate("livestats_stat_loadavg"), 92 ).i18n = "livestats" +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_fw/luci_fw.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_fw/luci_fw.lua new file mode 100644 index 0000000..2be03d6 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_fw/luci_fw.lua @@ -0,0 +1,13 @@ +module("luci.controller.luci_fw.luci_fw", package.seeall) + +function index() + require("luci.i18n").loadc("luci-fw") + local i18n = luci.i18n.translate + + entry({"admin", "network", "firewall"}, alias("admin", "network", "firewall", "zones"), i18n("fw_fw"), 60).i18n = "luci-fw" + entry({"admin", "network", "firewall", "zones"}, cbi("luci_fw/zones"), i18n("fw_zones"), 10) + entry({"admin", "network", "firewall", "redirect"}, arcombine(cbi("luci_fw/redirect"), cbi("luci_fw/rrule")), i18n("fw_redirect"), 30).leaf = true + entry({"admin", "network", "firewall", "rule"}, arcombine(cbi("luci_fw/traffic"), cbi("luci_fw/trule")), i18n("fw_traffic"), 20).leaf = true + + entry({"mini", "network", "portfw"}, cbi("luci_fw/miniportfw", {autoapply=true}), i18n("fw_portfw", "Portweiterleitung"), 70).i18n = "luci-fw" +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_statistics/luci_statistics.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_statistics/luci_statistics.lua new file mode 100644 index 0000000..f9fd60a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/luci_statistics/luci_statistics.lua @@ -0,0 +1,198 @@ +--[[ + +Luci statistics - statistics controller module +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: luci_statistics.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.luci_statistics.luci_statistics", package.seeall) + +function index() + + require("luci.fs") + require("luci.util") + require("luci.i18n") + require("luci.statistics.datatree") + + -- load language files + luci.i18n.loadc("rrdtool") + luci.i18n.loadc("statistics") + + -- get rrd data tree + local tree = luci.statistics.datatree.Instance() + + -- override entry(): check for existance .so where is derived from the called path + function _entry( path, ... ) + local file = path[5] or path[4] + if luci.fs.access( "/usr/lib/collectd/" .. file .. ".so" ) then + entry( path, ... ) + end + end + + -- override i18n(): try to translate stat_ or fall back to + function _i18n( str ) + return luci.i18n.translate( "stat_" .. str, str ) + end + + -- our collectd menu + local collectd_menu = { + output = { "rrdtool", "network", "unixsock", "csv" }, + system = { "exec", "email", "cpu", "df", "disk", "irq", "processes", "load" }, + network = { "interface", "netlink", "iptables", "tcpconns", "ping", "dns", "wireless" } + } + + -- create toplevel menu nodes + local st = entry({"admin", "statistics"}, call("statistics_index"), _i18n("statistics"), 80) + st.i18n = "statistics" + st.index = true + + entry({"admin", "statistics", "collectd"}, cbi("luci_statistics/collectd"), _i18n("collectd"), 10).subindex = true + + + -- populate collectd plugin menu + local index = 1 + for section, plugins in luci.util.kspairs( collectd_menu ) do + entry( + { "admin", "statistics", "collectd", section }, + call( "statistics_" .. section .. "plugins" ), + _i18n( section .. "plugins" ), + index * 10 + ).index = true + + for j, plugin in luci.util.vspairs( plugins ) do + _entry( + { "admin", "statistics", "collectd", section, plugin }, + cbi("luci_statistics/" .. plugin ), + _i18n( plugin ), + j * 10 + ) + end + + index = index + 1 + end + + -- output views + local page = entry( { "admin", "statistics", "graph" }, call("statistics_index"), _i18n("graphs"), 80) + page.i18n = "statistics" + page.setuser = "nobody" + page.setgroup = "nogroup" + + local vars = luci.http.formvalue(nil, true) + local span = vars.timespan or nil + + for i, plugin in luci.util.vspairs( tree:plugins() ) do + + -- get plugin instances + local instances = tree:plugin_instances( plugin ) + + -- plugin menu entry + entry( + { "admin", "statistics", "graph", plugin }, + call("statistics_render"), _i18n( plugin ), i + ).query = { timespan = span } + + -- if more then one instance is found then generate submenu + if #instances > 1 then + for j, inst in luci.util.vspairs(instances) do + -- instance menu entry + entry( + { "admin", "statistics", "graph", plugin, inst }, + call("statistics_render"), inst, j + ).query = { timespan = span } + end + end + end +end + +function statistics_index() + luci.template.render("admin_statistics/index") +end + +function statistics_outputplugins() + local plugins = { } + + for i, p in ipairs({ "rrdtool", "network", "unixsock", "csv" }) do + plugins[p] = luci.i18n.translate( "stat_" .. p, p ) + end + + luci.template.render("admin_statistics/outputplugins", {plugins=plugins}) +end + +function statistics_systemplugins() + local plugins = { } + + for i, p in ipairs({ "exec", "email", "df", "disk", "irq", "processes", "cpu" }) do + plugins[p] = luci.i18n.translate( "stat_" .. p, p ) + end + + luci.template.render("admin_statistics/systemplugins", {plugins=plugins}) +end + +function statistics_networkplugins() + local plugins = { } + + for i, p in ipairs({ "interface", "netlink", "iptables", "tcpconns", "ping", "dns", "wireless" }) do + plugins[p] = luci.i18n.translate( "stat_" .. p, p ) + end + + luci.template.render("admin_statistics/networkplugins", {plugins=plugins}) +end + + +function statistics_render() + + require("luci.statistics.rrdtool") + require("luci.template") + require("luci.model.uci") + + local vars = luci.http.formvalue() + local req = luci.dispatcher.context.request + local path = luci.dispatcher.context.path + local uci = luci.model.uci.cursor() + local spans = luci.util.split( uci:get( "luci_statistics", "collectd_rrdtool", "RRATimespans" ), "%s+", nil, true ) + local span = vars.timespan or uci:get( "luci_statistics", "rrdtool", "default_timespan" ) or spans[1] + local graph = luci.statistics.rrdtool.Graph( luci.util.parse_units( span ) ) + + local plugin, instances + local images = { } + + -- find requested plugin and instance + for i, p in ipairs( luci.dispatcher.context.path ) do + if luci.dispatcher.context.path[i] == "graph" then + plugin = luci.dispatcher.context.path[i+1] + instances = { luci.dispatcher.context.path[i+2] } + end + end + + -- no instance requested, find all instances + if #instances == 0 then + instances = { graph.tree:plugin_instances( plugin )[1] } + + -- index instance requested + elseif instances[1] == "-" then + instances[1] = "" + end + + + -- render graphs + for i, inst in ipairs( instances ) do + for i, img in ipairs( graph:render( plugin, inst ) ) do + table.insert( images, graph:strippngpath( img ) ) + end + end + + luci.template.render( "public_statistics/graph", { + images = images, + plugin = plugin, + timespans = spans, + current_timespan = span + } ) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/index.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/index.lua new file mode 100644 index 0000000..686d148 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/index.lua @@ -0,0 +1,53 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +module("luci.controller.mini.index", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + local root = node() + if not root.lock then + root.target = alias("mini") + root.index = true + end + + entry({"about"}, template("about")).i18n = "admin-core" + + --[[ + local page = entry({"mini"}, alias("mini", "index"), i18n("essentials", "Essentials"), 10) + page.i18n = "admin-core" + page.sysauth = "root" + page.sysauth_authenticator = "htmlauth" + page.index = true + ]]-- + --entry({"mini", "index"}, alias("mini", "index", "index"), i18n("overview"), 10).index = true + --entry({"mini", "index", "index"}, form("mini/index"), i18n("general"), 1).ignoreindex = true + --entry({"system", "luci"}, cbi("mini/luci", {autoapply=true}), i18n("settings"), 10) + --entry({"mini", "index", "logout"}, call("action_logout"), i18n("logout")) +end + +function action_logout() + local dsp = require "luci.dispatcher" + local sauth = require "luci.sauth" + if dsp.context.authsession then + sauth.kill(dsp.context.authsession) + dsp.context.urltoken.stok = nil + end + + luci.http.header("Set-Cookie", "sysauth=; path=" .. dsp.build_url()) + luci.http.redirect(luci.dispatcher.build_url()) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/network.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/network.lua new file mode 100644 index 0000000..054b1ed --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/network.lua @@ -0,0 +1,26 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: network.lua 3674 2008-10-31 09:35:53Z Cyrus $ +]]-- + +module("luci.controller.mini.network", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + -- entry({"network"}, alias("mini", "network", "index"), i18n("network"), 20).index = true + entry({"network"}, cbi("mini/network", {autoapply=true}), i18n("network"), 1) + entry({"wifi"}, cbi("mini/wifi", {autoapply=true}), i18n("wifi"), 10).i18n="wifi" + -- entry({"network", "dhcp"}, cbi("mini/dhcp", {autoapply=true}), "DHCP", 20) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/system.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/system.lua new file mode 100644 index 0000000..17b6309 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mini/system.lua @@ -0,0 +1,130 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: system.lua 3743 2008-11-09 20:09:31Z Cyrus $ +]]-- + +module("luci.controller.mini.system", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + +--[[ entry({"system"}, alias("mini", "system", "index"), i18n("system"), 40).index = true + entry({"system", "index"}, cbi("mini/system", {autoapply=true}), i18n("general"), 1) + entry({"system", "passwd"}, form("mini/passwd"), i18n("a_s_changepw"), 10) + entry({"system", "backup"}, call("action_backup"), i18n("a_s_backup"), 80) + entry({"system", "upgrade"}, call("action_upgrade"), i18n("a_s_flash"), 90) + entry({"system", "reboot"}, call("action_reboot"), i18n("reboot"), 100) +]]-- + +end + +function action_backup() + local reset_avail = os.execute([[grep '"rootfs_data"' /proc/mtd >/dev/null 2>&1]]) == 0 + local restore_cmd = "gunzip | tar -xC/ >/dev/null 2>&1" + local backup_cmd = "tar -c %s | gzip 2>/dev/null" + + local restore_fpi + luci.http.setfilehandler( + function(meta, chunk, eof) + if not restore_fpi then + restore_fpi = io.popen(restore_cmd, "w") + end + if chunk then + restore_fpi:write(chunk) + end + if eof then + restore_fpi:close() + end + end + ) + + local upload = luci.http.formvalue("archive") + local backup = luci.http.formvalue("backup") + local reset = reset_avail and luci.http.formvalue("reset") + + if upload and #upload > 0 then + luci.template.render("mini/applyreboot") + luci.sys.reboot() + elseif backup then + luci.util.perror(backup_cmd:format(_keep_pattern())) + local backup_fpi = io.popen(backup_cmd:format(_keep_pattern()), "r") + luci.http.header('Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % { + luci.sys.hostname(), os.date("%Y-%m-%d")}) + luci.http.prepare_content("application/x-targz") + luci.ltn12.pump.all(luci.ltn12.source.file(backup_fpi), luci.http.write) + elseif reset then + luci.template.render("mini/applyreboot") + luci.util.exec("mtd -r erase rootfs_data") + else + luci.template.render("mini/backup", {reset_avail = reset_avail}) + end +end + +function action_reboot() + local reboot = luci.http.formvalue("reboot") + luci.template.render("mini/reboot", {reboot=reboot}) + if reboot then + luci.sys.reboot() + end +end + +function action_upgrade() + require("luci.model.uci") + + local ret = nil + local plat = luci.fs.mtime("/lib/upgrade/platform.sh") + local tmpfile = "/tmp/firmware.img" + local keep_avail = true + + local file + luci.http.setfilehandler( + function(meta, chunk, eof) + if not file then + file = io.open(tmpfile, "w") + end + if chunk then + file:write(chunk) + end + if eof then + file:close() + end + end + ) + + local fname = luci.http.formvalue("image") + local keepcfg = keep_avail and luci.http.formvalue("keepcfg") + + if plat and fname then + ret = function() + return luci.sys.flash(tmpfile, keepcfg and _keep_pattern()) + end + end + + luci.http.prepare_content("text/html") + luci.template.render("mini/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail}) +end + +function _keep_pattern() + local kpattern = "" + local files = luci.model.uci.cursor():get_all("luci", "flash_keep") + if files then + kpattern = "" + for k, v in pairs(files) do + if k:sub(1,1) ~= "." and luci.fs.glob(v) then + kpattern = kpattern .. " " .. v + end + end + end + return kpattern +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mmc_over_gpio.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mmc_over_gpio.lua new file mode 100644 index 0000000..9c86bfd --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/mmc_over_gpio.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI mmc_over_gpio +(c) 2008 Yanira + +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: mmc_over_gpio.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.mmc_over_gpio", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("mmc_over_gpio") + if not luci.fs.access("/etc/config/mmc_over_gpio") then + return + end + + local page = entry({"admin", "system", "mmc_over_gpio"}, cbi("mmc_over_gpio"), luci.i18n.translate("mmc_over_gpio", "mmc_over_gpio"), 60) + page.i18n = "mmc_over_gpio" + page.dependent = true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ntpc.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ntpc.lua new file mode 100644 index 0000000..46595a7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ntpc.lua @@ -0,0 +1,32 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ntpc.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.ntpc", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("ntpc") + if not luci.fs.access("/etc/config/ntpclient") then + return + end + + local page = entry({"admin", "system", "ntpc"}, cbi("ntpc/ntpc"), luci.i18n.translate("ntpc"), 50) + page.i18n = "ntpc" + page.dependent = true + + + local page = entry({"mini", "system", "ntpc"}, cbi("ntpc/ntpcmini", {autoapply=true}), luci.i18n.translate("ntpc"), 50) + page.i18n = "ntpc" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/olsr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/olsr.lua new file mode 100644 index 0000000..652f6b9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/olsr.lua @@ -0,0 +1,225 @@ +module("luci.controller.olsr", package.seeall) + +function index() + if not luci.fs.access("/etc/config/olsrd") then + return + end + + require("luci.i18n").loadc("olsr") + local i18n = luci.i18n.translate + + local page = node("admin", "status", "olsr") + page.target = call("action_index") + page.title = "OLSR" + page.i18n = "olsr" + page.subindex = true + + local page = node("admin", "status", "olsr", "routes") + page.target = call("action_routes") + page.title = i18n("olsr_routes", "Routen") + page.order = 10 + + local page = node("admin", "status", "olsr", "topology") + page.target = call("action_topology") + page.title = i18n("olsr_topology", "Topologie") + page.order = 20 + + local page = node("admin", "status", "olsr", "hna") + page.target = call("action_hna") + page.title = "HNA" + page.order = 30 + + local page = node("admin", "status", "olsr", "mid") + page.target = call("action_mid") + page.title = "MID" + page.order = 50 + + local ol = entry( + {"admin", "services", "olsrd"}, + cbi("olsr/olsrd"), "OLSR" + ) + ol.i18n = "olsr" + ol.subindex = true + + entry( + {"admin", "services", "olsrd", "hna"}, + cbi("olsr/olsrdhna"), "HNA Announcements" + ) + + oplg = entry( + {"admin", "services", "olsrd", "plugins"}, + cbi("olsr/olsrdplugins"), "Plugins" + ) + oplg.i18n = "olsr" + oplg.leaf = true + oplg.subindex = true + + local uci = require("luci.model.uci").cursor() + uci:foreach("olsrd", "LoadPlugin", + function (section) + local lib = section.library + entry( + {"admin", "services", "olsrd", "plugins", lib }, + cbi("olsr/olsrdplugins"), + nil --'Plugin "%s"' % lib:gsub("^olsrd_",""):gsub("%.so.+$","") + ) + end + ) +end + +function action_index() + local data = fetch_txtinfo("links") + + if not data or not data.Links then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + local c = tonumber(a.Cost) + local d = tonumber(b.Cost) + + if not c or c == 0 then + return false + end + + if not d or d == 0 then + return true + end + + return c < d + end + + table.sort(data.Links, compare) + + luci.template.render("status-olsr/index", {links=data.Links}) +end + +function action_routes() + local data = fetch_txtinfo("routes") + + if not data or not data.Routes then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + local c = tonumber(a.ETX) + local d = tonumber(b.ETX) + + if not c or c == 0 then + return false + end + + if not d or d == 0 then + return true + end + + return c < d + end + + table.sort(data.Routes, compare) + + luci.template.render("status-olsr/routes", {routes=data.Routes}) +end + +function action_topology() + local data = fetch_txtinfo("topology") + + if not data or not data.Topology then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + return a["Dest. IP"] < b["Dest. IP"] + end + + table.sort(data.Topology, compare) + + luci.template.render("status-olsr/topology", {routes=data.Topology}) +end + +function action_hna() + local data = fetch_txtinfo("hna") + + if not data or not data.HNA then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + return a.Destination < b.Destination + end + + table.sort(data.HNA, compare) + + luci.template.render("status-olsr/hna", {routes=data.HNA}) +end + +function action_mid() + local data = fetch_txtinfo("mid") + + if not data or not data.MID then + luci.template.render("status-olsr/error_olsr") + return nil + end + + local function compare(a, b) + return a["IP address"] < b["IP address"] + end + + table.sort(data.MID, compare) + + luci.template.render("status-olsr/mid", {mids=data.MID}) +end + + +-- Internal +function fetch_txtinfo(otable) + require("luci.sys") + otable = otable or "" + local rawdata = luci.sys.httpget("http://127.0.0.1:2006/"..otable) + + if #rawdata == 0 then + if luci.fs.access("/proc/net/ipv6_route", "r") then + rawdata = luci.sys.httpget("http://[::1]:2006/"..otable) + if #rawdata == 0 then + return nil + end + else + return nil + end + end + + local data = {} + + local tables = luci.util.split(luci.util.trim(rawdata), "\r?\n\r?\n", nil, true) + + + for i, tbl in ipairs(tables) do + local lines = luci.util.split(tbl, "\r?\n", nil, true) + local name = table.remove(lines, 1):sub(8) + local keys = luci.util.split(table.remove(lines, 1), "\t") + local split = #keys - 1 + + data[name] = {} + + for j, line in ipairs(lines) do + local fields = luci.util.split(line, "\t", split) + data[name][j] = {} + for k, key in pairs(keys) do + data[name][j][key] = fields[k] + end + + if data[name][j].Linkcost then + data[name][j].LinkQuality, + data[name][j].NLQ, + data[name][j].ETX = + data[name][j].Linkcost:match("([%w.]+)/([%w.]+)[%s]+([%w.]+)") + end + end + end + + return data +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/p910nd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/p910nd.lua new file mode 100644 index 0000000..9dec110 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/p910nd.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI UVC Streamer +(c) 2008 Yanira + +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: p910nd.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.p910nd", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("p910nd") + if not luci.fs.access("/etc/config/p910nd") then + return + end + + local page = entry({"admin", "services", "p910nd"}, cbi("p910nd"), luci.i18n.translate("p910nd", "Printer server"), 60) + page.i18n = "p910nd" + page.dependent = true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/polipo.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/polipo.lua new file mode 100644 index 0000000..f521984 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/polipo.lua @@ -0,0 +1,28 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Aleksandar Krsteski + +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: polipo.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.polipo", package.seeall) + +function index() + if not luci.fs.access("/etc/config/polipo") then + return + end + + require("luci.i18n") + luci.i18n.loadc("polipo") + local i18n = luci.i18n.translate + + local p = entry({"admin", "services", "polipo"}, cbi("polipo"), i18n("polipo", "Polipo")) + p.dependent = true + p.i18n = "polipo" +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/qos.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/qos.lua new file mode 100644 index 0000000..7299dfa --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/qos.lua @@ -0,0 +1,29 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: qos.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.qos", package.seeall) + +function index() + if not luci.fs.access("/etc/config/qos") then + return + end + + local page = entry({"admin", "network", "qos"}, cbi("qos/qos"), "QoS") + page.i18n = "qos" + page.dependent = true + + + local page = entry({"mini", "network", "qos"}, cbi("qos/qosmini", {autoapply=true}), "QoS") + page.i18n = "qos" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/rpc.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/rpc.lua new file mode 100644 index 0000000..a1d1b89 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/rpc.lua @@ -0,0 +1,179 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: rpc.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local require = require +local pairs = pairs +local print = print +local pcall = pcall +local table = table + +module "luci.controller.rpc" + +function index() + local function authenticator(validator, accs) + local auth = luci.http.formvalue("auth", true) + if auth then + local sdat = luci.sauth.read(auth) + user = loadstring(sdat)().user + if user and luci.util.contains(accs, user) then + return user, auth + end + end + luci.http.status(403, "Forbidden") + end + + local rpc = node("rpc") + rpc.sysauth = "root" + rpc.sysauth_authenticator = authenticator + rpc.notemplate = true + + entry({"rpc", "uci"}, call("rpc_uci")) + entry({"rpc", "uvl"}, call("rpc_uvl")) + entry({"rpc", "fs"}, call("rpc_fs")) + entry({"rpc", "sys"}, call("rpc_sys")) + entry({"rpc", "ipkg"}, call("rpc_ipkg")) + entry({"rpc", "auth"}, call("rpc_auth")).sysauth = false +end + +function rpc_auth() + local jsonrpc = require "luci.jsonrpc" + local sauth = require "luci.sauth" + local http = require "luci.http" + local sys = require "luci.sys" + local ltn12 = require "luci.ltn12" + local util = require "luci.util" + + local loginstat + + local server = {} + server.challenge = function(user, pass) + local sid, token, secret + + if sys.user.checkpasswd(user, pass) then + sid = sys.uniqueid(16) + token = sys.uniqueid(16) + secret = sys.uniqueid(16) + + http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") + sauth.write(sid, util.get_bytecode({ + user=user, + token=token, + secret=secret + })) + end + + return sid and {sid=sid, token=token, secret=secret} + end + + server.login = function(...) + local challenge = server.challenge(...) + return challenge and challenge.sid + end + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(server, http.source()), http.write) +end + +function rpc_uci() + if not pcall(require, "luci.model.uci") then + luci.http.status(404, "Not Found") + return nil + end + local uci = require "luci.jsonrpcbind.uci" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(uci, http.source()), http.write) +end + +function rpc_uvl() + if not pcall(require, "luci.uvl") then + luci.http.status(404, "Not Found") + return nil + end + local uvl = require "luci.jsonrpcbind.uvl" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(uvl, http.source()), http.write) +end + +function rpc_fs() + local util = require "luci.util" + local io = require "io" + local fs2 = util.clone(require "luci.fs") + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + function fs2.readfile(filename) + local stat, mime = pcall(require, "mime") + if not stat then + error("Base64 support not available. Please install LuaSocket.") + end + + local fp = io.open(filename) + if not fp then + return nil + end + + local output = {} + local sink = ltn12.sink.table(output) + local source = ltn12.source.chain(ltn12.source.file(fp), mime.encode("base64")) + return ltn12.pump.all(source, sink) and table.concat(output) + end + + function fs2.writefile(filename, data) + local stat, mime = pcall(require, "mime") + if not stat then + error("Base64 support not available. Please install LuaSocket.") + end + + local file = io.open(filename, "w") + local sink = file and ltn12.sink.chain(mime.decode("base64"), ltn12.sink.file(file)) + return sink and ltn12.pump.all(ltn12.source.string(data), sink) or false + end + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(fs2, http.source()), http.write) +end + +function rpc_sys() + local sys = require "luci.sys" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(sys, http.source()), http.write) +end + +function rpc_ipkg() + if not pcall(require, "luci.model.ipkg") then + luci.http.status(404, "Not Found") + return nil + end + local ipkg = require "luci.model.ipkg" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(ipkg, http.source()), http.write) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/samba.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/samba.lua new file mode 100644 index 0000000..c5f5834 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/samba.lua @@ -0,0 +1,27 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: samba.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.samba", package.seeall) + +function index() + if not luci.fs.access("/etc/config/samba") then + return + end + require("luci.i18n") + luci.i18n.loadc("samba") + + local page = entry({"admin", "services", "samba"}, cbi("samba"), luci.i18n.translate("samba")) + page.i18n = "samba" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/siitwizard.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/siitwizard.lua new file mode 100644 index 0000000..64c9b98 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/siitwizard.lua @@ -0,0 +1,21 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: siitwizard.lua 3934 2008-12-23 05:18:08Z jow $ + +]]-- + +module "luci.controller.siitwizard" + +function index() + entry({"admin", "network", "siitwizard"}, form("siitwizard"), "SIIT 4over6 assistent", 99) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/splash/splash.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/splash/splash.lua new file mode 100644 index 0000000..b046ff4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/splash/splash.lua @@ -0,0 +1,29 @@ +module("luci.controller.splash.splash", package.seeall) + +function index() + entry({"admin", "services", "splash"}, cbi("splash/splash"), "Client-Splash") + + node("splash").target = call("action_dispatch") + node("splash", "splash", "activate").target = call("action_activate") + node("splash", "splash", "splash").target = template("splash_splash/splash") +end + +function action_dispatch() + local mac = luci.sys.net.ip4mac(luci.http.getenv("REMOTE_ADDR")) or "" + local status = luci.util.execl("luci-splash status "..mac)[1] + if #mac > 0 and ( status == "whitelisted" or status == "lease" ) then + luci.http.redirect(luci.dispatcher.build_url()) + else + luci.http.redirect(luci.dispatcher.build_url("splash", "splash", "splash")) + end +end + +function action_activate() + local mac = luci.sys.net.ip4mac(luci.http.getenv("REMOTE_ADDR")) + if mac and luci.http.formvalue("accept") then + os.execute("luci-splash add "..mac.." >/dev/null 2>&1") + luci.http.redirect(luci.model.uci.cursor():get("freifunk", "community", "homepage")) + else + luci.http.redirect(luci.dispatcher.build_url()) + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/tinyproxy.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/tinyproxy.lua new file mode 100644 index 0000000..4919c2a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/tinyproxy.lua @@ -0,0 +1,25 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tinyproxy.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.tinyproxy", package.seeall) + +function index() + if not luci.fs.access("/etc/config/tinyproxy") then + return + end + + local page = entry({"admin", "services", "tinyproxy"}, cbi("tinyproxy"), "Tinyproxy") + page.dependent = true + page.i18n = "tinyproxy" +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/upnp.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/upnp.lua new file mode 100644 index 0000000..7343bcc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/upnp.lua @@ -0,0 +1,30 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upnp.lua 3987 2009-01-02 21:35:25Z Cyrus $ +]]-- +module("luci.controller.upnp", package.seeall) + +function index() + if not luci.fs.access("/etc/config/upnpd") then + return + end + + local page = entry({"admin", "services", "upnp"}, cbi("upnp/upnp"), "UPNP") + page.i18n = "upnp" + page.dependent = true + + + local page = entry({"mini", "network", "upnp"}, cbi("upnp/upnpmini", {autoapply=true}), "UPNP") + page.i18n = "upnp" + page.dependent = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ushare.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ushare.lua new file mode 100644 index 0000000..702e446 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/ushare.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI uShare +(c) 2008 Yanira + +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: ushare.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.ushare", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("ushare") + if not luci.fs.access("/etc/config/ushare") then + return + end + + local page = entry({"admin", "services", "ushare"}, cbi("ushare"), luci.i18n.translate("ushare", "uShare"), 60) + page.i18n = "uvc_streamer" + page.dependent = true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/controller/uvc_streamer.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/uvc_streamer.lua new file mode 100644 index 0000000..7de7895 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/controller/uvc_streamer.lua @@ -0,0 +1,28 @@ +--[[ + +LuCI UVC Streamer +(c) 2008 Yanira + +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: uvc_streamer.lua 3987 2009-01-02 21:35:25Z Cyrus $ + +]]-- + +module("luci.controller.uvc_streamer", package.seeall) + +function index() + require("luci.i18n") + luci.i18n.loadc("uvc_streamer") + if not luci.fs.access("/etc/config/uvc-streamer") then + return + end + + local page = entry({"admin", "services", "uvc_streamer"}, cbi("uvc_streamer"), luci.i18n.translate("uvc_streamer", "UVC Streaming"), 60) + page.i18n = "uvc_streamer" + page.dependent = true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/debug.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/debug.lua new file mode 100644 index 0000000..f991ab8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/debug.lua @@ -0,0 +1,25 @@ +local debug = require "debug" +local io = require "io" +local collectgarbage = collectgarbage + +module "luci.debug" +__file__ = debug.getinfo(1, 'S').source:sub(2) + +-- Enables the memory tracer with given flags and returns a function to disable the tracer again +function trap_memtrace(flags) + flags = flags or "l" + local tracefile = io.open("/tmp/memtrace", "w") + + local function trap(what, line) + local info = debug.getinfo(2, "Sn") + tracefile:write(info.source..":"..line.."\t"..(info.namewhat or "").."\t"..(info.name or "").."\t"..collectgarbage("count").."\n") + end + + debug.sethook(trap, flags) + + return function() + debug.sethook() + tracefile:close() + end +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/dispatcher.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/dispatcher.lua new file mode 100644 index 0000000..ab5e7a4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/dispatcher.lua @@ -0,0 +1,720 @@ +--[[ +LuCI - Dispatcher + +Description: +The request dispatcher and module dispatcher generators + +FileId: +$Id: dispatcher.lua 4189 2009-01-30 15:29:53Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +--- LuCI web dispatcher. +local fs = require "luci.fs" +local sys = require "luci.sys" +local init = require "luci.init" +local util = require "luci.util" +local http = require "luci.http" + +module("luci.dispatcher", package.seeall) +context = util.threadlocal() + +authenticator = {} + +-- Index table +local index = nil + +-- Fastindex +local fi + + +--- Build the URL relative to the server webroot from given virtual path. +-- @param ... Virtual path +-- @return Relative URL +function build_url(...) + local path = {...} + local sn = http.getenv("SCRIPT_NAME") or "" + for k, v in pairs(context.urltoken) do + sn = sn .. "/;" .. k .. "=" .. http.urlencode(v) + end + return sn .. ((#path > 0) and "/" .. table.concat(path, "/") or "") +end + +--- Send a 404 error code and render the "error404" template if available. +-- @param message Custom error message (optional) +-- @return false +function error404(message) + luci.http.status(404, "Not Found") + message = message or "Not Found" + + require("luci.template") + if not luci.util.copcall(luci.template.render, "error404") then + luci.http.prepare_content("text/plain") + luci.http.write(message) + end + return false +end + +--- Send a 500 error code and render the "error500" template if available. +-- @param message Custom error message (optional)# +-- @return false +function error500(message) + luci.http.status(500, "Internal Server Error") + + require("luci.template") + if not luci.util.copcall(luci.template.render, "error500", {message=message}) then + luci.http.prepare_content("text/plain") + luci.http.write(message) + end + return false +end + +function authenticator.htmlauth(validator, accs, default) + local user = luci.http.formvalue("username") + local pass = luci.http.formvalue("password") + + if user and validator(user, pass) then + return user + end + + require("luci.i18n") + require("luci.template") + context.path = {} + luci.template.render("sysauth", {duser=default, fuser=user}) + return false + +end + +--- Dispatch an HTTP request. +-- @param request LuCI HTTP Request object +function httpdispatch(request) + luci.http.context.request = request + context.request = {} + local pathinfo = http.urldecode(request:getenv("PATH_INFO") or "", true) + + for node in pathinfo:gmatch("[^/]+") do + table.insert(context.request, node) + end + + local stat, err = util.copcall(dispatch, context.request) + if not stat then + luci.util.perror(err) + error500(err) + end + + luci.http.close() + + --context._disable_memtrace() +end + +--- Dispatches a LuCI virtual path. +-- @param request Virtual path +function dispatch(request) + --context._disable_memtrace = require "luci.debug".trap_memtrace() + local ctx = context + ctx.path = request + ctx.urltoken = ctx.urltoken or {} + + local conf = require "luci.config" + local lang = conf.main.lang + if lang == "auto" then + local aclang = http.getenv("HTTP_ACCEPT_LANGUAGE") or "" + for lpat in aclang:gmatch("[%w-]+") do + lpat = lpat and lpat:gsub("-", "_") + if conf.languages[lpat] then + lang = lpat + break + end + end + end + require "luci.i18n".setlanguage(lang) + + local c = ctx.tree + local stat + if not c then + c = createtree() + end + + local track = {} + local args = {} + ctx.args = args + ctx.requestargs = ctx.requestargs or args + local n + local t = true + local token = ctx.urltoken + local preq = {} + local freq = {} + + for i, s in ipairs(request) do + local tkey, tval + if t then + tkey, tval = s:match(";(%w+)=(.*)") + end + + if tkey then + token[tkey] = tval + else + t = false + preq[#preq+1] = s + freq[#freq+1] = s + c = c.nodes[s] + n = i + if not c then + break + end + + util.update(track, c) + + if c.leaf then + break + end + end + end + + if c and c.leaf then + for j=n+1, #request do + args[#args+1] = request[j] + freq[#freq+1] = request[j] + end + end + + ctx.requestpath = freq + ctx.path = preq + + if track.i18n then + require("luci.i18n").loadc(track.i18n) + end + + -- Init template engine + if (c and c.index) or not track.notemplate then + local tpl = require("luci.template") + local media = track.mediaurlbase or luci.config.main.mediaurlbase + if not pcall(tpl.Template, "themes/%s/header" % fs.basename(media)) then + media = nil + for name, theme in pairs(luci.config.themes) do + if name:sub(1,1) ~= "." and pcall(tpl.Template, + "themes/%s/header" % fs.basename(theme)) then + media = theme + end + end + assert(media, "No valid theme found") + end + + local viewns = setmetatable({}, {__index=function(table, key) + if key == "controller" then + return build_url() + elseif key == "REQUEST_URI" then + return build_url(unpack(ctx.requestpath)) + else + return rawget(table, key) or _G[key] + end + end}) + tpl.context.viewns = viewns + viewns.write = luci.http.write + viewns.include = function(name) tpl.Template(name):render(getfenv(2)) end + viewns.translate = function(...) return require("luci.i18n").translate(...) end + viewns.striptags = util.striptags + viewns.media = media + viewns.theme = fs.basename(media) + viewns.resource = luci.config.main.resourcebase + end + + track.dependent = (track.dependent ~= false) + assert(not track.dependent or not track.auto, "Access Violation") + + if track.sysauth then + local sauth = require "luci.sauth" + + local authen = type(track.sysauth_authenticator) == "function" + and track.sysauth_authenticator + or authenticator[track.sysauth_authenticator] + + local def = (type(track.sysauth) == "string") and track.sysauth + local accs = def and {track.sysauth} or track.sysauth + local sess = ctx.authsession + local verifytoken = false + if not sess then + sess = luci.http.getcookie("sysauth") + sess = sess and sess:match("^[A-F0-9]+$") + verifytoken = true + end + + local sdat = sauth.read(sess) + local user + + if sdat then + sdat = loadstring(sdat)() + if not verifytoken or ctx.urltoken.stok == sdat.token then + user = sdat.user + end + end + + if not util.contains(accs, user) then + if authen then + ctx.urltoken.stok = nil + local user, sess = authen(luci.sys.user.checkpasswd, accs, def) + if not user or not util.contains(accs, user) then + return + else + local sid = sess or luci.sys.uniqueid(16) + if not sess then + local token = luci.sys.uniqueid(16) + sauth.write(sid, util.get_bytecode({ + user=user, + token=token, + secret=luci.sys.uniqueid(16) + })) + ctx.urltoken.stok = token + end + luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path="..build_url()) + ctx.authsession = sid + end + else + luci.http.status(403, "Forbidden") + return + end + else + ctx.authsession = sess + end + end + + if track.setgroup then + luci.sys.process.setgroup(track.setgroup) + end + + if track.setuser then + luci.sys.process.setuser(track.setuser) + end + + local target = nil + if c then + if type(c.target) == "function" then + target = c.target + elseif type(c.target) == "table" then + target = c.target.target + end + end + + if c and (c.index or type(target) == "function") then + ctx.dispatched = c + ctx.requested = ctx.requested or ctx.dispatched + end + + if c and c.index then + local tpl = require "luci.template" + + if util.copcall(tpl.render, "indexer", {}) then + return true + end + end + + if type(target) == "function" then + util.copcall(function() + local oldenv = getfenv(target) + local module = require(c.module) + local env = setmetatable({}, {__index= + + function(tbl, key) + return rawget(tbl, key) or module[key] or oldenv[key] + end}) + + setfenv(target, env) + end) + + if type(c.target) == "table" then + target(c.target, unpack(args)) + else + target(unpack(args)) + end + else + error404() + end +end + +--- Generate the dispatching index using the best possible strategy. +function createindex() + local path = luci.util.libpath() .. "/controller/" + local suff = ".lua" + + if luci.util.copcall(require, "luci.fastindex") then + createindex_fastindex(path, suff) + else + createindex_plain(path, suff) + end +end + +--- Generate the dispatching index using the fastindex C-indexer. +-- @param path Controller base directory +-- @param suffix Controller file suffix +function createindex_fastindex(path, suffix) + index = {} + + if not fi then + fi = luci.fastindex.new("index") + fi.add(path .. "*" .. suffix) + fi.add(path .. "*/*" .. suffix) + end + fi.scan() + + for k, v in pairs(fi.indexes) do + index[v[2]] = v[1] + end +end + +--- Generate the dispatching index using the native file-cache based strategy. +-- @param path Controller base directory +-- @param suffix Controller file suffix +function createindex_plain(path, suffix) + local controllers = util.combine( + luci.fs.glob(path .. "*" .. suffix) or {}, + luci.fs.glob(path .. "*/*" .. suffix) or {} + ) + + if indexcache then + local cachedate = fs.mtime(indexcache) + if cachedate then + local realdate = 0 + for _, obj in ipairs(controllers) do + local omtime = fs.mtime(path .. "/" .. obj) + realdate = (omtime and omtime > realdate) and omtime or realdate + end + + if cachedate > realdate then + assert( + sys.process.info("uid") == fs.stat(indexcache, "uid") + and fs.stat(indexcache, "mode") == "rw-------", + "Fatal: Indexcache is not sane!" + ) + + index = loadfile(indexcache)() + return index + end + end + end + + index = {} + + for i,c in ipairs(controllers) do + local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".") + local mod = require(module) + local idx = mod.index + + if type(idx) == "function" then + index[module] = idx + end + end + + if indexcache then + fs.writefile(indexcache, util.get_bytecode(index)) + fs.chmod(indexcache, "a-rwx,u+rw") + end +end + +--- Create the dispatching tree from the index. +-- Build the index before if it does not exist yet. +function createtree() + if not index then + createindex() + end + + local ctx = context + local tree = {nodes={}} + local modi = {} + + ctx.treecache = setmetatable({}, {__mode="v"}) + ctx.tree = tree + ctx.modifiers = modi + + -- Load default translation + require "luci.i18n".loadc("default") + + local scope = setmetatable({}, {__index = luci.dispatcher}) + + for k, v in pairs(index) do + scope._NAME = k + setfenv(v, scope) + v() + end + + local function modisort(a,b) + return modi[a].order < modi[b].order + end + + for _, v in util.spairs(modi, modisort) do + scope._NAME = v.module + setfenv(v.func, scope) + v.func() + end + + return tree +end + +--- Register a tree modifier. +-- @param func Modifier function +-- @param order Modifier order value (optional) +function modifier(func, order) + context.modifiers[#context.modifiers+1] = { + func = func, + order = order or 0, + module + = getfenv(2)._NAME + } +end + +--- Clone a node of the dispatching tree to another position. +-- @param path Virtual path destination +-- @param clone Virtual path source +-- @param title Destination node title (optional) +-- @param order Destination node order value (optional) +-- @return Dispatching tree node +function assign(path, clone, title, order) + local obj = node(unpack(path)) + obj.nodes = nil + obj.module = nil + + obj.title = title + obj.order = order + + setmetatable(obj, {__index = _create_node(clone)}) + + return obj +end + +--- Create a new dispatching node and define common parameters. +-- @param path Virtual path +-- @param target Target function to call when dispatched. +-- @param title Destination node title +-- @param order Destination node order value (optional) +-- @return Dispatching tree node +function entry(path, target, title, order) + local c = node(unpack(path)) + + c.target = target + c.title = title + c.order = order + c.module = getfenv(2)._NAME + + return c +end + +--- Fetch or create a new dispatching node. +-- @param ... Virtual path +-- @return Dispatching tree node +function node(...) + local c = _create_node({...}) + + c.module = getfenv(2)._NAME + c.auto = nil + + return c +end + +function _create_node(path, cache) + if #path == 0 then + return context.tree + end + + cache = cache or context.treecache + local name = table.concat(path, ".") + local c = cache[name] + + if not c then + local new = {nodes={}, auto=true, path=util.clone(path)} + local last = table.remove(path) + + c = _create_node(path, cache) + + c.nodes[last] = new + cache[name] = new + + return new + else + return c + end +end + +-- Subdispatchers -- + +--- Create a redirect to another dispatching node. +-- @param ... Virtual path destination +function alias(...) + local req = {...} + return function(...) + for _, r in ipairs({...}) do + req[#req+1] = r + end + + dispatch(req) + end +end + +--- Rewrite the first x path values of the request. +-- @param n Number of path values to replace +-- @param ... Virtual path to replace removed path values with +function rewrite(n, ...) + local req = {...} + return function(...) + local dispatched = util.clone(context.dispatched) + + for i=1,n do + table.remove(dispatched, 1) + end + + for i, r in ipairs(req) do + table.insert(dispatched, i, r) + end + + for _, r in ipairs({...}) do + dispatched[#dispatched+1] = r + end + + dispatch(dispatched) + end +end + + +local function _call(self, ...) + if #self.argv > 0 then + return getfenv()[self.name](unpack(self.argv), ...) + else + return getfenv()[self.name](...) + end +end + +--- Create a function-call dispatching target. +-- @param name Target function of local controller +-- @param ... Additional parameters passed to the function +function call(name, ...) + return {type = "call", argv = {...}, name = name, target = _call} +end + + +local _template = function(self, ...) + require "luci.template".render(self.view) +end + +--- Create a template render dispatching target. +-- @param name Template to be rendered +function template(name) + return {type = "template", view = name, target = _template} +end + + +local function _cbi(self, ...) + local cbi = require "luci.cbi" + local tpl = require "luci.template" + local http = require "luci.http" + + local config = self.config or {} + local maps = cbi.load(self.model, ...) + + local state = nil + + for i, res in ipairs(maps) do + if config.autoapply then + res.autoapply = config.autoapply + end + local cstate = res:parse() + if not state or cstate < state then + state = cstate + end + end + + if config.on_valid_to and state and state > 0 and state < 2 then + http.redirect(config.on_valid_to) + return + end + + if config.on_changed_to and state and state > 1 then + http.redirect(config.on_changed_to) + return + end + + if config.on_success_to and state and state > 0 then + http.redirect(config.on_success_to) + return + end + + if config.state_handler then + if not config.state_handler(state, maps) then + return + end + end + + local pageaction = true + http.header("X-CBI-State", state or 0) + tpl.render("cbi/header", {state = state}) + for i, res in ipairs(maps) do + res:render() + if res.pageaction == false then + pageaction = false + end + end + tpl.render("cbi/footer", {pageaction=pageaction, state = state, autoapply = config.autoapply}) +end + +--- Create a CBI model dispatching target. +-- @param model CBI model to be rendered +function cbi(model, config) + return {type = "cbi", config = config, model = model, target = _cbi} +end + + +local function _arcombine(self, ...) + local argv = {...} + local target = #argv > 0 and self.targets[2] or self.targets[1] + setfenv(target.target, self.env) + target:target(unpack(argv)) +end + +--- Create a combined dispatching target for non argv and argv requests. +-- @param trg1 Overview Target +-- @param trg2 Detail Target +function arcombine(trg1, trg2) + return {type = "arcombine", env = getfenv(), target = _arcombine, targets = {trg1, trg2}} +end + + +local function _form(self, ...) + local cbi = require "luci.cbi" + local tpl = require "luci.template" + local http = require "luci.http" + + local maps = luci.cbi.load(self.model, ...) + local state = nil + + for i, res in ipairs(maps) do + local cstate = res:parse() + if not state or cstate < state then + state = cstate + end + end + + http.header("X-CBI-State", state or 0) + tpl.render("header") + for i, res in ipairs(maps) do + res:render() + end + tpl.render("footer") +end + +--- Create a CBI form model dispatching target. +-- @param model CBI form model tpo be rendered +function form(model) + return {type = "cbi", model = model, target = _form} +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/fs.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/fs.lua new file mode 100644 index 0000000..c574e3d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/fs.lua @@ -0,0 +1,270 @@ +--[[ +LuCI - Filesystem tools + +Description: +A module offering often needed filesystem manipulation functions + +FileId: +$Id: fs.lua 4104 2009-01-20 10:19:22Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local io = require "io" +local os = require "os" +local ltn12 = require "luci.ltn12" +local posix = require "posix" + +local type = type + +--- LuCI filesystem library. +module "luci.fs" + +--- Test for file access permission on given path. +-- @class function +-- @name access +-- @param str String value containing the path +-- @return Number containing the return code, 0 on sucess or nil on error +-- @return String containing the error description (if any) +-- @return Number containing the os specific errno (if any) +access = posix.access + +--- Evaluate given shell glob pattern and return a table containing all matching +-- file and directory entries. +-- @class function +-- @name glob +-- @param filename String containing the path of the file to read +-- @return Table containing file and directory entries or nil if no matches +-- @return String containing the error description (if no matches) +-- @return Number containing the os specific errno (if no matches) +glob = posix.glob + +--- Checks wheather the given path exists and points to a regular file. +-- @param filename String containing the path of the file to test +-- @return Boolean indicating wheather given path points to regular file +function isfile(filename) + return posix.stat(filename, "type") == "regular" +end + +--- Checks wheather the given path exists and points to a directory. +-- @param dirname String containing the path of the directory to test +-- @return Boolean indicating wheather given path points to directory +function isdirectory(dirname) + return posix.stat(dirname, "type") == "directory" +end + +--- Read the whole content of the given file into memory. +-- @param filename String containing the path of the file to read +-- @return String containing the file contents or nil on error +-- @return String containing the error message on error +function readfile(filename) + local fp, err = io.open(filename) + + if fp == nil then + return nil, err + end + + local data = fp:read("*a") + fp:close() + return data +end + +--- Write the contents of given string to given file. +-- @param filename String containing the path of the file to read +-- @param data String containing the data to write +-- @return Boolean containing true on success or nil on error +-- @return String containing the error message on error +function writefile(filename, data) + local fp, err = io.open(filename, "w") + + if fp == nil then + return nil, err + end + + fp:write(data) + fp:close() + + return true +end + +--- Copies a file. +-- @param source Source file +-- @param dest Destination +-- @return Boolean containing true on success or nil on error +function copy(source, dest) + return ltn12.pump.all( + ltn12.source.file(io.open(source)), + ltn12.sink.file(io.open(dest, "w")) + ) +end + +--- Renames a file. +-- @param source Source file +-- @param dest Destination +-- @return Boolean containing true on success or nil on error +function rename(source, dest) + local stat, err, code = os.rename(source, dest) + if code == 18 then + stat, err, code = copy(source, dest) + if stat then + stat, err, code = unlink(source) + end + end + return stat, err, code +end + +--- Get the last modification time of given file path in Unix epoch format. +-- @param path String containing the path of the file or directory to read +-- @return Number containing the epoch time or nil on error +-- @return String containing the error description (if any) +-- @return Number containing the os specific errno (if any) +function mtime(path) + return posix.stat(path, "mtime") +end + +--- Set the last modification time of given file path in Unix epoch format. +-- @param path String containing the path of the file or directory to read +-- @param mtime Last modification timestamp +-- @param atime Last accessed timestamp +-- @return 0 in case of success nil on error +-- @return String containing the error description (if any) +-- @return Number containing the os specific errno (if any) +utime = posix.utime + +--- Return the last element - usually the filename - from the given path with +-- the directory component stripped. +-- @class function +-- @name basename +-- @param path String containing the path to strip +-- @return String containing the base name of given path +-- @see dirname +basename = posix.basename + +--- Return the directory component of the given path with the last element +-- stripped of. +-- @class function +-- @name dirname +-- @param path String containing the path to strip +-- @return String containing the directory component of given path +-- @see basename +dirname = posix.dirname + +--- Return a table containing all entries of the specified directory. +-- @class function +-- @name dir +-- @param path String containing the path of the directory to scan +-- @return Table containing file and directory entries or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +dir = posix.dir + +--- Create a new directory, recursively on demand. +-- @param path String with the name or path of the directory to create +-- @param recursive Create multiple directory levels (optional, default is true) +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +function mkdir(path, recursive) + if recursive then + local base = "." + + if path:sub(1,1) == "/" then + base = "" + path = path:gsub("^/+","") + end + + for elem in path:gmatch("([^/]+)/*") do + base = base .. "/" .. elem + + local stat = posix.stat( base ) + + if not stat then + local stat, errmsg, errno = posix.mkdir( base ) + + if type(stat) ~= "number" or stat ~= 0 then + return stat, errmsg, errno + end + else + if stat.type ~= "directory" then + return nil, base .. ": File exists", 17 + end + end + end + + return 0 + else + return posix.mkdir( path ) + end +end + +--- Remove the given empty directory. +-- @class function +-- @name rmdir +-- @param path String containing the path of the directory to remove +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +rmdir = posix.rmdir + +--- Get information about given file or directory. +-- @class function +-- @name stat +-- @param path String containing the path of the directory to query +-- @return Table containing file or directory properties or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +stat = posix.stat + +--- Set permissions on given file or directory. +-- @class function +-- @name chmod +-- @param path String containing the path of the directory +-- @param perm String containing the permissions to set ([ugoa][+-][rwx]) +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +chmod = posix.chmod + +--- Create a hard- or symlink from given file (or directory) to specified target +-- file (or directory) path. +-- @class function +-- @name link +-- @param path1 String containing the source path to link +-- @param path2 String containing the destination path for the link +-- @param symlink Boolean indicating wheather to create a symlink (optional) +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +link = posix.link + +--- Remove the given file. +-- @class function +-- @name unlink +-- @param path String containing the path of the file to remove +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +unlink = posix.unlink + +--- Retrieve target of given symlink. +-- @class function +-- @name readlink +-- @param path String containing the path of the symlink to read +-- @return String containing the link target or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +readlink = posix.readlink diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/http.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/http.lua new file mode 100644 index 0000000..eecedcb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/http.lua @@ -0,0 +1,293 @@ +--[[ +LuCI - HTTP-Interaction + +Description: +HTTP-Header manipulator and form variable preprocessor + +FileId: +$Id: http.lua 3838 2008-11-29 21:59:06Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local ltn12 = require "luci.ltn12" +local protocol = require "luci.http.protocol" +local util = require "luci.util" +local string = require "string" +local coroutine = require "coroutine" + +local pairs, tostring, error = pairs, tostring, error + +--- LuCI Web Framework high-level HTTP functions. +module "luci.http" + +context = util.threadlocal() + +Request = util.class() +function Request.__init__(self, env, sourcein, sinkerr) + self.input = sourcein + self.error = sinkerr + + + -- File handler + self.filehandler = function() end + + -- HTTP-Message table + self.message = { + env = env, + headers = {}, + params = protocol.urldecode_params(env.QUERY_STRING or ""), + } + + self.parsed_input = false +end + +function Request.formvalue(self, name, noparse) + if not noparse and not self.parsed_input then + self:_parse_input() + end + + if name then + return self.message.params[name] + else + return self.message.params + end +end + +function Request.formvaluetable(self, prefix) + local vals = {} + prefix = prefix and prefix .. "." or "." + + if not self.parsed_input then + self:_parse_input() + end + + local void = self.message.params[nil] + for k, v in pairs(self.message.params) do + if k:find(prefix, 1, true) == 1 then + vals[k:sub(#prefix + 1)] = tostring(v) + end + end + + return vals +end + +function Request.content(self) + if not self.parsed_input then + self:_parse_input() + end + + return self.message.content, self.message.content_length +end + +function Request.getcookie(self, name) + local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";") + local p = ";" .. name .. "=(.-);" + local i, j, value = c:find(p) + return value and urldecode(value) +end + +function Request.getenv(self, name) + if name then + return self.message.env[name] + else + return self.message.env + end +end + +function Request.setfilehandler(self, callback) + self.filehandler = callback +end + +function Request._parse_input(self) + protocol.parse_message_body( + self.input, + self.message, + self.filehandler + ) + self.parsed_input = true +end + +--- Close the HTTP-Connection. +function close() + if not context.eoh then + context.eoh = true + coroutine.yield(3) + end + + if not context.closed then + context.closed = true + coroutine.yield(5) + end +end + +--- Return the request content if the request was of unknown type. +-- @return HTTP request body +-- @return HTTP request body length +function content() + return context.request:content() +end + +--- Get a certain HTTP input value or a table of all input values. +-- @param name Name of the GET or POST variable to fetch +-- @param noparse Don't parse POST data before getting the value +-- @return HTTP input value or table of all input value +function formvalue(name, noparse) + return context.request:formvalue(name, noparse) +end + +--- Get a table of all HTTP input values with a certain prefix. +-- @param prefix Prefix +-- @return Table of all HTTP input values with given prefix +function formvaluetable(prefix) + return context.request:formvaluetable(prefix) +end + +--- Get the value of a certain HTTP-Cookie. +-- @param name Cookie Name +-- @return String containing cookie data +function getcookie(name) + return context.request:getcookie(name) +end + +--- Get the value of a certain HTTP environment variable +-- or the environment table itself. +-- @param name Environment variable +-- @return HTTP environment value or environment table +function getenv(name) + return context.request:getenv(name) +end + +--- Set a handler function for incoming user file uploads. +-- @param callback Handler function +function setfilehandler(callback) + return context.request:setfilehandler(callback) +end + +--- Send a HTTP-Header. +-- @param key Header key +-- @param value Header value +function header(key, value) + if not context.headers then + context.headers = {} + end + context.headers[key:lower()] = value + coroutine.yield(2, key, value) +end + +--- Set the mime type of following content data. +-- @param mime Mimetype of following content +function prepare_content(mime) + if not context.headers or not context.headers["content-type"] then + if mime == "application/xhtml+xml" then + if not getenv("HTTP_ACCEPT") or + not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then + mime = "text/html; charset=UTF-8" + end + header("Vary", "Accept") + end + header("Content-Type", mime) + end +end + +--- Get the RAW HTTP input source +-- @return HTTP LTN12 source +function source() + return context.request.input +end + +--- Set the HTTP status code and status message. +-- @param code Status code +-- @param message Status message +function status(code, message) + code = code or 200 + message = message or "OK" + context.status = code + coroutine.yield(1, code, message) +end + +--- Send a chunk of content data to the client. +-- This function is as a valid LTN12 sink. +-- If the content chunk is nil this function will automatically invoke close. +-- @param content Content chunk +-- @param src_err Error object from source (optional) +-- @see close +function write(content, src_err) + if not content then + if src_err then + error(src_err) + else + close() + end + return true + elseif #content == 0 then + return true + else + if not context.eoh then + if not context.status then + status() + end + if not context.headers or not context.headers["content-type"] then + header("Content-Type", "text/html; charset=utf-8") + end + if not context.headers["cache-control"] then + header("Cache-Control", "no-cache") + header("Expires", "0") + end + + + context.eoh = true + coroutine.yield(3) + end + coroutine.yield(4, content) + return true + end +end + +--- Redirects the client to a new URL and closes the connection. +-- @param url Target URL +function redirect(url) + status(302, "Found") + header("Location", url) + close() +end + +--- Create a querystring out of a table of key - value pairs. +-- @param table Query string source table +-- @return Encoded HTTP query string +function build_querystring(table) + local s="?" + + for k, v in pairs(table) do + s = s .. urlencode(k) .. "=" .. urlencode(v) .. "&" + end + + return s +end + +--- Return the URL-decoded equivalent of a string. +-- @param str URL-encoded string +-- @param no_plus Don't decode + to " " +-- @return URL-decoded string +-- @see urlencode +urldecode = protocol.urldecode + +--- Return the URL-encoded equivalent of a string. +-- @param str Source string +-- @return URL-encoded string +-- @see urldecode +urlencode = protocol.urlencode diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol.lua new file mode 100644 index 0000000..ba365d2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol.lua @@ -0,0 +1,690 @@ +--[[ + +HTTP protocol implementation for LuCI +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: protocol.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +--- LuCI http protocol class. +-- This class contains several functions useful for http message- and content +-- decoding and to retrive form data from raw http messages. +module("luci.http.protocol", package.seeall) + +local ltn12 = require("luci.ltn12") + +HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size + +--- Decode an urlencoded string - optionally without decoding +-- the "+" sign to " " - and return the decoded string. +-- @param str Input string in x-www-urlencoded format +-- @param no_plus Don't decode "+" signs to spaces +-- @return The decoded string +-- @see urlencode +function urldecode( str, no_plus ) + + local function __chrdec( hex ) + return string.char( tonumber( hex, 16 ) ) + end + + if type(str) == "string" then + if not no_plus then + str = str:gsub( "+", " " ) + end + + str = str:gsub( "%%([a-fA-F0-9][a-fA-F0-9])", __chrdec ) + end + + return str +end + +--- Extract and split urlencoded data pairs, separated bei either "&" or ";" +-- from given url or string. Returns a table with urldecoded values. +-- Simple parameters are stored as string values associated with the parameter +-- name within the table. Parameters with multiple values are stored as array +-- containing the corresponding values. +-- @param url The url or string which contains x-www-urlencoded form data +-- @param tbl Use the given table for storing values (optional) +-- @return Table containing the urldecoded parameters +-- @see urlencode_params +function urldecode_params( url, tbl ) + + local params = tbl or { } + + if url:find("?") then + url = url:gsub( "^.+%?([^?]+)", "%1" ) + end + + for pair in url:gmatch( "[^&;]+" ) do + + -- find key and value + local key = urldecode( pair:match("^([^=]+)") ) + local val = urldecode( pair:match("^[^=]+=(.+)$") ) + + -- store + if type(key) == "string" and key:len() > 0 then + if type(val) ~= "string" then val = "" end + + if not params[key] then + params[key] = val + elseif type(params[key]) ~= "table" then + params[key] = { params[key], val } + else + table.insert( params[key], val ) + end + end + end + + return params +end + +--- Encode given string to x-www-urlencoded format. +-- @param str String to encode +-- @return String containing the encoded data +-- @see urldecode +function urlencode( str ) + + local function __chrenc( chr ) + return string.format( + "%%%02x", string.byte( chr ) + ) + end + + if type(str) == "string" then + str = str:gsub( + "([^a-zA-Z0-9$_%-%.%+!*'(),])", + __chrenc + ) + end + + return str +end + +--- Encode each key-value-pair in given table to x-www-urlencoded format, +-- separated by "&". Tables are encoded as parameters with multiple values by +-- repeating the parameter name with each value. +-- @param tbl Table with the values +-- @return String containing encoded values +-- @see urldecode_params +function urlencode_params( tbl ) + local enc = "" + + for k, v in pairs(tbl) do + if type(v) == "table" then + for i, v2 in ipairs(v) do + enc = enc .. ( #enc > 0 and "&" or "" ) .. + urlencode(k) .. "=" .. urlencode(v2) + end + else + enc = enc .. ( #enc > 0 and "&" or "" ) .. + urlencode(k) .. "=" .. urlencode(v) + end + end + + return enc +end + +-- (Internal function) +-- Initialize given parameter and coerce string into table when the parameter +-- already exists. +-- @param tbl Table where parameter should be created +-- @param key Parameter name +-- @return Always nil +local function __initval( tbl, key ) + if tbl[key] == nil then + tbl[key] = "" + elseif type(tbl[key]) == "string" then + tbl[key] = { tbl[key], "" } + else + table.insert( tbl[key], "" ) + end +end + +-- (Internal function) +-- Append given data to given parameter, either by extending the string value +-- or by appending it to the last string in the parameter's value table. +-- @param tbl Table containing the previously initialized parameter value +-- @param key Parameter name +-- @param chunk String containing the data to append +-- @return Always nil +-- @see __initval +local function __appendval( tbl, key, chunk ) + if type(tbl[key]) == "table" then + tbl[key][#tbl[key]] = tbl[key][#tbl[key]] .. chunk + else + tbl[key] = tbl[key] .. chunk + end +end + +-- (Internal function) +-- Finish the value of given parameter, either by transforming the string value +-- or - in the case of multi value parameters - the last element in the +-- associated values table. +-- @param tbl Table containing the previously initialized parameter value +-- @param key Parameter name +-- @param handler Function which transforms the parameter value +-- @return Always nil +-- @see __initval +-- @see __appendval +local function __finishval( tbl, key, handler ) + if handler then + if type(tbl[key]) == "table" then + tbl[key][#tbl[key]] = handler( tbl[key][#tbl[key]] ) + else + tbl[key] = handler( tbl[key] ) + end + end +end + + +-- Table of our process states +local process_states = { } + +-- Extract "magic", the first line of a http message. +-- Extracts the message type ("get", "post" or "response"), the requested uri +-- or the status code if the line descripes a http response. +process_states['magic'] = function( msg, chunk, err ) + + if chunk ~= nil then + -- ignore empty lines before request + if #chunk == 0 then + return true, nil + end + + -- Is it a request? + local method, uri, http_ver = chunk:match("^([A-Z]+) ([^ ]+) HTTP/([01]%.[019])$") + + -- Yup, it is + if method then + + msg.type = "request" + msg.request_method = method:lower() + msg.request_uri = uri + msg.http_version = tonumber( http_ver ) + msg.headers = { } + + -- We're done, next state is header parsing + return true, function( chunk ) + return process_states['headers']( msg, chunk ) + end + + -- Is it a response? + else + + local http_ver, code, message = chunk:match("^HTTP/([01]%.[019]) ([0-9]+) ([^\r\n]+)$") + + -- Is a response + if code then + + msg.type = "response" + msg.status_code = code + msg.status_message = message + msg.http_version = tonumber( http_ver ) + msg.headers = { } + + -- We're done, next state is header parsing + return true, function( chunk ) + return process_states['headers']( msg, chunk ) + end + end + end + end + + -- Can't handle it + return nil, "Invalid HTTP message magic" +end + + +-- Extract headers from given string. +process_states['headers'] = function( msg, chunk ) + + if chunk ~= nil then + + -- Look for a valid header format + local hdr, val = chunk:match( "^([A-Za-z][A-Za-z0-9%-_]+): +(.+)$" ) + + if type(hdr) == "string" and hdr:len() > 0 and + type(val) == "string" and val:len() > 0 + then + msg.headers[hdr] = val + + -- Valid header line, proceed + return true, nil + + elseif #chunk == 0 then + -- Empty line, we won't accept data anymore + return false, nil + else + -- Junk data + return nil, "Invalid HTTP header received" + end + else + return nil, "Unexpected EOF" + end +end + + +--- Creates a ltn12 source from the given socket. The source will return it's +-- data line by line with the trailing \r\n stripped of. +-- @param sock Readable network socket +-- @return Ltn12 source function +function header_source( sock ) + return ltn12.source.simplify( function() + + local chunk, err, part = sock:receive("*l") + + -- Line too long + if chunk == nil then + if err ~= "timeout" then + return nil, part + and "Line exceeds maximum allowed length" + or "Unexpected EOF" + else + return nil, err + end + + -- Line ok + elseif chunk ~= nil then + + -- Strip trailing CR + chunk = chunk:gsub("\r$","") + + return chunk, nil + end + end ) +end + +--- Decode a mime encoded http message body with multipart/form-data +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table withing the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +-- If an optional file callback function is given then it is feeded with the +-- file contents chunk by chunk and only the extracted file name is stored +-- within the params table. The callback function will be called subsequently +-- with three arguments: +-- o Table containing decoded (name, file) and raw (headers) mime header data +-- o String value containing a chunk of the file data +-- o Boolean which indicates wheather the current chunk is the last one (eof) +-- @param src Ltn12 source function +-- @param msg HTTP message object +-- @param filecb File callback function (optional) +-- @return Value indicating successful operation (not nil means "ok") +-- @return String containing the error if unsuccessful +-- @see parse_message_header +function mimedecode_message_body( src, msg, filecb ) + + if msg and msg.env.CONTENT_TYPE then + msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$") + end + + if not msg.mime_boundary then + return nil, "Invalid Content-Type found" + end + + + local tlen = 0 + local inhdr = false + local field = nil + local store = nil + local lchunk = nil + + local function parse_headers( chunk, field ) + + local stat + repeat + chunk, stat = chunk:gsub( + "^([A-Z][A-Za-z0-9%-_]+): +([^\r\n]+)\r\n", + function(k,v) + field.headers[k] = v + return "" + end + ) + until stat == 0 + + chunk, stat = chunk:gsub("^\r\n","") + + -- End of headers + if stat > 0 then + if field.headers["Content-Disposition"] then + if field.headers["Content-Disposition"]:match("^form%-data; ") then + field.name = field.headers["Content-Disposition"]:match('name="(.-)"') + field.file = field.headers["Content-Disposition"]:match('filename="(.+)"$') + end + end + + if not field.headers["Content-Type"] then + field.headers["Content-Type"] = "text/plain" + end + + if field.name and field.file and filecb then + __initval( msg.params, field.name ) + __appendval( msg.params, field.name, field.file ) + + store = filecb + elseif field.name then + __initval( msg.params, field.name ) + + store = function( hdr, buf, eof ) + __appendval( msg.params, field.name, buf ) + end + else + store = nil + end + + return chunk, true + end + + return chunk, false + end + + local function snk( chunk ) + + tlen = tlen + ( chunk and #chunk or 0 ) + + if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then + return nil, "Message body size exceeds Content-Length" + end + + if chunk and not lchunk then + lchunk = "\r\n" .. chunk + + elseif lchunk then + local data = lchunk .. ( chunk or "" ) + local spos, epos, found + + repeat + spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "\r\n", 1, true ) + + if not spos then + spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true ) + end + + + if spos then + local predata = data:sub( 1, spos - 1 ) + + if inhdr then + predata, eof = parse_headers( predata, field ) + + if not eof then + return nil, "Invalid MIME section header" + elseif not field.name then + return nil, "Invalid Content-Disposition header" + end + end + + if store then + store( field, predata, true ) + end + + + field = { headers = { } } + found = found or true + + data, eof = parse_headers( data:sub( epos + 1, #data ), field ) + inhdr = not eof + end + until not spos + + if found then + if #data > 78 then + lchunk = data:sub( #data - 78 + 1, #data ) + data = data:sub( 1, #data - 78 ) + + if store then + store( field, data, false ) + else + return nil, "Invalid MIME section header" + end + else + lchunk, data = data, nil + end + else + if inhdr then + lchunk, eof = parse_headers( data, field ) + inhdr = not eof + else + store( field, lchunk, false ) + lchunk, chunk = chunk, nil + end + end + end + + return true + end + + return ltn12.pump.all( src, snk ) +end + +--- Decode an urlencoded http message body with application/x-www-urlencoded +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table withing the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +-- @param src Ltn12 source function +-- @param msg HTTP message object +-- @return Value indicating successful operation (not nil means "ok") +-- @return String containing the error if unsuccessful +-- @see parse_message_header +function urldecode_message_body( src, msg ) + + local tlen = 0 + local lchunk = nil + + local function snk( chunk ) + + tlen = tlen + ( chunk and #chunk or 0 ) + + if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then + return nil, "Message body size exceeds Content-Length" + elseif tlen > HTTP_MAX_CONTENT then + return nil, "Message body size exceeds maximum allowed length" + end + + if not lchunk and chunk then + lchunk = chunk + + elseif lchunk then + local data = lchunk .. ( chunk or "&" ) + local spos, epos + + repeat + spos, epos = data:find("^.-[;&]") + + if spos then + local pair = data:sub( spos, epos - 1 ) + local key = pair:match("^(.-)=") + local val = pair:match("=([^%s]*)%s*$") + + if key and #key > 0 then + __initval( msg.params, key ) + __appendval( msg.params, key, val ) + __finishval( msg.params, key, urldecode ) + end + + data = data:sub( epos + 1, #data ) + end + until not spos + + lchunk = data + end + + return true + end + + return ltn12.pump.all( src, snk ) +end + +--- Try to extract an http message header including information like protocol +-- version, message headers and resulting CGI environment variables from the +-- given ltn12 source. +-- @param src Ltn12 source function +-- @return HTTP message object +-- @see parse_message_body +function parse_message_header( src ) + + local ok = true + local msg = { } + + local sink = ltn12.sink.simplify( + function( chunk ) + return process_states['magic']( msg, chunk ) + end + ) + + -- Pump input data... + while ok do + + -- get data + ok, err = ltn12.pump.step( src, sink ) + + -- error + if not ok and err then + return nil, err + + -- eof + elseif not ok then + + -- Process get parameters + if ( msg.request_method == "get" or msg.request_method == "post" ) and + msg.request_uri:match("?") + then + msg.params = urldecode_params( msg.request_uri ) + else + msg.params = { } + end + + -- Populate common environment variables + msg.env = { + CONTENT_LENGTH = msg.headers['Content-Length']; + CONTENT_TYPE = msg.headers['Content-Type'] or msg.headers['Content-type']; + REQUEST_METHOD = msg.request_method:upper(); + REQUEST_URI = msg.request_uri; + SCRIPT_NAME = msg.request_uri:gsub("?.+$",""); + SCRIPT_FILENAME = ""; -- XXX implement me + SERVER_PROTOCOL = "HTTP/" .. string.format("%.1f", msg.http_version); + QUERY_STRING = msg.request_uri:match("?") + and msg.request_uri:gsub("^.+?","") or "" + } + + -- Populate HTTP_* environment variables + for i, hdr in ipairs( { + 'Accept', + 'Accept-Charset', + 'Accept-Encoding', + 'Accept-Language', + 'Connection', + 'Cookie', + 'Host', + 'Referer', + 'User-Agent', + } ) do + local var = 'HTTP_' .. hdr:upper():gsub("%-","_") + local val = msg.headers[hdr] + + msg.env[var] = val + end + end + end + + return msg +end + +--- Try to extract and decode a http message body from the given ltn12 source. +-- This function will examine the Content-Type within the given message object +-- to select the appropriate content decoder. +-- Currently the application/x-www-urlencoded and application/form-data +-- mime types are supported. If the encountered content encoding can't be +-- handled then the whole message body will be stored unaltered as "content" +-- property within the given message object. +-- @param src Ltn12 source function +-- @param msg HTTP message object +-- @param filecb File data callback (optional, see mimedecode_message_body()) +-- @return Value indicating successful operation (not nil means "ok") +-- @return String containing the error if unsuccessful +-- @see parse_message_header +function parse_message_body( src, msg, filecb ) + -- Is it multipart/mime ? + if msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and + msg.env.CONTENT_TYPE:match("^multipart/form%-data") + then + + return mimedecode_message_body( src, msg, filecb ) + + -- Is it application/x-www-form-urlencoded ? + elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and + msg.env.CONTENT_TYPE:match("^application/x%-www%-form%-urlencoded") + then + return urldecode_message_body( src, msg, filecb ) + + + -- Unhandled encoding + -- If a file callback is given then feed it chunk by chunk, else + -- store whole buffer in message.content + else + + local sink + + -- If we have a file callback then feed it + if type(filecb) == "function" then + sink = filecb + + -- ... else append to .content + else + msg.content = "" + msg.content_length = 0 + + sink = function( chunk, err ) + if chunk then + if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then + msg.content = msg.content .. chunk + msg.content_length = msg.content_length + #chunk + return true + else + return nil, "POST data exceeds maximum allowed length" + end + end + return true + end + end + + -- Pump data... + while true do + local ok, err = ltn12.pump.step( src, sink ) + + if not ok and err then + return nil, err + elseif not err then + return true + end + end + + return true + end +end + +--- Table containing human readable messages for several http status codes. +-- @class table +statusmsg = { + [200] = "OK", + [206] = "Partial Content", + [301] = "Moved Permanently", + [302] = "Found", + [304] = "Not Modified", + [400] = "Bad Request", + [403] = "Forbidden", + [404] = "Not Found", + [405] = "Method Not Allowed", + [408] = "Request Time-out", + [411] = "Length Required", + [412] = "Precondition Failed", + [416] = "Requested range not satisfiable", + [500] = "Internal Server Error", + [503] = "Server Unavailable", +} diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/conditionals.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/conditionals.lua new file mode 100644 index 0000000..24d6d16 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/conditionals.lua @@ -0,0 +1,154 @@ +--[[ + +HTTP protocol implementation for LuCI - RFC2616 / 14.19, 14.24 - 14.28 +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: conditionals.lua 3652 2008-10-29 19:41:33Z jow $ + +]]-- + +--- LuCI http protocol implementation - HTTP/1.1 bits. +-- This class provides basic ETag handling and implements most of the +-- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . +module("luci.http.protocol.conditionals", package.seeall) + +local date = require("luci.http.protocol.date") + + +--- Implement 14.19 / ETag. +-- @param stat A file.stat structure +-- @return String containing the generated tag suitable for ETag headers +function mk_etag( stat ) + if stat ~= nil then + return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime ) + end +end + +--- 14.24 / If-Match +-- Test whether the given message object contains an "If-Match" header and +-- compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +function if_match( req, stat ) + local h = req.headers + local etag = mk_etag( stat ) + + -- Check for matching resource + if type(h['If-Match']) == "string" then + for ent in h['If-Match']:gmatch("([^, ]+)") do + if ( ent == '*' or ent == etag ) and stat ~= nil then + return true + end + end + + return false, 412 + end + + return true +end + +--- 14.25 / If-Modified-Since +-- Test whether the given message object contains an "If-Modified-Since" header +-- and compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +-- @return Table containing extra HTTP headers if the precondition failed +function if_modified_since( req, stat ) + local h = req.headers + + -- Compare mtimes + if type(h['If-Modified-Since']) == "string" then + local since = date.to_unix( h['If-Modified-Since'] ) + + if stat == nil or since < stat.mtime then + return true + end + + return false, 304, { + ["ETag"] = mk_etag( stat ); + ["Date"] = date.to_http( os.time() ); + ["Last-Modified"] = date.to_http( stat.mtime ) + } + end + + return true +end + +--- 14.26 / If-None-Match +-- Test whether the given message object contains an "If-None-Match" header and +-- compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +-- @return Table containing extra HTTP headers if the precondition failed +function if_none_match( req, stat ) + local h = req.headers + local etag = mk_etag( stat ) + + -- Check for matching resource + if type(h['If-None-Match']) == "string" then + for ent in h['If-None-Match']:gmatch("([^, ]+)") do + if ( ent == '*' or ent == etag ) and stat ~= nil then + if req.request_method == "get" or + req.request_method == "head" + then + return false, 304, { + ["ETag"] = mk_etag( stat ); + ["Date"] = date.to_http( os.time() ); + ["Last-Modified"] = date.to_http( stat.mtime ) + } + else + return false, 412 + end + end + end + end + + return true +end + +--- 14.27 / If-Range +-- The If-Range header is currently not implemented due to the lack of general +-- byte range stuff in luci.http.protocol . This function will always return +-- false, 412 to indicate a failed precondition. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +function if_range( req, stat ) + -- Sorry, no subranges (yet) + return false, 412 +end + +--- 14.28 / If-Unmodified-Since +-- Test whether the given message object contains an "If-Unmodified-Since" +-- header and compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +function if_unmodified_since( req, stat ) + local h = req.headers + + -- Compare mtimes + if type(h['If-Unmodified-Since']) == "string" then + local since = date.to_unix( h['If-Unmodified-Since'] ) + + if stat ~= nil and since <= stat.mtime then + return false, 412 + end + end + + return true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/date.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/date.lua new file mode 100644 index 0000000..11a2475 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/date.lua @@ -0,0 +1,115 @@ +--[[ + +HTTP protocol implementation for LuCI - date handling +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: date.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +--- LuCI http protocol implementation - date helper class. +-- This class contains functions to parse, compare and format http dates. +module("luci.http.protocol.date", package.seeall) + +require("luci.sys.zoneinfo") + + +MONTHS = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" +} + +--- Return the time offset in seconds between the UTC and given time zone. +-- @param tz Symbolic or numeric timezone specifier +-- @return Time offset to UTC in seconds +function tz_offset(tz) + + if type(tz) == "string" then + + -- check for a numeric identifier + local s, v = tz:match("([%+%-])([0-9]+)") + if s == '+' then s = 1 else s = -1 end + if v then v = tonumber(v) end + + if s and v then + return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) ) + + -- lookup symbolic tz + elseif luci.sys.zoneinfo.OFFSET[tz:lower()] then + return luci.sys.zoneinfo.OFFSET[tz:lower()] + end + + end + + -- bad luck + return 0 +end + +--- Parse given HTTP date string and convert it to unix epoch time. +-- @param data String containing the date +-- @return Unix epoch time +function to_unix(date) + + local wd, day, mon, yr, hr, min, sec, tz = date:match( + "([A-Z][a-z][a-z]), ([0-9]+) " .. + "([A-Z][a-z][a-z]) ([0-9]+) " .. + "([0-9]+):([0-9]+):([0-9]+) " .. + "([A-Z0-9%+%-]+)" + ) + + if day and mon and yr and hr and min and sec then + -- find month + local month = 1 + for i = 1, 12 do + if MONTHS[i] == mon then + month = i + break + end + end + + -- convert to epoch time + return tz_offset(tz) + os.time( { + year = yr, + month = month, + day = day, + hour = hr, + min = min, + sec = sec + } ) + end + + return 0 +end + +--- Convert the given unix epoch time to valid HTTP date string. +-- @param time Unix epoch time +-- @return String containing the formatted date +function to_http(time) + return os.date( "%a, %d %b %Y %H:%M:%S GMT", time ) +end + +--- Compare two dates which can either be unix epoch times or HTTP date strings. +-- @param d1 The first date or epoch time to compare +-- @param d2 The first date or epoch time to compare +-- @return -1 - if d1 is lower then d2 +-- @return 0 - if both dates are equal +-- @return 1 - if d1 is higher then d2 +function compare(d1, d2) + + if d1:match("[^0-9]") then d1 = to_unix(d1) end + if d2:match("[^0-9]") then d2 = to_unix(d2) end + + if d1 == d2 then + return 0 + elseif d1 < d2 then + return -1 + else + return 1 + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/mime.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/mime.lua new file mode 100644 index 0000000..49f02b8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/http/protocol/mime.lua @@ -0,0 +1,98 @@ +--[[ + +HTTP protocol implementation for LuCI - mime handling +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: mime.lua 2641 2008-07-22 01:15:39Z jow $ + +]]-- + +--- LuCI http protocol implementation - mime helper class. +-- This class provides functions to guess mime types from file extensions and +-- vice versa. +module("luci.http.protocol.mime", package.seeall) + +require("luci.util") + +--- MIME mapping table containg extension - mimetype relations. +-- @class table +MIME_TYPES = { + ["txt"] = "text/plain"; + ["js"] = "text/javascript"; + ["css"] = "text/css"; + ["htm"] = "text/html"; + ["html"] = "text/html"; + ["patch"] = "text/x-patch"; + ["c"] = "text/x-csrc"; + ["h"] = "text/x-chdr"; + ["o"] = "text/x-object"; + ["ko"] = "text/x-object"; + + ["bmp"] = "image/bmp"; + ["gif"] = "image/gif"; + ["png"] = "image/png"; + ["jpg"] = "image/jpeg"; + ["jpeg"] = "image/jpeg"; + ["svg"] = "image/svg+xml"; + + ["zip"] = "application/zip"; + ["pdf"] = "application/pdf"; + ["xml"] = "application/xml"; + ["doc"] = "application/msword"; + ["ppt"] = "application/vnd.ms-powerpoint"; + ["xls"] = "application/vnd.ms-excel"; + ["odt"] = "application/vnd.oasis.opendocument.text"; + ["odp"] = "application/vnd.oasis.opendocument.presentation"; + ["pl"] = "application/x-perl"; + ["sh"] = "application/x-shellscript"; + ["php"] = "application/x-php"; + ["deb"] = "application/x-deb"; + ["iso"] = "application/x-cd-image"; + ["tgz"] = "application/x-compressed-tar"; + + ["mp3"] = "audio/mpeg"; + ["ogg"] = "audio/x-vorbis+ogg"; + ["wav"] = "audio/x-wav"; + + ["mpg"] = "video/mpeg"; + ["mpeg"] = "video/mpeg"; + ["avi"] = "video/x-msvideo"; +} + +--- Extract extension from a filename and return corresponding mime-type or +-- "application/octet-stream" if the extension is unknown. +-- @param filename The filename for which the mime type is guessed +-- @return String containign the determined mime type +function to_mime(filename) + if type(filename) == "string" then + local ext = filename:match("[^%.]+$") + + if ext and MIME_TYPES[ext:lower()] then + return MIME_TYPES[ext:lower()] + end + end + + return "application/octet-stream" +end + +--- Return corresponding extension for a given mime type or nil if the +-- given mime-type is unknown. +-- @param mimetype The mimetype to retrieve the extension from +-- @return String with the extension or nil for unknown type +function to_ext(mimetype) + if type(mimetype) == "string" then + for ext, type in luci.util.kspairs( MIME_TYPES ) do + if type == mimetype then + return ext + end + end + end + + return nil +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/httpd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd.lua new file mode 100644 index 0000000..609ae68 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd.lua @@ -0,0 +1,126 @@ +--[[ + +HTTP server implementation for LuCI - core +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich +(c) 2008 Steven Barth + +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: httpd.lua 2974 2008-08-27 17:45:58Z Cyrus $ + +]]-- + +module("luci.httpd", package.seeall) +require("socket") + +THREAD_IDLEWAIT = 0.01 +THREAD_TIMEOUT = 90 +THREAD_LIMIT = nil + +local reading = {} +local clhandler = {} +local erhandler = {} + +local threadc = 0 +local threads = {} +local threadm = {} +local threadi = {} + +local _meta = {__mode = "k"} +setmetatable(threadm, _meta) +setmetatable(threadi, _meta) + + +function Socket(ip, port) + local sock, err = socket.bind( ip, port ) + + if sock then + sock:settimeout( 0, "t" ) + end + + return sock, err +end + +function corecv(socket, ...) + threadi[socket] = true + + while true do + local chunk, err, part = socket:receive(...) + + if err ~= "timeout" then + threadi[socket] = false + return chunk, err, part + end + + coroutine.yield() + end +end + +function cosend(socket, chunk, i, ...) + threadi[socket] = true + i = i or 1 + + while true do + local stat, err, sent = socket:send(chunk, i, ...) + + if err ~= "timeout" then + threadi[socket] = false + return stat, err, sent + else + i = sent and (sent + 1) or i + end + + coroutine.yield() + end +end + +function register(socket, s_clhandler, s_errhandler) + table.insert(reading, socket) + clhandler[socket] = s_clhandler + erhandler[socket] = s_errhandler +end + +function run() + while true do + step() + end +end + +function step() + local idle = true + if not THREAD_LIMIT or threadc < THREAD_LIMIT then + local now = os.time() + for i, server in ipairs(reading) do + local client = server:accept() + if client then + threadm[client] = now + threadc = threadc + 1 + threads[client] = coroutine.create(clhandler[server]) + end + end + end + + for client, thread in pairs(threads) do + coroutine.resume(thread, client) + local now = os.time() + if coroutine.status(thread) == "dead" then + threadc = threadc - 1 + threads[client] = nil + elseif threadm[client] and threadm[client] + THREAD_TIMEOUT < now then + threads[client] = nil + threadc = threadc - 1 + client:close() + elseif not threadi[client] then + threadm[client] = now + idle = false + end + end + + if idle then + socket.sleep(THREAD_IDLEWAIT) + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/file.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/file.lua new file mode 100644 index 0000000..50e9a58 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/file.lua @@ -0,0 +1,199 @@ +--[[ + +HTTP server implementation for LuCI - file handler +(c) 2008 Steven Barth +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: file.lua 2510 2008-07-05 20:12:24Z jow $ + +]]-- + +module("luci.httpd.handler.file", package.seeall) + +require("luci.httpd.module") +require("luci.http.protocol.date") +require("luci.http.protocol.mime") +require("luci.http.protocol.conditionals") +require("luci.fs") +local ltn12 = require("luci.ltn12") + +Simple = luci.util.class(luci.httpd.module.Handler) +Response = luci.httpd.module.Response + +function Simple.__init__(self, docroot, dirlist) + luci.httpd.module.Handler.__init__(self) + self.docroot = docroot + self.dirlist = dirlist and true or false + self.proto = luci.http.protocol + self.mime = luci.http.protocol.mime + self.date = luci.http.protocol.date + self.cond = luci.http.protocol.conditionals +end + +function Simple.getfile(self, uri) + local file = self.docroot .. uri:gsub("%.%./+", "") + local stat = luci.fs.stat(file) + + return file, stat +end + +function Simple.handle_get(self, request, sourcein, sinkerr) + local file, stat = self:getfile( self.proto.urldecode( request.env.PATH_INFO, true ) ) + + if stat then + if stat.type == "regular" then + + -- Generate Entity Tag + local etag = self.cond.mk_etag( stat ) + + -- Check conditionals + local ok, code, hdrs + + ok, code, hdrs = self.cond.if_modified_since( request, stat ) + if ok then + ok, code, hdrs = self.cond.if_match( request, stat ) + if ok then + ok, code, hdrs = self.cond.if_unmodified_since( request, stat ) + if ok then + ok, code, hdrs = self.cond.if_none_match( request, stat ) + if ok then + local f, err = io.open(file) + + if f then + -- Send Response + return Response( + 200, { + ["Date"] = self.date.to_http( os.time() ); + ["Last-Modified"] = self.date.to_http( stat.mtime ); + ["Content-Type"] = self.mime.to_mime( file ); + ["Content-Length"] = stat.size; + ["ETag"] = etag; + } + ), ltn12.source.file(f) + else + return self:failure( 403, err:gsub("^.+: ", "") ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + + elseif stat.type == "directory" then + + local ruri = request.request_uri:gsub("/$","") + local duri = self.proto.urldecode( ruri, true ) + local root = self.docroot:gsub("/$","") + + -- check for index files + local index_candidates = { + "index.html", "index.htm", "default.html", "default.htm", + "index.txt", "default.txt" + } + + -- try to find an index file and redirect to it + for i, candidate in ipairs( index_candidates ) do + local istat = luci.fs.stat( + root .. "/" .. duri .. "/" .. candidate + ) + + if istat ~= nil and istat.type == "regular" then + return Response( 301, { + ["Location"] = ruri .. "/" .. candidate + } ), ltn12.source.empty() + end + end + + + local html = string.format( + '\n' .. + '\n' .. + '\n' .. + '\n' .. + 'Index of %s/\n' .. + '

Index of %s/


    ', + duri, duri + ) + + local entries = luci.fs.dir( file ) + + if type(entries) == "table" then + for i, e in luci.util.spairs( + entries, function(a,b) + if entries[a] == '..' then + return true + elseif entries[b] == '..' then + return false + else + return ( entries[a] < entries[b] ) + end + end + ) do + if e ~= '.' and ( e == '..' or e:sub(1,1) ~= '.' ) then + local estat = luci.fs.stat( file .. "/" .. e ) + + if estat.type == "directory" then + html = html .. string.format( + '
  • %s/ ' .. + '(directory)
    ' .. + 'Changed: %s

  • ', + ruri, self.proto.urlencode( e ), e, + self.date.to_http( estat.mtime ) + ) + else + html = html .. string.format( + '
  • %s ' .. + '(%s)
    ' .. + 'Size: %i Bytes | ' .. + 'Changed: %s

  • ', + ruri, self.proto.urlencode( e ), e, + self.mime.to_mime( e ), + estat.size, self.date.to_http( estat.mtime ) + ) + end + end + end + + html = html .. '

' + + return Response( + 200, { + ["Date"] = self.date.to_http( os.time() ); + ["Content-Type"] = "text/html; charset=ISO-8859-15"; + } + ), ltn12.source.string(html) + else + return self:failure(403, "Permission denied") + end + else + return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file) + end + else + return self:failure(404, "No such file: " .. file) + end +end + +function Simple.handle_head(self, ...) + local response, sourceout = self:handle_get(...) + return response +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/luci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/luci.lua new file mode 100644 index 0000000..e662d3f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/handler/luci.lua @@ -0,0 +1,96 @@ +--[[ + +HTTP server implementation for LuCI - luci handler +(c) 2008 Steven Barth + +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: luci.lua 3680 2008-11-01 10:53:51Z Cyrus $ + +]]-- + +module("luci.httpd.handler.luci", package.seeall) + +require("luci.dispatcher") +require("luci.http") +require("luci.http.protocol.date") +local ltn12 = require("luci.ltn12") + +Luci = luci.util.class(luci.httpd.module.Handler) +Response = luci.httpd.module.Response + +function Luci.__init__(self, limit) + luci.httpd.module.Handler.__init__(self) + self.limit = limit or 5 + self.running = {} + setmetatable(self.running, {__mode = "k"}) +end + +function Luci.handle_head(self, ...) + local response, sourceout = self:handle_get(...) + return response +end + +function Luci.handle_post(self, ...) + return self:handle_get(...) +end + +function Luci.handle_get(self, request, sourcein, sinkerr) + local r = luci.http.Request( + request.env, + sourcein, + sinkerr + ) + + local res, id, data1, data2 = true, 0, nil, nil + local headers = {} + local status = 200 + local active = true + + local x = coroutine.create(luci.dispatcher.httpdispatch) + while not id or id < 3 do + coroutine.yield() + + res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + status = 500 + headers["Content-Type"] = "text/plain" + local err = {id} + return Response( status, headers ), function() return table.remove(err) end + end + + if id == 1 then + status = data1 + elseif id == 2 then + headers[data1] = data2 + end + end + + local function iter() + local res, id, data = coroutine.resume(x) + if not res then + return nil, id + elseif not id or not active then + return true + elseif id == 5 then + active = false + + while (coroutine.resume(x)) do + end + + return nil + elseif id == 4 then + return data + end + if coroutine.status(x) == "dead" then + return nil + end + end + + return Response(status, headers), iter +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/module.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/module.lua new file mode 100644 index 0000000..7f4580a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/module.lua @@ -0,0 +1,136 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: module.lua 2476 2008-06-29 16:15:26Z Cyrus $ +]]-- +module("luci.httpd.module", package.seeall) +require("luci.util") +require("luci.http.protocol") +local ltn12 = require("luci.ltn12") + + + +-- Server handler implementation +Handler = luci.util.class() + +-- Constructor +function Handler.__init__(self) + self.filters = {} + self.handler = {} +end + + +-- Adds a filter to the filter chain +function Handler.addfilter(self, filter) + table.insert(self.filters, filter) +end + + +-- Creates a failure reply +function Handler.failure(self, code, message) + local response = Response(code, { ["Content-Type"] = "text/plain" }) + local sourceout = ltn12.source.string(message) + + return response, sourceout +end + +-- Processes a request +function Handler.process(self, request, sourcein, sinkerr, ...) + local stat, response, sourceout + + -- Process incoming filters + for i, f in ipairs(self.filters) do + local i = f:get("input") + + if i then + sourcein = ltn12.source.chain(sourcein, i) + end + + if f.request then + f:request(request) + end + end + + -- Detect request Method + local hname = "handle_" .. request.request_method + if self[hname] then + -- Run the handler + stat, response, sourceout = luci.util.copcall( + self[hname], self, request, sourcein, sinkerr, ... + ) + + -- Check for any errors + if not stat then + response, sourceout = self:failure(500, response) + end + else + response, sourceout = self:failure(405, luci.http.protocol.statusmsg[405]) + end + + -- Check data + if not luci.util.instanceof(response, Response) then + response, sourceout = self:failure(500, "Core error: Invalid module response!") + end + + -- Process outgoing filters + for i, f in ipairs(self.filters) do + local o = f:get("output") + + if o then + sourceout = ltn12.source.chain(sourceout, o) + end + + if f.response then + f:response(response) + end + end + + return response, sourceout +end + + + +-- Server Filter implementation +Filter = luci.util.class() + +function Filter.get(self, name) + return self[name] and function(...) return self[name](self, ...) end +end + +-- Filters the incoming body stream +-- abstract function Filter.input(chunk) + +-- Filters the outgoing body stream +-- abstract function Filter.output(chunk) + +-- Filters the request object +-- abstract function Filter.request(request) + +-- Filters the response object +-- abstract function Filter.response(response) + + + +-- Handler Response +Response = luci.util.class() + +function Response.__init__(self, status, headers) + self.status = tonumber(status) or 200 + self.headers = (type(headers) == "table") and headers or {} +end + +function Response.addheader(self, key, value) + self.headers[key] = value +end + +function Response.setstatus(self, status) + self.status = status +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/server.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/server.lua new file mode 100644 index 0000000..efd5374 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/httpd/server.lua @@ -0,0 +1,241 @@ +--[[ + +HTTP server implementation for LuCI - helper class +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich +(c) 2008 Steven Barth + +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: server.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +module("luci.httpd.server", package.seeall) +require("socket") +require("socket.http") +require("luci.util") + +READ_BUFSIZE = 1024 +VERSION = 0.2 + + +VHost = luci.util.class() + +function VHost.__init__(self, handler) + self.handler = handler + self.dhandler = {} +end + +function VHost.process(self, request, sourcein, sinkerr, ...) + local handler = self.handler + + local uri = request.env.REQUEST_URI:match("^([^?]*)") + + -- SCRIPT_NAME + request.env.SCRIPT_NAME = "" + + -- Call URI part + request.env.PATH_INFO = uri + + for k, dhandler in pairs(self.dhandler) do + if k == uri or k.."/" == uri:sub(1, #k+1) then + handler = dhandler + request.env.SCRIPT_NAME = k + request.env.PATH_INFO = uri:sub(#k+1) + break; + end + end + + if handler then + return handler:process(request, sourcein, sinkerr, ...) + end +end + + +function VHost.set_default_handler(self, handler) + self.handler = handler +end + + +function VHost.set_handler(self, match, handler) + self.dhandler[match] = handler +end + + + +Server = luci.util.class() + +function Server.__init__(self, host) + self.host = host + self.vhosts = {} +end + +function Server.set_default_vhost(self, vhost) + self.host = vhost +end + +-- Sets a vhost +function Server.set_vhost(self, name, vhost) + self.vhosts[name] = vhost +end + +function Server.create_daemon_handlers(self) + return function(...) return self:process(...) end, + function(...) return self:error_overload(...) end +end + + +function Server.error(self, socket, code, msg) + hcode = tostring(code) + + socket:send( "HTTP/1.0 " .. hcode .. " " .. + luci.http.protocol.statusmsg[code] .. "\r\n" ) + socket:send( "Connection: close\r\n" ) + socket:send( "Content-Type: text/plain\r\n\r\n" ) + + if msg then + socket:send( "HTTP-Error " .. code .. ": " .. msg .. "\r\n" ) + end +end + +function Server.error_overload(self, socket) + self:error(socket, 503, "Too many simultaneous connections") +end + + +function Server.process( self, client ) + + -- Setup sockets and sources + local thread = { + receive = function(self, ...) return luci.httpd.corecv(client, ...) end, + send = function(self, ...) return luci.httpd.cosend(client, ...) end, + close = function(self, ...) return client:close(...) end, + getfd = function(self, ...) return client:getfd(...) end, + dirty = function(self, ...) return client:dirty(...) end + } + + client:settimeout( 0 ) + + local sourcein = ltn12.source.empty() + local sourcehdr = luci.http.protocol.header_source( thread ) + local sinkerr = ltn12.sink.file( io.stderr ) + + local close = false + + local reading = { client } + + local message, err + + repeat + -- parse headers + message, err = luci.http.protocol.parse_message_header( sourcehdr ) + + if not message then + self:error( thread, 400, err ) + break + end + + -- keep-alive + if message.http_version == 1.1 then + close = (message.env.HTTP_CONNECTION == "close") + else + close = not message.env.HTTP_CONNECTION or message.env.HTTP_CONNECTION == "close" + end + + if message.request_method == "get" or message.request_method == "head" then + -- Be happy + + elseif message.request_method == "post" then + -- If we have a HTTP/1.1 client and an Expect: 100-continue header then + -- respond with HTTP 100 Continue message + if message.http_version == 1.1 and message.headers['Expect'] and + message.headers['Expect'] == '100-continue' + then + thread:send("HTTP/1.1 100 Continue\r\n\r\n") + end + + if message.headers['Transfer-Encoding'] and + message.headers['Transfer-Encoding'] ~= "identity" then + sourcein = socket.source("http-chunked", thread) + elseif message.env.CONTENT_LENGTH then + sourcein = socket.source("by-length", thread, + tonumber(message.env.CONTENT_LENGTH)) + else + self:error( thread, 411, luci.http.protocol.statusmsg[411] ) + break; + end + + -- FIXME: Close for POST requests + close = true + else + self:error( thread, 405, luci.http.protocol.statusmsg[405] ) + break; + + end + + + local host = self.vhosts[message.env.HTTP_HOST] or self.host + if not host then + self:error( thread, 500, "Unable to find matching host" ) + break; + end + + local response, sourceout = host:process( + message, sourcein, sinkerr, + client, io.stderr + ) + if not response then + self:error( thread, 500, "Error processing handler" ) + end + + -- Post process response + local sinkmode = close and "close-when-done" or "keep-open" + + if sourceout then + if not response.headers["Content-Length"] then + if message.http_version == 1.1 then + response.headers["Transfer-Encoding"] = "chunked" + sinkmode = "http-chunked" + else + close = true + sinkmode = "close-when-done" + end + end + end + + if close then + response.headers["Connection"] = "close" + end + + + local sinkout = socket.sink(sinkmode, thread) + + local header = + message.env.SERVER_PROTOCOL .. " " .. + tostring(response.status) .. " " .. + luci.http.protocol.statusmsg[response.status] .. "\r\n" + + header = header .. "Server: LuCI HTTPd/" .. tostring(VERSION) .. "\r\n" + + + for k,v in pairs(response.headers) do + header = header .. k .. ": " .. v .. "\r\n" + end + + thread:send(header .. "\r\n") + + if sourceout then + local eof = false + repeat + coroutine.yield() + eof = not ltn12.pump.step(sourceout, sinkout) + until eof + end + until close + + client:close() +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n.lua new file mode 100644 index 0000000..b031d82 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n.lua @@ -0,0 +1,98 @@ +--[[ +LuCI - Internationalisation + +Description: +A very minimalistic but yet effective internationalisation module + +FileId: +$Id: i18n.lua 3652 2008-10-29 19:41:33Z jow $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +--- LuCI translation library. +module("luci.i18n", package.seeall) +require("luci.util") + +table = {} +i18ndir = luci.util.libpath() .. "/i18n/" +loaded = {} +context = luci.util.threadlocal() +default = "en" + +--- Clear the translation table. +function clear() + table = {} +end + +--- Load a translation and copy its data into the translation table. +-- @param file Language file +-- @param lang Two-letter language code +-- @param force Force reload even if already loaded (optional) +-- @return Success status +function load(file, lang, force) + lang = lang and lang:gsub("_", "-") or "" + if force or not loaded[lang] or not loaded[lang][file] then + local f = loadfile(i18ndir .. file .. "." .. lang .. ".lua") + if f then + table[lang] = table[lang] or {} + setfenv(f, table[lang]) + f() + loaded[lang] = loaded[lang] or {} + loaded[lang][file] = true + return true + else + return false + end + else + return true + end +end + +--- Load a translation file using the default translation language. +-- Alternatively load the translation of the fallback language. +-- @param file Language file +-- @param force Force reload even if already loaded (optional) +function loadc(file, force) + load(file, default, force) + return load(file, context.lang, force) +end + +--- Set the context default translation language. +-- @param lang Two-letter language code +function setlanguage(lang) + context.lang = lang:gsub("_", "-") +end + +--- Return the translated value for a specific translation key. +-- @param key Translation key +-- @param def Default translation +-- @return Translated string +function translate(key, def) + return (table[context.lang] and table[context.lang][key]) + or (table[default] and table[default][key]) + or def +end + +--- Return the translated value for a specific translation key and use it as sprintf pattern. +-- @param key Translation key +-- @param default Default translation +-- @param ... Format parameters +-- @return Translated and formatted string +function translatef(key, default, ...) + return translate(key, default):format(...) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.de.lua new file mode 100644 index 0000000..ccfdc01 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.de.lua @@ -0,0 +1,346 @@ +a_i_i_admin1 = 'Dies ist der Administrationsbereich von LuCI.' +a_i_i_admin2 = 'LuCI ist eine freie, flexible und benutzerfreundliche grafische Oberfläche zur Konfiguration von OpenWrt Kamikaze.' +a_i_i_admin3 = 'Auf den folgenden Seiten können alle wichtigen Einstellungen des Routers vorgenommen werden.' +a_i_i_admin4 = 'Hinweis: In LuCI werden getätigte Änderungen erst nach einem Klick auf Änderungen - Speichern & Anwenden angewandt.' +a_i_i_admin5 = 'Wir sind natürlich stets darum bemüht, diese Oberfläche noch besser und intuitiver zu Gestalten und freuen uns über jegliche Art von Feedback oder Verbesserungsvorschlägen.' +a_i_i_admin6 = 'Und nun wünschen wir viel Spaß mit dem Router!' +a_i_i_hello = 'Hallo!' +a_i_i_team = 'Das LuCI-Team' +a_i_keepflash = 'Zu übernehmende Dateien bei Firmwareupgrade' +a_i_keepflash1 = 'Die folgenden Dateien und Verzeichnisse werden beim Aktualisieren der Firmware über die Oberfläche automatisch in die neue Firmware übernommen.' +a_i_luci1 = 'Hier können Eigenschaften und die Funktionalität der Oberfläche angepasst werden.' +a_i_ucicommit = 'UCI-Befehle beim Anwenden' +a_i_ucicommit1 = 'Beim Anwenden der Konfiguration aus der Oberflächliche heraus können automatisch die relevanten Dienste neugestart werden, sodass Änderungen sofort nach dem Anwenden aktiv werden und der Router nicht erst neugestartet werden muss.' +a_i_ui = 'Benutzeroberfläche' +a_n_i_bridge = 'Netzwerkbrücke' +a_n_i_bridge1 = 'überbrückt angegebene Schnittstelle(n)' +a_n_ifaces1 = 'An dieser Stelle können die einzelnen Schnittstellen des Netzwerkes konfiguriert werden. Es können mehrere Schnittstellen zu einer Brücke zusammengefasst werden, indem diese durch Leerzeichen getrennt aufgezählt werden und ein entsprechender Haken im Feld Netzwerkbrücke gesetzt wird. Es können VLANs in der Notation SCHNITTSTELLE.VLANNR (z.B.: eth0.1) verwendet werden.' +a_n_ptp = 'Punkt-zu-Punkt Verbindungen' +a_n_ptp1 = 'Punkt-zu-Punkt Verbindungen über PPPoE oder PPTP werden häufig dazu verwendet, um über DSL o.ä. Techniken eine Verbindung zum Internetgateway eines Internetzugangsanbieters aufzubauen.' +a_n_r_netmask1 = 'falls Ziel ein Netzwerk ist' +a_n_r_target1 = 'Host-IP oder Netzwerk' +a_n_r_target6 = 'IPv6 Host- oder Netzwerk-Addresse (CIDR)' +a_n_routes = 'Routen' +a_n_routes4 = 'IPv4 Routen' +a_n_routes6 = 'IPv6 Routen' +a_n_routes1 = 'Routen geben an, über welche Schnittstelle und welches Gateway ein bestimmter Host oder ein bestimmtes Netzwerk erreicht werden kann.' +a_n_routes_static = 'Statische Routen' +a_n_routes_static4 = 'Statische IPv4 Routen' +a_n_routes_static6 = 'Statische IPv6 Routen' +a_n_routes_kernel4 = 'Aktive IPv4-Routen' +a_n_routes_kernel6 = 'Aktive IPv6-Routen' +a_n_switch = 'Switch' +a_n_switch1 = 'Die Netzwerkschnittstellen am Router können zu verschienden VLANs zusammengefasst werden, in denen Geräte miteinander direkt kommunizieren können. VLANs werden auch häufig dazu genutzt, um Netzwerke voneiander zu trennen. So ist oftmals eine Schnittstelle als Uplink zu einem größerem Netz, wie dem Internet vorkonfiguriert und die anderen Schnittstellen bilden ein VLAN für das lokale Netzwerk.' +a_n_conntrack = 'Aktive Verbindungen' +a_n_conntrack_desc = 'Diese Seite gibt eine Ãœbersicht über aktive Netzwerkverbindungen.' +a_network1 = 'In diesem Bereich finden sich alle netzwerkbezogenen Einstellungen.' +a_network2 = 'Der Netzwerkswitch kann bei den meisten Routern frei konfiguriert und in mehrere VLANs aufgeteilt werden.' +a_network3 = 'Schnittstellen und PPPoE/PPTP-Einstellungen ermöglichen die freie Organisation des Netzwerks und die Anbindung an ein WAN.' +a_network4 = 'DHCP ermöglichst die automatische Netzwerkkonfiguration von Rechnern im (W)LAN.' +a_network5 = 'Portweiterleitung und Firewall erlauben eine effektive Absicherung des Netzes, bei gleichzeitiger Bereitstellung von externen Diensten.' +a_s_changepw = 'Passwort ändern' +a_s_changepw1 = 'Ändert das Passwort des Systemverwalters (Benutzer "root")' +a_s_changepw_changed = 'Passwort erfolgreich geändert' +a_s_changepw_nomatch = 'Passwörter stimmen nicht überein' +a_s_desc = 'An dieser Stelle können Grundeinstellungen des Systems wie Hostname oder Zeitzone vorgenommen werden.' +a_s_flash = 'Upgrade' +a_s_flash_flashed = 'Flashvorgang erfolgreich. Router startet neu...' +a_s_flash_flasherr = 'Flashvorgang fehlgeschlagen' +a_s_flash_fwimage = 'Firmwareimage' +a_s_flash_received = 'Abbild empfangen. Starte Flashvorgang. SCHALTEN SIE DAS GERÄT NICHT AUS!' +a_s_flash_inprogress = 'Schreibe Firmware...' +a_s_flash_fwupgrade = 'Firmware aktualisieren' +a_s_flash_keepcfg = 'Konfigurationsdateien übernehmen' +a_s_flash_notimplemented = 'Diese Funktion steht leider (noch) nicht zur Verfügung.' +a_s_flash_upgrade1 = 'Ersetzt die installierte Firmware (das Betriebssystem des Routers) durch ein neues. Das Format der Firmware ist plattformabhängig.' +a_s_fstab = 'Einhängepunkte' +a_s_fstab_active = 'Eingehängte Dateisysteme' +a_s_fstab_used = 'Benutzt' +a_s_fstab_avail = 'Verfügbar' +a_s_fstab_device1 = 'Die Gerätedatei des Speichers oder der Partition (z.B.: /dev/sda)' +a_s_fstab_fs1 = 'Das Dateisystem mit dem der Speicher formatiert ist (z.B.: ext3)' +a_s_fstab_mountpoint = 'Einhängepunkt' +a_s_fstab_mountpoints = 'Einhängepunkte' +a_s_fstab_mountpoints1 = 'Einhängepunkte bestimmen, an welcher Stelle des Dateisystems bestimmte Laufwerke und Speicher zur Verwendung eingebunden werden.' +a_s_fstab_swap1 = 'Falls der Arbeitsspeicher des Routers nicht ausreicht, kann dieser nicht benutzte Daten zeitweise auf einem SWAP-Laufwerk auslagern um so die effektive Größe des Arbeitsspeichers zu erhöhen. Die Auslagerung der Daten ist natürlich bedeutend langsamer als direkte Arbeitsspeicherzugriffe.' +a_s_i_system1 = 'Hier finden sich Einstellungen, die das System selbst, dessen Kennung, installierte Software und Hardware, Authentifizierung oder eingehängte Speicher betreffen.' +a_s_i_system2 = 'Diese Einstellungen definieren die Grundlage des Systems, auf dem die installierte Software aufbaut.' +a_s_i_system3 = 'Beachte bitte, dass eine fehlerhafte Konfiguration den Start des Routers verhindern oder dich vom Zugriff auf diesen ausschließen kann.' +a_s_p_ipkg = 'OPKG-Konfiguration' +a_s_p_ipkg_pkglists = 'Paketlisten' +a_s_p_ipkg_targets = 'Installationsziele' +a_s_packages = 'Paketverwaltung' +a_s_packages_do = 'Aktionen ausführen' +a_s_packages_install = 'Installation von' +a_s_packages_installurl = 'Paket herunterladen und installieren' +a_s_packages_ipkg = 'Paketlisten und Installationsziele bearbeiten' +a_s_packages_name = 'Paketname' +a_s_packages_remove = 'Deinstallation von' +a_s_packages_search = 'Paket suchen' +a_s_packages_update = 'Paketlisten aktualisieren' +a_s_packages_updatelist = 'Paketlisten aktualisieren' +a_s_packages_upgrade = 'Installierte Pakete aktualisieren' +a_s_reboot1 = 'Startet das Betriebssystem des Routers neu.' +a_s_reboot_do = 'Neustart durchführen' +a_s_reboot_running = 'Bitte warten: Neustart wird durchgeführt...' +a_s_reboot_u = 'Warnung: Es gibt ungespeicherte Änderungen, die beim Neustart verloren gehen!' +a_s_sshkeys = 'SSH-Schlüssel' +a_s_sshkeys1 = 'Hier können öffentliche SSH-Schlüssel (einer pro Zeile) zur Authentifizierung abgelegt werden.' +a_srv_d_pwauth = 'Passwortanmeldung' +a_srv_d_pwauth1 = 'Erlaube Anmeldung per Passwort' +a_srv_dropbear1 = 'Der SSH-Server ermöglicht Shell-Zugriff über das Netzwerk und bietet einen integrierten SCP-Dienst.' +a_srv_http1 = 'Ein kleiner Webserver, der für die Bereitstellung von LuCI genutzt werden kann.' +a_srv_http_authrealm = 'Anmeldeaufforderung' +a_srv_http_authrealm1 = 'Aufforderungstext zum Anmelden im Administrationsbereich' +a_srv_http_config1 = '/etc/httpd.conf wenn leer' +a_srv_http_root = 'Wurzelverzeichnis' +a_srv_http_keepalive = 'Keep-Alive aktivieren' +a_srv_http_timeout = 'Verbindungszeitlimit' +a_srv_http_path = 'Pluginpfad' +a_srv_lucittpd = 'Ein schlanker HTTP/1.1 webserver in C und Lua geschrieben um LuCI zu betreiben.' +a_srv_services1 = 'Dienste und Dämonen stellen bestimmte Funktionalitäten auf dem Router zur Verfügung.' +a_srv_services2 = 'Es handelt sich hierbei meist um Netzwerkserver, die verschiedene Aufgaben auf dem Router erfüllen, beispielsweise Shell-Zugang ermöglichen oder diese Weboberfläche per HTTP anbieten.' +a_st_i_status1 = 'Hier finden sich Informationen über den aktuellen Status des Systems, beispielsweise Prozessortakt, Speicherauslastung und Netzwerkschnittstellen.' +a_st_i_status2 = 'Zusätzlich können hier Protokolldaten, des Kernels und diverser Systemdienste eingesehen werden, um deren Zustand zu kontrollieren.' +a_w_devices1 = 'An dieser Stelle können eingebaute WLAN-Geräte konfiguriert werden.' +a_w_apisolation = 'AP-Isolation' +a_w_apisolation1 = 'Unterbindet Client-Client-Verkehr' +a_w_athburst = 'Atheros-Frameburst' +a_w_brcmburst = 'Broadcom-Frameburst' +a_w_channel = 'Funkkanal' +a_w_connlimit = 'Verbindungslimit' +a_w_countrycode = 'Ländercode' +a_w_distance1 = 'Distanz zum am weitesten entfernten Funkpartner (m)' +a_w_diversity = 'Diversität' +a_w_hideessid = 'ESSID verstecken' +a_w_netid = 'Netzkennung (ESSID)' +a_w_network1 = 'WLAN-Netz zu Netzwerk hinzufügen' +a_w_networks1 = 'Pro WLAN-Gerät können mehrere Netze bereitgestellt werden. Es sollte beachtet werden, dass es hardware- / treiberspezifische Einschränkungen gibt. So kann pro WLAN-Gerät in der Regel entweder 1 Ad-Hoc-Zugang ODER bis zu 3 Access-Point und 1 Client-Zugang gleichzeitig erstellt werden.' +a_w_netmanual = ' - Neues Netzwerk erstellen - ' +a_w_radiusport = 'Radius-Port' +a_w_radiussrv = 'Radius-Server' +a_w_rxantenna = 'Empfangsantenne' +a_w_txantenna = 'Sendeantenne' +a_w_txpwr = 'Sendeleistung' +a_w_wifi1 = 'Hier finden sich Konfiugrationsmöglichkeiten für Drahtlos-Netzwerke nach dem WLAN-Standard.' +a_w_wifi2 = '802.11b/g/a/n-Geräte können so einfach in das bestehende physische Netzwerk integriert werden. Die Unterstützung von virtuellen Adaptern ermöglicht auch den Einsatz als Wireless-Repeater oder von mehreren Netzwerken gleichzeitig auf einem Gerät.' +a_w_wifi3 = 'Es werden Managed, Client, Ad-Hoc und WDS-Modus unterstützt sowie WPA und WPA2-Verschlüsselung zur gesicherten Kommunikation.' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_client = 'Client' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_monitor = 'Monitor' +a_w_wds = 'WDS' +accept = 'Annehmen' +aliases = 'Aliasse' +bitrate = 'Bitrate' +c_contributors = 'Mitwirkende Entwickler' +c_leaddev = 'Leitende Entwicklung' +c_lucidesc = 'LuCI ist eine Sammlung freier Lua-Software einschließlich eines MVC-Webframeworks und einer Weboberfläche für eingebettete Geräte. Luci steht unter der Apache-Lizenz.' +c_projecthome = 'Projekt Homepage' +c_thanksto = 'Dank an' +configure = 'Konfigurieren' +contact = 'Kontakt' +contact1 = 'Diese Daten sind auf der öffentlichen Kontaktseite sichtbar. Bitte gib an, wie man dich am besten kontaktieren kann. Diese Informationen sollten nach der Picopeering Vereinbarung mindestens deine E-Mail-Adresse enthalten. Damit dein Knoten durch Topographieprogramme erfasst werden kann, gib bitte deine Geokoordinaten oder zumindest deine Straße und Hausnummer unter Standort an.' +coord = 'Koordinaten' +coord1 = 'Bitte als Breite;Länge (z.B: 51.5;12.9) angeben' +cpu = 'Prozessor' +decline = 'Ablehnen' +defroutes = 'Standardrouten' +destination = 'Ziel' +dhcp_dhcp_dynamicdhcp = 'Dynamisches DHCP' +dhcp_dhcp_force = 'Start erzwingen' +dhcp_dhcp_ignore = 'Schnittstelle ignorieren' +dhcp_dhcp_ignore_desc = 'DHCP für dieses Netzwerk deaktivieren' +dhcp_dhcp_leasetime = 'Laufzeit' +dhcp_dhcp_dhcpoption = 'DHCP-Optionen' +dhcp_dhcp_dhcpoption_desc = 'Siehe "dnsmasq --help dhcp" für eine Liste verfügbarer Optionen.' +dhcp_dhcp_limit_desc = 'Anzahl zu vergebender Adressen -1' +dhcp_dhcp_start_desc = 'Erste vergebene Adresse (letztes Oktett)' +dhcp_dnsmasq_addnhosts = 'Zusätzliche Hostdatei' +dhcp_dnsmasq_authoritative = 'Authoritativ' +dhcp_dnsmasq_authoritative_desc = 'Dies ist der einzige DHCP im lokalen Netz' +dhcp_dnsmasq_boguspriv = 'Private Anfragen filtern' +dhcp_dnsmasq_boguspriv_desc = 'Reverse DNS-Anfragen für lokale Netze nicht weiterleiten' +dhcp_dnsmasq_dhcpleasemax = 'max. DHCP-Leases' +dhcp_dnsmasq_dnsforwardmax = 'gleichzeitige Abfragen' +dhcp_dnsmasq_domain = 'Lokale Domain' +dhcp_dnsmasq_domainneeded = 'Anfragen nur mit Domain' +dhcp_dnsmasq_domainneeded_desc = 'Anfragen ohne Domainnamen nicht weiterleiten' +dhcp_dnsmasq_ednspacket_max = 'max. EDNS.0 Paketgröße' +dhcp_dnsmasq_expandhosts = 'Erweitere Hosts' +dhcp_dnsmasq_expandhosts_desc = 'Fügt Domainnamen zu einfachen Hosteinträgen in der Resolvdatei hinzu' +dhcp_dnsmasq_filterwin2k = 'Windowsanfragen filtern' +dhcp_dnsmasq_filterwin2k_desc = 'nutzlose DNS-Anfragen aktueller Windowssysteme filtern' +dhcp_dnsmasq_leasefile = 'Leasedatei' +dhcp_dnsmasq_leasefile_desc = 'Speicherort für vergebenen DHCP-Adressen' +dhcp_dnsmasq_local = 'Lokale Server' +dhcp_dnsmasq_localisequeries = 'Lokalisiere Anfragen' +dhcp_dnsmasq_localisequeries_desc = 'Gibt die Adresse eines Hostnamen entsprechend seines Subnetzes zurück' +dhcp_dnsmasq_logqueries = 'Schreibe Abfragelog' +dhcp_dnsmasq_nohosts = 'Ignoriere /etc/hosts' +dhcp_dnsmasq_nonegcache = 'Unbekannte nicht cachen' +dhcp_dnsmasq_nonegcache_desc = 'Negative DNS-Antworten nicht zwischenspeichern' +dhcp_dnsmasq_noresolv = 'Ignoriere Resolvdatei' +dhcp_dnsmasq_port = 'DNS-Port' +dhcp_dnsmasq_queryport = 'Abfrageport' +dhcp_dnsmasq_readethers = 'Verwende /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Lese Informationen aus /etc/ethers um den DHCP-Server zu konfigurieren' +dhcp_dnsmasq_resolvfile = 'Resolvdatei' +dhcp_dnsmasq_resolvfile_desc = 'Lokale DNS-Datei' +dhcp_dnsmasq_strictorder = 'Strikte Reihenfolge' +dhcp_dnsmasq_strictorder_desc = 'DNS-Server werden strikt der Reihenfolge in der Resolvdatei nach abgefragt' +dhcp_dnsmasq_enabletftp = 'TFTP-Server aktivieren' +dhcp_dnsmasq_tftproot = 'TFTP-Server Wurzelverzeichnis' +dhcp_dnsmasq_dhcpboot = 'Netzwerk-Boot Abbild' +file = 'Datei' +frag = 'Frag.' +frequency = 'Frequenz' +iface = 'Schnittstelle' +iwscan = 'WLAN-Scan' +iwscan1 = 'Drahtlosnetzwerke in der lokalen Umgebung des Routers:' +iwscan_encr = 'Vers.' +iwscan_link = 'Verb.' +iwscan_noise = 'Rausch' +iwscan_signal = 'Signal' +link = 'Verb.' +dhcp_leases = 'Zuweisungen' +luci_ethers = 'Statische Einträge' +dhcp_timeremain = 'Verbleibende Gültigkeit' +dhcp_leases_active = 'Aktive Zuweisungen' +network_interface_prereq = 'Für die Unterstützung von UMTS/GPRS muss "comgt", für PPPoE "ppp-mod-pppoe", für PPPoA "ppp-mod-pppoa" und für PPtP "pptp" installiert sein' +network_interface_prereq_mini = 'Für die Unterstützung von PPPoE muss "ppp-mod-pppoe" und für PPtP "pptp" installiert sein' +network_interface_demand = 'Automatische Trennung' +network_interface_demand_desc = 'Zeit (in s) nach der die Verbindung bei Inaktivität getrennt wird' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'Anzahl fehlgeschlagener Verbindungstests nach der automatisch neu verbunden wird' +network_interface_server = 'PPTP-Server' +network_interface_device = 'Modemgerät' +network_interface_device_desc = 'Geräteknoten des Modems, z.B. /dev/ttyUSB0' +network_interface_defaultroute = 'Standardroute ersetzen' +network_interface_defaultroute_desc = 'Lässt pppd die aktuelle Standardroute ersetzen und über die PPP Schnittstelle leiten' +network_interface_peerdns = 'DNS der Gegenstelle nutzen' +network_interface_peerdns_desc = 'Konfiguriert den lokalen DNS-Server so, dass er die von der Gegenstelle angekündigten Nameserver-Adressen nutzt' +network_interface_ipv6 = 'IPv6 für die PPP-Verbindung aktivieren' +network_interface_connect = 'Verbindungs-Script' +network_interface_connect_desc = 'Lässt pppd das angegebene Script nach dem Aufbau der PPP Verbindung abarbeiten' +network_interface_disconnect = 'Trennuns-Script' +network_interface_disconnect_desc = 'Lässt pppd das angegebene Script vor dem Trennen der PPP Verbindung abarbeiten' +network_interface_pppd_options = 'Weitere pppd Optionen' +network_interface_pppd_options_desc = 'Hier können zusätzliche Kommandozeilenargumente für pppd angegeben werden' +network_interface_apn = 'Zugriffspunkt (APN)' +network_interface_pincode = 'PIN-Code' +network_interface_pincode_desc = 'Stellen Sie sicher das die richtige PIN hier eingetragen wird, sonst könnte die SIM-Karte gesperrt werden!' +network_interface_service = 'Dienstart' +network_interface_maxwait = 'Initialisierungszeit' +network_interface_maxwait_desc = 'Zeit in Sekunden um auf die Initialisierung des Modems zu warten bevor ein Verbindungsversuch unternommen wird' +network_switch_desc = 'Die zu einem VLAN gehörenden Schnittstellen werden durch Leerzeichen getrennt. Die Schnittstelle mit der höchsten Nummer (meistens 5) bildet in der Regel die Verbindung zur internen Netzschnittstelle des Routers. Bei Geräten mit 5 Schnittstellen ist in der Regel die Schnittstelle mit der niedrigsten Nummer (0) die standardmäßige Uplinkschnittstelle des Routers.' +network_interface_encaps = 'PPPoA Kapselung' + +noise = 'Rausch' +power = 'Leistung' +routes = 'Routen' +routes_gateway = 'Gateway' +routes_metric = 'Metrik' +routes_netmask = 'Netzmaske' +rts = 'RTS' +signal = 'Signal' +status = 'Status' +system_type = 'Systemtyp' +texteditor = 'Texteditor' +uci_applied = 'Die folgenden Änderungen wurden übernommen' +uci_reverted = 'Die folgenden Änderungen wurden verworfen' +m_n_local = 'Lokales Netz' +m_n_inet = 'Internetverbindung' +m_n_route = 'Weiterleiten' +m_n_bridge = 'Ãœberbrücken' +m_w_ap = 'Anbieten (Access Point)' +m_w_adhoc = 'Unabhängig (Ad-Hoc)' +m_w_client = 'Einklinken (Client)' +m_w_wds = 'Verteilen (WDS)' +m_w_clientmode = 'Verbindungsmodus' +system_system_logsize = 'Größe des Systemprotokollpuffers' +system_system_logip = 'Externer Systemprotokollserver' +system_system_conloglevel = 'Protokollausgabelevel' +system_system_conloglevel_desc = 'Level auf der Konsole ausgegebener Meldungen' +m_i_processor = 'Prozessor' +m_i_memory = 'Hauptspeicher' +m_i_systemtime = 'Lokale Zeit' +m_i_uptime = 'Laufzeit' +m_n_d_firstaddress = 'Erste vergebene Adresse' +m_n_d_numleases = 'Anzahl vergebener Adressen' +routingtable = 'Routingtabelle' +wlanscan = 'WLAN-Scan' +m_n_keepalive = 'automatisch neu verbinden' +m_n_dialondemand = 'trennen bei Inaktivität nach' +m_n_pptp_server = 'PPTP-Server' +a_s_applyreboot1 = 'Änderungen angewandt.' +a_s_backup = 'Sichern / Wiederherstellen' +a_s_backup_backup = 'Sicherung erstellen' +a_s_backup_archive = 'Sicherungsarchiv' +a_s_backup_reset = 'Grundeinstellungen wiederherstellen' +a_s_backup_reset1 = 'Alle aktuellen Einstellungen verwerfen und Grundeinstellungen wiederherstellen?' +a_s_backup_restore = 'Sicherung wiederherstellen' +a_s_backup1 = 'Auf dieser Seite können Sicherungen der Konfiguration erstellt und eingespielt werden und - wenn möglich - die Grundeinstellungen wiederhergestellt werden.' +leds = 'LED Konfiguration' +leds_desc = 'Passt das Verhalten der Geräte-LEDs an - wenn dies möglich ist.' +system_led_name = 'LED Name' +system_led_sysfs = 'LED Gerät' +system_led_default = 'Grundzustand' +system_led_default_desc = 'ausgewählt = an' +system_led_trigger = 'Auslöser' +system_led_trigger_none = 'Keiner' +system_led_trigger_defaulton = 'Immer an' +system_led_trigger_timer = 'Taktgeber' +system_led_trigger_heartbeat = 'Herzschlag (Mittlere Systemlast)' +system_led_trigger_netdev = 'Netzwerkschnittstelle' +system_led_delayoff = 'Einschaltverzögerung' +system_led_delayoff_desc = 'Zeit (in ms) die die LED deaktiviert ist' +system_led_delayon = 'Ausschaltverzögerung' +system_led_delayon_desc = 'Zeit (in ms) die die LED aktiviert ist' +system_led_dev = 'Schnittstelle' +system_led_mode = 'Auslösemodus' +system_led_mode_link = 'Verbindung hergestellt' +system_led_mode_tx = 'Senden' +system_led_mode_rx = 'Empfangen' +network_interface_up = 'Aktiv' +network_interface_hwaddr = 'MAC-Adresse' +network_interface_hwaddr_desc = 'Hardware Adresse' +network_interface_txrx = 'Traffic' +network_interface_txrx_desc = 'gesendet / empfangen' +network_interface_err = 'Fehler' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Firewallzone anlegen / zuweisen' +network_interface_fwzone_desc = 'Diese Schnittstelle gehört bis jetzt zu keiner Firewallzone.' +process_head = 'Prozesse' +process_descr = 'Diese Tabelle gibt eine Ãœbersicht über aktuell laufende Systemprozeese und deren Status.' +process_pid = 'PID' +process_owner = 'Besitzer' +process_command = 'Befehl' +process_cpu = 'CPU-Nutzung (%)' +process_mem = 'Speichernutzung (%)' +process_hup = 'Auflegen' +process_term = 'Beenden' +process_kill = 'Töten' +mem_cached = 'gecached' +mem_buffered = 'gepuffert' +mem_free = 'frei' +a_s_crontab = 'Geplante Aufgaben' +a_s_crontab1 = 'Dies ist die System-Crontab in der geplante Aufgaben definiert werden können.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Pfad zum CA-Zertifikat' +a_w_eaptype = 'EAP-Methode' +a_w_tlsprivkey = 'Pfad zum Privaten Schlüssel' +a_w_tlsprivkeypwd = 'Passwort des Privaten Schlüssels' +a_w_peapauth = 'PEAP-Authentifizierung' +a_w_peapidentity = 'PEAP-Identitäz' +a_w_peappassword = 'PEAP-Passwort' +a_w_create = 'Netzwerk anlegen' +hostnames = 'Rechnernamen' +hostnames_entries = 'Host-Einträge' +hostnames_hostname = 'Rechnername' +hostnames_address = 'IP-Adresse' +luci_components = "LuCI Komponenten" +m_n_mssfix = "Segmentgrößen Clamping" +m_n_mssfix_desc = "Behebt Probleme bei nicht erreichbaren Webseiten, Absenden von Formularen oder anderes unerwartetes Verhalten für einige ISPs." +dhcp_desc = 'Mit DHCP können Netzwerkteilnehmer automatisch Einstellungen wie IP-Adresse, Präfix, DNS-Server, usw. beziehen.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.en.lua new file mode 100644 index 0000000..cb2aa4e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.en.lua @@ -0,0 +1,329 @@ +uci_applied = 'The following changes have been applied' +uci_reverted = 'The following changes have been reverted' +a_i_ui = 'User Interface' +c_lucidesc = 'LuCI is a collection of free Lua software including an MVC-Webframework and webinterface for embedded devices. LuCI is licensed under the Apache-License.' +c_projecthome = 'Project Homepage' +c_leaddev = 'Lead Development' +c_contributors = 'Contributing Developers' +c_thanksto = 'Thanks To' +a_i_i_hello = 'Hello!' +a_i_i_admin1 = 'This is the administration area of LuCI.' +a_i_i_admin2 = 'LuCI is a free, flexible, and user friendly graphical interface for configuring OpenWrt Kamikaze.' +a_i_i_admin3 = 'On the following pages you can adjust all important settings of your router.' +a_i_i_admin4 = 'Notice: In LuCI changes have to be confirmed by clicking Changes - Save & Apply before being applied.' +a_i_i_admin5 = 'As we always want to improve this interface we are looking forward to your feedback and suggestions.' +a_i_i_admin6 = 'And now have fun with your router!' +a_i_i_team = 'The LuCI Team' +a_i_luci1 = 'Here you can customize the settings and the functionality of LuCI.' +a_i_ucicommit = 'Post-commit actions' +a_i_ucicommit1 = 'These commands will be executed automatically when a given UCI configuration is committed allowing changes to be applied instantly.' +a_i_keepflash = 'Files to be kept when flashing a new firmware' +a_i_keepflash1 = 'When flashing a new firmware with LuCI these files will be added to the new firmware installation.' +a_st_i_status1 = 'Here you can find information about the current system status like CPU clock frequency, memory usage or network interface data.' +a_st_i_status2 = 'Also kernel or service logfiles can be viewed here to get an overview over their current state.' +iwscan = 'WLAN-Scan' +iwscan1 = 'Wifi networks in your local environment' +iwscan_encr = 'Encr.' +iwscan_link = 'Link' +iwscan_signal = 'Signal' +iwscan_noise = 'Noise' +routes = 'Routes' +routes_netmask = 'Netmask' +routes_gateway = 'Gateway' +routes_metric = 'Metric' +a_s_desc = 'Here you can configure the basic aspects of your device like its hostname or the timezone.' +a_s_packages = 'Software' +a_s_changepw = 'Admin Password' +a_s_p_ipkg = 'OPKG-Configuration' +a_s_sshkeys = 'SSH-Keys' +a_s_fstab = 'Mount Points' +a_s_flash = 'Flash Firmware' +a_s_i_system1 = 'Change settings related to the system itself, its identification, installed hard- and software, authentication or mount points.' +a_s_i_system2 = 'These settings define the base of your system.' +a_s_i_system3 = 'Pay attention as any misconfiguration here may prevent your device from booting or may lock yourself out of it.' +a_s_packages_do = 'Perform Actions' +a_s_packages_install = 'Install' +a_s_packages_installurl = 'Download and install package' +a_s_packages_ipkg = 'Edit package lists and installation targets' +a_s_packages_name = 'Package name' +a_s_packages_remove = 'Remove' +a_s_packages_search = 'Find package' +a_s_packages_update = 'Package lists updated' +a_s_packages_updatelist = 'Update package lists' +a_s_packages_upgrade = 'Upgrade installed packages' +a_s_p_ipkg_pkglists = 'Package lists' +a_s_p_ipkg_targets = 'Installation targets' +a_s_changepw1 = 'Change the password of the system administrator (User root)' +a_s_changepw_changed = 'Password successfully changed' +a_s_changepw_nomatch = 'Error: Passwords do not match' +a_s_sshkeys1 = 'Here you can paste public SSH-Keys (one per line) for SSH public-key authentication.' +a_s_fstab_mountpoints = 'Mount Points' +a_s_fstab_mountpoints1 = 'Mount Points define at which point a memory device will be attached to the filesystem' +a_s_fstab_active = 'Mounted file systems' +a_s_fstab_used = 'Used' +a_s_fstab_avail = 'Available' +a_s_fstab_mountpoint = 'Mount Point' +a_s_fstab_device1 = 'The device file of the memory or partition (e.g. /dev/sda1)' +a_s_fstab_fs1 = 'The filesystem that was used to format the memory (e.g. ext3)' +a_s_fstab_swap1 = 'If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable RAM. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the RAM.' +a_s_flash_flashed = 'Firmware successfully flashed. Rebooting device...' +a_s_flash_flasherr = 'Failed to flash' +a_s_flash_fwimage = 'Firmware image' +a_s_flash_received = 'Image received. About to start flashing process. DO NOT POWER OFF THE DEVICE!' +a_s_flash_inprogress = 'Writing firmware...' +a_s_flash_fwupgrade = 'Flash Firmware' +a_s_flash_keepcfg = 'Keep configuration files' +a_s_flash_notimplemented = 'Sorry, this function is not (yet) available for your platform.' +a_s_flash_upgrade1 = 'Replaces the installed firmware with a new one. The firmware format is platform-dependent.' +a_s_reboot1 = 'Reboots the operating system of your device' +a_s_reboot_do = 'Perform reboot' +a_s_reboot_running = 'Please wait: Device rebooting...' +a_s_reboot_u = 'Warning: There are unsaved changes that will be lost while rebooting!' +a_s_applyreboot1 = 'Changes applied.' +a_s_backup = 'Backup / Restore' +a_s_backup_backup = 'Create backup' +a_s_backup_archive = 'Backup Archive' +a_s_backup_reset = 'Reset router to defaults' +a_s_backup_reset1 = 'Proceed reverting all settings and resetting to firmware defaults?' +a_s_backup_restore = 'Restore backup' +a_s_backup1 = 'Here you can backup and restore your router configuration and - if possible - reset the router to the default settings.' +a_srv_http = 'HTTP-Server' +a_srv_ssh = 'SSH-Server' +a_srv_services1 = 'Services and daemons perform certain tasks on your device.' +a_srv_services2 = 'Most of them are network servers, that offer a certain service for your device or network like shell access, serving webpages like LuCI, doing mesh routing, sending e-mails, ...' +a_srv_http1 = 'A small webserver which can be used to serve LuCI.' +a_srv_http_authrealm = 'Authentication Realm' +a_srv_http_authrealm1 = 'The realm which will be displayed at the authentication prompt for protected pages.' +a_srv_http_config1 = 'defaults to /etc/httpd.conf' +a_srv_http_root = 'Document root' +a_srv_dropbear1 = 'Dropbear offers SSH network shell access and an integrated SCP server' +a_srv_d_pwauth = 'Password authentication' +a_srv_d_pwauth1 = 'Allow SSH password authentication' +a_w_channel = 'Channel' +a_w_wifi1 = 'On this pages you can find configuration options for WLAN based wireless networks.' +a_w_wifi2 = 'You can easily integrate your 802.11a/b/g/n-devices into your physical network and use the virtual adapter support to build wireless repeaters or offer several networks with one device.' +a_w_wifi3 = 'There is support for Managed, Client, Ad-Hoc and WDS operating modes as well as WPA and WPA2 encryption for secure communnication.' +a_w_devices1 = 'Here you can configure installed wifi devices.' +a_w_txantenna = 'Transmit Antenna' +a_w_rxantenna = 'Receive Antenna' +a_w_distance1 = 'Distance to furthest station (in meter)' +a_w_diversity = 'Diversity' +a_w_countrycode = 'Country Code' +a_w_connlimit = 'Connection Limit' +a_w_networks1 = 'You can run several wifi networks with one device. Be aware that there are certain hardware and driverspecific restrictions. Normally you can operate 1 Ad-Hoc or up to 3 Master-Mode and 1 Client-Mode network simultaneously.' +a_w_netid = 'Network Name (ESSID)' +a_w_network1 = 'Add the Wifi network to physical network' +a_w_netmanual = ' - Create new Network - ' +a_w_txpwr = 'Transmit Power' +a_w_brcmburst = 'Broadcom Frameburst' +a_w_athburst = 'Atheros Frameburst' +a_w_radiussrv = 'RadiusServer' +a_w_radiusport = 'Radius-Port' +a_w_apisolation = 'AP-Isolation' +a_w_apisolation1 = 'Prevents Client to Client communication' +a_w_hideessid = 'Hide ESSID' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq is a combined DHCP-Server and DNS-Forwarder for NAT firewalls' +dhcp_dnsmasq_domainneeded = 'Domain required' +dhcp_dnsmasq_domainneeded_desc = 'Don't forward DNS-Requests without DNS-Name' +dhcp_dnsmasq_authoritative = 'Authoritative' +dhcp_dnsmasq_authoritative_desc = 'This is the only DHCP in the local network' +dhcp_dnsmasq_boguspriv = 'Filter private' +dhcp_dnsmasq_boguspriv_desc = 'Don't forward reverse lookups for local networks' +dhcp_dnsmasq_filterwin2k = 'Filter useless' +dhcp_dnsmasq_filterwin2k_desc = 'filter useless DNS-queries of Windows-systems' +dhcp_dnsmasq_localisequeries = 'Localise queries' +dhcp_dnsmasq_localisequeries_desc = 'localises the hostname depending on its subnet' +dhcp_dnsmasq_local = 'Local Server' +dhcp_dnsmasq_domain = 'Local Domain' +dhcp_dnsmasq_expandhosts = 'Expand Hosts' +dhcp_dnsmasq_expandhosts_desc = 'adds domain names to hostentries in the resolv file' +dhcp_dnsmasq_nonegcache = 'don't cache unknown' +dhcp_dnsmasq_nonegcache_desc = 'prevents caching of negative DNS-replies' +dhcp_dnsmasq_readethers = 'Use /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Read /etc/ethers to configure the DHCP-Server' +dhcp_dnsmasq_leasefile = 'Leasefile' +dhcp_dnsmasq_leasefile_desc = 'file where given DHCP-leases will be stored' +dhcp_dnsmasq_resolvfile = 'Resolvfile' +dhcp_dnsmasq_resolvfile_desc = 'local DNS file' +dhcp_dnsmasq_nohosts = 'Ignore /etc/hosts' +dhcp_dnsmasq_strictorder = 'Strict order' +dhcp_dnsmasq_strictorder_desc = 'DNS-Server will be queried in the order of the resolvfile' +dhcp_dnsmasq_logqueries = 'Log queries' +dhcp_dnsmasq_noresolv = 'Ignore resolve file' +dhcp_dnsmasq_dnsforwardmax = 'concurrent queries' +dhcp_dnsmasq_port = 'DNS-Port' +dhcp_dnsmasq_ednspacket_max = 'max. EDNS0 paket size' +dhcp_dnsmasq_dhcpleasemax = 'max. DHCP-Leases' +dhcp_dnsmasq_addnhosts = 'additional hostfile' +dhcp_dnsmasq_queryport = 'query port' +dhcp_dnsmasq_enabletftp = 'Enable TFTP-Server' +dhcp_dnsmasq_tftproot = 'TFTP-Server Root' +dhcp_dnsmasq_dhcpboot = 'Network Boot Image' +a_n_switch = 'Switch' +a_n_conntrack = 'Active Connections' +a_n_conntrack_desc = 'This page gives an overview over currently active network connections.' +a_n_routes = 'Routes' +a_n_routes4 = 'IPv4 Routes' +a_n_routes6 = 'IPv6 Routes' +a_network1 = 'In this area you find all network-related settings.' +a_network2 = 'On most routers the network switch can be freely configured and splitted up into several VLANs.' +a_network3 = 'Interfaces and PPPoE / PPTP-Settings allow a custom organisation of the network and connections to other networks like the internet.' +a_network4 = 'With DHCP devices in your local network can be automatically configured for network communication.' +a_network5 = 'Firewall and portforwarding can be used to secure your network while providing services to external networks.' +a_n_switch1 = 'The network ports on your router can be combined to several VLANs in which computers can communicate directly with each other. VLANs are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network.' +network_switch_desc = 'Ports belonging to a VLAN are separated with spaces. The port with the highest number (usually 5) is oftern the connection to the internal network interface of the router. On devices with 5 ports often the one with the lowest number (0) is the predefined Uplink port.' +a_n_ifaces1 = 'On this page you can configure the network interfaces. You can bridge several interfaces by ticking the "bridge interfaces" field and enter the names of several network interfaces separated by spaces. You can also use VLAN notation INTERFACE.VLANNR (e.g.: eth0.1).' +a_n_i_bridge = 'Bridge interfaces' +a_n_i_bridge1 = 'creates a bridge over specified interface(s)' +dhcp_desc = 'With DHCP network members can automatically receive their network settings (IP-address, netmask, DNS-server, ...).' +dhcp_dhcp_leasetime = 'Leasetime' +dhcp_dhcp_dynamicdhcp = 'Dynamic DHCP' +dhcp_dhcp_ignore = 'Ignore interface' +dhcp_dhcp_ignore_desc = 'disable DHCP for this interface' +dhcp_dhcp_force = 'Force' +dhcp_dhcp_start_desc = 'first address (last octet)' +dhcp_dhcp_limit_desc = 'number of leased addresses -1' +dhcp_dhcp_dhcpoption = 'DHCP-Options' +dhcp_dhcp_dhcpoption_desc = 'See "dnsmasq --help dhcp" for a list of available options.' +dhcp_leases = 'Leases' +luci_ethers = 'Static Leases' +dhcp_timeremain = 'Leasetime remaining' +dhcp_leases_active = 'Active Leases' +a_n_ptp = 'Point-to-Point Connections' +a_n_ptp1 = 'Point-to-Point connections with PPPoE or PPTP are often used to connect a device over DSL or similar technologies to an internet access point.' +network_interface_prereq = 'You need to install "comgt" for UMTS/GPRS, "ppp-mod-pppoe" for PPPoE, "ppp-mod-pppoa" for PPPoA or "pptp" for PPtP support' +network_interface_prereq_mini = 'You need to install "ppp-mod-pppoe" for PPPoE or "pptp" for PPtP support' +network_interface_server = 'PPTP-Server' +network_interface_demand = 'Automatic Disconnect' +network_interface_demand_desc = 'Time (in seconds) after which an unused connection will be closed' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'Number of failed connection tests to initiate automatic reconnect' +network_interface_device = 'Modem device' +network_interface_device_desc = 'The device node of your modem, e.g. /dev/ttyUSB0' +network_interface_defaultroute = 'Replace default route' +network_interface_defaultroute_desc = 'Let pppd replace the current default route to use the PPP interface after successful connect' +network_interface_peerdns = 'Use peer DNS' +network_interface_peerdns_desc = 'Configure the local DNS server to use the name servers adverticed by the PPP peer' +network_interface_ipv6 = 'Enable IPv6 on PPP link' +network_interface_connect = 'Connect script' +network_interface_connect_desc = 'Let pppd run this script after establishing the PPP link' +network_interface_disconnect = 'Disconnect script' +network_interface_disconnect_desc = 'Let pppd run this script before tearing down the PPP link' +network_interface_pppd_options = 'Additional pppd options' +network_interface_pppd_options_desc = 'Specify additional command line arguments for pppd here' +network_interface_apn = 'Access point (APN)' +network_interface_pincode = 'PIN code' +network_interface_pincode_desc = 'Make sure that you provide the correct pin code here or you might lock your sim card!' +network_interface_service = 'Service type' +network_interface_maxwait = 'Setup wait time' +network_interface_maxwait_desc = 'Seconds to wait for the modem to become ready before attempting to connect' +network_interface_encaps = 'PPPoA Encapsulation' + +a_n_r_routes1 = 'Routes specify over which interface and gateway a certain host or network can be reached.' +a_n_routes_static = 'Static Routes' +a_n_routes_static4 = 'Static IPv4 Routes' +a_n_routes_static6 = 'Static IPv6 Routes' +a_n_routes_kernel4 = 'Active IPv4-Routes' +a_n_routes_kernel6 = 'Active IPv6-Routes' +a_n_r_target1 = 'Host-IP or Network' +a_n_r_target6 = 'IPv6-Address or Network (CIDR)' +a_n_r_netmask1 = 'if target is a network' +m_n_inet = 'Internet Connection' +m_n_local = 'Local Network' +m_n_route = 'Route' +m_n_brdige = 'Bridge' +m_w_ap = 'Provide (Access Point)' +m_w_adhoc = 'Independent (Ad-Hoc)' +m_w_client = 'Join (Client)' +m_w_wds = 'Distributed (WDS)' +m_w_clientmode = 'Clientmode' +system_system_logsize = 'System log buffer size' +system_system_logip = 'External system log server' +system_system_conloglevel = 'Log output level' +system_system_conloglevel_desc = 'Level of log messages on the console' +m_i_processor = 'Processor' +m_i_memory = 'Memory' +m_i_systemtime = 'Local Time' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'First leased address' +m_n_d_numleases = 'Number of leased addresses' +routingtable = 'Routing table' +wlanscan = 'Wifi scan' +frequency = 'Frequency' +power = 'Power' +noise = 'Noise' +signal = 'Signal' +link = 'Link' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Bitrate' +m_n_keepalive = 'automatically reconnect' +m_n_dialondemand = 'disconnect when idle for' +m_n_pptp_server = 'PPTP-Server' +leds = 'LED Configuration' +leds_desc = 'Customizes the behaviour of the device LEDs if possible.' +system_led_name = 'LED Name' +system_led_sysfs = 'LED Device' +system_led_default = 'Default state' +system_led_default_desc = 'ticked = on' +system_led_trigger = 'Trigger' +system_led_trigger_none = 'None' +system_led_trigger_defaulton = 'Default On' +system_led_trigger_timer = 'Timer' +system_led_trigger_heartbeat = 'Heartbeat (Load Average)' +system_led_trigger_netdev = 'Network Device' +system_led_delayoff = 'Off-State Delay' +system_led_delayoff_desc = 'Time (in ms) the LED is off' +system_led_delayon = 'On-State Delay' +system_led_delayon_desc = 'Time (in ms) the LED is on' +system_led_dev = 'Device' +system_led_mode = 'Trigger Mode' +system_led_mode_link = 'Link On' +system_led_mode_tx = 'Transmit' +system_led_mode_rx = 'Receive' +network_interface_up = 'Active' +network_interface_hwaddr = 'MAC-Address' +network_interface_hwaddr_desc = 'Hardware Address' +network_interface_txrx = 'Traffic' +network_interface_txrx_desc = 'transmitted / received' +network_interface_err = 'Errors' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Create / Assign firewall-zone' +network_interface_fwzone_desc = 'This interface does not belong to any firewall zone yet.' +process_head = 'Processes' +process_descr = 'This list gives an overview over currently running system processes and their status.' +process_pid = 'PID' +process_owner = 'Owner' +process_command = 'Command' +process_cpu = 'CPU usage (%)' +process_mem = 'Memory usage (%)' +process_hup = 'Hang Up' +process_term = 'Terminate' +process_kill = 'Kill' +mem_cached = 'cached' +mem_buffered = 'buffered' +mem_free = 'free' +a_s_crontab = 'Scheduled Tasks' +a_s_crontab1 = 'This is the system crontab in which scheduled tasks can be defined.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Path to CA-Certificate' +a_w_eaptype = 'EAP-Method' +a_w_tlsprivkey = 'Path to Private Key' +a_w_tlsprivkeypwd = 'Password of Private Key' +a_w_peapauth = 'PEAP-Authentication' +a_w_peapidentity = 'PEAP-Identity' +a_w_peappassword = 'PEAP-Password' +a_w_create = 'Create Network' +hostnames = 'Hostnames' +hostnames_entries = 'Host entries' +hostnames_hostname = 'Hostname' +hostnames_address = 'IP address' +luci_components = "LuCI Components" +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.fr.lua new file mode 100644 index 0000000..a4789a0 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.fr.lua @@ -0,0 +1,327 @@ +uci_applied = 'Les changements suivants ont été appliqués' +uci_reverted = 'Les changements suivants ont été annulés' +a_i_ui = 'Interface utilisateur' +c_lucidesc = 'LuCI est une suite logicielle d'applications Lua software incluant un MVC-Webframework et une interface web pour équipements embarqués. Luci est sous license Apache.' +c_projecthome = 'Page d'accueil du projet' +c_leaddev = 'Développeurs principaux' +c_contributors = 'Contributeurs' +c_thanksto = 'Merci à' +a_i_i_hello = 'Bonjour !' +a_i_i_admin1 = 'Voici la page d'administration de LuCI.' +a_i_i_admin2 = 'LuCI est une interface graphique libre, flexible, et user friendly pour configurer OpenWrt Kamikaze.' +a_i_i_admin3 = 'Dans les pages suivantes vous pouvez ajuster tous les réglages importants de votre routeur.' +a_i_i_admin4 = 'Vous trouverez une page de navigation sur le côté gauche permettant d'accèder aux différentes pages de configuration.' +a_i_i_admin5 = 'Nous souhaitons améliorer l'interface de manière permanente, vos retours et suggestions sont primordiaux.' +a_i_i_admin6 = 'Et maintenant que la fête commence !' +a_i_i_team = 'L'équipe LuCI' +a_i_luci1 = 'Ici, vous pouvez personnaliser les réglages et les fonctionnalités de LuCI.' +a_i_ucicommit = 'Actions post-changements' +a_i_ucicommit1 = 'Ces commandes seront executées automatiquement lorsqu'une configuration UCI est appliquée, les changement prenant effet immédiatement.' +a_i_keepflash = 'Fichiers à conserver lors d'une mise à jour du firmware' +a_i_keepflash1 = 'Lors d'une nouvelle installation, ces fichiers seront ajoutés à la nouvelle installation.' +a_st_i_status1 = 'Ici, vous trouverez des informations sur l'état actuel du système comme la fréquence processeur, utilisation mémoire et trafic réseau.' +a_st_i_status2 = 'Les journaux des services ou du noyau peuvent être vus ici afin d'obtenir un aperçu de leur état.' +iwscan = 'Scan WLAN' +iwscan1 = 'Réseaux Wi-Fi dans votre environnement' +iwscan_encr = 'Chiffrement' +iwscan_link = 'Lien' +iwscan_signal = 'Signal' +iwscan_noise = 'Bruit' +routes = 'Routes' +routes_netmask = 'Masque réseau' +routes_gateway = 'Passerelle' +routes_metric = 'Metrique' +a_s_desc = 'Ici, vous pouvez configurer les aspects basiques de votre routeur comme son nom ou son fuseau horaire.' +a_s_packages = 'Logiciels' +a_s_changepw = 'Mot de passe administrateur' +a_s_p_ipkg = 'Configuration OPKG' +a_s_sshkeys = 'Clés SSH' +a_s_fstab = 'Points de montage' +a_s_flash = 'Mise à jour firmware' +a_s_i_system1 = 'Changements en rapport avec le système, son identification le logiciel/matériel installé, l'authentification ou points de montage.' +a_s_i_system2 = 'Ces réglages définissent la base de votre système.' +a_s_i_system3 = 'Soyez vigilent car un mauvais réglage peut empêcher votre équipement de démarrer, ou vous empêcher de vous y connecter.' +a_s_packages_do = 'Accomplir les actions' +a_s_packages_install = 'Installer' +a_s_packages_installurl = 'Télécharge et installe le paquet' +a_s_packages_ipkg = 'Editer la liste des paquets et le répertoire de destination' +a_s_packages_name = 'Nom du paquet' +a_s_packages_remove = 'Désinstaller' +a_s_packages_search = 'Trouver un paquet' +a_s_packages_update = 'Liste des paquets mise à jour' +a_s_packages_updatelist = 'Mettre à jour la liste des paquets' +a_s_packages_upgrade = 'Mettre à jour les paquets installés' +a_s_p_ipkg_pkglists = 'Listes de paquets' +a_s_p_ipkg_targets = 'Répertoires de destination' +a_s_changepw1 = 'Changer le mot de passe du système (Utilisateur "root")' +a_s_changepw_changed = 'Mot de passe changé avec succès' +a_s_changepw_nomatch = 'Erreur: les mots de passe ne correspondent pas' +a_s_sshkeys1 = 'Vous pouvez copier ici des clés SSH publiques (une par ligne) pour une authentification SSH sur clés publiques.' +a_s_fstab_mountpoints = 'Points de montage' +a_s_fstab_mountpoints1 = 'Les points de montage définissent l'attachement d'un périphérique au système de fichier.' +a_s_fstab_active = 'Systèmes de fichiers montés' +a_s_fstab_used = 'Utilisé' +a_s_fstab_avail = 'Disponible' +a_s_fstab_mountpoint = 'Point de montage' +a_s_fstab_device1 = 'Le périphérique de bloc contenant la partition (ex : /dev/sda1)' +a_s_fstab_fs1 = 'Le système de fichiers utilisé pour formatter le support de stockage (ex : ext3)' +a_s_fstab_swap1 = 'Si la mémoire physique n'est pas en quantité suffisante, les données inutilisées peuvent être temporairement transférée sur une partition d'échange, relevant la quantité de RAM disponible. Ce processus est lent car la mémoire d'échange ne peut être accédée aux taux de transfert de la RAM.' +a_s_flash_flashed = 'Firmware installé avec succès. Redémarrage...' +a_s_flash_flasherr = 'Programme lors de la programmation' +a_s_flash_fwimage = 'Image firmware' +a_s_flash_received = 'Image reçue. Début du processus de flashage. NE PAS ETEINDRE L'EQUIPEMENT !' +a_s_flash_inprogress = 'Ecriture du firmware...' +a_s_flash_fwupgrade = 'Mise à jour firmware' +a_s_flash_keepcfg = 'Conserver les fichiers de configuration' +a_s_flash_notimplemented = 'Désolé, cette fonction n'est pas (encore) disponible pour votre plateforme.' +a_s_flash_upgrade1 = 'Remplace les fichiers existants par les nouveaux. Le format du firmware est dépendant de la plateforme.' +a_s_reboot1 = 'Redémarrage du système d'exploitation de votre équipement' +a_s_reboot_do = 'Redémarrer' +a_s_reboot_running = 'Patientez s'il vous plaît: équipement en cours de redémarrage...' +a_s_reboot_u = 'Attention : il reste des changements non appliqués qui seront perdus après redémarrage !' +a_s_applyreboot1 = 'Changements appliqués.' +a_s_backup = 'Sauvegarder / Restaurer' +a_s_backup_backup = 'Créer une archive de sauvegarde' +a_s_backup_archive = 'Sauvegarder l'archive' +a_s_backup_reset = 'Revenir à la configuration par défaut du routeur' +a_s_backup_reset1 = 'Etes-vous sûr de vouloir revenir à la configuration par défaut du firmware ?' +a_s_backup_restore = 'Restaurer une sauvegarde' +a_s_backup1 = 'Ici, vous pouvez sauvegarder et restaurer la configuration de votre routeur et, si possible, restaurer la configuration par défaut du routeur.' +a_srv_http = 'Serveur HTTP' +a_srv_ssh = 'Serveur SSH' +a_srv_services1 = 'Les services et démons accomplissent certaines tâches sur votre équipement.' +a_srv_services2 = 'La plupart d'entre eux sont des serveurs réseaux, qui vous offrent certains services comme un accès shell, accéder à des pages comme LuCI, faire du routage mesh, envoyer des e-mails ...' +a_srv_http1 = 'Un serveur web léger qui peut être utilisé pour LuCI.' +a_srv_http_authrealm = 'Domaine d'authentification' +a_srv_http_authrealm1 = 'Le domaine qui sera affiché lors de la fenêtre d'authentification.' +a_srv_http_config1 = 'fichier de configuration par défaut : /etc/httpd.conf' +a_srv_http_root = 'Page racine' +a_srv_dropbear1 = 'Dropbear est un serveur SSH et intègre un serveur SCP' +a_srv_d_pwauth = 'Authentification par mot de passe' +a_srv_d_pwauth1 = 'Autoriser l'authentification SSH par mot de passe' +a_w_channel = 'Canal' +a_w_wifi1 = 'Dans cette page vous trouverez des options de configuration pour les réseau sans-fils.' +a_w_wifi2 = 'Vous pouvez facilement installer un périphérique 802.11a/b/g/n dans votre réseau physique existant et utiliser la gestion des interfaces virtuelles pour créer des répéteurs sans-fils ou fournir plusieurs réseaux avec un seul équipement.' +a_w_wifi3 = 'Les modes Point d'accès, Station, Ad-Hoc et WDS couplés aux chiffrements WPA et WPA2 sont gérés.' +a_w_devices1 = 'Ici vous pouvez configurer les équipements Wi-Fi installés.' +a_w_txantenna = 'Antenne transmission' +a_w_rxantenna = 'Antenne réception' +a_w_distance1 = 'Distance vers la station la plus éloignée (m)' +a_w_diversity = 'Diversité' +a_w_countrycode = 'Code pays' +a_w_connlimit = 'Limite de connexion' +a_w_networks1 = 'Vous pouvez faire fonctionner plusieurs réseaux Wi-Fi sur un seul équipement. Il existe des limitations matérielles et liées au pilote. En général vous pouvez faire fonctionner simultanément 1 réseau Ad-Hoc et 3 points d'accès simultanément.' +a_w_netid = 'Nom du réseau (ESSID)' +a_w_network1 = 'Ajouter ce réseau Wi-Fi au réseau physique' +a_w_netmanual = ' - Créer un nouveau réseau - ' +a_w_txpwr = 'Puissance d'émission' +a_w_brcmburst = 'Technologie Broadcom Frameburst' +a_w_athburst = 'Technologie Atheros Frameburst' +a_w_radiussrv = 'Serveur Radius' +a_w_radiusport = 'Port Radius' +a_w_apisolation = 'Isolation AP' +a_w_apisolation1 = 'Empêche la communication directe Client à Client' +a_w_hideessid = 'Cacher le ESSID' +a_w_ap = 'Point d'accès' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq est un serveur DHCP combiné à un requêteur DNS pour les pare-feu NAT' +dhcp_dnsmasq_domainneeded = 'Domain requis' +dhcp_dnsmasq_domainneeded_desc = 'Ne pas transmettre de requêtes DNS sans nom DNS' +dhcp_dnsmasq_authoritative = 'Authoritaire' +dhcp_dnsmasq_authoritative_desc = 'C'est le seul serveur DHCP sur le réseau local' +dhcp_dnsmasq_boguspriv = 'Filtrer les requêtes privées' +dhcp_dnsmasq_boguspriv_desc = 'Ne pas transmettre les requêtes de recherche inverse pour les réseaux locaux' +dhcp_dnsmasq_filterwin2k = 'Filtrer les requêtes inutiles' +dhcp_dnsmasq_filterwin2k_desc = 'filtre les requêtes inutiles émises par les systèmes Windows' +dhcp_dnsmasq_localisequeries = 'Localiser les requêtes' +dhcp_dnsmasq_localisequeries_desc = 'localiser la réponse suivant l'émetteur de la requête' +dhcp_dnsmasq_local = 'Serveur local' +dhcp_dnsmasq_domain = 'Domaine local' +dhcp_dnsmasq_expandhosts = 'Etendre le nom d'hôte' +dhcp_dnsmasq_expandhosts_desc = 'concatène le nom de domaine aux noms d'hôtes' +dhcp_dnsmasq_nonegcache = 'Ne pas mettre en cache les requêtes négatives' +dhcp_dnsmasq_nonegcache_desc = 'empêche la mise en cache de requêtes DNS erronnées' +dhcp_dnsmasq_readethers = 'Utiliser /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Lire /etc/ethers pour configurer le serveur DHCP' +dhcp_dnsmasq_leasefile = 'Fichier de baux' +dhcp_dnsmasq_leasefile_desc = 'fichier dans lequel les baux DHCP seront stockés' +dhcp_dnsmasq_resolvfile = 'Fichier de résolution' +dhcp_dnsmasq_resolvfile_desc = 'fichier de résolution local' +dhcp_dnsmasq_nohosts = 'Ignorer /etc/hosts' +dhcp_dnsmasq_strictorder = 'Ordre stricte' +dhcp_dnsmasq_strictorder_desc = 'Les serveurs DNS du fichier de résolution seront interrogés dans l'ordre' +dhcp_dnsmasq_logqueries = 'Journaliser les requêtes' +dhcp_dnsmasq_noresolv = 'Ignorer le fichier de résolution' +dhcp_dnsmasq_dnsforwardmax = 'Requêtes concurrentes maximum' +dhcp_dnsmasq_port = 'Port DNS' +dhcp_dnsmasq_ednspacket_max = 'taille maximum du paquet. EDNS.0 ' +dhcp_dnsmasq_dhcpleasemax = 'baux maximum' +dhcp_dnsmasq_addnhosts = 'fichiers de noms d'hôtes supplémentaires' +dhcp_dnsmasq_queryport = 'port de requête' +dhcp_dnsmasq_enabletftp = 'Activer le serveur TFTP' +dhcp_dnsmasq_tftproot = 'Racine du serveur TFTP' +dhcp_dnsmasq_dhcpboot = 'Image de démarrage réseau' +a_n_switch = 'Switch' +a_n_conntrack = 'Connexions Actives' +a_n_conntrack_desc = 'Cette page donne une vue d'ensemble des connexions réseaux actuellement actives.' +a_n_routes = 'Routes' +a_n_routes4 = 'IPv4 Routes' +a_n_routes6 = 'IPv6 Routes' +a_network1 = 'Dans cette section vous trouverez tous les réglages relatifs au réseau.' +a_network2 = 'Sur la plupart des routeurs, les ports des switchs peuvent être configurés et séparés en plusieurs VLANs.' +a_network3 = 'Les réglages des interfaces et du PPPoE / PPTP vous permettent une configuration personalisée du réseau.' +a_network4 = 'Les équipements utilisant DHCP dans votre réseau local peuvent être configurés automatique pour l'accès au réseau.' +a_network5 = 'Le pare-feu et la redirection de ports peuvent être utilisés pour fournir un service interne à un réseau extérieur.' +a_n_switch1 = 'Les ports de votre routeur peuvent être configurés pour combiner plusieurs VLANs dans lesquels les machines connectées peuvent dialoguer directement l'une avec l'autre. Les VLANs sont souvent utilisés pour séparer différences sous-réseaux. Bien souvent il y a un port d'uplink pour une connexion vers un réseau plus vaste, comme internet et les autres ports sont réservés au réseau local.' +network_switch_desc = 'Les ports appartenant à un VLAN sont séparés par des espaces. Le port ayant le numéro le plus élevé (5 en général) est souvent connecté à l'interface interne du routeur. Les équipements avec 5 ports ont souvent leur port 0 comme port d'uplink par défaut.' +a_n_ifaces1 = 'Dans cette page vous pourrez configurer les interfaces réseaux. Vous pouvez bridger différentes interfaces en cochant le champ "bridger les interfaces" et en saisissant les noms des interfaces réseau séparées par des espaces. Vous pouvez aussi utiliser la notation VLAN, INTERFACE.VLANNB (ex : eth0.1).' +a_n_i_bridge = 'Bridger les interfaces' +a_n_i_bridge1 = 'créer un bridge entre plusieurs interfaces' +dhcp_desc = 'Avec DHCP, les machines connectées au réseau peuvent recevoir leurs réglages réseau directement (adresse IP, masque de réseau, serveur DNS, ...)' +dhcp_dhcp_leasetime = 'Durée du bail' +dhcp_dhcp_dynamicdhcp = 'DHCP dynamique' +dhcp_dhcp_ignore = 'Ignorer l'interface' +dhcp_dhcp_ignore_desc = 'désactiver DHCP sur cette interface' +dhcp_dhcp_force = 'Forcer' +dhcp_dhcp_start_desc = 'première addresse (dernier octet)' +dhcp_dhcp_limit_desc = 'nombre d'adresses disponibles - 1' +dhcp_dhcp_dhcpoption = 'Options DHCP' +dhcp_dhcp_dhcpoption_desc = 'Voir "dnsmasq --help dhcp" pour une liste d'options disponibles.' +dhcp_leases = 'Baux' +luci_ethers = 'Baux Statiques' +dhcp_timeremain = 'Durée de validité' +dhcp_leases_active = 'Baux actifs' +a_n_ptp = 'Connexions Point-à-Point' +a_n_ptp1 = 'Les connexions Point-à-Point en PPPoE ou PPTP sont souvent utilisées pour connecter un équipement à internet sur du DSL ou une technologie similaire.' +network_interface_prereq = 'Vous avez besoin d'installer "comgt" pour le support UMTS/GPRS, "ppp-mod-pppoe" pour le PPPoE, "ppp-mod-pppoa" pour le PPPoA ou "pptp" pour le PPtP' +network_interface_prereq_mini = 'Vous avez besoin d'installer "ppp-mod-pppoe" pour le support PPPoE ou "pptp" pour le PPtP' +network_interface_server = 'Serveur PPTP' +network_interface_demand = 'Déconnexion automatique' +network_interface_demand_desc = 'Délai d'inactivité à partir duquel la connexion est coupée' +network_interface_keepalive = 'Maintenir la connexion' +network_interface_keepalive_desc = 'Reconnexion si la connexion est perdue' +network_interface_device = 'Interface Modem' +network_interface_device_desc = 'Le noeud d'interface de votre modem, e.g. /dev/ttyUSB0' +network_interface_defaultroute = 'Remplacer la route par défaut' +network_interface_defaultroute_desc = 'Laisser pppd remplacer la route par défaut courante pour utiliser l'interface PPP après l'établissement de la connexion' +network_interface_peerdns = 'Utiliser le DNS fourni' +network_interface_peerdns_desc = 'Configurer le serveur DNS local pour utiliser le serveur de nom fourni par le pair PPP' +network_interface_ipv6 = 'Activer l'IPv6 sur le lien PPP' +network_interface_connect = 'Script de Connexion' +network_interface_connect_desc = 'pppd exécutera ce script après l'établissement du lien PPP' +network_interface_disconnect = 'Script de Déconnexion' +network_interface_disconnect_desc = 'pppd exécutera ce script avant de déconnecter le lien PPP' +network_interface_pppd_options = 'Options pppd supplémentaires' +network_interface_pppd_options_desc = 'Spécifiez ici des arguments de ligne de commande supplémentaire pour pppd' +network_interface_apn = 'Point d'accès (APN)' +network_interface_pincode = 'code PIN' +network_interface_pincode_desc = 'Assurez-vous de fournir le bon code PIN ou vous pourriez bloquer votre carte SIM !' +network_interface_service = 'Type de service' +network_interface_maxwait = 'Délai d'initialisation' +network_interface_maxwait_desc = 'Secondes à attendre pour que le modem soit prêt avant d'essayer de se connecter' +a_n_r_routes1 = 'Avec les routes statiques vous pouvez spécifier à travers quelle interface ou passerelle un réseau peut être contacté.' +a_n_routes_static = 'Routes statiques' +a_n_routes_static4 = 'Routes IPv4 statiques' +a_n_routes_static6 = 'Routes IPv6 statiques' +a_n_routes_kernel4 = 'Routes IPv4 actives' +a_n_routes_kernel6 = 'Routes IPv6 actives' +a_n_r_target1 = 'adresse IP ou réseau' +a_n_r_target6 = 'adresse IPv6 ou réseau' +a_n_r_netmask1 = 'si la destination est un réseau' +m_n_inet = 'Connexion Internet' +m_n_local = 'Réseau Local' +m_n_route = 'Route' +m_n_brdige = 'Bridge' +m_w_ap = 'Point d'accès' +m_w_adhoc = 'Ad-Hoc' +m_w_client = 'Client' +m_w_wds = 'WDS' +m_w_clientmode = 'Mode client' +system_system_logsize = 'Taille de buffer du journal système' +system_system_logip = 'Serveur externe pour le journal système' +system_system_conloglevel = 'Niveau de gravité du journal' +system_system_conloglevel_desc = 'Niveau de gravité du journal système affiché sur la console' +m_i_processor = 'Processeur' +m_i_memory = 'Mémoire' +m_i_systemtime = 'Heure Locale' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'Première adresse attribuée' +m_n_d_numleases = 'Nombre d'adresses attribuées' +routingtable = 'Table de routage' +wlanscan = 'Scan Wifi' +frequency = 'Fréquence' +power = 'Puissance' +noise = 'Bruit' +signal = 'Signal' +link = 'Lien' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Débit binaire' +m_n_keepalive = 'reconnecter automatiquement' +m_n_dialondemand = 'déconnecter après une inactivité de' +m_n_pptp_server = 'Serveur PPTP' +leds = 'Configuration des LEDs' +leds_desc = 'Personnaliser le comportement des LEDs si possible.' +system_led_name = 'Nom de la LED' +system_led_sysfs = 'Inteface de la LED' +system_led_default = 'Etat par défaut' +system_led_default_desc = 'ticked = on' +system_led_trigger = 'Clignotant' +system_led_trigger_none = 'Aucun' +system_led_trigger_defaulton = 'Allumé par défaut' +system_led_trigger_timer = 'Timer' +system_led_trigger_heartbeat = 'Heartbeat (Load Average)' +system_led_trigger_netdev = 'Interface Réseau' +system_led_delayoff = 'Délai de l'état Off' +system_led_delayoff_desc = 'Temps (en ms) pendant lequel la LED est éteinte' +system_led_delayon = 'Délai de l'état On' +system_led_delayon_desc = 'Temps (en ms) pendant lequel la LED est allumée' +system_led_dev = 'Interface' +system_led_mode = 'Mode Clignotant' +system_led_mode_link = 'Lien établi' +system_led_mode_tx = 'Transmet' +system_led_mode_rx = 'Reçoit' +network_interface_up = 'Active' +network_interface_hwaddr = 'Addresse MAC' +network_interface_hwaddr_desc = 'Addresse matériel' +network_interface_txrx = 'Trafic' +network_interface_txrx_desc = 'transmis / reçu' +network_interface_err = 'Erreurs' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Créer / Assigner une zone du pare-feu' +network_interface_fwzone_desc = 'Cette interface n'appartient à aucune zone du pare-feu pour le moment.' +process_head = 'Processus' +process_descr = 'Cette liste donne une vue d'ensemble des processus en exécution et leur statut.' +process_pid = 'PID' +process_owner = 'Propriétaire' +process_command = 'Commande' +process_cpu = 'Utilisation CPU (%)' +process_mem = 'Utilisation Mémoire (%)' +process_hup = 'Signal (HUP)' +process_term = 'Terminer' +process_kill = 'Tuer' +mem_cached = 'mis en cache' +mem_buffered = 'bufferisé' +mem_free = 'libre' +a_s_crontab = 'Tâches Régulières' +a_s_crontab1 = 'Ceci est le système crontab avec lequel sont définies les tâches récurrentes.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Chemin de la CA' +a_w_eaptype = 'Méthode EAP' +a_w_tlsprivkey = 'Chemin de la clé privée' +a_w_tlsprivkeypwd = 'Mot de passe de la clé privée' +a_w_peapauth = 'Authentification' +a_w_peapidentity = 'Identité' +a_w_peappassword = 'Mot de passe' +a_w_create = 'Créer un réseau' +hostnames = 'Noms d'hôtes' +hostnames_entries = 'Entrées d'hôtes' +hostnames_hostname = 'Nom d'hôte' +hostnames_address = 'Adresse IP' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.it.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.it.lua new file mode 100644 index 0000000..2a62788 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.it.lua @@ -0,0 +1,327 @@ +uci_applied = 'Le seguenti modifiche sono state applicate' +uci_reverted = 'Le seguenti modifiche sono state annullate' +a_i_ui = 'Interfaccia utente' +c_lucidesc = 'LuCI è una collezione di software libero scritto in Lua comprendente un Webframework e interfaccia web MVC per dispositivi integrati. LuCI è rilasciato sotto la Apache-License.' +c_projecthome = 'Sito del progetto' +c_leaddev = 'Lead Development' +c_contributors = 'Contributing Developers' +c_thanksto = 'Ringraziamenti' +a_i_i_hello = 'Ciao!' +a_i_i_admin1 = 'Questa è l'area d'amministrazione di LuCI.' +a_i_i_admin2 = 'LuCI è un'interfaccia grafica gratuita, flessibile, e amichevole per configurare OpenWrt Kamikaze.' +a_i_i_admin3 = 'Nelle seguenti pagine puoi impostare tutti i settaggi più importanti del tuo router' +a_i_i_admin4 = 'Nota: Le modifiche devono essere confermate in LuCI cliccando Modifiche - Salva e Applica prima di essere applicate.' +a_i_i_admin5 = 'dal momento che vogliamo migliorare quest'interfaccia accettiamo suggerimenti.' +a_i_i_admin6 = 'Ed ora buon divertimento con il tuo router!' +a_i_i_team = 'Il Team di LuCI' +a_i_luci1 = 'Qui puoi personalizzare i settaggi e le funzionalità di LuCI.' +a_i_ucicommit = 'Azioni post-modifica' +a_i_ucicommit1 = 'Questi comandi verranno eseguiti automaticamente quando un comando di configurazione UCI viene applicato permettendo alle modifiche di essere applicate immediatamente.' +a_i_keepflash = 'Files da conservare quando si aggiorna un nuovo firmware' +a_i_keepflash1 = 'Quando si aggiorna un firmware con LuCI questi files verranno aggiunti al nuovo firmware.' +a_st_i_status1 = 'Qui puoi trovare informazione sullo stato del sistema come frequenza di clock della CPU, uso della memoria o dati della scheda di rete.' +a_st_i_status2 = 'Inoltre i log del kernel o dei servizi sono visualizzabili qui per avere un riassunto dello stato attuale.' +iwscan = 'Scansione WLAN' +iwscan1 = 'Reti Wifi nell'ambiente circostante' +iwscan_encr = 'Encr.' +iwscan_link = 'Collegamento' +iwscan_signal = 'Segnale' +iwscan_noise = 'Disturbo' +routes = 'Route' +routes_netmask = 'Maschera di rete' +routes_gateway = 'Gateway' +routes_metric = 'Metrica' +a_s_desc = 'Qui puoi configurare gli aspetti base del tuo dispositivo come l'hostname o il fuso orario.' +a_s_packages = 'Software' +a_s_changepw = 'Password di Amministratore' +a_s_p_ipkg = 'Configurazione di OPKG' +a_s_sshkeys = 'Chiavi SSHs' +a_s_fstab = 'Punti di mount' +a_s_flash = 'Aggiorna firmware' +a_s_i_system1 = 'Modifica impostazioni relative al sistema, la sua identificazione, installazioni hardware e software, autenticazione o punti di mount.' +a_s_i_system2 = 'Queste impostazioni definiscono la base del tuo sistema.' +a_s_i_system3 = 'Fai attenzione perchè una cattiva configurazione qui può impedire al tuo dispositivo di avviarsi o impedirti di entrarvi.' +a_s_packages_do = 'Esegui azioni' +a_s_packages_install = 'Installa' +a_s_packages_installurl = 'Scarica e installa pacchetto' +a_s_packages_ipkg = 'Modifica lista dei pacchetti e destinazione dell'installazione' +a_s_packages_name = 'Nome pacchetto' +a_s_packages_remove = 'Rimuovi' +a_s_packages_search = 'Cerca pacchetto' +a_s_packages_update = 'Lista pacchetti aggiornata' +a_s_packages_updatelist = 'Aggiorna lista pacchetti' +a_s_packages_upgrade = 'Upgrade installed packages' +a_s_p_ipkg_pkglists = 'Lista pacchetti' +a_s_p_ipkg_targets = 'Destinazione installazione' +a_s_changepw1 = 'Cambia la password dell'amministratore di sistema (Utente root)' +a_s_changepw_changed = 'Password cambiata con successo' +a_s_changepw_nomatch = 'Errore: le password non corrispondono' +a_s_sshkeys1 = 'Qui puoi incollare le tue chiavi SSH (una per linea) per l'autenticazione SSH a chiave pubblica.' +a_s_fstab_mountpoints = 'Punti di mount' +a_s_fstab_mountpoints1 = 'I punti di mount definiscono in quale punto un dispositivo di memoria verrà attaccato al tuo filesystem' +a_s_fstab_active = 'File system montati' +a_s_fstab_used = 'Usati' +a_s_fstab_avail = 'Disponibili' +a_s_fstab_mountpoint = 'Punto di mount' +a_s_fstab_device1 = 'Il file del dispositivo di memoria o della partizione (e.s. /dev/sda1)' +a_s_fstab_fs1 = 'Il filesystem usato per formattare la memoria (e.s. ext3)' +a_s_fstab_swap1 = 'Se la tua memoria è insufficiente i dati non usati possono venire temporaneamente spostati in un'area di swap risultando in un più grande quantitativo di RAM usabile. Sappi che spostare dati in swap è un processo molto lento e che il dispositivo di swap non può essere acceduto alle alte velocità della RAM.' +a_s_flash_flashed = 'Firmware aggiornato con successo. Riavvio il dispositivo...' +a_s_flash_flasherr = 'Aggiornamento fallito' +a_s_flash_fwimage = 'Firmware image' +a_s_flash_received = 'Firmware ricevuto. Mi preparo ad aggiornare il dispositivo. NON SPEGNERE IL DISPOSITIVO!' +a_s_flash_inprogress = 'Scrivendo il firmware...' +a_s_flash_fwupgrade = 'Aggiorna firmware' +a_s_flash_keepcfg = 'Mantieni files di configurazione' +a_s_flash_notimplemented = 'Spiacente, questa funzione non è (ancora) disponibile per la tua piattaforma.' +a_s_flash_upgrade1 = 'Sostituisce il firmware installato con uno nuovo. Il firmware è dipendente dalla piattaforma.' +a_s_reboot1 = 'Riavvia il sistema operativo del tuo dispositivo' +a_s_reboot_do = 'Esegui un riavvio' +a_s_reboot_running = 'Per favore attendi: Riavvio del dispositivo...' +a_s_reboot_u = 'Attenzione: Ci sono modifiche non salvate che verranno persi riavviando!' +a_s_applyreboot1 = 'Modifiche applicate.' +a_s_backup = 'Backup / Ripristina' +a_s_backup_backup = 'Crea un backup' +a_s_backup_archive = 'Archivio di backup' +a_s_backup_reset = 'Ripristina il router come predefinito' +a_s_backup_reset1 = 'Procedi annullando tutte le modifiche e resettando ai predefiniti del firmware?' +a_s_backup_restore = 'Ripristina backup' +a_s_backup1 = 'Qui puoi salvare e ripristinare la configurazione del tuo router e - se possibile - resettare il router con le impostazioni predefinite.' +a_srv_http = 'Server HTTP' +a_srv_ssh = 'Server SSH' +a_srv_services1 = 'Servizi e demoni svolgono alcune azioni sul tuo dispositivo.' +a_srv_services2 = 'Molti di loro sono servers, che offrono un determinato servizio al tuo dispositivo o alla tua rete come accesso shell, servire pagine web come LuCI, fare mesh routing, inviare e-mails, ...' +a_srv_http1 = 'Un piccolo webserver che può essere usato per servire LuCI.' +a_srv_http_authrealm = 'Authentication Realm' +a_srv_http_authrealm1 = 'Il realm che verrà visualizzato al prompt di autenticazione per le pagine protette.' +a_srv_http_config1 = 'predefinito /etc/httpd.conf' +a_srv_http_root = 'Radice dei documenti' +a_srv_dropbear1 = 'Dropbear offre accesso SSH e integra un server SCP' +a_srv_d_pwauth = 'Password di authenticazione' +a_srv_d_pwauth1 = 'Permetti autenticazione SSH tramite password' +a_w_channel = 'Canale' +a_w_wifi1 = 'In questa pagina puoi trovare impostazioni di configurazione per reti WLAN.' +a_w_wifi2 = 'Puoi facilmente integrare i tuoi dispositivi 802.11a/b/g/n-devices nella tua rete fisica e usare la scheda di rete virtuale per costruire ripetitori wireless o offrire più di una rete con un solo dispositivo.' +a_w_wifi3 = 'Sono supportate le modalità operative Managed, Client, Ad-Hoc and WDS come per la crittografia WPA e WPA2 per comunicazioni sicure.' +a_w_devices1 = 'Qui puoi configurare i tuoi dispositivi wireless installati.' +a_w_txantenna = 'Antenna trasmittente' +a_w_rxantenna = 'Antenna ricevente' +a_w_distance1 = 'Distanza della stazione più lontana (in metri)' +a_w_diversity = 'Diversity' +a_w_countrycode = 'Codice nazione' +a_w_connlimit = 'Limite connessioni' +a_w_networks1 = 'Puoi avere più reti wifi con un solo dispositivo. Sappi ceh ci sono alcune restrizioni relative all'hardware ed al driver.Normalmente puoi avere 1 rete Ad-Hoc o fino a 3 reti Master e uan rete in modalità Client contemporaneamente.' +a_w_netid = 'Nome rete (ESSID)' +a_w_network1 = 'Aggiungi la rete Wifi alla rete fisica' +a_w_netmanual = ' - Crea nuova rete - ' +a_w_txpwr = 'Potenza di trasmissione' +a_w_brcmburst = 'Frameburst Broadcom' +a_w_athburst = 'Frameburst Atheros' +a_w_radiussrv = 'Server Radius' +a_w_radiusport = 'Porta Radius' +a_w_apisolation = 'Isolazione AP' +a_w_apisolation1 = 'Impedisci la comunicazione fra Client' +a_w_hideessid = 'Nascondi ESSID' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq è un server DHCP e forwarder DNS per firewall NAT' +dhcp_dnsmasq_domainneeded = 'Dominio richiesto' +dhcp_dnsmasq_domainneeded_desc = 'Non inoltrare le richieste DNS senza nome DNS' +dhcp_dnsmasq_authoritative = 'Autoritativo' +dhcp_dnsmasq_authoritative_desc = 'Questo è l'unico server DHCP nella tua rete locale' +dhcp_dnsmasq_boguspriv = 'Filtra privati' +dhcp_dnsmasq_boguspriv_desc = 'Non inoltrare richieste per le reti locali' +dhcp_dnsmasq_filterwin2k = 'Filtra inutili' +dhcp_dnsmasq_filterwin2k_desc = 'Filtra richieste DNS inutili di sistemi windows' +dhcp_dnsmasq_localisequeries = 'Localizza richieste' +dhcp_dnsmasq_localisequeries_desc = 'localizza l'hostname a seconda delle sue sottoreti' +dhcp_dnsmasq_local = 'Server locale' +dhcp_dnsmasq_domain = 'Dominio locale' +dhcp_dnsmasq_expandhosts = 'Espandi host' +dhcp_dnsmasq_expandhosts_desc = 'aggiungi nomi di dominio nel file resolv' +dhcp_dnsmasq_nonegcache = 'non tenere sconosciuti in cache' +dhcp_dnsmasq_nonegcache_desc = 'impedisci la cache di risposte DNS negative' +dhcp_dnsmasq_readethers = 'Usa /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Leggi /etc/ethers per configurare il server DHCP' +dhcp_dnsmasq_leasefile = 'File di lease' +dhcp_dnsmasq_leasefile_desc = 'file dove vengono salvati i lease DHCP assegnati' +dhcp_dnsmasq_resolvfile = 'File resolv' +dhcp_dnsmasq_resolvfile_desc = 'File DNS locale' +dhcp_dnsmasq_nohosts = 'Ignora /etc/hosts' +dhcp_dnsmasq_strictorder = 'Ordine severo' +dhcp_dnsmasq_strictorder_desc = 'I server DNS verranno contattati nell'ordine del file resolv' +dhcp_dnsmasq_logqueries = 'Logga richieste' +dhcp_dnsmasq_noresolv = 'Ignora file resolv' +dhcp_dnsmasq_dnsforwardmax = 'richieste contemporanee' +dhcp_dnsmasq_port = 'Porta DNS' +dhcp_dnsmasq_ednspacket_max = 'Dimensione massima pacchetto EDNS0' +dhcp_dnsmasq_dhcpleasemax = 'Numero massimo di lease DHCP' +dhcp_dnsmasq_addnhosts = 'file hosts aggiuntivo' +dhcp_dnsmasq_queryport = 'porta per le richieste' +dhcp_dnsmasq_enabletftp = 'Abilita server TFTP' +dhcp_dnsmasq_tftproot = 'Radice del server TFTP' +dhcp_dnsmasq_dhcpboot = 'Immagine boot da rete' +a_n_switch = 'Switch' +a_n_conntrack = 'Connessioni attive' +a_n_conntrack_desc = 'Questa pagina ti da una riassunto delle connessioni adesso attive.' +a_n_routes = 'Route' +a_n_routes4 = 'Route IPv4' +a_n_routes6 = 'Route IPv6' +a_network1 = 'In quest'area puoi trovare tutte le impostazioni relative alla rete.' +a_network2 = 'Su molti router lo switch può essere suddiviso liberamente in molte VLANs.' +a_network3 = 'Le impostazioni delle interfacce e di PPPoE / PPTP permettono una configurazione personalizzata della rete e delle connessioni ad altre reti come Internet.' +a_network4 = 'Con DHCP i dispositivi nella tua rete locale possono venire automaticamente configurati per la comunicazione in rete.' +a_network5 = 'Firewall e portforwarding possono essere usati per proteggere la tua rete offrendo servizi alle reti esterne.' +a_n_switch1 = 'Le porte di rete del tuo router possono essere combinate in molte VLAN nelle quali i computer possono comunicare direttamente fra di loro. Le VLAN sono spesso usate per separare segmenti di rete differenti. Spesso c'è come predefinita una porta per la connessione alla prossiam rete più grande come Internet e altre porte per le reti locali.' +network_switch_desc = 'Le porte che appartengono ad una VLAN sono separate con spazi. La porta con priorità più alta (di solito 5) è spesso la connessione all'interfaccia di rete più interna del router. Su dispositivi con 5 porte spesso la porta più bassa (0) è quella di Uplink.' +a_n_ifaces1 = 'In questa pagina puoi configurare le interfacce di rete.Puoi unire più interfacce spuntando la voce "unisci interfacce" e inserendo i nomi di più interfacce di rete separate da spazi. Puoi anche usare la notazione VLAN INTERFACCIA.VLANNUM (e.s.: eth0.1).' +a_n_i_bridge = 'Unisci interfacce' +a_n_i_bridge1 = 'Crea un bridge sulle interfacce selezionate' +dhcp_desc = 'Con DHCP i membri della rete possono ricevere automaticamente le loro impostazioni di rete (indirizzi IP, maschere di rete, server DNS, ...).' +dhcp_dhcp_leasetime = 'Tempo di lease' +dhcp_dhcp_dynamicdhcp = 'DHCP dinamico' +dhcp_dhcp_ignore = 'Ignora interfaccia' +dhcp_dhcp_ignore_desc = 'disabilita DHCP per queste interfacce' +dhcp_dhcp_force = 'Forza' +dhcp_dhcp_start_desc = 'primo indirizzo (ultimo ottetto)' +dhcp_dhcp_limit_desc = 'numero di indirizzi serviti -1' +dhcp_dhcp_dhcpoption = 'Opzioni DHCP' +dhcp_dhcp_dhcpoption_desc = 'Vedi "dnsmasq --help dhcp" per una lista di opzioni disponibile.' +dhcp_leases = 'Lease' +luci_ethers = 'Leases statici' +dhcp_timeremain = 'Tempo lease residuo' +dhcp_leases_active = 'Lease attivi' +a_n_ptp = 'Connessioni Point-to-Point' +a_n_ptp1 = 'Connessioni Point-to-Point con PPPoE o PPTP sono spesso usate per connettere un dispositivo su DSL o tecnologie simili ad un an access point internet.' +network_interface_prereq = 'Devi installare "comgt" per il supporto UMTS/GPRS, "ppp-mod-pppoe" per PPPoE, "ppp-mod-pppoa" per PPPoA e "pptp" per PPtP' +network_interface_prereq_mini = 'Devi installare "ppp-mod-pppoe" per il supporto PPPoE e "pptp" per PPtP' +network_interface_server = 'Server PPTP' +network_interface_demand = 'Disconnetti automaticamente' +network_interface_demand_desc = 'Tempo (in secondi) dopo il quale una connessione inattiva verrà chiusa' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'Numero di test di connettività falliti prima di una riconnessione' +network_interface_device = 'Dispositivo modem' +network_interface_device_desc = 'Il device node del tuo modem, e.s. /dev/ttyUSB0' +network_interface_defaultroute = 'Sostituisci route di default' +network_interface_defaultroute_desc = 'Consenti a pppd di sostituire la route di default con la route corrente per usare l'interfaccia PPP dopo una connessione riuscita' +network_interface_peerdns = 'Usa DNS ottenuti' +network_interface_peerdns_desc = 'Configura il server DNS locale per usare i server DNSnegoziati da PPP' +network_interface_ipv6 = 'Attiva IPv6 sul collegamento PPP' +network_interface_connect = 'Script connessione' +network_interface_connect_desc = 'Permette a pppd di avviare questo script dopo l'avvenuta connessione PPP' +network_interface_disconnect = 'Script disconnessione' +network_interface_disconnect_desc = 'Permette a pppd di avviare questo script prima della disconnessione PPP' +network_interface_pppd_options = 'Opzioni pppd aggiuntive' +network_interface_pppd_options_desc = 'Specifica opzioni linea di comando aggiuntive per pppd qui' +network_interface_apn = 'Access point (APN)' +network_interface_pincode = 'Codice PIN' +network_interface_pincode_desc = 'Fai attenzione di inserire il codice PIN corretto qui o potresti bloccare la tua sim card!' +network_interface_service = 'Tipo di servizio' +network_interface_maxwait = 'Tempo di attesa inizializzazione' +network_interface_maxwait_desc = 'Secondi da attendere prima che il modem diventi pronto prima di provare a connettersi' +a_n_r_routes1 = 'Le route specificano attraverso quale interfaccia e gateway un certo host o rete può essere raggiunto.' +a_n_routes_static = 'Route statiche' +a_n_routes_static4 = 'Route statiche IPv4' +a_n_routes_static6 = 'Route statiche IPv6' +a_n_routes_kernel4 = 'Route IPv4 attive' +a_n_routes_kernel6 = 'Route IPv6 attive' +a_n_r_target1 = 'IP dell'host o rete' +a_n_r_target6 = 'Indirizzo IPv6 o rete (CIDR)' +a_n_r_netmask1 = 'se la destinazione è una rete' +m_n_inet = 'Connessione Internet' +m_n_local = 'Rete locale' +m_n_route = 'Route' +m_n_brdige = 'Bridge' +m_w_ap = 'Offri (Access Point)' +m_w_adhoc = 'Independente (Ad-Hoc)' +m_w_client = 'Partecipa (Client)' +m_w_wds = 'Distribuita (WDS)' +m_w_clientmode = 'Modalità client' +system_system_logsize = 'Dimensione buffer log di sistema' +system_system_logip = 'Server log di sistema esterno' +system_system_conloglevel = 'Livello output di log' +system_system_conloglevel_desc = 'Livello output di log sulla console' +m_i_processor = 'Processore' +m_i_memory = 'Memoria' +m_i_systemtime = 'Ora locale' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'Primo indirizzo offerto' +m_n_d_numleases = 'Numero di indirizzi offerti' +routingtable = 'Tabella di routing' +wlanscan = 'Scansione Wifi' +frequency = 'Frequenza' +power = 'Potenza' +noise = 'Rumore' +signal = 'Segnale' +link = 'Collegamento' +frag = 'Framm.' +rts = 'RTS' +bitrate = 'Bitrate' +m_n_keepalive = 'riconnetti automaticamente' +m_n_dialondemand = 'disconnetti quando non usata per' +m_n_pptp_server = 'Server PPTP' +leds = 'Configurazione LED' +leds_desc = 'Personalizza la configurazione dei LED del sistema se possibile.' +system_led_name = 'Nome LED' +system_led_sysfs = 'Dispositivo LED' +system_led_default = 'Stato predefinito' +system_led_default_desc = 'spuntato = on' +system_led_trigger = 'Causa' +system_led_trigger_none = 'Nessuna' +system_led_trigger_defaulton = 'Predefinito on' +system_led_trigger_timer = 'Timer' +system_led_trigger_heartbeat = 'Battito (Carico medio)' +system_led_trigger_netdev = 'Dispositivo di rete' +system_led_delayoff = 'Tempo dello stato off' +system_led_delayoff_desc = 'Per quanto tempo (in ms) il LED è off' +system_led_delayon = 'Tempo dello stato on' +system_led_delayon_desc = 'Per quanto tempo (in ms) il LED è on' +system_led_dev = 'Dispositivo' +system_led_mode = 'Modalità causa' +system_led_mode_link = 'Collegamento on' +system_led_mode_tx = 'Trasmissione' +system_led_mode_rx = 'Ricezione' +network_interface_up = 'Attiva' +network_interface_hwaddr = 'Indirizzo MAC' +network_interface_hwaddr_desc = 'Hardware Address' +network_interface_txrx = 'Traffico' +network_interface_txrx_desc = 'transmessi / ricevuti' +network_interface_err = 'Errori' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Crea / Assegna zona firewall' +network_interface_fwzone_desc = 'Questa interfaccia non appartiene a nessuna zona del firewall ancora.' +process_head = 'Processi' +process_descr = 'Questa lista da un riassunto dei processi correntemente attivi e del loro stato.' +process_pid = 'PID' +process_owner = 'Proprietario' +process_command = 'Comando' +process_cpu = 'Uso CPU (%)' +process_mem = 'Uso Memory (%)' +process_hup = 'Hangup' +process_term = 'Termina' +process_kill = 'Uccidi' +mem_cached = 'in cache' +mem_buffered = 'in buffer' +mem_free = 'libera' +a_s_crontab = 'Operazioni programmate' +a_s_crontab1 = 'Questa è la crontab del sistema nella quale possono essere definiti le operazioni da programmare.' +a_w_nasid = 'ID della NAS' +a_w_cacert = 'Percorso al certificato CA' +a_w_eaptype = 'Metodo EAP' +a_w_tlsprivkey = 'Percorso alla chiave privata' +a_w_tlsprivkeypwd = 'Password della chiave privata' +a_w_peapauth = 'Autenticazione PEAP' +a_w_peapidentity = 'Identità PEAP' +a_w_peappassword = 'Password PEAP' +a_w_create = 'Crea rete' +hostnames = 'Hostname' +hostnames_entries = 'Campi host' +hostnames_hostname = 'Hostname' +hostnames_address = 'Indirizzo IP' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.pt-br.lua new file mode 100644 index 0000000..585ba86 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.pt-br.lua @@ -0,0 +1,327 @@ +uci_applied = 'As seguintes alterações foram aplicadas' +uci_reverted = 'As seguintes alterações foram recuperadas' +a_i_ui = 'Interface do Usuário' +c_lucidesc = 'LuCI é uma coleção gratuita de softwares Lua incluindo um Framework Web MVC e uma Interface Web para equipamentos embarcados. LuCI é licenciado sob a Licença Apache.' +c_projecthome = 'Página do Projeto' +c_leaddev = 'Líder(es) do Desenvolvimento' +c_contributors = 'Desenvolvedores que Crontribuíram' +c_thanksto = 'Obrigado à' +a_i_i_hello = 'Olá!' +a_i_i_admin1 = 'Esta é a área de administração LuCI.' +a_i_i_admin2 = 'LuCI é gratuito, flexível e uma interface gráfica fácil de utilizar para configurar OpenWrt Kamikaze.' +a_i_i_admin3 = 'Nas próximas páginas você pode ajustar todas as definições importantes do seu roteador.' +a_i_i_admin4 = 'Aviso: No LuCI as alterações devem ser confirmadas clicando em Alterações - Salvar & Aplicar antes de serem aplicadas.' +a_i_i_admin5 = 'Como nós sempre queremos melhorar essa interface, estamos ansiosos para seus comentários e sugestões.' +a_i_i_admin6 = 'E agora divirta-se com o seu roteador!' +a_i_i_team = 'O Time do LuCI' +a_i_luci1 = 'Aqui você pode customizar as configurações e funcionalidades do LuCI.' +a_i_ucicommit = 'Ações pós-gravação' +a_i_ucicommit1 = 'Estes comandos são executados automaticamente quando uma determinada configuração da UCI está gravada, permitindo mudanças a serem aplicadas instantaneamente.' +a_i_keepflash = 'Arquivos que devem ser mantidos quando gravar um novo firmware.' +a_i_keepflash1 = 'Quando gravar um novo firmware com o LuCI estes arquivos serão adicionados ao novo firmware instalado.' +a_st_i_status1 = 'Aqui você pode encontrar informações sobre o estado atual do sistema, como CPU, frequência do relógio, uso de memória ou da interface de rede de dados.' +a_st_i_status2 = 'Também os arquivos de logs do kernel ou dos serviços podem serem vistos aqui para obter uma visão geral sobre o seu estado atual.' +iwscan = 'WLAN-Scan' +iwscan1 = 'Redes Wifi no seu ambiente local' +iwscan_encr = 'Encr.' +iwscan_link = 'Link' +iwscan_signal = 'Sinal' +iwscan_noise = 'Ruído' +routes = 'Rotas' +routes_netmask = 'Netmask' +routes_gateway = 'Gateway' +routes_metric = 'Métrica' +a_s_desc = 'Aqui você pode configurar os aspectos básicos do seu equipamento como o nome do host ou o fuso horário.' +a_s_packages = 'Software' +a_s_changepw = 'Senha do Admin' +a_s_p_ipkg = 'Configuração-OPKG' +a_s_sshkeys = 'Chaves-SSH' +a_s_fstab = 'Pontos de Montagem' +a_s_flash = 'Atualizar Firmware' +a_s_i_system1 = 'Altera as configurações relacionadas com o sistema em si, sua identificação, hardware e software instalados, autenticação ou pontos de montagem.' +a_s_i_system2 = 'Essas configurações definem a base do seu sistema.' +a_s_i_system3 = 'Preste atenção de que qualquer configuração errada aqui pode impedir o seu equipamento de inicilizar ou talvez bloquear seu acesso de fora à ele.' +a_s_packages_do = 'Executar Ações' +a_s_packages_install = 'Instalar' +a_s_packages_installurl = 'Fazer download e instalar pacote' +a_s_packages_ipkg = 'Editar listas de pacotes e destinos de instalação' +a_s_packages_name = 'Nome do Pacote' +a_s_packages_remove = 'Remover' +a_s_packages_search = 'Procurar pacote' +a_s_packages_update = 'Listas de pacotes atualizadas' +a_s_packages_updatelist = 'Atualizar listas de pacotes' +a_s_packages_upgrade = 'Atualizar os pacotes instalados' +a_s_p_ipkg_pkglists = 'Listas de pacotes' +a_s_p_ipkg_targets = 'Destino de Instalação' +a_s_changepw1 = 'Altera a senha do administrador do sistema (Usuário root)' +a_s_changepw_changed = 'Senha alterada com sucesso' +a_s_changepw_nomatch = 'Erro: As senhas estão diferentes' +a_s_sshkeys1 = 'Aqui você pode colar suas Chaves-SSH públicas (uma por linha) para a autenticação SSH por chave-pública.' +a_s_fstab_mountpoints = 'Pontos de Montagem' +a_s_fstab_mountpoints1 = 'Pontos de montagem definem em que ponto um dispositivo de memória será anexado ao sistema de arquivos' +a_s_fstab_active = 'Sistemas de arquivos montados' +a_s_fstab_used = 'Usado' +a_s_fstab_avail = 'Disponível' +a_s_fstab_mountpoint = 'Ponto de Montagem' +a_s_fstab_device1 = 'O arquivo do dispositivo de memória ou a partição (ex. /dev/sda1)' +a_s_fstab_fs1 = 'O sistema que foi usado para formatar a memória (ex. ext3)' +a_s_fstab_swap1 = 'Se a sua memória física for insuficiente, os dados poderão ser trocados temporariamente para um dispositivo swap, resultando em uma maior quantidade de memória utilizável RAM. Esteja ciente de que a troca de dados (swap) é um processo muito lento pois o dispositivo swap não pode ser acessado com um nível elevado de memória RAM.' +a_s_flash_flashed = 'Firmware gravado com sucesso. Reiniciando o equipamento...' +a_s_flash_flasherr = 'Falha na gravação' +a_s_flash_fwimage = 'Imagem do firmware' +a_s_flash_received = 'Imagem recebida. Durante o processo de gravação, NÃO DESLIGUE O EQUIPAMENTO!' +a_s_flash_inprogress = 'Gravando firmware...' +a_s_flash_fwupgrade = 'Atualizar Firmware' +a_s_flash_keepcfg = 'Manter arquivos de configuração' +a_s_flash_notimplemented = 'Desculpe, esta função não está (ainda) disponível para sua plataforma.' +a_s_flash_upgrade1 = 'Substitui o firmware instalado por um mais novo. O formato do firmware depende da plataforma.' +a_s_reboot1 = 'Reinicia o seu equipamento' +a_s_reboot_do = 'Executar reinicialização' +a_s_reboot_running = 'Por favor aguarde: Equipamento reiniciando...' +a_s_reboot_u = 'Aviso: Existem alterações não salvas que serão perdidas durante a reinicialização!' +a_s_applyreboot1 = 'Alterações aplicadas.' +a_s_backup = 'Backup / Restauração' +a_s_backup_backup = 'Criar backup' +a_s_backup_archive = 'Arquivo de backup' +a_s_backup_reset = 'Restaurar as configurações padrão do roteador' +a_s_backup_reset1 = 'Proceder com a restauração de as configurações padrões?' +a_s_backup_restore = 'Restaurar backup' +a_s_backup1 = 'Aqui você pode fazer o backup e restaurar as configurações do seu roteador e - se possível - restaurar seu roteador para as configurações padrão.' +a_srv_http = 'Servidor-HTTP' +a_srv_ssh = 'Servidor-SSH' +a_srv_services1 = 'Serviços e daemons executando diversas tarefas no seu equipamento.' +a_srv_services2 = 'A maioria deles são servidores de rede, que oferecem um determinado serviço para seu equipamento ou rede como acesso shell, servindo páginas web como o LuCI, fazendo roteamento, enviando e-mails, ...' +a_srv_http1 = 'Um pequeno servidor web que pode ser utilizado para servir a interface LuCI.' +a_srv_http_authrealm = 'Autenticação Realm' +a_srv_http_authrealm1 = 'O realm que será mostrado no prompt de autenticação das páginas protegidas.' +a_srv_http_config1 = 'padrão é /etc/httpd.conf' +a_srv_http_root = 'Diretório raiz' +a_srv_dropbear1 = 'Dropbear oferece um acesso shell seguro à rede (SSH) e um servidor SCP integrado' +a_srv_d_pwauth = 'Autenticação por senha' +a_srv_d_pwauth1 = 'Permitir autenticação SSH por senha' +a_w_channel = 'Canal' +a_w_wifi1 = 'Nesta página você encontrará opções de configuração WLAN baseada em redes sem fio.' +a_w_wifi2 = 'Você pode facilmente integrar seus equipamentos 802.11a/b/g/n com sua rede física e usar o adaptador virtual para construir repetidoras wireless ou oferecer várias redes com um equipamento.' +a_w_wifi3 = 'Há suporte para os modos Managed, Client, Ad-Hoc e WDS bem como encriptação WPA e WPA2 proteger a comunicação.' +a_w_devices1 = 'Aqui você pode configurar dispositivos wifi instalados wifi. ' +a_w_txantenna = 'Antena de Transmissão' +a_w_rxantenna = 'Antena para Recebimento' +a_w_distance1 = 'Distãncia para a estação mais distante (em metros)' +a_w_diversity = 'Diversidade' +a_w_countrycode = 'Código do País' +a_w_connlimit = 'Limite de Conexão' +a_w_networks1 = 'Você pode executar várias redes wifi com um dispositivo. Esteja ciente de que existem certas restrições de hardware e de driver específico. Normalmente você pode operar 1 rede Ad-Hoc ou até 3 redes Master-Mode e 1 Client-Mode simultaneamente.' +a_w_netid = 'Nome da Rede (ESSID)' +a_w_network1 = 'Adicione a rede Wifi à rede física' +a_w_netmanual = ' - Criar nova Rede - ' +a_w_txpwr = 'Potência de Transmissão' +a_w_brcmburst = 'Broadcom Frame Burst' +a_w_athburst = 'Atheros Frame Burst' +a_w_radiussrv = 'Servidor Radius' +a_w_radiusport = 'Porta-Radius' +a_w_apisolation = 'Isolamento do AP' +a_w_apisolation1 = 'Impede a comunicação de Cliente para Cliente' +a_w_hideessid = 'Ocultar ESSID' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq é um combinado Servidor-DHCP e Encaminhador-DNS para firewalls NAT' +dhcp_dnsmasq_domainneeded = 'Domínio requerido' +dhcp_dnsmasq_domainneeded_desc = 'Não encaminhar Requisições-DNS sem o Nome do DNS' +dhcp_dnsmasq_authoritative = 'Autoritário' +dhcp_dnsmasq_authoritative_desc = 'Este é o único DHCP na rede local' +dhcp_dnsmasq_boguspriv = 'Filtro privado' +dhcp_dnsmasq_boguspriv_desc = 'Não encaminhar as pesquisas reversas para redes locais' +dhcp_dnsmasq_filterwin2k = 'Filtro de inutilidade' +dhcp_dnsmasq_filterwin2k_desc = 'Filtro de initulidades de consultas-DNS de sistemas windows' +dhcp_dnsmasq_localisequeries = 'Locallizar consultas' +dhcp_dnsmasq_localisequeries_desc = 'Localizar o hostname dependendo de sua sub-rede' +dhcp_dnsmasq_local = 'Servidor Local' +dhcp_dnsmasq_domain = 'Domínio Local' +dhcp_dnsmasq_expandhosts = 'Expandir Hosts' +dhcp_dnsmasq_expandhosts_desc = 'Adiciona os nomes dos domínios às entradas de hosts no arquivo resolv' +dhcp_dnsmasq_nonegcache = 'Não fazer cache desconhecido' +dhcp_dnsmasq_nonegcache_desc = 'Impede o cache de respostas-DNS negativas' +dhcp_dnsmasq_readethers = 'Usar /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Ler /etc/ethers para configurar o Servidor-DHCP' +dhcp_dnsmasq_leasefile = 'Arquivo Lease' +dhcp_dnsmasq_leasefile_desc = 'Arquivo onde os Leases-DHCP serão armazenados' +dhcp_dnsmasq_resolvfile = 'Arquivo Resolv' +dhcp_dnsmasq_resolvfile_desc = 'Arquivo local de DNS' +dhcp_dnsmasq_nohosts = 'Ignorar /etc/hosts' +dhcp_dnsmasq_strictorder = 'Ordem Exata' +dhcp_dnsmasq_strictorder_desc = 'Servidor-DNS será consultado na ordem do arquivo resolv' +dhcp_dnsmasq_logqueries = 'Log das consultas' +dhcp_dnsmasq_noresolv = 'Ignorar arquivo resolv' +dhcp_dnsmasq_dnsforwardmax = 'Consultas simultâneas' +dhcp_dnsmasq_port = 'Porta do DNS' +dhcp_dnsmasq_ednspacket_max = 'tamanho max. do pacote EDNS0' +dhcp_dnsmasq_dhcpleasemax = 'max. de DHCP-Leases' +dhcp_dnsmasq_addnhosts = 'arquivo host adicional' +dhcp_dnsmasq_queryport = 'porta para consulta' +dhcp_dnsmasq_enabletftp = 'Ativar servidor TFTP' +dhcp_dnsmasq_tftproot = 'Diretório raiz do servidor TFTP' +dhcp_dnsmasq_dhcpboot = 'Imagem para o boot remoto' +a_n_switch = 'Switch' +a_n_conntrack = 'Conexões Ativas' +a_n_conntrack_desc = 'Esta página fornece informações sobre as conexões de rede ativas.' +a_n_routes = 'Rotas' +a_n_routes4 = 'Rotas IPv4' +a_n_routes6 = 'Rotas IPv6' +a_network1 = 'Neste espaço você encontrará todas as configurações relacionadas à rede.' +a_network2 = 'Na maioria dos roteadores o switch de rede pode ser configurado livremente e dividos em diversas VLANs.' +a_network3 = 'Interfaces e Configurações-PPPoE / PPTP permite uma organização customizada da rede e conexões com outras redes, como a Internet.' +a_network4 = 'Com o DHCP dispositivos na sua rede local podem ser automaticamente configurados para a comunicação da rede.' +a_network5 = 'Firewall e redirecionamento de portas podem ser usados para proteger sua rede ao mesmo tempo que prestam serviços às redes externas.' +a_n_switch1 = 'As portas de rede do seu roteador podem ser combinadas com diversas VLANs em que os computadores podem se comunicar diretamente entre si. VLANs são frequentemente usadas para separar segmentos de redes diferentes. Muitas vezes é padrão uma porta Uplink para a conexão com a próxima maior rede, como a Internet e outras portas para uma rede local.' +network_switch_desc = 'Portas que pertencem a uma VLAN são separadas com espaços. A porta com o maior número (geralmente 5) é muitas vezes a conexão com a interface de rede interna do roteador. Em dispositivos com 5 portas muitas vezes a porta com o número mais baixo (0) é a porta predefinida como Uplink.' +a_n_ifaces1 = 'Nesta página você pode configurar as interfaces de rede. Você pode ter várias interfaces do tipo bridge, assinalando o campo "interfaces bridge" e entrar com os nomes de várias interfaces de rede separadas por espaços. Você pode também usar a notação para VLAN INTERFACE.VLANNR (ex.: eth0.1).' +a_n_i_bridge = 'Interfaces bridge' +a_n_i_bridge1 = 'cria uma bridge sobre determinada(s) interface(s)' +dhcp_desc = 'Com o DHCP membros da rede podem automaticamente receber suas configurações de rede (endereço-IP, netmask, servidor-DNS, ...).' +dhcp_dhcp_leasetime = 'Tempo de Lease' +dhcp_dhcp_dynamicdhcp = 'DHCP Dinâmico' +dhcp_dhcp_ignore = 'Ignorar Interface' +dhcp_dhcp_ignore_desc = 'desabilitar DHCP para esta interface' +dhcp_dhcp_force = 'Forçar' +dhcp_dhcp_start_desc = 'primeiro endereço (último octeto)' +dhcp_dhcp_limit_desc = 'número de endereços para lease -1' +dhcp_dhcp_dhcpoption = 'Opções-DHCP' +dhcp_dhcp_dhcpoption_desc = 'Veja "dnsmasq --help dhcp" para a lista disponível de opções.' +dhcp_leases = 'Leases' +luci_ethers = 'Leases Estáticos' +dhcp_timeremain = 'Tempo de lease restante' +dhcp_leases_active = 'Leases Ativos' +a_n_ptp = 'Conexões Ponto-a-Ponto' +a_n_ptp1 = 'Conexões Ponto-a-Ponto com PPPoE ou PPTP muitas vezes são usados para conectar um dispositivo sobre DSL ou tecnologia similar para um ponto de acesso à internet.' +network_interface_prereq = 'Você precisa instalar os pacotes "comgt" para UMTS/GPRS, "ppp-mod-pppoe" para PPPoE, "ppp-mod-pppoa" para PPPoA ou "pptp" para o suporte PPtP' +network_interface_prereq_mini = 'Você precisa instalar os pacotes "ppp-mod-pppoe" para PPPoE ou "pptp" para o suporte PPtP' +network_interface_server = 'Servidor-PPTP' +network_interface_demand = 'Desconexão Automática' +network_interface_demand_desc = 'Tempo (em segundos) para desconexão de uma conexão não mais utilizada' +network_interface_keepalive = 'Manter em Atividade' +network_interface_keepalive_desc = 'Número de falhas do teste de conexão para incializar uma reconexão automática' +network_interface_device = 'Dispositivo do Modem' +network_interface_device_desc = 'O caminho do dispostivo do seu modem, ex. /dev/ttyUSB0' +network_interface_defaultroute = 'Susbtituir a rota padrão' +network_interface_defaultroute_desc = 'Permitir o pppd substituir a rota padrão atual e usar a interface PPP como padrão após a conexão ser efetuada com sucesso' +network_interface_peerdns = 'Utilizar DNS do ponto' +network_interface_peerdns_desc = 'Configurar o servidor DNS local para usar o servidores de nomes fornecidos pelo ponto PPP' +network_interface_ipv6 = 'Ativar IPv6 no link PPP' +network_interface_connect = 'Script de conexão' +network_interface_connect_desc = 'Deixar o pppd executar este script após o estabelecimento do link PPP' +network_interface_disconnect = 'Script de desconexão' +network_interface_disconnect_desc = 'Deixar o pppd executar esse script antes de derrubar o link PPP' +network_interface_pppd_options = 'Opções adicionais do pppd' +network_interface_pppd_options_desc = 'Especificar argumentos adicionais por linha de comando para o pppd aqui' +network_interface_apn = 'Ponto de acesso (APN)' +network_interface_pincode = 'Código PIN' +network_interface_pincode_desc = 'Certifique-se de que você forneceu o código PIN correto aqui, ou você pode bloquear o seu cartão SIM!' +network_interface_service = 'Tipo do serviço' +network_interface_maxwait = 'Configurar tempo de espera' +network_interface_maxwait_desc = 'Segundos de espera para o modem ficar pronto antes de tentar se conectar' +a_n_r_routes1 = 'Rotas específicas sobre qual interface e gateway um determinado host ou rede pode ser alcançado.' +a_n_routes_static = 'Rotas Estáticas' +a_n_routes_static4 = 'Rotas Estáticas IPv4' +a_n_routes_static6 = 'Rotas Estáticas IPv6' +a_n_routes_kernel4 = 'Rotas-IPv4 ativas' +a_n_routes_kernel6 = 'Rotas-IPv6 ativas' +a_n_r_target1 = 'IP do host ou rede' +a_n_r_target6 = 'IPv6 do host ou rede' +a_n_r_netmask1 = 'se o destino for uma rede' +m_n_inet = 'Conexão com a Internet' +m_n_local = 'Rede Local' +m_n_route = 'Rota' +m_n_brdige = 'Bridge' +m_w_ap = 'Provedor (Access Point)' +m_w_adhoc = 'Independente (Ad-Hoc)' +m_w_client = 'Cliente (Client)' +m_w_wds = 'Distribuído (WDS)' +m_w_clientmode = 'Modo CLient' +system_system_logsize = 'Tamanho do buffer do sistema de log' +system_system_logip = 'Servidor externo do sistema de log' +system_system_conloglevel = 'Nível de saída do log' +system_system_conloglevel_desc = 'Nível das mensagens de log no console' +m_i_processor = 'Processador' +m_i_memory = 'Memória' +m_i_systemtime = 'Hora Local' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'Primeiro endereço de lease' +m_n_d_numleases = 'Número de endereços de lease' +routingtable = 'Tebela de roteamento' +wlanscan = 'Procurar redes Wifi' +frequency = 'Frequência' +power = 'Potência' +noise = 'Ruído' +signal = 'Sinal' +link = 'Link' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Bitrate' +m_n_keepalive = 'reconectar automaticamente' +m_n_dialondemand = 'desconectar quando ocioso por' +m_n_pptp_server = 'Servidor-PPTP' +leds = 'Configuração do LED' +leds_desc = 'Customiza o comportamento do dispositivo de LEDs se possível.' +system_led_name = 'Nome do LED' +system_led_sysfs = 'Dispositivo do LED' +system_led_default = 'Estado padrão' +system_led_default_desc = 'selecionado como = ligado' +system_led_trigger = 'Evento' +system_led_trigger_none = 'Nenhum' +system_led_trigger_defaulton = 'Padrão Ligado' +system_led_trigger_timer = 'Contador' +system_led_trigger_heartbeat = 'Carga Média' +system_led_trigger_netdev = 'Dispositivo de Rede' +system_led_delayoff = 'Tempo no Estado Desligado' +system_led_delayoff_desc = 'Tempo (em ms) do LED desligado' +system_led_delayon = 'Tempo no Estado Ligado' +system_led_delayon_desc = 'Tempo (em ms) do LED ligado' +system_led_dev = 'Dispositivo' +system_led_mode = 'Modo do Evento' +system_led_mode_link = 'Link Ativo' +system_led_mode_tx = 'Transmitir' +system_led_mode_rx = 'Receber' +network_interface_up = 'Ativo' +network_interface_hwaddr = 'Endereço-MAC' +network_interface_hwaddr_desc = 'Endereço do Hardware' +network_interface_txrx = 'Tráfego' +network_interface_txrx_desc = 'transmitido / recebido' +network_interface_err = 'Erros' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Criar / Atribuir à uma zona de firewall' +network_interface_fwzone_desc = 'Esta interface não pertence a nenhuma zona de firewall ainda.' +process_head = 'Processos' +process_descr = 'Esta lista fornece uma visão geral sobre os processos atualmente sendo executados no sistema.' +process_pid = 'PID' +process_owner = 'Dono' +process_command = 'Comando' +process_cpu = 'Uso da CPU (%)' +process_mem = 'Uso de memória (%)' +process_hup = 'Hang Up' +process_term = 'Terminar' +process_kill = 'Matar' +mem_cached = 'em cache' +mem_buffered = 'em buffer' +mem_free = 'livre' +a_s_crontab = 'Tarefas Agendadas' +a_s_crontab1 = 'Este é o sistema de agendamento de tarefas.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Caminho do Certificado CA' +a_w_eaptype = 'Método EAP' +a_w_tlsprivkey = 'Caminho da Chave Privada' +a_w_tlsprivkeypwd = 'Senha da Chave Privada' +a_w_peapauth = 'Autenticação PEAP' +a_w_peapidentity = 'Identidate-PEAP' +a_w_peappassword = 'Senha-PEAP' +a_w_create = 'Criar Rede' +hostnames = 'Hostnames' +hostnames_entries = 'Entrada do Host' +hostnames_hostname = 'Hostname' +hostnames_address = 'Endereço de IP' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.ru.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.ru.lua new file mode 100644 index 0000000..4961495 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/admin-core.ru.lua @@ -0,0 +1,269 @@ +uci_applied = 'Данные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ принÑÑ‚Ñ‹' +uci_reverted = 'Данные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ отвергнуты' +a_i_ui = 'ПользовательÑкий интерфейÑ' +c_lucidesc = 'LuCI Ñто Ñвободное Lua програмное обеÑпечение Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ MVC-Вебфреймворк и веб Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð²Ñтраиваемый в уÑтройÑтва. LuCI раÑпроÑтранÑетÑÑ Ð¿Ð¾Ð´ лицензией Apache-License.' +c_projecthome = 'ДомашнÑÑ Ñтраница проекта' +c_leaddev = 'Ведущие разработчики' +c_contributors = 'Помогавшие в разработке' +c_thanksto = 'БлагодарÑ' +a_i_i_hello = 'Добро пожаловать.' +a_i_i_admin1 = 'Это зона ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ LuCI.' +a_i_i_admin2 = 'LuCI Ñвободный, гибкий и дружелюбный грфичеÑкий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ Ð½Ð°Ñтройки OpenWrt Kamikaze.' +a_i_i_admin3 = 'С помощью Ñтих Ñтраниц вы можете изменить оÑновные наÑтройки вашего роутера.' +a_i_i_admin4 = 'Внимание: Ð’ LuCI Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð½Ð¸Ð¼Ð°ÑŽÑ‚ÑÑ Ð¿Ð¾Ñле Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ - ПринÑÑ‚ÑŒ.' +a_i_i_admin5 = 'Так же мы вÑегда желаем улучшить Ñтот интерфейÑ, мы вÑегда обратим внимание на ваши вопроÑÑ‹ и предложениÑ.' +a_i_i_admin6 = 'Ртеперь повеÑелитеÑÑŒ Ñо Ñвоим роутером!' +a_i_i_team = 'Команда LuCI' +a_i_luci1 = 'ЗдеÑÑŒ вы можете изменить наÑтройки и функциональноÑÑ‚ÑŒ LuCI.' +a_i_ucicommit = 'ЗапуÑк команд' +a_i_ucicommit1 = 'Эти команды будут запущенны автоматичеÑки когда Ð´Ð°Ð½Ð½Ð°Ñ UCI ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð° и Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ принÑÑ‚Ñ‹.' +a_i_keepflash = 'Файлы которые необходимо Ñохранить при перепрошивании' +a_i_keepflash1 = 'ПоÑле перепрошивки LuCI Ñти файлы будут добавлены в обновлённую ÑиÑтему .' +a_st_i_status1 = 'ЗдеÑÑŒ вы можете найти информацию о текущей ÑтатиÑтики ÑиÑтемы вроде чаÑтоты процеÑÑора, иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ð¼Ñти или Ñетевого интерфейÑа.' +a_st_i_status2 = 'Ртак же Ñдра или ÑервиÑов, ÑиÑтемный журнал может быть так же проÑмотрен здеÑÑŒ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ что бы получить полный обзор текущего ÑоÑтоÑÐ½Ð¸Ñ ÑиÑтемы.' +iwscan = 'WLAN-Сканирование' +iwscan1 = 'Обзор ÑущеÑтвующих Wi-Fi Ñетей' +iwscan_encr = 'Шифрование' +iwscan_link = 'СвÑзь' +iwscan_signal = 'Сигнал' +iwscan_noise = 'Шум' +routes = 'Маршруты' +routes_netmask = 'Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ Ð¼Ð°Ñка' +routes_gateway = 'Шлюз' +routes_metric = 'Метрика' +a_s_desc = 'ЗдеÑÑŒ вы можете наÑтроить оÑновные параметры вашего уÑтройÑтва такие как Ð¸Ð¼Ñ Ñ…Ð¾Ñта или чаÑовой поÑÑ.' +a_s_packages = 'Программное обеÑпечение' +a_s_changepw = 'Пароль админиÑтратора' +a_s_p_ipkg = 'OPKG-ÐаÑтройка' +a_s_sshkeys = 'SSH-Ключи' +a_s_fstab = 'ДиÑковые разделы' +a_s_flash = 'Обновление прошивки' +a_s_i_system1 = 'Изменение наÑтроек ÑиÑтемы ÑвÑзанных Ñ Ñамоидентификацией, уÑÑ‚Ñтанвкой аппаратно и/или програмного обеÑпечениÑ, идентификацией или диÑковыми разделами.' +a_s_i_system2 = 'Эти наÑтройки определÑÑŽÑ‚ оÑнову вашей ÑиÑтемы.' +a_s_i_system3 = 'Ðеобходимо тчательно отнеÑтиÑÑŒ к нижеÑледующим наÑтройкам, в результате неправильной конфигурации которых вы можете потерÑÑ‚ÑŒ управление над ÑиÑтемой или уÑтройÑто может не загружатьÑÑ.' +a_s_packages_do = 'ПринÑÑ‚ÑŒ изменениÑ' +a_s_packages_install = 'УÑтановка' +a_s_packages_installurl = 'Загрузить и уÑтановить пакеты' +a_s_packages_ipkg = 'Изменить лиÑтинг пакетов и путей уÑтановки' +a_s_packages_name = 'Ð˜Ð¼Ñ Ð¿Ð°ÐºÐµÑ‚Ð°' +a_s_packages_remove = 'Удалить' +a_s_packages_search = 'Ðайти пакет' +a_s_packages_update = 'ЛиÑтинг пакетов обновлён' +a_s_packages_updatelist = 'Обновить лиÑтинг пакетов' +a_s_packages_upgrade = 'Заменить уÑтановленные пакеты' +a_s_p_ipkg_pkglists = 'ЛиÑтинг пакетов' +a_s_p_ipkg_targets = 'Путь уÑтановки' +a_s_changepw1 = 'Изменение Ð¿Ð°Ñ€Ð¾Ð»Ñ ÑиÑтемного админиÑтратора (Пользователь root)' +a_s_changepw_changed = 'Пароль уÑпешно изменён' +a_s_changepw_nomatch = 'Ошибка: Пароли не Ñовпадают' +a_s_sshkeys1 = 'ЗдеÑÑŒ вы можете вÑтавить публичный SSH-Ключ Ð´Ð»Ñ SSH публичной-ключевой аутентификации.' +a_s_fstab_mountpoints = 'Точки монтированиÑ' +a_s_fstab_mountpoints1 = 'Точки Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÑÑŽÑ‚ к каком запоминающему уÑтройÑтву будет приÑоединена Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема' +a_s_fstab_active = 'Монтированные файловые ÑиÑтемы"' +a_s_fstab_used = 'ИÑпользованно"' +a_s_fstab_avail = 'ДоÑтупно"' +a_s_fstab_mountpoint = 'Точка приÑоединениÑ' +a_s_fstab_device1 = 'УÑтройÑтво или раздел (пример /dev/sda1)' +a_s_fstab_fs1 = 'Формат файловой ÑиÑтемы (пример ext3)' +a_s_fstab_swap1 = 'ЕÑли физичеÑкой RAM не хватает можно воÑпользоватьÑÑ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ð¼ хранением данных в файле-подкачке. Ð’ результате RAM памÑти будет доÑтупно в большем количеÑтве. Ðо помните, файл подкачки работает гораздо медленнее RAM так что не ждите обработки информации на ÑкороÑÑ‚ÑÑ… Ñравнимых Ñ RAM.' +a_s_flash_flashed = 'Прошивка уÑпешно обновленна. Перезагрузка уÑтройÑтва...' +a_s_flash_flasherr = 'Прошивка невозможна' +a_s_flash_fwimage = 'Файл прошивки' +a_s_flash_fwupgrade = 'Прошить' +a_s_flash_keepcfg = 'Сохранить конфигурационные файлы' +a_s_flash_notimplemented = 'Извините, Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¿Ð¾ÐºÐ° не доÑтупна на вашей платформе.' +a_s_flash_upgrade1 = 'ЗаменÑет уÑтановленную прошивку на новую. Формат прошивки платформо-завиÑимый.' +a_s_reboot1 = 'Сразу произойдёт перезагрузка вашей ÑиÑтемы' +a_s_reboot_do = 'Выполнить перезагрузку' +a_s_reboot_running = 'ПозалуйÑта подождите: УÑтройÑтво перезагружаетÑÑ...' +a_s_reboot_u = 'Внимание: ЕÑÑ‚ÑŒ неÑохранённые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ðµ потерÑÑŽÑ‚ÑÑ Ð¿Ð¾Ñле перезагрузки!' +a_s_applyreboot1 = 'Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð½ÑÑ‚Ñ‹.' +a_s_backup = 'Резервирование / ВоÑÑтановление' +a_s_backup_backup = 'Создать резервную копию' +a_s_backup_archive = 'Ðрхив воÑÑтановлениÑ' +a_s_backup_reset = 'СброÑить роутер к наÑтройкам по умолчанию' +a_s_backup_reset1 = 'Перейти к возврашению вÑех наÑтроек и уÑтановить наÑтройки по умолчанию?' +a_s_backup_restore = 'ВоÑÑтановить резервную копию' +a_s_backup1 = 'ЗдеÑÑŒ вы можете Ñделать резевную копию и воÑÑановить конфигурацию вашего роутера, еÑли Ñто возможно, или уÑтановить наÑтройки по умолчанию.' +a_srv_http = 'HTTP-Сервер' +a_srv_ssh = 'SSH-Сервер' +a_srv_services1 = 'СервиÑÑ‹ и демоны выполнÑющие определённые задачи на уÑтройÑтвах.' +a_srv_services2 = 'БольшинÑтво из них Ñетевые Ñерверы, которые выполнÑÑŽÑ‚ определённые задачи Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… уÑтройÑтв или Ñетей наподобие shell-доÑтупа, web-Ñтраниц таких как LuCI, выполнÑÑŽÑ‚ mesh-маршрутизацию, отправлÑÑŽÑ‚ пиÑьма , ...' +a_srv_http1 = 'Маленький веб-Ñервер, Ñлужащий Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ LuCI.' +a_srv_http_authrealm = 'ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑ‚ÑŒ' +a_srv_http_authrealm1 = 'Что будет показано при авторизации на защищённых Ñтраницах.' +a_srv_http_config1 = 'по умолчанию /etc/httpd.conf' +a_srv_http_root = 'ÐšÐ¾Ñ€Ð½ÐµÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°' +a_srv_dropbear1 = 'Dropbear Ñто SSH-Ñервер Ñо вÑтроенным SCP' +a_srv_d_pwauth = 'ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ паролю' +a_srv_d_pwauth1 = 'Разрешить SSH аутентификацию по паролю' +a_w_channel = 'Канал' +a_w_wifi1 = 'Ðа Ñтой Ñтраничке можно наÑтроить WLAN оÑнованную на беÑпроводных ÑетÑÑ….' +a_w_wifi2 = 'Ð’Ñ‹ можете легко интегрировать ваши 802.11a/b/g/n-уÑтройÑтва в вашу физичеÑкую Ñеть и иÑпользовать виртуальные ÑтройÑтва Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð±ÐµÑпроводных повторителей или ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… Ñетевых топологий на одном физичеÑком уÑтройÑтве.' +a_w_wifi3 = 'Поддерживаемые режимы: Точка, Клиент, Ad-Hoc и WDS, а так же WPA и WPA2 шифрование Ð´Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐµÐ¹ безопаÑноÑти.' +a_w_devices1 = 'ЗдеÑÑŒ вы можете наÑтроить уÑтановленные Wi-Fi уÑтройÑтва.' +a_w_txantenna = 'ÐŸÐµÑ€ÐµÐ´Ð°ÑŽÑ‰Ð°Ñ Ð°Ð½Ñ‚ÐµÐ½Ð½Ð°' +a_w_rxantenna = 'ÐŸÑ€Ð¸Ð½Ð¸Ð¼Ð°ÑŽÑ‰Ð°Ñ Ð°Ð½Ñ‚ÐµÐ½Ð½Ð°' +a_w_distance1 = 'ДиÑÑ‚Ð°Ð½Ñ†Ð¸Ñ Ð´Ð¾ Ñамой дальней Ñтанции (в метрах)' +a_w_diversity = 'РазновидноÑÑ‚ÑŒ антенн' +a_w_countrycode = 'Код Ñтраны' +a_w_connlimit = 'Ограничение Ñоединений' +a_w_networks1 = 'Ð’Ñ‹ можете наÑтраивать различные wifi Ñети на одном уÑтройÑтве. Помните что еÑÑ‚ÑŒ определённые програмные и аппаратные ограничениÑ. Ðормально вы можете иÑпользовать например 1 Ad-Hoc или до 3 Точек и Ñимулированных 1 Клиента.' +a_w_netid = 'Ðазвание Ñети (ESSID)' +a_w_network1 = 'Добавить Wifi Ñеть в физичеÑкую Ñеть' +a_w_txpwr = 'МощьноÑÑ‚ÑŒ передатчика' +a_w_brcmburst = 'Broadcom Frameburst' +a_w_athburst = 'Atheros Frameburst' +a_w_radiussrv = 'RadiusServer' +a_w_radiusport = 'Radius-Port' +a_w_apisolation = 'AP-Isolation' +a_w_apisolation1 = 'Ðе позволÑет клиентам обмениватьÑÑ Ð´Ñ€ÑƒÐ³ Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¼ информацией' +a_w_hideessid = 'Скрыть ESSID' +a_w_ap = 'Точка доÑтупа' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'ПÑевдо Ad-Hoc (ahdemo)' +a_w_client = 'Клиент' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq Ñодержит в Ñебе DHCP-Сервер и DNS-Forwarder Ð´Ð»Ñ NAT' +dhcp_dnsmasq_domainneeded = 'Domain required' +dhcp_dnsmasq_domainneeded_desc = 'Ðе форвардить DNS-запроÑÑ‹ без DNS-имени' +dhcp_dnsmasq_authoritative = 'Authoritative' +dhcp_dnsmasq_authoritative_desc = 'Только DHCP в локальной Ñети' +dhcp_dnsmasq_boguspriv = 'Filter private' +dhcp_dnsmasq_boguspriv_desc = 'не форвардить реверÑные-Ð´Ð½Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑÑ‹ Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð¹ Ñети' +dhcp_dnsmasq_filterwin2k = 'Filter useless' +dhcp_dnsmasq_filterwin2k_desc = 'фильтровать ненужные DNS-запроÑÑ‹ Windows-ÑиÑтем' +dhcp_dnsmasq_localisequeries = 'Localise queries' +dhcp_dnsmasq_localisequeries_desc = 'локализировать Ð¸Ð¼Ñ Ñ…Ð¾Ñта отноÑÑщегоÑÑ Ðº данной подÑети' +dhcp_dnsmasq_local = 'Локальный Ñервер' +dhcp_dnsmasq_domain = 'Локальный домен' +dhcp_dnsmasq_expandhosts = 'Expand Hosts' +dhcp_dnsmasq_expandhosts_desc = 'ДобавлÑÑ‚ÑŒ доменные имена в хоÑÑ‚Ñ‹' +dhcp_dnsmasq_nonegcache = 'Don't cache unknown' +dhcp_dnsmasq_nonegcache_desc = 'Запрещать кешировать негативные DNS-ответы' +dhcp_dnsmasq_readethers = 'Use /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Читать /etc/ethers Ð´Ð»Ñ Ð½Ð°Ñтройки DHCP-Сервера' +dhcp_dnsmasq_leasefile = 'Leasefile' +dhcp_dnsmasq_leasefile_desc = 'файл где выданные DHCP-leases хранÑÑ‚ÑÑ' +dhcp_dnsmasq_resolvfile = 'Resolvfile' +dhcp_dnsmasq_resolvfile_desc = 'Локальный DNS файл' +dhcp_dnsmasq_nohosts = 'Ignore /etc/hosts' +dhcp_dnsmasq_strictorder = 'Strict order' +dhcp_dnsmasq_strictorder_desc = 'DNS-Сервер будет обращатьÑÑ Ðº resolvfile' +dhcp_dnsmasq_logqueries = 'Log queries' +dhcp_dnsmasq_noresolv = 'Ignore resolvfile' +dhcp_dnsmasq_dnsforwardmax = 'concurrent queries' +dhcp_dnsmasq_port = 'DNS-Port' +dhcp_dnsmasq_ednspacket_max = 'max. EDNS0 размер пакета' +dhcp_dnsmasq_dhcpleasemax = 'max. DHCP-Leases' +dhcp_dnsmasq_addnhosts = 'дополнительный hostfile' +dhcp_dnsmasq_queryport = 'порт запроÑов' +a_n_switch = 'Свитч' +a_n_routes = 'МаршрутизациÑ' +a_n_routes4 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv4' +a_n_routes6 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv6' +a_n_routes1 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñлужит Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· какой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¸ шлюз можно пройти к определённому хоÑту или Ñегменту Ñети.' +a_network1 = 'Ð’ Ñтом разделе вы Ñможете найти вÑÑ‘ что каÑаетÑÑ Ð½Ð°Ñтроек Ñети.' +a_network2 = 'Ð’ большенÑтве роутеров Ñетевой Ñвитч может быть Ñвободно наÑтроен и добавлен в различные VLAN'Ñ‹.' +a_network3 = 'ÐаÑтройка PPPoE / PPTP позволÑет Ñети и Ñетевые ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº поÑтавщику уÑлуг Интернет.' +a_network4 = 'C DHCP уÑтройÑтва находÑщиеÑÑ Ð² вашей Ñети могут автоматичеÑки IP-адреÑа и вÑе необходимые наÑтройки.' +a_network5 = 'Файрволл и Ð¿Ñ€Ð¾Ð±Ñ€Ð¾Ñ Ð¿Ð¾Ñ€Ñ‚Ð¾Ð² иÑпользуетÑÑ Ð´Ð»Ñ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð°Ð´Ñ‘Ð¶Ð½Ð¾ÑÑ‚ÑŒ и гибкоÑти вашей Ñети.' +a_n_switch1 = 'Сетевые порты на вашем роутере могут маршрутизироватьÑÑ Ð² различные VLAN'Ñ‹ и ÑоединÑÑ‚ÑŒ компютеры напрÑмую. VLAN'Ñ‹ обычно иÑпользуют Ð´Ð»Ñ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкого Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñетей.' +network_switch_desc = 'Порты принадлежашие VLAN'ам разделÑÑŽÑ‚ÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð°Ð¼Ð¸. Порт Ñ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð¼ значением (обычно 5) обычно иÑпользуют Ð´Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½Ð¸Ñ… Ñетей. Ðа уÑтройÑтвах Ñ 5 портами, порт Ñ Ð½Ð°Ð¸Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ значением (0) предназначен Ð´Ð»Ñ Uplink.' +a_n_ifaces1 = 'Ðа Ñтой Ñтраничке вы можете Ñконфигурировать Ñетевые интерфейÑÑ‹. Ð’Ñ‹ можете ÑоединÑÑ‚ÑŒ различные интерфейÑÑ‹ в "моÑÑ‚" Ð¿Ð¾Ð¼ÐµÑ‡Ð°Ñ Ð¸Ñ… как "МоÑÑ‚" и добавлÑÑ‚ÑŒ имена различных Ñетей принадлежащих Ñетевым интерфейÑам разделённые пробелом. Также вы можете иÑпользовать Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ VLAN'ов например INTERFACE.VLANNR (ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ ÐºÐ°Ðº: eth0.1).' +a_n_i_bridge = 'МоÑÑ‚' +a_n_i_bridge1 = 'Ñоздаёт моÑÑ‚ Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… Ñетевых интерфейÑов' +dhcp_desc = 'С помощью DHCP члены Ñетей могут автоматичеÑки получить такие наÑтройки как (IP-ÐдреÑ, Ñетевую маÑку, DNS-имÑ, ...).' +dhcp_dhcp_leasetime = 'Leasetime' +dhcp_dhcp_dynamicdhcp = 'Dynamic DHCP' +dhcp_dhcp_ignore = 'Ignore interface' +dhcp_dhcp_ignore_desc = 'отключить DHCP Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ интерфейÑа' +dhcp_dhcp_force = 'Force' +dhcp_dhcp_start_desc = 'первый Ð°Ð´Ñ€ÐµÑ (поÑледний октет)' +dhcp_dhcp_limit_desc = 'количеÑтво арендованных адреÑов -1' +dhcp_leases = 'Leases' +luci_ethers = 'Static Leases' +dhcp_timeremain = 'Leasetime remaining' +dhcp_leases_active = 'Active Leases' +a_n_ptp = 'Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ°-точка' +a_n_ptp1 = 'Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° PPPoE или PPTP обычно иÑпользуютÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· DSL или подобные технологии Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº поÑтавщику уÑлуг Интернет.' +network_interface_server = 'PPTP-Сервер' +network_interface_demand = 'Automatic Disconnect' +network_interface_demand_desc = 'Ð’Ñ€ÐµÐ¼Ñ (в Ñек.) поÑле которого неиÑпользованное Ñоединение будет закрыто' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'КоличеÑтво неудачных Ñоединений Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ переподÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº Ñерверу' +a_n_r_routes1 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñлужит Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· какой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¸ шлюз можно пройти к определённому хоÑту или Ñегменту Ñети.' +a_n_routes_static = 'СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ' +a_n_routes_static4 = 'СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv4' +a_n_routes_static6 = 'СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv6' +a_n_routes_kernel4 = 'Включение IPv4-Маршрутизации' +a_n_routes_kernel6 = 'Включение IPv6-Маршрутизации' +a_n_r_target1 = 'ХоÑÑ‚-IP или Ñеть' +a_n_r_target6 = 'ХоÑÑ‚-IPv6 или Ñеть' +a_n_r_netmask1 = 'еÑли Ñеть' +m_n_inet = 'Интернет Ñоединение' +m_n_local = 'Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ñеть' +m_n_route = 'Маршрут' +m_n_brdige = 'МоÑÑ‚' +m_w_ap = 'ОбеÑпечивает (AP)' +m_w_adhoc = 'ÐезаыиÑÐ¸Ð¼Ð°Ñ (Ad-Hoc)' +m_w_client = 'ПриÑоединитьÑÑ (Client)' +m_w_wds = 'РаÑÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ð°Ñ (WDS)' +m_w_clientmode = 'Режим клиента' +system_system_logsize = 'Размер буфера ÑиÑтемного журнала' +system_system_logip = 'Внешний Ñервер ÑиÑтемного журналированиÑ' +system_system_conloglevel = 'Уровень ÑиÑтемного логгированиÑ' +system_system_conloglevel_desc = 'Уровень ÑиÑтемного Ð»Ð¾Ð³Ð³Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½Ñоли' +m_i_processor = 'ПроцеÑÑор' +m_i_memory = 'ПамÑÑ‚ÑŒ' +m_i_systemtime = 'Локальное времÑ' +m_i_uptime = 'Ð’Ñ€ÐµÐ¼Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹' +m_n_d_firstaddress = 'Первый арендованный адреÑ' +m_n_d_numleases = 'КоличеÑтво арендованных адреÑов' +routingtable = 'Таблица маршрутизации' +wlanscan = 'ПоиÑк Wi-Fi Ñетей' +frequency = 'ЧаÑтота' +power = 'МощьноÑÑ‚ÑŒ' +noise = 'Шум' +signal = 'Сигнал' +link = 'СвÑзь' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Битрейт' +m_n_keepalive = 'автоматичеÑки переподÑоединÑÑ‚ÑÑ' +m_n_dialondemand = 'отÑоединитьÑÑ ÐºÐ¾Ð³Ð´Ð° проÑтой длÑ' +m_n_pptp_server = 'PPTP-Сервер' +leds = 'ÐаÑтройка LED' +leds_desc = 'ÐаÑтройка Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ LED'ов еÑли Ñто возможно.' +system_led_name = 'LED ИмÑ' +system_led_sysfs = 'LED УÑтройÑтво' +system_led_default = 'СоÑтоÑние по умолчанию' +system_led_default_desc = 'мигание = включено' +system_led_trigger = 'Триггер' +system_led_trigger_none = 'нет' +system_led_trigger_defaulton = 'По умолчанию включено' +system_led_trigger_timer = 'Таймер' +system_led_trigger_heartbeat = 'Стук (СреднÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°)' +system_led_trigger_netdev = 'Сетевое уÑтройÑтво' +system_led_delayoff = 'Задержка выключена' +system_led_delayoff_desc = 'Ð²Ñ€ÐµÐ¼Ñ (в мÑ) LED выключен' +system_led_delayon = 'Задержка включена' +system_led_delayon_desc = 'Ð²Ñ€ÐµÐ¼Ñ (в мÑ) LED включен' +system_led_dev = 'УÑтройÑтво' +system_led_mode = 'Триггерный режим' +system_led_mode_link = 'СвÑзь включена' +system_led_mode_tx = 'Передача' +system_led_mode_rx = 'Приём' +network_interface_up = 'Ðктивен' +network_interface_hwaddr = 'MAC-ÐдреÑ' +network_interface_hwaddr_desc = 'ÐÐ´Ñ€ÐµÑ ÑƒÑтройÑтва' +network_interface_txrx = 'Трафик' +network_interface_txrx_desc = 'передано / получено' +network_interface_err = 'Ошибок' +network_interface_err_desc = 'Перед. / Получ.' +network_interface_fwzone = 'Создать / Добавить Файрвол-зону' +network_interface_fwzone_desc = 'Этот Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð½Ðµ принадлежит ни к одной Файрвол-зоне.' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.de.lua new file mode 100644 index 0000000..7f7087b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.de.lua @@ -0,0 +1,16 @@ +cbi_add = 'Eintrag hinzufügen' +cbi_del = 'Eintrag entfernen' +cbi_replace = 'Eintrag ersetzen' +cbi_invalid = 'Ungültige Eingabe' +cbi_invalid_section = 'Validierung fehlgeschlagen: Bitte die Eingabefelder auf Fehler überprüfen.' +cbi_missing = 'Dieses Feld muss ausgefüllt werden' +cbi_deperror = 'Validierung fehlgeschlagen: Mindestens ein benötigtes Feld ist leer oder hat einen ungültigen Wert' +cbi_reqerror = 'Nicht erfüllte Abhängigkeit für dieses Feld' +cbi_addopt = '-- Zusätzliches Feld --' +cbi_sectempty = 'Diese Sektion enthält noch keine Einträge' +cbi_manual = '-- benutzerdefiniert --' +cbi_select = '-- Bitte auswählen --' +cbi_gorel = 'Gehe zu relevanter Konfigurationsseite' +cbi_applying = 'Änderungen werden angewandt' +cbi_upload = 'hochgeladene Datei' +cbi_browser = 'Datei suchen...' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.en.lua new file mode 100644 index 0000000..7e5ae15 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.en.lua @@ -0,0 +1,17 @@ +cbi_add = 'Add entry' +cbi_del = 'Remove entry' +cbi_replace = 'Replace entry' +cbi_invalid = 'Invalid input value' +cbi_invalid_section = 'Validation failed: Please check any input fields for mistakes.' +cbi_missing = 'This field is mandatory' +cbi_deperror = 'Validation failed: At least one mandatory field has no or an invalid value' +cbi_reqerror = 'A requirement for this option was not met' +cbi_addopt = '-- Additional Field --' +cbi_optional = ' (optional)' +cbi_sectempty = 'This section contains no values yet' +cbi_manual = '-- custom --' +cbi_select = '-- Please choose --' +cbi_gorel = 'Go to relevant configuration page' +cbi_applying = 'Applying changes' +cbi_upload = 'Uploaded File' +cbi_browser = 'Search file...' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.fr.lua new file mode 100644 index 0000000..a62ccc9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.fr.lua @@ -0,0 +1,17 @@ +cbi_add = 'Ajouter une entrée' +cbi_del = 'Supprimer l'entrée' +cbi_replace = 'Remplacer l'entrée' +cbi_invalid = 'Erreur : donnée entrée invalide' +cbi_invalid_section = 'Erreur de validation : merci de vérifier les champs de saisie.' +cbi_missing = 'Ce champ est obligatoire' +cbi_deperror = 'Erreur de validation : au moins un champ est vide ou a une valeur incorrecte' +cbi_reqerror = 'Une spécification pour cette option n'a pu être vérifiée' +cbi_addopt = '-- Champ Supplémentaire --' +cbi_optional = ' (optionnel)' +cbi_sectempty = 'Cette section ne contient pas encore de valeur' +cbi_manual = '-- autre --' +cbi_select = '-- Choisir --' +cbi_gorel = 'Aller à la page de configuration correspondante' +cbi_applying = 'Changements en cours d'application' +cbi_upload = 'Fichier Uploadé' +cbi_browser = 'Chercher un fichier...' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.it.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.it.lua new file mode 100644 index 0000000..13174ae --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.it.lua @@ -0,0 +1,17 @@ +cbi_add = 'Aggiungi campo' +cbi_del = 'Rimuovi campo' +cbi_replace = 'Sostituisci campo' +cbi_invalid = 'Valore immesso non valido' +cbi_invalid_section = 'Validazione fallita: Per favore controlla i campi immessi.' +cbi_missing = 'Questo campo è obbligatorio' +cbi_deperror = 'Validazione fallita: Almeno un campo obbligatorio manca o è invalido' +cbi_reqerror = 'Un requisito per questa opzione non è stato soddisfatto' +cbi_addopt = '-- Campo aggiuntivo --' +cbi_optional = ' (opzionale)' +cbi_sectempty = 'Questa sezione non contiene ancora valori' +cbi_manual = '-- personalizzato --' +cbi_select = '-- Per favore scegli --' +cbi_gorel = 'Vai alla pagina di configurazione relativa' +cbi_applying = 'Applica modifiche' +cbi_upload = 'Invia file' +cbi_browser = 'Cerca file...' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.pt-br.lua new file mode 100644 index 0000000..2ac6ddf --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.pt-br.lua @@ -0,0 +1,17 @@ +cbi_add = 'Adicionar entrada' +cbi_del = 'Remover entrada' +cbi_replace = 'Substituir entrada' +cbi_invalid = 'Valor inválido' +cbi_invalid_section = 'A validação falhou: Por favor, verifique por erros em algum dos campos de entrada.' +cbi_missing = 'Este campo é obrigatório' +cbi_deperror = 'A validação falhou: É obrigatório pelo menos um campo com o valor correto.' +cbi_reqerror = 'Um requisito para esta opção não foi cumprido' +cbi_addopt = '-- Campo Adicional --' +cbi_optional = ' (opcional)' +cbi_sectempty = 'Esta seção não contêm valores ainda' +cbi_manual = '-- customizado --' +cbi_select = '-- Por favor escolha --' +cbi_gorel = 'Ir para a página relacionada à configuração' +cbi_applying = 'Aplicando mudanças' +cbi_upload = 'Fazer upload do arquivo' +cbi_browser = 'Procurar arquivo...' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.ru.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.ru.lua new file mode 100644 index 0000000..805699b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/cbi.ru.lua @@ -0,0 +1,10 @@ +cbi_add = 'Добавить' +cbi_del = 'Удалить' +cbi_invalid = 'Ошибка: Введёное значение не верно' +cbi_missing = 'Ошибка: Это поле обÑзательно к заполнению' +cbi_addopt = '-- Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° --' +cbi_optional = ' (дополнительно)' +cbi_sectempty = 'Эта ÑÐµÐºÑ†Ð¸Ñ Ð¿Ð¾ÐºÐ° не Ñодержит значений' +cbi_manual = '-- выборочный --' +cbi_select = '-- ПожалуйÑта выберете --' +cbi_gorel = 'Перейти к Ñтранице конфигурации' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.de.lua new file mode 100644 index 0000000..f731b7c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.de.lua @@ -0,0 +1,8 @@ +ddns = 'Dynamisches DNS' +ddns_desc = 'Dynamisches DNS erlaubt es, den Router bei dynamischer IP-Adresse über einen festen DNS-Namen zu erreichen.' +ddns_service_ipsource = 'Quelle der IP-Adresse' +ddns_service_checkinterval = 'Teste auf neue IP alle' +ddns_service_checkunit = 'Test-Zeiteinheit' +ddns_service_forceinterval = 'Erzwinge Aktualisierung alle' +ddns_service_forceunit = 'Erzwinge-Zeiteinheit' +ddns_service_updateurl = 'Eigene Update-URL' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.en.lua new file mode 100644 index 0000000..b8afdf4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.en.lua @@ -0,0 +1,8 @@ +ddns = 'Dynamic DNS' +ddns_desc = 'Dynamic DNS allows that your router can be reached with a fixed hostname while having a dynamically changing IP-Address.' +ddns_service_ipsource = 'Source of IP-Address' +ddns_service_checkinterval = 'Check for changed IP every' +ddns_service_checkunit = 'Check-Time unit' +ddns_service_forceinterval = 'Force update every' +ddns_service_forceunit = 'Force-Time unit' +ddns_service_updateurl = 'Custom Update-URL' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.fr.lua new file mode 100644 index 0000000..8e5b6fa --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.fr.lua @@ -0,0 +1,8 @@ +ddns = 'DNS Dynamique' +ddns_desc = 'Le DNS Dynamique permet au routeur d'être joint avec un nom d'hôte fixe bien que changeant dynamiquement d'adresse IP.' +ddns_service_ipsource = 'Source de l'adresse IP' +ddns_service_checkinterval = 'Vérifier l'adresse IP toutes les' +ddns_service_checkunit = 'Unité de temps' +ddns_service_forceinterval = 'Vérification forcée toutes les' +ddns_service_forceunit = 'Unité de temps' +ddns_service_updateurl = 'Url de mise à jour personnalisée' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.pt-br.lua new file mode 100644 index 0000000..58375c2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ddns.pt-br.lua @@ -0,0 +1,8 @@ +ddns = 'DNS Dinâmico' +ddns_desc = 'DNS dinâmico permite que o seu router possa ser encontrado a partir de um hostname fixo, mesmo usando um Endereço-IP dinâmico.' +ddns_service_ipsource = 'Origem do Endereço-IP' +ddns_service_checkinterval = 'Verificar a cada mudança de IP' +ddns_service_checkunit = 'Unidade de tempo para verificação' +ddns_service_forceinterval = 'Forçar atualização a cada' +ddns_service_forceunit = 'Unidade de tempo para atualização forçada' +ddns_service_updateurl = 'URL para atualização customizada' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.de.lua new file mode 100644 index 0000000..238cba5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.de.lua @@ -0,0 +1,102 @@ +skiplink1 = 'Zur Navigation springen' +skiplink2 = 'Zum Inhalt springen' +navigation = 'Navigation' +about = 'Ãœber' +add = 'Hinzufügen' +addresses = 'Adressen' +aliases = 'Aliasse' +all = 'alle' +administration = 'Administration' +essentials = 'Vereinfacht' +apply = 'Anwenden' +back = 'zurück' +basicsettings = 'Grundeinstellungen' +broadcast = 'IPv4-Broadcast' +changes = 'Änderungen' +channel = 'Kanal' +cidr6 = 'CIDR-Notation: Adresse/Prefix' +code = 'Code' +config = 'Konfiguration' +configfile = 'Konfigurationsdatei' +confirmation = 'Bestätigung' +delete = 'Löschen' +descr = 'Beschreibung' +design = 'Design' +destination = 'Ziel' +device = 'Gerät' +devices = 'Geräte' +disable = 'deaktivieren' +distance = 'Distanz' +dmesg = 'Kernelprotokoll' +dnsserver = 'DNS-Server' +edit = 'Bearbeiten' +enable = 'aktivieren' +encryption = 'Verschlüsselung' +error = 'Fehler' +filesystem = 'Dateisystem' +filter = 'Filter' +gateway = 'IPv4-Gateway' +gateway6 = 'IPv6-Gateway' +general = 'Allgemeines' +hostname = 'Hostname' +install = 'Installieren' +installed = 'installiert' +interface = 'Schnittstelle' +interfaces = 'Schnittstellen' +ipaddress = 'IPv4-Adresse' +ip6address = 'IPv6-Adresse' +legend = 'Legende' +library = 'Bibliothek' +load = 'Last' +login = 'Anmelden' +logout = 'Abmelden' +key = 'Schlüssel' +language = 'Sprache' +limit = 'Limit' +macaddress = 'MAC-Adresse' +manpage = 'siehe '%s' manpage' +metric = 'Metrik' +mode = 'Modus' +name = 'Name' +netmask = 'IPv4-Netzmaske' +network = 'Netzwerk' +networks = 'Netzwerke' +none = 'keine' +notinstalled = 'nicht installiert' +ok = 'OK' +options = 'Optionen' +overview = 'Ãœbersicht' +packagemanager = 'Packet-Manager' +password = 'Passwort' +path = 'Pfad' +port = 'Port' +ports = 'Ports' +protocol = 'Protokoll' +reboot = 'Neu Starten' +reset = 'Zurücksetzen' +revert = 'Verwerfen' +save = 'Speichern' +saveapply = 'Speichern & Anwenden' +scan = 'Scan' +service = 'Dienst' +services = 'Dienste' +settings = 'Einstellungen' +size = 'Größe' +source = 'Quelle' +start = 'Start' +static = 'statisch' +statistics = 'Statistiken' +status = 'Status' +submit = 'Absenden' +syslog = 'Systemprotokoll' +system = 'System' +target = 'Ziel' +timezone = 'Zeitzone' +type = 'Typ' +unknownerror = 'Unbekannter Fehler' +unsavedchanges = 'Ungespeicherte Änderungen' +username = 'Benutzername' +version = 'Version' +webui = 'Weboberfläche' +wifi = 'Drahtlos' +zone = 'Zone' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.en.lua new file mode 100644 index 0000000..d923a88 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.en.lua @@ -0,0 +1,102 @@ +skiplink1 = 'Skip to navigation' +skiplink2 = 'Skip to content' +navigation = 'Navigation' +about = 'About' +add = 'Add' +addresses = 'Addresses' +aliases = 'Aliases' +all = 'all' +back = 'back' +administration = 'Administration' +essentials = 'Essentials' +apply = 'Apply' +basicsettings = 'Basic Settings' +broadcast = 'IPv4-Broadcast' +changes = 'Changes' +channel = 'Channel' +cidr6 = 'CIDR-Notation: address/prefix' +code = 'Code' +config = 'Configuration' +configfile = 'Configuration file' +confirmation = 'Confirmation' +delete = 'Delete' +descr = 'Description' +design = 'Design' +destination = 'Destination' +device = 'Device' +devices = 'Devices' +disable = 'disable' +distance = 'Distance' +dmesg = 'Kernel Log' +dnsserver = 'DNS-Server' +edit = 'Edit' +enable = 'enable' +encryption = 'Encryption' +error = 'Error' +filesystem = 'Filesystem' +filter = 'Filter' +gateway = 'IPv4-Gateway' +gateway6 = 'IPv6-Gateway' +general = 'General' +hostname = 'Hostname' +install = 'Install' +installed = 'installed' +interface = 'Interface' +interfaces = 'Interfaces' +ipaddress = 'IPv4-Address' +ip6address = 'IPv6-Address' +legend = 'Legend' +library = 'Library' +logout = 'Logout' +key = 'Key' +language = 'Language' +limit = 'Limit' +load = 'Load' +login = 'Login' +macaddress = 'MAC-Address' +manpage = 'see '%s' manpage' +metric = 'Metric' +mode = 'Mode' +name = 'Name' +netmask = 'IPv4-Netmask' +network = 'Network' +networks = 'Networks' +none = 'none' +notinstalled = 'not installed' +ok = 'OK' +options = 'Options' +overview = 'Overview' +packagemanager = 'Package Manager' +password = 'Password' +path = 'Path' +port = 'Port' +ports = 'Ports' +protocol = 'Protocol' +reboot = 'Reboot' +reset = 'Reset' +revert = 'Revert' +save = 'Save' +saveapply = 'Save & Apply' +scan = 'Scan' +service = 'Service' +services = 'Services' +settings = 'Settings' +size = 'Size' +source = 'Source' +start = 'Start' +static = 'static' +status = 'Status' +statistics = 'Statistics' +submit = 'Submit' +syslog = 'System Log' +system = 'System' +target = 'Target' +timezone = 'Timezone' +type = 'Type' +unknownerror = 'Unknown Error' +unsavedchanges = 'Unsaved Changes' +username = 'Username' +version = 'Version' +webui = 'Web UI' +wifi = 'Wifi' +zone = 'Zone' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.fr.lua new file mode 100644 index 0000000..8d9fa10 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.fr.lua @@ -0,0 +1,99 @@ +about = 'A propos' +add = 'Ajouter' +all = 'tous' +addresses = 'Adresses' +aliases = 'Alias' +back = 'retour' +administration = 'Administration' +essentials = 'Essentiel' +apply = 'Appliquer' +basicsettings = 'Paramètres de base' +broadcast = 'Broadcast IPv4' +changes = 'Changements' +channel = 'Canal' +cidr6 = 'Notation CIDR : adresse/prefixe' +code = 'Code' +config = 'Configuration' +configfile = 'Fichier de configuration' +confirmation = 'Confirmation' +delete = 'Effacer' +descr = 'Description' +design = 'Apparence' +destination = 'Destination' +device = 'Equipement' +devices = 'Equipements' +disable = 'désactiver' +distance = 'Distance' +dmesg = 'Journal du noyau' +dnsserver = 'Serveur DNS' +edit = 'Editer' +enable = 'activer' +encryption = 'Chiffrement' +error = 'Erreur' +filesystem = 'Système de fichiers' +filter = 'Filtrer' +gateway = 'Passerelle' +gateway6 = 'Passerelle IPv6' +general = 'Général' +hostname = 'Nom d'hôte' +install = 'Installer' +installed = 'installé' +interface = 'Interface' +interfaces = 'Interfaces' +ipaddress = 'Adresse IP' +ip6address = 'Adresse IPv6' +legend = 'Légende' +library = 'Bibliothèque' +logout = 'Déconnexion' +key = 'Clé' +language = 'Langue' +limit = 'Limite' +load = 'Charger' +login = 'Connexion' +macaddress = 'Adresse MAC' +manpage = 'voir la page de man de '%s'' +metric = 'Metrique' +mode = 'Mode' +name = 'Nom' +netmask = 'Masque réseau' +network = 'Réseau' +networks = 'Réseaux' +none = 'aucun' +notinstalled = 'pas installé' +ok = 'OK' +options = 'Options' +overview = 'Vue d'ensemble' +packagemanager = 'Gestionnaire de paquets' +password = 'Mot de passe' +path = 'Chemin' +port = 'Port' +ports = 'Ports' +protocol = 'Protocole' +reboot = 'Redémarrage' +reset = 'Remise à zéro' +revert = 'Revenir' +save = 'Sauvegarder' +saveapply = 'Sauvegarder et Appliquer' +scan = 'Scan' +service = 'Service' +services = 'Services' +settings = 'Réglages' +size = 'Taille' +source = 'Source' +start = 'Démarrer' +static = 'statique' +status = 'Status' +statistics = 'Statistiques' +submit = 'Soumettre' +syslog = 'Journal système' +system = 'Système' +target = 'Cible' +timezone = 'Fuseau horaire' +type = 'Type' +unknownerror = 'Erreur inconnue' +unsavedchanges = 'Changements non appliqués' +username = 'Nom d'utilisateur' +version = 'Version' +webui = 'IU Web' +wifi = 'Wi-Fi' +zone = 'Zone' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.it.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.it.lua new file mode 100644 index 0000000..7ffc729 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.it.lua @@ -0,0 +1,102 @@ +skiplink1 = 'Salta a navigazione' +skiplink2 = 'Salta a contenuto' +navigation = 'Navigazione' +about = 'Informazioni su' +add = 'Aggiungi' +addresses = 'Indirizzi' +aliases = 'Alias' +all = 'tutti' +back = 'indietro' +administration = 'Amministrazione' +essentials = 'Essenziali' +apply = 'Applica' +basicsettings = 'Impostazioni di base' +broadcast = 'Broadcast IPv4' +changes = 'Modifiche' +channel = 'Canale' +cidr6 = 'Notazione CIDR: indirizzo/prefisso' +code = 'Codice' +config = 'Configurazione' +configfile = 'File di configurazione' +confirmation = 'Conferma' +delete = 'Cancella' +descr = 'Descrizione' +design = 'Design' +destination = 'Destinazione' +device = 'Dispositivo' +devices = 'Dispositivi' +disable = 'disabilita' +distance = 'Distanza' +dmesg = 'Log del kernel' +dnsserver = 'Server DNS' +edit = 'Modifica' +enable = 'abilita' +encryption = 'Crittografia' +error = 'Errore' +filesystem = 'Filesystem' +filter = 'Filtro' +gateway = 'Gateway IPv4' +gateway6 = 'Gateway IPv6' +general = 'Generale' +hostname = 'Hostname' +install = 'Installa' +installed = 'installato' +interface = 'Interfaccia' +interfaces = 'Interfacce' +ipaddress = 'Indirizzo IPv4' +ip6address = 'Indirizzo IPv6' +legend = 'Legenda' +library = 'Libreria' +logout = 'Logout' +key = 'Chiave' +language = 'Lingua' +limit = 'Limite' +load = 'Carico' +login = 'Login' +macaddress = 'Indirizzo MAC' +manpage = 'leggi il manuale di '%s'' +metric = 'Metrica' +mode = 'Modalità' +name = 'Nome' +netmask = 'Maschera di rete IPv4' +network = 'Rete' +networks = 'Reti' +none = 'nessuna' +notinstalled = 'non installato' +ok = 'OK' +options = 'Opzioni' +overview = 'Riassunto' +packagemanager = 'Gestore pacchetti' +password = 'Password' +path = 'Percorso' +port = 'Porta' +ports = 'Porte' +protocol = 'Protocollo' +reboot = 'Riavvia' +reset = 'Reset' +revert = 'Ripristina' +save = 'Salva' +saveapply = 'Salva & applica' +scan = 'Scan' +service = 'Servizio' +services = 'Servizi' +settings = 'Impostazioni' +size = 'Dimensione' +source = 'Origine' +start = 'Inizio' +static = 'statico' +status = 'Stato' +statistics = 'Statistiche' +submit = 'Invia' +syslog = 'Log di sistema' +system = 'Sistema' +target = 'Destinazione' +timezone = 'Fuso orario' +type = 'Tipo' +unknownerror = 'Errore sconosciuto' +unsavedchanges = 'Modifiche non salvate' +username = 'Username' +version = 'Versione' +webui = 'UI web' +wifi = 'Wifi' +zone = 'Zona' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.pt-br.lua new file mode 100644 index 0000000..26672bd --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.pt-br.lua @@ -0,0 +1,103 @@ +skiplink1 = 'Ir para a navegação' +skiplink2 = 'Ir para o conteúdo' +navigation = 'Navegação' +about = 'Sobre' +add = 'Adicionar' +addresses = 'Endereços' +aliases = 'Aliases' +all = 'todos' +allf = 'todas' +back = 'voltar' +administration = 'Administração' +essentials = 'Básico' +apply = 'Aplicar' +basicsettings = 'Configurações Básicas' +broadcast = 'Broadcast-IPv4' +changes = 'Alterações' +channel = 'Canal' +cidr6 = 'Notação-CIDR: endereço/prefixo' +code = 'Código' +config = 'Configuração' +configfile = 'Arquivo de configuração' +confirmation = 'Confirmação' +delete = 'Apagar' +descr = 'Descrição' +design = 'Tema' +destination = 'Destino' +device = 'Dispositivo' +devices = 'Dispositivos' +disable = 'desativar' +distance = 'Distância' +dmesg = 'Log do Kernel' +dnsserver = 'Servidor-DNS' +edit = 'Editar' +enable = 'ativar' +encryption = 'Criptografia' +error = 'Erro' +filesystem = 'Sistema de arquivo' +filter = 'Filtro' +gateway = 'Gateway-IPv4' +gateway6 = 'Gateway-IPv6' +general = 'Geral' +hostname = 'Hostname' +install = 'Instalar' +installed = 'instalado' +interface = 'Interface' +interfaces = 'Interfaces' +ipaddress = 'Endereço-IPv4' +ip6address = 'Endereço-IPv6' +legend = 'Legenda' +library = 'Biblioteca' +logout = 'Logout' +key = 'Chave' +language = 'Idioma' +limit = 'Limite' +load = 'Carga' +login = 'Login' +macaddress = 'Endereço-MAC' +manpage = 'veja sobre '%s' no manual' +metric = 'Métrica' +mode = 'Modo' +name = 'Nome' +netmask = 'Netmask-IPv4' +network = 'Rede' +networks = 'Redes' +none = 'nenhum' +notinstalled = 'não instalado' +ok = 'OK' +options = 'Opções' +overview = 'Visão geral' +packagemanager = 'Gerenciador de Pacotes' +password = 'Senha' +path = 'Caminho' +port = 'Porta' +ports = 'Portas' +protocol = 'Protocolo' +reboot = 'Reboot' +reset = 'Restaurar' +revert = 'Recuperar' +save = 'Salvar' +saveapply = 'Salvar & Aplicar' +scan = 'Scanear' +service = 'Serviço' +services = 'Serviços' +settings = 'Configurações' +size = 'Tamanho' +source = 'Origem' +start = 'Início' +static = 'estático' +status = 'Status' +statistics = 'Estatísticas' +submit = 'Enviar' +syslog = 'Log do Sistema' +system = 'Sistema' +target = 'Destino' +timezone = 'Fuso Horário' +type = 'Tipo' +unknownerror = 'Erro Desconhecido' +unsavedchanges = 'Alterações não Salvas' +username = 'Nome do usuário' +version = 'Versão' +webui = 'Web UI' +wifi = 'Wifi' +zone = 'Zona' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.ru.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.ru.lua new file mode 100644 index 0000000..fe59e45 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/default.ru.lua @@ -0,0 +1,95 @@ +about = 'О программе' +add = 'Добавить' +addresses = 'ÐдреÑ' +aliases = 'СÑылка' +all = 'Ð’Ñе' +administration = 'Управление' +essentials = 'Essentials' +apply = 'ПринÑÑ‚ÑŒ' +basicsettings = 'Ðачальные УÑтановки' +broadcast = 'IPv4-Широковещательный' +changes = 'ИзменениÑ' +channel = 'Канал' +cidr6 = 'CIDR-Обозначение: адреÑ/префикÑ' +code = 'Код' +config = 'КонфигурациÑ' +configfile = 'Файл конфигурации' +confirmation = 'Подтверждение' +delete = 'Удалить' +descr = 'ОпиÑание' +design = 'Создание' +device = 'УÑтройÑтво' +devices = 'УÑтройÑтва' +disable = 'выключено' +distance = 'РаÑÑтоÑние' +dmesg = 'Kernel log' +dnsserver = 'DNS-Сервер' +edit = 'Редактировать' +enable = 'включено' +encryption = 'Шифрование' +error = 'Ошибка' +filesystem = 'Ð¤Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема' +filter = 'Фильтр' +gateway = 'IPv4-Шлюз' +gateway6 = 'IPv6-Шлюз' +general = 'ОÑновной' +hostname = 'Ð˜Ð¼Ñ Ñ…Ð¾Ñта' +install = 'УÑтановка' +installed = 'уÑтановленные' +interface = 'ИнтерфейÑ' +interfaces = 'ИнтерфейÑÑ‹' +ipaddress = 'IPv4-ÐдреÑ' +ip6address = 'IPv6-ÐдреÑ' +legend = 'ÐадпиÑÑŒ' +library = 'Библиотека' +logout = 'Выход' +key = 'Ключ' +language = 'Язык' +limit = 'Предел' +load = 'Загрузка' +login = 'Вход' +macaddress = 'MAC-ÐдреÑ' +manpage = 'Ñмотрите '%s' руководÑтво' +metric = 'Метрика' +mode = 'Режим' +name = 'ИмÑ' +netmask = 'IPv4-МаÑка' +network = 'Сеть' +networks = 'Сети' +none = 'ничего' +notinstalled = 'не уÑтановленно' +ok = 'OK' +options = 'Опции' +overview = 'Обзор' +packagemanager = 'Менеджер пакетов' +password = 'Пароль' +path = 'Путь' +port = 'Порт' +ports = 'Порты' +protocol = 'Протокол' +reboot = 'Перезагрузка' +reset = 'СброÑ' +revert = 'Вернуть' +save = 'Сохранить' +saveapply = 'Сохранить & ПринÑÑ‚ÑŒ' +service = 'СервиÑ' +services = 'СервиÑÑ‹' +settings = 'ÐаÑтройки' +size = 'Размер' +start = 'Старт' +static = 'ÑтатичеÑкий' +status = 'СтатуÑ' +statistics = 'СтатиÑтика' +submit = 'Отправить' +syslog = 'СиÑтемный журнал' +system = 'СиÑтема' +target = 'Цель' +timezone = 'Ð’Ñ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð·Ð¾Ð½Ð°' +type = 'Тип' +unknownerror = 'ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°' +unsavedchanges = 'ÐепринÑтые изменениÑ' +username = 'Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ' +version = 'ВерÑиÑ' +webui = 'Web UI' +wifi = 'Wi-Fi' +zone = 'Зона' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.de.lua new file mode 100644 index 0000000..27382b3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.de.lua @@ -0,0 +1,21 @@ +ff_hellonet = 'Hallo und willkommen im Netz von' +ff_public1 = 'Wir sind eine Initiative zur Schaffung eines freien, offenen und unabhängigen Funknetzwerks auf WLAN-Basis.' +ff_public2 = 'Dies ist der Zugangspunkt ' +ff_public3 = 'Er wird betrieben von ' +ff_public4 = 'Weitere Informationen zur globalen Freifunkinitiative findest du unter' +ff_public5 = 'Hast du Interesse an diesem Projekt, dann wende dich an deine lokale Gemeinschaft' +ff_public6 = 'Der Internetzugang über das experimentelle Freifunknetz ist an technische und organisatorische Bedingungen geknüpft und deshalb möglicherweise nicht (immer) gewährleistet.' +ff_location = 'Standort' +ff_mail = 'E-Mail' +ff_mail1 = 'Bitte unbedingt angeben!' +ff_nickname = 'Pseudonym' +ff_name = 'Name' +ff_node = 'Knoten' +ff_note = 'Notiz' +ff_phone = 'Telefon' +ff_ram = 'Hauptspeicher' +ff_free = 'Frei' +ff_buffers = 'Buffers' +ff_cached = 'Cached' +ff_total = 'Gesamt' +ff_geocoord = 'Geokoordinaten' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.en.lua new file mode 100644 index 0000000..cf3ae4d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/freifunk.en.lua @@ -0,0 +1,21 @@ +ff_hellonet = 'Hello and welcome in the network of' +ff_public1 = 'We are an initiative to establish a free, independent and open wireless mesh network.' +ff_public2 = 'This is the access point' +ff_public3 = 'It is operated by' +ff_public4 = 'You can find further information about the global Freifunk initiative at' +ff_public5 = 'If you are interested in our project then contact the local community' +ff_public6 = 'Internet access depends on technical and organisational conditions and may or may not work for you.' +ff_location = 'Location' +ff_mail = 'E-Mail' +ff_mail1 = 'You really should provide your address here!' +ff_nickname = 'Nickname' +ff_name = 'Realname' +ff_node = 'Node' +ff_note = 'Notice' +ff_phone = 'Phone' +ff_ram = 'Memory' +ff_free = 'Free' +ff_buffers = 'Buffers' +ff_cached = 'Cached' +ff_total = 'Total' +ff_geocoord = 'Coordinates' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.de.lua new file mode 100644 index 0000000..ca276ab --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.de.lua @@ -0,0 +1,7 @@ +disk = 'Festplatte' +enable_debug = 'Debug-Ausgaben aktivieren' +hd_idle = 'hd-idle' +hd_idle_desc = 'hd-idle ist ein Hilfsprogramm um externe Festplatten nach einer festgelegten Leerlaufzeit herunter zu fahren.' +idle_time_interval = 'Leerlaufzeit' +idle_time_unit = 'Leerlaufzeiteinheit' +settings = 'Einstellungen' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.en.lua new file mode 100644 index 0000000..2ec7780 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.en.lua @@ -0,0 +1,7 @@ +disk = 'Disk' +enable_debug = 'Enable debug' +hd_idle = 'hd-idle' +hd_idle_desc = 'hd-idle is a utility program for spinning-down external disks after a period of idle time.' +idle_time_interval = 'Idle-Time' +idle_time_unit = 'Idle-Time unit' +settings = 'Settings' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.pt-br.lua new file mode 100644 index 0000000..a1d253d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/hd_idle.pt-br.lua @@ -0,0 +1,7 @@ +disk = 'Disco' +enable_debug = 'Habilitar debug' +hd_idle = 'Hd-idle' +hd_idle_desc = 'Hd-idle é um programa utilitário para ativar o modo "economia de energia" (spinning-down) de discos externos após um período de ociosidade.' +idle_time_interval = 'Tempo de ociosidade' +idle_time_unit = 'Unidade do tempo de ociosidade' +settings = 'Configurações' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.de.lua new file mode 100644 index 0000000..13b6a4a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.de.lua @@ -0,0 +1,5 @@ +initmgr = 'Startscripte' +initmgr_desc = 'Hier können installierte Startscripte aktiviert oder deaktiviert werden. Änderungen werden erst mit einem Geräteneustart angewendet.
Warnung: Wenn essentialle Startscripte wie "network" deaktiviert werden könnte das Gerät unerreichbar werden!' +initmgr_index = 'Startpriorität' +initmgr_name = 'Startscript' +initmgr_enabled = 'Aktivieren/Deaktivieren' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.en.lua new file mode 100644 index 0000000..6e6da7b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.en.lua @@ -0,0 +1,5 @@ +initmgr = 'Initscripts' +initmgr_desc = 'You can enable or disable installed init scripts here. Changes will applied after a device reboot.
Warning: If you disable essential init scripts like "network", your device might become inaccesable!' +initmgr_index = 'Start priority' +initmgr_name = 'Initscript' +initmgr_enabled = 'Enable/Disable' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.pt-br.lua new file mode 100644 index 0000000..f6e3d5d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/initmgr.pt-br.lua @@ -0,0 +1,5 @@ +initmgr = 'Scripts de Inicialização' +initmgr_desc = 'Você pode ativar ou desativar os scripts de inicialização instalados aqui. As mudanças serão aplicadas após a reinicialização do equipamento.
Aviso: Se você desativar algum script de inicialização essencial como por exemplo "rede/network", o dispositivo poderá tornar-se inacessível!' +initmgr_index = 'Prioridade de inicialização' +initmgr_name = 'Script de inicialização' +initmgr_enabled = 'Ativar/Desativar' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.de.lua new file mode 100644 index 0000000..33c1eb1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.de.lua @@ -0,0 +1,8 @@ +livestats_incoming = "eingehend" +livestats_outgoing = "ausgehend" +livestats_traffic = "Netzverkehr auf" +livestats_wifi = "Signal-Rauschabstand für" +livestats_loadavg = "Durchschnittliche Systemlast" +livestats_stat_wireless = "Echtzeit-Drahtlosstatus" +livestats_stat_traffic = "Echtzeit-Netzwerkverkehr" +livestats_stat_loadavg = "Echtzeit-Systemlast" \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.en.lua new file mode 100644 index 0000000..04d326a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/livestats.en.lua @@ -0,0 +1,8 @@ +livestats_incoming = "incoming" +livestats_outgoing = "outgoing" +livestats_traffic = "traffic on" +livestats_wifi = "signal-to-noise ratio for" +livestats_loadavg = "load average" +livestats_stat_wireless = "Realtime Wireless Status" +livestats_stat_traffic = "Realtime Network Traffic" +livestats_stat_loadavg = "Realtime System Load" \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.de.lua new file mode 100644 index 0000000..9659839 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.de.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Portweiterleitung' +fw_redirect = 'Umleitungen' +fw_redirect_desc = 'Umleitungen erlauben es das Ziel von weitergeleiteten Paketen zu verändern.' +fw_forwarding = 'Zone-zu-Zone Verkehr' +fw_fw = 'Firewall' +fw_zone = 'Zone' +fw_zones = 'Zonen' +fw_custfwd = 'Erweiterte Weiterleitung' +firewall_rule = 'Erweiterte Regeln' +firewall_rule_desc = 'Mit erweiterten Regeln kann die Firewall an die eigenen Bedürfnisse angepasst werden. Es werden nur neue Verbindungen betrachtet. Pakete, die zu bereits bestehenden Verbindungen gehören werden automatisch akzeptiert.' +fw_fw1 = 'Die Firewall erstellt Netzwerkzonen über bestimmte Netzwerkschnittstellen um den Netzverkehr zu trennen.' +fw_src = 'Quelle' +fw_dest = 'Ziel' +fw_traffic = 'Verkehrskontrolle' +fw_mtufix = 'MSS Clamping' +fw_dropinvalid = 'Ungültige Pakete verwerfen' +firewall_rule_src = 'Eingangszone' +firewall_rule_dest = 'Ausgangszone' +firewall_rule_srcip = 'Quelladresse' +firewall_rule_destip = 'Zieladresse' +firewall_rule_srcmac = 'Quell-MAC-Adresse' +firewall_rule_srcport = 'Quellport' +firewall_rule_destport = 'Zielport' +firewall_rule_target = 'Aktion' +fw_accept = 'annehmen' +fw_reject = 'zurückweisen' +fw_drop = 'verwerfen' +fw_portfw1 = 'Portweiterleitungen ermöglichen es interne Netzwerkdienste aus einem externen Netzwerk heraus erreichbar zu machen.' +firewall_redirect_src_desc = 'Externe Zone' +firewall_redirect_srcdport = 'Externer Port' +firewall_redirect_srcdport_desc = 'Port od. Erster-Letzter Port' +firewall_redirect_destip = 'Interne Adresse' +firewall_redirect_destip_desc = 'IP-Adresse' +firewall_redirect_destport = 'Interner Port (optional)' +firewall_redirect_destport_desc = 'Port od. Erster-Letzter Port' +firewall_redirect_srcip = 'Quelladresse' +firewall_redirect_srcmac = 'Quell-MAC-Adresse' +fw_forwarding1 = 'An dieser Stelle kann festgelegt zwischen welchen Zonen Netzverkehr hin und her fließen kann. Es werden nur neue Verbindungen betrachtet. Pakete, die zu bereits bestehenden Verbindungen gehören werden automatisch akzeptiert. Bei gelegentlich auftretenden Verbindungsproblemen kann MSS Clamping helfen, ansonsten sollte dies aus Performancegründen deaktiviert bleiben.' +firewall_forwarding_src = 'Eingang' +firewall_forwarding_dest = 'Ausgang' +firewall_defaults = 'Grundeinstellungen' +firewall_defaults_desc = 'Grundeinstellungen die verwendet werden, wenn keine andere Regel angewandt werden kann.' +firewall_defaults_synflood = 'Schutz vor SYN-flood-Attacken' +firewall_defaults_input = 'Eingehender Verkehr' +firewall_defaults_output = 'Ausgehender Verkehr' +firewall_defaults_forward = 'Weitergeleiteter Verkehr' +firewall_zone_desc = 'Zonen teilen das Netzwerk in mehrere Bereiche ein um Netzverkehr sicher zu trennen. Ein oder mehrere Netzwerke gehören zu einer Zone. Das MASQ-Flag legt fest, dass aller ausgehende Netzverkehr einer Zone NAT-maskiert wird.' +firewall_zone_input = 'Eingehender Verkehr' +firewall_zone_input_desc = 'Standardaktion' +firewall_zone_output = 'Ausgehender Verkehr' +firewall_zone_output_desc = 'Standardaktion' +firewall_zone_forward = 'Weitergeleiteter Verkehr' +firewall_zone_forward_desc = 'Standardaktion' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Netzwerke' +firewall_zone_network_desc = 'verbundene Netzwerke' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.en.lua new file mode 100644 index 0000000..14bfa3c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.en.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Port forwarding' +fw_redirect = 'Traffic Redirection' +fw_redirect_desc = 'Traffic redirection allows you to change the destination address of forwarded packets.' +fw_forwarding = 'Zone-to-Zone traffic' +fw_fw = 'Firewall' +fw_zone = 'Zone' +fw_zones = 'Zones' +fw_custfwd = 'Custom forwarding' +fw_fw1 = 'The firewall creates zones over your network interfaces to control network traffic flow.' +firewall_rule = 'Advanced Rules' +firewall_rule_desc = 'Advanced rules let you customize the firewall to your needs. Only new connections will be matched. Packets belonging to already open connections are automatically allowed to pass the firewall.' +firewall_rule_src = 'Input Zone' +firewall_rule_dest = 'Output Zone' +firewall_rule_srcip = 'Source address' +firewall_rule_destip = 'Destination address' +firewall_rule_srcmac = 'Source MAC-Address' +firewall_rule_srcport = 'Source port' +firewall_rule_destport = 'Destination port' +firewall_rule_target = 'Action' +fw_accept = 'accept' +fw_reject = 'reject' +fw_drop = 'drop' +fw_src = 'Source' +fw_dest = 'Destination' +fw_traffic = 'Traffic Control' +fw_mtufix = 'MSS Clamping' +fw_dropinvalid = 'Drop invalid packets' +fw_portfw1 = 'Port forwarding allows to provide network services in the internal network to an external network.' +firewall_redirect_src_desc = 'External Zone' +firewall_redirect_srcdport = 'External port' +firewall_redirect_srcdport_desc = 'port or range as first-last' +firewall_redirect_srcip = 'Source address' +firewall_redirect_srcmac = 'Source MAC' +firewall_redirect_destip = 'Internal address' +firewall_redirect_destip_desc = 'IP-Address' +firewall_redirect_destport = 'Internal port (optional)' +firewall_redirect_destport_desc = 'port or range as first-last' +fw_forwarding1 = 'Here you can specify which network traffic is allowed to flow between network zones. Only new connections will be matched. Packets belonging to already open connections are automatically allowed to pass the firewall. If you experience occasional connection problems try enabling MSS Clamping otherwise disable it for performance reasons.' +firewall_forwarding_src = 'Input' +firewall_forwarding_dest = 'Output' +firewall_defaults = 'Defaults' +firewall_defaults_desc = 'These are the default settings that are used if no other rules match.' +firewall_defaults_synflood = 'SYN-flood protection' +firewall_defaults_input = 'Incoming Traffic' +firewall_defaults_output = 'Outgoing Traffic' +firewall_defaults_forward = 'Forwarded Traffic' +firewall_zone_desc = 'Zones part the network interfaces into certain isolated areas to separate network traffic. One or more networks can belong to a zone. The MASQ-flag enables NAT masquerading for all outgoing traffic on this zone.' +firewall_zone_input = 'Incoming Traffic' +firewall_zone_input_desc = 'Default Policy' +firewall_zone_output = 'Outgoing Traffic' +firewall_zone_output_desc = 'Default Policy' +firewall_zone_forward = 'Forwarded Traffic' +firewall_zone_forward_desc = 'Default Policy' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Networks' +firewall_zone_network_desc = 'contained networks' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.fr.lua new file mode 100644 index 0000000..a3b11e8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.fr.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Redirection de port' +fw_redirect = 'Redirection de trafic' +fw_redirect_desc = 'La redirection de trafic vous permet de changer l'adresse de destination des paquets transférés.' +fw_forwarding = 'Trafic inter-zone' +fw_fw = 'Pare-Feu' +fw_zone = 'Zone' +fw_zones = 'Zones' +fw_custfwd = 'Transfert particulière' +fw_fw1 = 'Le pare-feu crée des zone à partir des interfaces réseaux pour controller le trafic réseau.' +firewall_rule = 'Règles Avancées' +firewall_rule_desc = 'Les règles avancées vous laisse personnaliser le pare-feu selon vos besoins. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu.' +firewall_rule_src = 'Zone d'Entrée (Input)' +firewall_rule_dest = 'Zone de Sortie (Output)' +firewall_rule_srcip = 'Adresse source' +firewall_rule_destip = 'Adresse de destination' +firewall_rule_srcmac = 'Adresse MAC source' +firewall_rule_srcport = 'Port source' +firewall_rule_destport = 'Port de destination' +firewall_rule_target = 'Action' +fw_accept = 'accepter' +fw_reject = 'rejeter' +fw_drop = 'ignorer (drop)' +fw_src = 'Source' +fw_dest = 'Destination' +fw_traffic = 'Contrôle de Trafic' +fw_mtufix = 'MSS-Correction' +fw_dropinvalid = 'Drop incorrect packets' +fw_portfw1 = 'La redirection de port vous permet d'exposer des services réseaux de votre réseau local au réseau externe.' +firewall_redirect_src_desc = 'Zone externe' +firewall_redirect_srcdport = 'Port externe' +firewall_redirect_srcdport_desc = 'port ou plage de ports (premier-dernier)' +firewall_redirect_srcip = 'Adresse source' +firewall_redirect_srcmac = 'MAC source' +firewall_redirect_destip = 'Adresse interne' +firewall_redirect_destip_desc = 'Adresse IP' +firewall_redirect_destport = 'Port interne' +firewall_redirect_destport_desc = 'port ou plage de ports (premier-dernier)' +fw_forwarding1 = 'Ici, vous pouvez spécifier quel trafic réseau est autorisé à transiter entre les zones réseaux. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu.' +firewall_forwarding_src = 'Entrée (Input)' +firewall_forwarding_dest = 'Sortie (Output)' +firewall_defaults = 'Défauts' +firewall_defaults_desc = 'Ceci sont les paramètres par défaut qui sont utilisés si aucune autre règle ne s'applique.' +firewall_defaults_synflood = 'Protection anti SYN-flood' +firewall_defaults_input = 'Trafic Entrant' +firewall_defaults_output = 'Trafic Sortant' +firewall_defaults_forward = 'Trafic Transféré' +firewall_zone_desc = 'Les zones partagent les interfaces réseaux en régions isolées pour séparer les trafic réseaux. Seules les nouvelles connexions seront prises en compte. Les paquets appartenant à des connexions déjà ouvertes sont automatiquement admises à passer le pare-feu.' +firewall_zone_input = 'Trafic Entrant' +firewall_zone_input_desc = 'Politique par Défaut' +firewall_zone_output = 'Trafic Sortant' +firewall_zone_output_desc = 'Politique par Défaut' +firewall_zone_forward = 'Trafic Transféré' +firewall_zone_forward_desc = 'Politique par Défaut' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Réseaux' +firewall_zone_network_desc = 'réseaux compris' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.pt-br.lua new file mode 100644 index 0000000..3b38dc5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/luci-fw.pt-br.lua @@ -0,0 +1,56 @@ +fw_portfw = 'Redirecionamento de portas' +fw_redirect = 'Redirecionamento de Tráfego' +fw_redirect_desc = 'Redirecionamento do tráfego permite que você altere o endereço de destino dos pacotes enviados.' +fw_forwarding = 'Tráfego de Zona-para-Zona' +fw_fw = 'Firewall' +fw_zone = 'Zona' +fw_zones = 'Zonas' +fw_custfwd = 'Redirecionamento customizado' +fw_fw1 = 'O firewall cria zonas sobre suas interfaces de rede para controlar o fluxo do tráfego.' +firewall_rule = 'Regras Avançadas' +firewall_rule_desc = 'As regras avançadas permitem que você personalize o firewall de acordo com suas necessidades. Somente novas conexões serão processadas. Pacotes pertencentes às conexões já abertas estão automaticamente permitidos para passar pelo firewall.' +firewall_rule_src = 'Zona de Entrada' +firewall_rule_dest = 'Zona de Saída' +firewall_rule_srcip = 'Endereço de origem' +firewall_rule_destip = 'Endereço de destino' +firewall_rule_srcmac = 'Endereço-MAC de origem' +firewall_rule_srcport = 'Porta de origem' +firewall_rule_destport = 'Porta de destino' +firewall_rule_target = 'Ação' +fw_accept = 'aceitar' +fw_reject = 'rejeitar' +fw_drop = 'dropar' +fw_src = 'Origem' +fw_dest = 'Destino' +fw_traffic = 'Controle de Tráfego' +fw_mtufix = 'MSS-Correction' +fw_dropinvalid = 'Drop invalid packets' +fw_portfw1 = 'O redirecionamento de portas permite prover serviços de rede na rede interna para uma rede externa.' +firewall_redirect_src_desc = 'Zona Externa' +firewall_redirect_srcdport = 'Porta Externa' +firewall_redirect_srcdport_desc = 'porta ou intervalo primeira-última' +firewall_redirect_srcip = 'Endereço de origem' +firewall_redirect_srcmac = 'MAC de origem' +firewall_redirect_destip = 'Endereço interno' +firewall_redirect_destip_desc = 'Endereço-IP' +firewall_redirect_destport = 'Porta interna (opcional)' +firewall_redirect_destport_desc = 'porta ou intervalo primeira-última' +fw_forwarding1 = 'Aqui você pode especificar qual tráfego de rede será permitido para o fluxo entre zonas das redes. Somente novas conexões serão processadas. Pacotes pertencentes à conexões já abertas estão automaticamente permitidos para passar pelo firewall.' +firewall_forwarding_src = 'Entrada' +firewall_forwarding_dest = 'Saída' +firewall_defaults = 'Padrões' +firewall_defaults_desc = 'Estas são as configurações padrões, que serão usadas se não houver outras regras.' +firewall_defaults_synflood = 'Proteção SYN-flood' +firewall_defaults_input = 'Tráfego de Entrada' +firewall_defaults_output = 'Tráfego de Saída' +firewall_defaults_forward = 'Tráfego Redirecionado' +firewall_zone_desc = 'Zonas são interfaces de redes usadas para separar o tráfego da rede. Uma ou mais redes podem pertencer a uma zona. A flag-MASQ ativa o mascaramento NAT para todo o tráfego de saída desta zona.' +firewall_zone_input = 'Tráfego de Entrada' +firewall_zone_input_desc = 'Política Padrão' +firewall_zone_output = 'Tráfego de Saída' +firewall_zone_output_desc = 'Política Padrão' +firewall_zone_forward = 'Tráfego Redirecionado' +firewall_zone_forward_desc = 'Política Padrão' +firewall_zone_masq = 'MASQ' +firewall_zone_network = 'Redes' +firewall_zone_network_desc = 'redes contidas' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.de.lua new file mode 100644 index 0000000..543f98d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.de.lua @@ -0,0 +1,3 @@ +mmc_over_gpio = 'MMC/SD Treiberkonfiguration' +mmc_over_gpio_desc = 'Konfiguriert die Einstellungen des MMC/SD Karten Treibers' +settings = 'Einstellungen' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.en.lua new file mode 100644 index 0000000..a1ee564 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.en.lua @@ -0,0 +1,3 @@ +mmc_over_gpio = 'MMC/SD driver configuration' +mmc_over_gpio_desc = 'MMC/SD driver configuration' +settings = 'Settings' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.pt-br.lua new file mode 100644 index 0000000..954a89d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/mmc_over_gpio.pt-br.lua @@ -0,0 +1,3 @@ +mmc_over_gpio = 'Configuração do driver MMC/SD' +mmc_over_gpio_desc = 'Configuração do driver MMC/SD' +settings = 'Configurações' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.de.lua new file mode 100644 index 0000000..42ca434 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.de.lua @@ -0,0 +1,9 @@ +ntpc = 'Zeitsynchronisation' +ntpc_desc = 'Synchronisiert die Systemzeit' +ntpc_timeserver = 'Zeitserver' +ntpc_interval = 'Aktualisierungsintervall (in s)' +ntpc_count = 'Anzahl der Zeitmessungen' +ntpc_count_desc = 'leer = unendlich' +ntpc_drift = 'Zeitgeberjustierung' +ntpc_drift_freq = 'Frequenzabweichung' +ntpc_current = 'Aktuelle Systemzeit' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.en.lua new file mode 100644 index 0000000..35e3904 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.en.lua @@ -0,0 +1,9 @@ +ntpc = 'Time Synchronisation' +ntpc_desc = 'Synchronizes the system time' +ntpc_timeserver = 'Time Server' +ntpc_interval = 'Update Interval (in s)' +ntpc_count = 'Count of Time Measurements' +ntpc_count_desc = 'empty = infinite' +ntpc_drift = 'Clock Adjustment' +ntpc_drift_freq = 'Offset Frequency' +ntpc_current = 'Current system time' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.pt-br.lua new file mode 100644 index 0000000..be3ce5b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ntpc.pt-br.lua @@ -0,0 +1,9 @@ +ntpc = 'Sincronização de Horário' +ntpc_desc = 'Sincroniza a hora do sistema' +ntpc_timeserver = 'Servidor de Hora' +ntpc_interval = 'Intervalo de Atualização (em s)' +ntpc_count = 'Quantas vezes irá atualizar' +ntpc_count_desc = 'vazio = infinito' +ntpc_drift = 'Ajuste do Relógio' +ntpc_drift_freq = 'Frequência do Offset' +ntpc_current = 'Hora atual do sistema' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.de.lua new file mode 100644 index 0000000..4e652c8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.de.lua @@ -0,0 +1,127 @@ +olsrd = 'OLSR Daemon' +olsrd_neighbour_ip = 'Nachbar-IP' +olsrd_local_ip = 'Lokale Interface-IP' +olsrd_network = 'Angekündigtes Netzwerk' +olsrd_gateway = 'OLSR-Gateway' +olsrd_node = 'OLSR-Knoten' +olsrd_error = 'Es konnte keine Verbindung zum OLSR-Daemon hergestellt werden!' +olsrd_error_desc = 'Stellen Sie sicher das OLSRd läuft und das "txtinfo" Plugin auf Port 2006 geladen und "127.0.0.1" als Accept-Host gesetzt ist.' +olsrd_hna = 'OLSR - HNA-Ankündigungen' +olsrd_plugins = 'OLSR - Plugins' +olsrd_links = 'OLSR-Verbindungen' +olsrd_links_desc = 'Ãœbersicht über aktuell bestehende OLSR-Verbindungen' +olsrd_links_etx_desc = 'Zu erwartende Sendeversuche pro Paket' +olsrd_links_lq_desc = 'Erfolgsquote gesendeter Pakete' +olsrd_links_nlq_desc = 'Erfolgsquote empfangener Pakete' +olsrd_routes = 'Bekannte OLSR-Routen' +olsrd_routes_desc = 'Ãœbersicht über zur Zeit bekannte Routen zu anderen OLSR-Knoten' +olsrd_topology = 'Aktive OLSR-Knoten' +olsrd_topology_desc = 'Ãœbersicht über zur Zeit bekannte andere OLSR-Knoten' +olsrd_topology_lasthop = 'letzter Hop' +olsrd_hna2 = 'Aktive HNA-Ankündigungen' +olsrd_hna_desc = 'Ãœbersicht über zur Zeit aktive OLSR-Netzwerk-Ankündigungen' +olsrd_mid = 'Aktive MID-Ankündigungen' +olsrd_mid_desc = 'Ãœbersicht über bekannte Mehrfachschnittstellenmeldungen' +olsrd_mid_aliases = 'Sekundäre OLSR Schnittstellen' +olsrd_etx_ff = 'Freifunk' +olsrd_etx_float = 'Gleitkomma' +olsrd_etx_fpm = 'Festkomma' +olsrd_olsrd = 'Allgemeine Einstellungen' +olsrd_olsrd_allownoint = 'Start ohne Netzwerk' +olsrd_olsrd_clearscreen = 'Ansicht zurücksetzen' +olsrd_olsrd_debuglevel = 'Debugmodus' +olsrd_olsrd_fibmetric = 'FIB-Metrik' +olsrd_olsrd_ipversion = 'Internet Protokoll' +olsrd_olsrd_linkqualityaging = 'VQ-Alterung' +olsrd_olsrd_linkqualityalgorithm = 'VQ-Algorithmus' +olsrd_olsrd_linkqualitydijkstralimit = 'VQ-Dijkstralimit' +olsrd_olsrd_linkqualityfisheye = 'VQ-Fisheye' +olsrd_olsrd_linkqualitylevel = 'VQ-Level' +olsrd_olsrd_linkqualitylevel_1 = 'MPR-Auswahl' +olsrd_olsrd_linkqualitylevel_2 = 'MPR-Auswahl und Routing' +olsrd_olsrd_linkqualitywinsize = 'VQ-Fenstergröße' +olsrd_olsrd_mprcoverage = 'MPR-Erfassung' +olsrd_olsrd_pollrate = 'Abfragerate' +olsrd_olsrd_tcredundancy = 'TC-Redundanz' +olsrd_olsrd_tcredundancy_0 = 'MPR-Selektoren' +olsrd_olsrd_tcredundancy_1 = 'MPR-Selektoren und MPR' +olsrd_olsrd_tcredundancy_2 = 'Alle Nachbarn' +olsrd_olsrd_usehysteresis = 'Hysterese aktivieren' +olsrd_olsrd_willingness = 'Bereitschaft' +olsrd_interface_hellointerval = 'Hello-Intervall' +olsrd_interface_hellovaliditytime = 'Hello-Gültigkeit' +olsrd_interface_hnainterval = 'HNA-Intervall' +olsrd_interface_hnavaliditytime = 'HNA-Gültigkeit' +olsrd_interface_ip4broadcast = 'IPv4 Broadcast' +olsrd_interface_midinterval = 'MID-Intervall' +olsrd_interface_midvaliditytime = 'MID-Gültigkeit' +olsrd_interface_tcinterval = 'TC-Intervall' +olsrd_interface_tcvaliditytime = 'TC-Gültigkeit' +olsrd_interface_ip6addrtype = 'IPv6 Adresstyp' +olsrd_ipcconnect = 'IPC-Einstellungen' +olsrd_ipcconnect_desc = 'IPC-Verbindungen ermöglichen die Fernsteuerung des lokalen OLSR-Prozesses durch externe Programme' +olsrd_ipcconnect_host = 'Erlaubte Hostadressen' +olsrd_ipcconnect_host_desc = 'Mehrere mit Leerzeichen trennen' +olsrd_ipcconnect_maxconnections = 'Maximale Anzahl von Verbindungen' +olsrd_ipcconnect_maxconnections_desc = '0 deaktiviert IPC' +olsrd_ipcconnect_net = 'Erlaubte Netzbereiche' +olsrd_ipcconnect_net_desc = 'Adresse Maske; mehrere mit Leerzeichen' +olsrd_hna4 = 'IPv4 HNA-Ankündigungen' +olsrd_hna4_desc = 'Hna4-Entries ermöglichen die Ankündigung von lokalen IPv4 Host- und Netz-Routen im Mesh-Netzwerk' +olsrd_hna4_netaddr = 'Netzwerk-Adresse' +olsrd_hna4_netaddr_desc = 'IPv4 Adresse' +olsrd_hna4_netmask = 'Netzmaske' +olsrd_hna4_netmask_desc = 'IPv4 Adresse' +olsrd_hna6 = 'IPv6 HNA-Ankündigungen' +olsrd_hna6_desc = 'Hna6-Entries ermöglichen die Ankündigung von lokalen IPv6 Host- und Netz-Routen im Mesh-Netzwerk' +olsrd_hna6_netaddr = 'Netzwerk-Adresse' +olsrd_hna6_netaddr_desc = 'IPv6 Adresse' +olsrd_hna6_prefix = 'Prefix' +olsrd_hna6_prefix_desc = 'IPv6 Prefix' +olsrd_loadplugin = 'Pluginkonfiguration' +olsrd_loadplugin_ignore = 'Plugin aktivieren' +olsrd_loadplugin_library = 'Bibliothek' +olsrd_loadplugin_accept = 'Verbindungsaufbau von Addressen zulassen' +olsrd_loadplugin_ping = 'Pingtest Adressen' +olsrd_loadplugin_interval = 'Intervall' +olsrd_loadplugin_hna = 'HNA Ankündigungen' +olsrd_loadplugin_hna_desc = 'Format: IP-Adresse Netzmaske / OLSR kündigt dieses Netzwerk an sobald das Gateway erreichbar ist' +olsrd_loadplugin_addhosts = 'Alternative \"hosts\" Datei' +olsrd_loadplugin_addhosts_desc = 'Der Inhalt dieser Datei wird mit in die autogenerierte \"hosts\" Datei übernommen' +olsrd_loadplugin_dnsserver = 'DNS-Server' +olsrd_loadplugin_hosts = 'Alternative Hostnamen' +olsrd_loadplugin_hosts_desc = 'Format: Interface-IP Hostname' +olsrd_loadplugin_hostsfile = 'Pfad zur \"hosts\" Datei' +olsrd_loadplugin_lat = 'Latitude' +olsrd_loadplugin_latlonfile = 'Ausgabedatei für Koordinaten' +olsrd_loadplugin_latlonfile_desc = 'OLSR schreibt alle empfangenen Koordinaten anderer Knoten in diese Datei' +olsrd_loadplugin_latloninfile = 'Eingabedatei für Koordinaten' +olsrd_loadplugin_latloninfile_desc = 'OLSR prüft diese Datei periodisch auf neue Koordinaten und propagiert diese' +olsrd_loadplugin_lon = 'Longitude' +olsrd_loadplugin_name = 'Hostnamen' +olsrd_loadplugin_namechangescript = 'Kommando bei Namensänderungen' +olsrd_loadplugin_namechangescript_desc = 'OLSR ruft dieses Kommando auf sobald sich Einträge in der \"hosts\" Datei ändern' +olsrd_loadplugin_resolvfile = 'Pfad zur \"resolv\" Datei' +olsrd_loadplugin_serviceschangescript = 'Kommando bei Serviceänderungen' +olsrd_loadplugin_serviceschangescript_desc = 'OLSR ruft dieses Kommando auf sobald neue Service-Ankündigungen empfangen werden' +olsrd_loadplugin_sighuppidfile = 'PID-Datei für SIGHUP Signale' +olsrd_loadplugin_sighuppidfile_desc = 'OLSR sendet ein HUP Signal an den in der PID Datei angegebenen Prozess sobald sich die \"hosts\" oder \"resolv\" Datei ändert' +olsrd_loadplugin_suffix = 'Domain-Suffix' +olsrd_loadplugin_timeout = 'Timeout' +olsrd_loadplugin_bmfinterface = 'Name für die BMF-Schnittstelle' +olsrd_loadplugin_bmfinterfaceid = 'IP-Adresse für die BMF-Schnittstelle' +olsrd_loadplugin_dolocalbroadcast = 'Lokale Broadcasts weiterleiten' +olsrd_loadplugin_capturepacketsonolsrinterfaces = 'Broadcasts von OLSR-Schnittstellen weiterleiten' +olsrd_loadplugin_bmfmechanism = 'Verteilungsmechanismus' +olsrd_loadplugin_broadcastretransmitcount = 'Anzahl der Neuversendungen pro Paket' +olsrd_loadplugin_fanoutlimit = 'Mindestanzahl der Nachbarn für Broadcastweiterleitung' +olsrd_loadplugin_nonolsrif = 'Nicht-OLSR-Interfaces' +olsrd_loadplugin_port = 'Verwendeter Port' +olsrd_loadplugin_host = 'Verbindungsaufbau von Hosts zulassen' +olsrd_loadplugin_net = 'Verbindungsaufbau von Subnetzen zulassen' +olsrd_loadplugin_net_desc = 'Format: IP-Adresse Netzmaske' +olsrd_loadplugin_redistribute = 'Verwendete Protokolle' +olsrd_loadplugin_exportroutes = 'Routen nur an Quagga oder auch an Kernel exportieren' +olsrd_loadplugin_localpref = 'Lokale Routen immer bevorzugen' +olsrd_loadplugin_distance = 'Distanz für exportierte Routen' +olsrd_loadplugin_keyfile = 'Schlüsseldatei' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.en.lua new file mode 100644 index 0000000..dc1e442 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/olsr.en.lua @@ -0,0 +1,127 @@ +olsrd = 'OLSR Daemon' +olsrd_neighbour_ip = 'Neighbour IP' +olsrd_local_ip = 'Local interface IP' +olsrd_network = 'Announced network' +olsrd_gateway = 'OLSR gateway' +olsrd_node = 'OLSR node' +olsrd_error = 'Unable to connect to the OLSR daemon!' +olsrd_error_desc = 'Make sure that OLSRd is running, the "txtinfo" plugin is loaded, configured on port 2006 and accepts connections from "127.0.0.1".' +olsrd_hna = 'OLSR - HNA-Announcements' +olsrd_plugins = 'OLSR - Plugins' +olsrd_links = 'OLSR connections' +olsrd_links_desc = 'Overview of currently established OLSR connections' +olsrd_links_etx_desc = 'Expected retransmission count' +olsrd_links_lq_desc = 'Success rate of sent packages' +olsrd_links_nlq_desc = 'Success rate of received packages' +olsrd_routes = 'Known OLSR routes' +olsrd_routes_desc = 'Overview of currently known routes to other OLSR nodes' +olsrd_topology = 'Active OLSR nodes' +olsrd_topology_desc = 'Overview of currently known OLSR nodes' +olsrd_topology_lasthop = 'Last hop' +olsrd_hna2 = 'Active host net announcements' +olsrd_hna_desc = 'Overview of currently active OLSR host net announcements' +olsrd_mid = 'Active MID announcements' +olsrd_mid_desc = 'Overview of known multiple interface announcements' +olsrd_mid_aliases = 'Secondary OLSR interfaces' +olsrd_etx_ff = 'Freifunk' +olsrd_etx_float = 'floating point' +olsrd_etx_fpm = 'fixed point math' +olsrd_olsrd = 'General settings' +olsrd_olsrd_allownoint = 'Start without network' +olsrd_olsrd_clearscreen = 'Clear screen' +olsrd_olsrd_debuglevel = 'Debugmode' +olsrd_olsrd_fibmetric = 'FIB metric' +olsrd_olsrd_ipversion = 'Internet protocol' +olsrd_olsrd_linkqualityaging = 'LQ aging' +olsrd_olsrd_linkqualityalgorithm = 'LQ algorithm' +olsrd_olsrd_linkqualitydijkstralimit = 'LQ Dijkstra limit' +olsrd_olsrd_linkqualityfisheye = 'LQ fisheye' +olsrd_olsrd_linkqualitylevel = 'LQ level' +olsrd_olsrd_linkqualitylevel_1 = 'MPR selection' +olsrd_olsrd_linkqualitylevel_2 = 'MPR selection and routing' +olsrd_olsrd_linkqualitywinsize = 'LQ window size' +olsrd_olsrd_mprcoverage = 'MPR coverage' +olsrd_olsrd_pollrate = 'Pollrate' +olsrd_olsrd_tcredundancy = 'TC redundancy' +olsrd_olsrd_tcredundancy_0 = 'MPR selectors' +olsrd_olsrd_tcredundancy_1 = 'MPR selectors and MPR' +olsrd_olsrd_tcredundancy_2 = 'all neighbours' +olsrd_olsrd_usehysteresis = 'Use hysteresis' +olsrd_olsrd_willingness = 'Willingness' +olsrd_interface_hellointerval = 'Hello interval' +olsrd_interface_hellovaliditytime = 'Hello validity time' +olsrd_interface_hnainterval = 'HNA interval' +olsrd_interface_hnavaliditytime = 'HNA validity time' +olsrd_interface_ip4broadcast = 'IPv4 broadcast' +olsrd_interface_midinterval = 'MID interval' +olsrd_interface_midvaliditytime = 'MID validity time' +olsrd_interface_tcinterval = 'TC interval' +olsrd_interface_tcvaliditytime = 'TC validity time' +olsrd_interface_ip6addrtype = 'IPv6 address type' +olsrd_ipcconnect = 'IPC settings' +olsrd_ipcconnect_desc = 'IPC connections enable you to remote-control the local OLSRd instance using external programs' +olsrd_ipcconnect_host = 'Allowed host addresses' +olsrd_ipcconnect_host_desc = 'Multiple separated by spaces' +olsrd_ipcconnect_maxconnections = 'Maxmimum connection count' +olsrd_ipcconnect_maxconnections_desc = 'Set to 0 to disable IPC' +olsrd_ipcconnect_net = 'Allowed subnets' +olsrd_ipcconnect_net_desc = 'Address Mask; multiple separated by space' +olsrd_hna4 = 'IPv4 HNA announcements' +olsrd_hna4_desc = 'Hna4 entries allow you to propagate local IPv4 host- and network-routes into the mesh network' +olsrd_hna4_netaddr = 'Network address' +olsrd_hna4_netaddr_desc = 'IPv4 address' +olsrd_hna4_netmask = 'Netmask' +olsrd_hna4_netmask_desc = 'IPv4 address' +olsrd_hna6 = 'IPv6 HNA announcements' +olsrd_hna6_desc = 'Hna6 entries allow you to propagate local IPv6 host- and network-routes into the mesh network' +olsrd_hna6_netaddr = 'Network address' +olsrd_hna6_netaddr_desc = 'IPv6 address' +olsrd_hna6_prefix = 'Prefix' +olsrd_hna6_prefix_desc = 'IPv6 prefix' +olsrd_loadplugin = 'Plugin configuration' +olsrd_loadplugin_ignore = 'Enable plugin' +olsrd_loadplugin_library = 'Library' +olsrd_loadplugin_accept = 'Allow connections from this hosts' +olsrd_loadplugin_ping = 'Ping test addresses' +olsrd_loadplugin_interval = 'Interval' +olsrd_loadplugin_hna = 'HNA announcements' +olsrd_loadplugin_hna_desc = 'Format: IP-Address Netmask / OLSR will announce this network once it is reachable' +olsrd_loadplugin_addhosts = 'Alternative \"hosts\" file' +olsrd_loadplugin_addhosts_desc = 'The contents of this file will be appended to the autogenerated \"hosts\" file' +olsrd_loadplugin_dnsserver = 'DNS server' +olsrd_loadplugin_hosts = 'Alternative hostnames' +olsrd_loadplugin_hosts_desc = 'Format: Interface-IP Hostname' +olsrd_loadplugin_hostsfile = 'Path to the \"hosts\" file' +olsrd_loadplugin_lat = 'Latitude' +olsrd_loadplugin_latlonfile = 'Output file for coordinates' +olsrd_loadplugin_latlonfile_desc = 'OLSR will write received coordinates of other nodes to this file' +olsrd_loadplugin_latloninfile = 'Input file for coordinates' +olsrd_loadplugin_latloninfile_desc = 'OLSR periodically checks this file for new coordinates and propagates them' +olsrd_loadplugin_lon = 'Longitude' +olsrd_loadplugin_name = 'Hostnames' +olsrd_loadplugin_namechangescript = 'Command for name changes' +olsrd_loadplugin_namechangescript_desc = 'OLSR executes this command once entries in the \"hosts\" are changed' +olsrd_loadplugin_resolvfile = 'Path to the \"resolv\" file' +olsrd_loadplugin_serviceschangescript = 'Command for service changes' +olsrd_loadplugin_serviceschangescript_desc = 'OLSR excutes this command once new service announcements are received' +olsrd_loadplugin_sighuppidfile = 'PID file for SIGHUP signals' +olsrd_loadplugin_sighuppidfile_desc = 'OLSR sends a HUP signal to this PID once the \"hosts\" oder \"resolv\" file is changed' +olsrd_loadplugin_suffix = 'Domain suffix' +olsrd_loadplugin_timeout = 'Timeout' +olsrd_loadplugin_bmfinterface = 'Name of the BMF interface' +olsrd_loadplugin_bmfinterfaceid = 'IP address of the BMF interface' +olsrd_loadplugin_dolocalbroadcast = 'Redirect local broadcasts' +olsrd_loadplugin_capturepacketsonolsrinterfaces = 'Also redirect broadcasts from OLSR interfaces' +olsrd_loadplugin_bmfmechanism = 'Propagation mechanism' +olsrd_loadplugin_broadcastretransmitcount = 'Number of retransmissions per package' +olsrd_loadplugin_fanoutlimit = 'Minimum number of neighbours for broadcast redirection' +olsrd_loadplugin_nonolsrif = 'Non-OLSR interfaces' +olsrd_loadplugin_port = 'Used port' +olsrd_loadplugin_host = 'Allow connections from hosts' +olsrd_loadplugin_net = 'Allow connections from subnets' +olsrd_loadplugin_net_desc = 'Format: IP-AddresseNetmask' +olsrd_loadplugin_redistribute = 'Used protocols' +olsrd_loadplugin_exportroutes = 'Only export routes to Quagga or to kernel too' +olsrd_loadplugin_localpref = 'Always prefer local routes' +olsrd_loadplugin_distance = 'Distance of exported routes' +olsrd_loadplugin_keyfile = 'Key file' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.de.lua new file mode 100644 index 0000000..b8cf6e6 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.de.lua @@ -0,0 +1,4 @@ +p910nd = 'p910nd - Drucker server' +p910nd_desc = 'Bevor p910nd verwendet werden kann muessen Pakete fuer USB (kmod-usb-printer) und Parallelport (kmod-lp) Support installiert werden.' +bidirectional = 'Bidirektionaler Modus' +port_help = 'p910nd hoert auf Port 910+N. Z.B. 9100 fuer ersten Drucker' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.en.lua new file mode 100644 index 0000000..c9b3c8f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.en.lua @@ -0,0 +1,4 @@ +p910nd = 'p910nd - Printer server' +p910nd_desc = 'First you have to install the packages to get support for USB (kmod-usb-printer) or parallel port (kmod-lp).' +bidirectional = 'Bidirectional mode' +port_help = 'p910nd listens on port 910+N. E.g. 9100 for the first printer.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.pt-br.lua new file mode 100644 index 0000000..71e4acb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/p910nd.pt-br.lua @@ -0,0 +1,4 @@ +p910nd = 'P910nd - Servidor de impressão' +p910nd_desc = 'Primeiro você deve instalar os pacotes para obter suporte USB (kmod-usb-printer) ou porta paralela (kmod-lp).' +bidirectional = 'Modo bidirecional' +port_help = 'p910nd escuta na porta 910+N. Ex. 9100 para a primeira impressora.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/polipo.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/polipo.en.lua new file mode 100644 index 0000000..23b1836 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/polipo.en.lua @@ -0,0 +1,43 @@ +polipo = 'Polipo' +polipo_cache = 'On-Disk Cache' +polipo_cache_cacheisshared = 'Shared cache' +polipo_cache_cacheisshared_desc = 'Enable if cache (proxy) is shared by multiple users.' +polipo_cache_desc = 'To enable polipo on-disk cache cleaning (highly recommended), you should add a cron job in Scheduled Tasks services that will execute /usr/sbin/polipo_purge script. For example to perform disk cache cleanup every day at 6:00 in the morning you should add the following line in Scheduled Tasks "0 6 * * * /usr/sbin/polipo_purge" (without quotes).' +polipo_cache_diskcacheroot = 'Disk cache location' +polipo_cache_diskcacheroot_desc = 'Location where polipo will cache files permanently. Use of external storage devices is recommended, because the cache can grow considerably. Leave it empty to disable on-disk cache.' +polipo_cache_diskcachetruncatesize = 'Truncate cache files size (in bytes)' +polipo_cache_diskcachetruncatesize_desc = 'Size to which cached files should be truncated. (default value: 1048576)' +polipo_cache_diskcachetruncatetime = 'Truncate cache files time' +polipo_cache_diskcachetruncatetime_desc = 'Time after which cached files will be truncated. (default value: 4d12h)' +polipo_cache_diskcacheunlinktime = 'Delete cache files time' +polipo_cache_diskcacheunlinktime_desc = 'Time after which cached files will be deleted. (default value: 32d)' +polipo_desc = 'Polipo is a small and fast caching web proxy.' +polipo_general = 'General' +polipo_general_allowedclients = 'Allowed clients' +polipo_general_allowedclients_desc = 'When listen address is set to 0.0.0.0 or :: (IPv6), you must list clients that are allowed to connect. The format is IP address or network address (192.168.1.123, 192.168.1.0/24, 2001:660:116::/48 (IPv6)).' +polipo_general_chunkhighmark = 'In RAM cache size (in bytes)' +polipo_general_chunkhighmark_desc = 'How much RAM should Polipo use for its cache.' +polipo_general_dnsnameserver = 'DNS server address' +polipo_general_dnsnameserver_desc = 'Set the DNS server address to use, if you want Polipo to use different DNS server than the host system.' +polipo_general_dnsqueryipv6 = 'Query DNS for IPv6' +polipo_general_dnsqueryipv6_desc = 'false = Do not query IPv6; reluctantly = Query both, prefer IPv4; happily = Query both, prefer IPv6; true = Query only IPv6' +polipo_general_dnsusegethostbyname = 'Query DNS by hostname' +polipo_general_dnsusegethostbyname_desc = 'false = Never use system DNS resolver; reluctantly = Query DNS directly, if DNS server is unavailable fail to system DNS resolver; happily = Query DNS directly, if host could not be found fallback to system DNS resolver; true = Always use system DNS resolver' +polipo_general_logfacility = 'Syslog facility' +polipo_general_logfile = 'Log file location' +polipo_general_logfile_desc = 'Use of external storage device is recommended, because the log file is written frequently and can grow considerably.' +polipo_general_logsyslog = 'Log to syslog' +polipo_general_parentauthcredentials = 'Parent proxy authentication' +polipo_general_parentauthcredentials_desc = 'Basic HTTP authentication supported. Provide username and password in username:password format.' +polipo_general_parentproxy = 'Parent proxy address' +polipo_general_parentproxy_desc = 'Parent proxy address (in host:port format), to which Polipo will forward the requests.' +polipo_general_proxyaddress = 'Listen address' +polipo_general_proxyaddress_desc = 'The interface on which Polipo will listen. To listen on all interfaces use 0.0.0.0 or :: (IPv6).' +polipo_general_proxyport = 'Listen port' +polipo_general_proxyport_desc = 'Port on which Polipo will listen. (default value: 8123)' +polipo_pmm = 'Poor Man's Multiplexing' +polipo_pmm_desc = 'Poor Man's Multiplexing (PMM) is a technique that simulates multiplexing by requesting an instance in multiple segments. It tries to lower the latency caused by the weakness of HTTP protocol. NOTE: some sites may not work with PMM enabled.' +polipo_pmm_pmmfirstsize = 'First PMM segment size (in bytes)' +polipo_pmm_pmmfirstsize_desc = 'Size of the first PMM segment. If not defined, it defaults to twice the PMM segment size.' +polipo_pmm_pmmsize = 'PMM segments size (in bytes)' +polipo_pmm_pmmsize_desc = 'To enable PMM, PMM segment size must be set to some positive value.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.de.lua new file mode 100644 index 0000000..1ef5499 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.de.lua @@ -0,0 +1,17 @@ +qos = 'Quality of Service' +qos_interface_classgroup = 'Klassifizierung' +qos_interface_overhead = 'Overheadberechnung' +qos_interface_download = 'Downlink' +qos_interface_upload = 'Uplink' +qos_classify = 'Priorisierung' +qos_classify_target = 'Priorität' +qos_classify_srchost = 'Quelladresse' +qos_classify_srchost_dest = 'Quellnetz / Quellhost' +qos_classify_dsthost = 'Zieladresse' +qos_classify_dsthost_dest = 'Zielnetz / Zielhost' +qos_classify_portrange = 'Portbereich' +qos_bulk = 'niedrig' +qos_normal = 'normal' +qos_express = 'express' +qos_priority = 'priorisiert' +qos_connbytes = 'Bytes gesendet' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.en.lua new file mode 100644 index 0000000..67494e7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.en.lua @@ -0,0 +1,18 @@ +qos = 'Quality of Service' +qos_desc = 'With QoS you can priorize network traffic selected by adresses, ports or services.' +qos_interface_classgroup = 'Classification' +qos_interface_overhead = 'Calculate Overhead' +qos_interface_download = 'Downlink' +qos_interface_upload = 'Uplink' +qos_classify = 'Prioritization' +qos_classify_target = 'Priority' +qos_classify_srchost = 'Source address' +qos_classify_srchost_dest = 'source network / source host' +qos_classify_dsthost = 'Target address' +qos_classify_dsthost_dest = 'target network / target host' +qos_classify_portrange = 'portrange' +qos_bulk = 'low' +qos_normal = 'normal' +qos_express = 'express' +qos_priority = 'priority' +qos_connbytes = 'Bytes sent' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.fr.lua new file mode 100644 index 0000000..73c54dc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.fr.lua @@ -0,0 +1,17 @@ +qos = 'Qualité de service' +qos_bulk = 'lent' +qos_classify = 'Priorité' +qos_classify_dsthost = 'Adresse de destination' +qos_classify_dsthost_dest = 'Réseau de destination / Hôte de destination' +qos_classify_portrange = 'ports' +qos_classify_srchost = 'Adresse source' +qos_classify_srchost_dest = 'Réseau source / Hôte source' +qos_classify_target = 'Priorité' +qos_desc = 'Avec la QOS, vous pouvez donner des priorités au trafic de votre réseau en fonction des adresses, des ports ou des services présents.' +qos_express = 'express' +qos_interface_classgroup = 'Classification' +qos_interface_download = 'Liaison descendante' +qos_interface_overhead = 'calcul de la surcharge' +qos_interface_upload = 'Liaison montante' +qos_normal = 'normal' +qos_priority = 'prioritaire' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.pt-br.lua new file mode 100644 index 0000000..582e7aa --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/qos.pt-br.lua @@ -0,0 +1,17 @@ +qos = 'Qualidade de Serviço' +qos_desc = 'Com QoS você pode priozirar o tráfego da rede selecionada por endereços, portas ou serviços.' +qos_interface_classgroup = 'Classificação' +qos_interface_overhead = 'Calcular Overhead' +qos_interface_download = 'Link para download' +qos_interface_upload = 'Link para upload' +qos_classify = 'Priorização' +qos_classify_target = 'Prioridade' +qos_classify_srchost = 'Endereço de origem' +qos_classify_srchost_dest = 'rede de origem / host de origem' +qos_classify_dsthost = 'Endereço de destino' +qos_classify_dsthost_dest = 'rede de destino / host de destino' +qos_classify_portrange = 'faixa de portas' +qos_bulk = 'baixa' +qos_normal = 'normal' +qos_express = 'expressa' +qos_priority = 'alta' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.lua new file mode 100644 index 0000000..afd97f0 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.lua @@ -0,0 +1,70 @@ +stat_dg_title_wireless__signal_noise = [[%H: Drahtlos - Signal-Noise-Verhältnis]] +stat_dg_label_wireless__signal_noise = [[dBm]] +stat_ds_signal_noise = [[Noise-Level]] +stat_ds_signal_power = [[Signalstärke]] +stat_dg_title_wireless__signal_quality = [[%H: Drahtlos - Signalqualität]] +stat_dg_label_wireless__signal_quality = [[n]] +stat_ds_signal_quality = [[Signalqualität]] +stat_dg_title_ping = [[%H: ICMP Antwortzeiten]] +stat_dg_label_ping = [[ms]] +stat_ds_ping = [[%di]] +stat_dg_title_iptables__ipt_packets = [[%H: Firewall - Verarbeitete Pakete]] +stat_dg_label_iptables__ipt_packets = [[Pakete/s]] +stat_ds_ipt_packets = [[Kette "%di"]] +stat_dg_title_netlink__if_octets = [[%H: Netlink - Transfer auf %pi]] +stat_dg_label_netlink__if_octets = [[Bytes/s]] +stat_ds_if_octets = [[Bytes (%ds)]] +stat_dg_title_netlink__if_packets = [[%H: Netlink - Pakete auf %pi]] +stat_dg_label_netlink__if_packets = [[Pakete/s]] +stat_ds_if_packets = [[Verarbeitet (%ds)]] +stat_ds_if_dropped = [[Verworfen (%ds)]] +stat_ds_if_errors = [[Fehler (%ds)]] +stat_dg_title_netlink__if_multicast = [[%H: Netlink - Multicast auf %pi]] +stat_dg_label_netlink__if_multicast = [[Pakete/s]] +stat_ds_if_multicast = [[Pakete]] +stat_dg_title_netlink__if_collisions = [[%H: Netlink - Kollisionen auf %pi]] +stat_dg_label_netlink__if_collisions = [[Kollisionen/s]] +stat_ds_if_collisions = [[Kollisionen]] +stat_dg_title_netlink__if_tx_errors = [[%H: Netlink - Fehler auf %pi]] +stat_dg_label_netlink__if_tx_errors = [[Fehler/s]] +stat_ds_if_tx_errors = [[%di]] +stat_ds_if_rx_errors = [[%di]] +stat_dg_title_processes = [[%H: Prozesse]] +stat_dg_label_processes = [[Prozesse/s]] +stat_ds_ps_state = [[%di]] +stat_dg_title_processes__ps_cputime = [[%H: Prozess %pi - Verbrauchte CPU Zeit]] +stat_dg_label_processes__ps_cputime = [[Jiffies]] +stat_ds_ps_cputime__syst = [[System]] +stat_ds_ps_cputime__user = [[User]] +stat_dg_title_processes__ps_count = [[%H: Prozess %pi - Threads und Prozesse]] +stat_dg_label_processes__ps_count = [[Anzahl]] +stat_ds_ps_count__threads = [[Threads]] +stat_ds_ps_count__processes = [[Prozesse]] +stat_dg_title_processes__ps_pagefaults = [[%H: Prozess %pi - Speicherzugriffsfehler]] +stat_dg_label_processes__ps_pagefaults = [[Zugriffsfehler]] +stat_ds_ps_pagefaults = [[Zugriffsfehler]] +stat_dg_title_processes__ps_rss = [[%H: Process %pi - Virtueller Speicher]] +stat_dg_label_processes__ps_rss = [[Bytes]] +stat_ds_ps_rss = [[virtueller Speicher]] +stat_dg_title_cpu = [[%H: Auslastung auf Prozessor #%pi]] +stat_dg_label_cpu = [[%]] +stat_ds_cpu = [[%di]] +stat_dg_title_interface__if_octets = [[%H: Transfer auf %di]] +stat_dg_label_interface__if_octets = [[Bytes/s]] +stat_dg_title_interface__if_packets = [[%H: Pakete auf %di]] +stat_dg_label_interface__if_packets = [[Pakete/s]] +stat_dg_title_tcpconns = [[%H: TCP-Verbindungen auf Port %pi]] +stat_dg_label_tcpconns = [[Verbindungen/s]] +stat_ds_tcp_connections = [[%di]] +stat_dg_title_df = [[%H: Speicherverbrauch auf %di]] +stat_dg_label_df = [[Bytes]] +stat_ds_df__free = [[verfügbar]] +stat_ds_df__used = [[belegt ]] +stat_dg_title_irq = [[%H: Interrupts]] +stat_dg_label_irq = [[Aufrufe/s]] +stat_ds_irq = [[IRQ %di]] +stat_dg_title_load = [[%H: Systemlast]] +stat_dg_label_load = [[Last]] +stat_ds_load__shortterm = [[1 Minute]] +stat_ds_load__midterm = [[5 Minuten]] +stat_ds_load__longterm = [[15 Minuten]] diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.xml.hide b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.xml.hide new file mode 100644 index 0000000..1432321 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.de.xml.hide @@ -0,0 +1,96 @@ + + + + +%H: Drahtlos - Signal-Noise-Verhältnis +dBm +Noise-Level +Signalstärke + +%H: Drahtlos - Signalqualität +n +Signalqualität + +%H: ICMP Antwortzeiten +ms +%di + +%H: Firewall - Verarbeitete Pakete +Pakete/s +Kette "%di" + +%H: Netlink - Transfer auf %pi +Bytes/s +Bytes (%ds) + +%H: Netlink - Pakete auf %pi +Pakete/s +Verarbeitet (%ds) +Verworfen (%ds) +Fehler (%ds) + +%H: Netlink - Multicast auf %pi +Pakete/s +Pakete + +%H: Netlink - Kollisionen auf %pi +Kollisionen/s +Kollisionen + +%H: Netlink - Fehler auf %pi +Fehler/s +%di +%di + +%H: Prozesse +Prozesse/s +%di + +%H: Prozess %pi - Verbrauchte CPU Zeit +Jiffies +System +User + +%H: Prozess %pi - Threads und Prozesse +Anzahl +Threads +Prozesse + +%H: Prozess %pi - Speicherzugriffsfehler +Zugriffsfehler +Zugriffsfehler + +%H: Process %pi - Virtueller Speicher +Bytes +virtueller Speicher + +%H: Auslastung auf Prozessor #%pi +% +%di + +%H: Transfer auf %di +Bytes/s + +%H: Pakete auf %di +Pakete/s + +%H: TCP-Verbindungen auf Port %pi +Verbindungen/s +%di + +%H: Speicherverbrauch auf %di +Bytes +verfügbar +belegt + +%H: Interrupts +Aufrufe/s +IRQ %di + +%H: Systemlast +Last +1 Minute +5 Minuten +15 Minuten + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.lua new file mode 100644 index 0000000..2da4be8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.lua @@ -0,0 +1,69 @@ +stat_dg_title_wireless__signal_noise = [[%H: Wireless - Signal Noise Ratio]] +stat_dg_label_wireless__signal_noise = [[dBm]] +stat_ds_signal_noise = [[Noise Level]] +stat_ds_signal_power = [[Signal Strength]] +stat_dg_title_wireless__signal_quality = [[%H: Wireless - Signal Quality]] +stat_dg_label_wireless__signal_quality = [[n]] +stat_ds_signal_quality = [[Signal Quality]] +stat_dg_title_ping = [[%H: ICMP Roundtrip Times]] +stat_dg_label_ping = [[ms]] +stat_ds_ping = [[%di]] +stat_dg_title_iptables__ipt_packets = [[%H: Firewall - Processed Packets]] +stat_dg_label_iptables__ipt_packets = [[Packets/s]] +stat_ds_ipt_packets = [[Chain "%di"]] +stat_dg_title_netlink__if_octets = [[%H: Netlink - Transfer on %pi]] +stat_dg_label_netlink__if_octets = [[Bytes/s]] +stat_ds_if_octets = [[Bytes (%ds)]] +stat_dg_title_netlink__if_packets = [[%H: Netlink - Packets on %pi]] +stat_dg_label_netlink__if_packets = [[Packets/s]] +stat_ds_if_packets = [[Processed (%ds)]] +stat_ds_if_dropped = [[Dropped (%ds)]] +stat_ds_if_errors = [[Errors (%ds)]] +stat_dg_title_netlink__if_multicast = [[%H: Netlink - Multicast on %pi]] +stat_dg_label_netlink__if_multicast = [[Packets/s]] +stat_ds_if_multicast = [[Packets]] +stat_dg_title_netlink__if_collisions = [[%H: Netlink - Collisions on %pi]] +stat_dg_label_netlink__if_collisions = [[Collisions/s]] +stat_ds_if_collisions = [[Collisions]] +stat_dg_title_netlink__if_tx_errors = [[%H: Netlink - Errors on %pi]] +stat_dg_label_netlink__if_tx_errors = [[Errors/s]] +stat_ds_if_tx_errors = [[%di]] +stat_ds_if_rx_errors = [[%di]] +stat_dg_title_processes = [[%H: Processes]] +stat_dg_label_processes = [[Processes/s]] +stat_ds_ps_state = [[%di]] +stat_dg_title_processes__ps_cputime = [[%H: Process %pi - used cpu time]] +stat_dg_label_processes__ps_cputime = [[Jiffies]] +stat_ds_ps_cputime__syst = [[system]] +stat_ds_ps_cputime__user = [[user]] +stat_dg_title_processes__ps_count = [[%H: Process %pi - threads and processes]] +stat_dg_label_processes__ps_count = [[Count]] +stat_ds_ps_count = [[%ds]] +stat_dg_title_processes__ps_pagefaults = [[%H: Process %pi - page faults]] +stat_dg_label_processes__ps_pagefaults = [[Pagefaults]] +stat_ds_ps_pagefaults = [[page faults]] +stat_dg_title_processes__ps_rss = [[%H: Process %pi - virtual memory size]] +stat_dg_label_processes__ps_rss = [[Bytes]] +stat_ds_ps_rss = [[virtual memory]] +stat_dg_title_cpu = [[%H: Usage on Processor #%pi]] +stat_dg_label_cpu = [[%]] +stat_ds_cpu = [[%di]] +stat_dg_title_interface__if_octets = [[%H: Transfer on %di]] +stat_dg_label_interface__if_octets = [[Bytes/s]] +stat_dg_title_interface__if_packets = [[%H: Packets on %di]] +stat_dg_label_interface__if_packets = [[Packets/s]] +stat_dg_title_tcpconns = [[%H: TCP-Connections to Port %pi]] +stat_dg_label_tcpconns = [[Connections/s]] +stat_ds_tcp_connections = [[%di]] +stat_dg_title_df = [[%H: Disk Space Usage on %di]] +stat_dg_label_df = [[Bytes]] +stat_ds_df__free = [[%ds]] +stat_ds_df__used = [[%ds]] +stat_dg_title_irq = [[%H: Interrupts]] +stat_dg_label_irq = [[Issues/s]] +stat_ds_irq = [[IRQ %di]] +stat_dg_title_load = [[%H: System Load]] +stat_dg_label_load = [[Load]] +stat_ds_load__shortterm = [[1 min]] +stat_ds_load__midterm = [[5 min]] +stat_ds_load__longterm = [[15 min]] diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.xml.hide b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.xml.hide new file mode 100644 index 0000000..8e3de05 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.en.xml.hide @@ -0,0 +1,95 @@ + + + + +%H: Wireless - Signal Noise Ratio +dBm +Noise Level +Signal Strength + +%H: Wireless - Signal Quality +n +Signal Quality + +%H: ICMP Roundtrip Times +ms +%di + +%H: Firewall - Processed Packets +Packets/s +Chain "%di" + +%H: Netlink - Transfer on %pi +Bytes/s +Bytes (%ds) + +%H: Netlink - Packets on %pi +Packets/s +Processed (%ds) +Dropped (%ds) +Errors (%ds) + +%H: Netlink - Multicast on %pi +Packets/s +Packets + +%H: Netlink - Collisions on %pi +Collisions/s +Collisions + +%H: Netlink - Errors on %pi +Errors/s +%di +%di + +%H: Processes +Processes/s +%di + +%H: Process %pi - used cpu time +Jiffies +system +user + +%H: Process %pi - threads and processes +Count +%ds + +%H: Process %pi - page faults +Pagefaults +page faults + +%H: Process %pi - virtual memory size +Bytes +virtual memory + +%H: Usage on Processor #%pi +% +%di + +%H: Transfer on %di +Bytes/s + +%H: Packets on %di +Packets/s + +%H: TCP-Connections to Port %pi +Connections/s +%di + +%H: Disk Space Usage on %di +Bytes +%ds +%ds + +%H: Interrupts +Issues/s +IRQ %di + +%H: System Load +Load +1 min +5 min +15 min + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.lua new file mode 100644 index 0000000..708f34c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.lua @@ -0,0 +1,69 @@ +stat_dg_title_wireless__signal_noise = '%H: Wireless - Relação Sinal/Ruido' +stat_dg_label_wireless__signal_noise = 'dBm' +stat_ds_signal_noise = 'Nivel de Ruido' +stat_ds_signal_power = 'Forca do Sinal' +stat_dg_title_wireless__signal_quality = '%H: Wireless - Qualidade do Sinal' +stat_dg_label_wireless__signal_quality = 'n' +stat_ds_signal_quality = 'Qualidade do Sinal' +stat_dg_title_ping = '%H: Tempo de resposta ICMP' +stat_dg_label_ping = 'ms' +stat_ds_ping = '%di' +stat_dg_title_iptables__ipt_packets = '%H: Firewall - Pacotes Processados' +stat_dg_label_iptables__ipt_packets = 'Pacote/s' +stat_ds_ipt_packets = 'Cadeia "%di"' +stat_dg_title_netlink__if_octets = '%H: Netlink - Transferencia na %pi' +stat_dg_label_netlink__if_octets = 'Bytes/s' +stat_ds_if_octets = 'Bytes (%ds)' +stat_dg_title_netlink__if_packets = '%H: Netlink - Pacotes na %pi' +stat_dg_label_netlink__if_packets = 'Packets/s' +stat_ds_if_packets = 'Processado (%ds)' +stat_ds_if_dropped = 'Dropado (%ds)' +stat_ds_if_errors = 'Erros (%ds)' +stat_dg_title_netlink__if_multicast = '%H: Netlink - Multicast na %pi' +stat_dg_label_netlink__if_multicast = 'Pacote/s' +stat_ds_if_multicast = 'Pacotes' +stat_dg_title_netlink__if_collisions = '%H: Netlink - Colisoes na %pi' +stat_dg_label_netlink__if_collisions = 'Colisao(es)' +stat_ds_if_collisions = 'Colisoes' +stat_dg_title_netlink__if_tx_errors = '%H: Netlink - Erros na %pi' +stat_dg_label_netlink__if_tx_errors = 'Erro/s' +stat_ds_if_tx_errors = '%di' +stat_ds_if_rx_errors = '%di' +stat_dg_title_processes = '%H: Processos' +stat_dg_label_processes = 'Processo/s' +stat_ds_ps_state = '%di' +stat_dg_title_processes__ps_cputime = '%H: Processo %pi - tempo usado da cpu' +stat_dg_label_processes__ps_cputime = 'Jiffies' +stat_ds_ps_cputime__syst = 'sistema' +stat_ds_ps_cputime__user = 'usuario' +stat_dg_title_processes__ps_count = '%H: Processo %pi - threads e processos' +stat_dg_label_processes__ps_count = 'Contagem' +stat_ds_ps_count = '%ds' +stat_dg_title_processes__ps_pagefaults = '%H: Prcesso %pi - pagina de erros' +stat_dg_label_processes__ps_pagefaults = 'Pagina de erros' +stat_ds_ps_pagefaults = 'pagina de erros' +stat_dg_title_processes__ps_rss = '%H: Processo %pi - tamanho da memoria virtual' +stat_dg_label_processes__ps_rss = 'Bytes' +stat_ds_ps_rss = 'memoria virtual' +stat_dg_title_cpu = '%H: Usado no Processado #%pi' +stat_dg_label_cpu = '%' +stat_ds_cpu = '%di' +stat_dg_title_interface__if_octets = '%H: Transferencia na %di' +stat_dg_label_interface__if_octets = 'Bytes/s' +stat_dg_title_interface__if_packets = '%H: Pacotes na %di' +stat_dg_label_interface__if_packets = 'Pacote/s' +stat_dg_title_tcpconns = '%H: Conexoes TCP na Porta %pi' +stat_dg_label_tcpconns = 'Conexao(oes)' +stat_ds_tcp_connections = '%di' +stat_dg_title_df = '%H: Utilizacao de Espaco em Disco em %di' +stat_dg_label_df = 'Bytes' +stat_ds_df__free = '%ds' +stat_ds_df__used = '%ds' +stat_dg_title_irq = '%H: Interrupcoes' +stat_dg_label_irq = 'Erro/s' +stat_ds_irq = 'IRQ %di' +stat_dg_title_load = '%H: Carga do Sistema' +stat_dg_label_load = 'Carga' +stat_ds_load__shortterm = '1 min' +stat_ds_load__midterm = '5 min' +stat_ds_load__longterm = '15 min' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.xml.hide b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.xml.hide new file mode 100644 index 0000000..7f369c1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/rrdtool.pt-br.xml.hide @@ -0,0 +1,95 @@ + + + + +%H: Wireless - Relação Sinal/Ruido +dBm +Nivel de Ruido +Forca do Sinal + +%H: Wireless - Qualidade do Sinal +n +Qualidade do Sinal + +%H: Tempo de resposta ICMP +ms +%di + +%H: Firewall - Pacotes Processados +Pacote/s +Cadeia "%di" + +%H: Netlink - Transferencia na %pi +Bytes/s +Bytes (%ds) + +%H: Netlink - Pacotes na %pi +Packets/s +Processado (%ds) +Dropado (%ds) +Erros (%ds) + +%H: Netlink - Multicast na %pi +Pacote/s +Pacotes + +%H: Netlink - Colisoes na %pi +Colisao(es) +Colisoes + +%H: Netlink - Erros na %pi +Erro/s +%di +%di + +%H: Processos +Processo/s +%di + +%H: Processo %pi - tempo usado da cpu +Jiffies +sistema +usuario + +%H: Processo %pi - threads e processos +Contagem +%ds + +%H: Prcesso %pi - pagina de erros +Pagina de erros +pagina de erros + +%H: Processo %pi - tamanho da memoria virtual +Bytes +memoria virtual + +%H: Usado no Processador #%pi +% +%di + +%H: Transferencia na %di +Bytes/s + +%H: Pacotes na %di +Pacote/s + +%H: Conexoes TCP na Porta %pi +Conexao(oes) +%di + +%H: Utilizacao de Espaco em Disco em %di +Bytes +%ds +%ds + +%H: Interrupcoes +Erro/s +IRQ %di + +%H: Carga do Sistema +Carga +1 min +5 min +15 min + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.de.lua new file mode 100644 index 0000000..8273895 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.de.lua @@ -0,0 +1,17 @@ +samba = 'Netzwerkfreigaben' +samba_samba_name = 'Hostname' +samba_samba_description = 'Beschreibung' +samba_samba_workgroup = 'Arbeitsgruppe' +samba_samba_homes = 'Heimatverzeichnisse freigeben' +samba_samba_homes_desc = 'Systembenutzer können ihre Heimatverzeichnis über Netzwerkfreigaben erreichen.' +samba_sambashare = 'Dateifreigaben' +samba_sambashare_path = 'Freigabepfad' +samba_sambashare_path_desc = 'Physischer Pfad' +samba_sambashare_users = 'Erlaubte Benutzer' +samba_sambashare_users_desc = 'optional' +samba_sambashare_readonly = 'Nur Lesen' +samba_sambashare_guestok = 'Gäste erlauben' +samba_sambashare_createmask = 'Anlegemaske' +samba_sambashare_createmask_desc = 'Maske für neue Dateien' +samba_sambashare_dirmask = 'Verzeichnismaske' +samba_sambashare_dirmask_desc = 'Maske für neue Verzeichnisse' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.en.lua new file mode 100644 index 0000000..30e9339 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.en.lua @@ -0,0 +1,17 @@ +samba = 'Network Shares' +samba_samba_name = 'Hostname' +samba_samba_description = 'Description' +samba_samba_workgroup = 'Workgroup' +samba_samba_homes = 'Share home-directories' +samba_samba_homes_desc = 'System users can reach their home directories via network shares.' +samba_sambashare = 'Shared Directories' +samba_sambashare_path = 'Shared Directory' +samba_sambashare_path_desc = 'Physical Path' +samba_sambashare_users = 'Allowed Users' +samba_sambashare_users_desc = 'optional' +samba_sambashare_readonly = 'Read Only' +samba_sambashare_guestok = 'Allow Guests' +samba_sambashare_createmask = 'Create Mask' +samba_sambashare_createmask_desc = 'Mask for new files' +samba_sambashare_dirmask = 'Directory Mask' +samba_sambashare_dirmask_desc = 'Mask for new directories' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.pt-br.lua new file mode 100644 index 0000000..9129ef6 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/samba.pt-br.lua @@ -0,0 +1,17 @@ +samba = 'Compartilhamentos de Rede' +samba_samba_name = 'Hostname' +samba_samba_description = 'Descrição' +samba_samba_workgroup = 'Grupo de Trabalho' +samba_samba_homes = 'Compartilhar diretórios home' +samba_samba_homes_desc = 'Usuários do sistema poderão acessar seu diretório home através dos compartilhamentos de rede.' +samba_sambashare = 'Diretórios Compartilhados' +samba_sambashare_path = 'Diretório Compartilhado' +samba_sambashare_path_desc = 'Caminho Físico' +samba_sambashare_users = 'Usuários Permitidos' +samba_sambashare_users_desc = 'opcional' +samba_sambashare_readonly = 'Somente Leitura' +samba_sambashare_guestok = 'Permitir Convidados' +samba_sambashare_createmask = 'Criar Máscara' +samba_sambashare_createmask_desc = 'Máscara para novos arquivos' +samba_sambashare_dirmask = 'Máscara do Diretório' +samba_sambashare_dirmask_desc = 'Máscara para novos diretórios' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.de.lua new file mode 100644 index 0000000..1e2e1f1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.de.lua @@ -0,0 +1,212 @@ +stat_statistics = 'Statistiken' +stat_desc = 'Das Statistik-Paket basiert auf Collectd und nutzt RRD Tool um die gesammelten Daten in Diagramme zu rendern.' +stat_systemplugins = 'Systemplugins' +stat_networkplugins = 'Netzwerkplugins' +stat_outputplugins = 'Ausgabeplugins' +stat_showtimespan = 'Zeitspanne zeigen »' +stat_graphs = 'Diagramme' +stat_collectd = 'Collectd' +stat_cpu = 'Prozessor' +stat_ping = 'Ping' +stat_iptables = 'Firewall' +stat_netlink = 'Netlink' +stat_processes = 'Prozesse' +stat_wireless = 'Drahtlos' +stat_tcpconns = 'TCP-Verbindungen' +stat_interface = 'Schnittstellen' +stat_df = 'Plattenspeicher' +stat_irq = 'Interrupts' +stat_disk = 'Plattenauslastung' +stat_exec = 'Exec' +stat_rrdtool = 'RRDTool' +stat_network = 'Netzwerk' +stat_csv = 'CSV Ausgabe' +stat_load = 'Systemlast' +stat_dns = 'DNS' +stat_email = 'Email' +stat_unixsock = 'UnixSock' +lucistatistics = 'Statistiken' +lucistatistics_collectd = 'Collectd Einstellungen' +lucistatistics_collectd_desc = 'Collectd ist ein schlankes Dienstprogramm zum Sammeln von Systemdaten aus verschiedenen Quellen mittels diverser Plugins. Auf dieser Seite können generelle Einstellungen für den Collectd-Daemon vorgenommen werden.' +lucistatistics_collectd_hostname = 'Hostname' +lucistatistics_collectd_basedir = 'Basisverzeichnis' +lucistatistics_collectd_include = 'Verzeichnis für Unterkonfigurationen' +lucistatistics_collectd_plugindir = 'Verzeichnis für Collectd-Plugins' +lucistatistics_collectd_pidfile = 'Pfad zu PID-Datei' +lucistatistics_collectd_typesdb = 'Dataset-Definitionen' +lucistatistics_collectd_interval = 'Daten-Sammelintervall' +lucistatistics_collectd_interval_desc = 'Sekunden' +lucistatistics_collectd_readthreads = 'Anzahl paralleler Sammelprozesse' +lucistatistics_collectd_fqdnlookup = 'automatisch vollen Hostnamen herausfinden' +lucistatistics_collectdcpu = 'CPU Plugin Konfiguration' +lucistatistics_collectdcpu_desc = 'Das CPU-Plugin sammelt grundlegende Statistiken über die Prozessorauslastung.' +lucistatistics_collectdcpu_enable = 'Plugin aktivieren' +lucistatistics_collectdcsv = 'CSV Plugin Konfiguration' +lucistatistics_collectdcsv_desc = 'Das CSV-Plugin speichert die gesammelten Daten im CSV-Format, geeignet für die Weiterverarbeitung durch externe Programme.' +lucistatistics_collectdcsv_enable = 'Plugin aktivieren' +lucistatistics_collectdcsv_datadir = 'Speicherverzeichnis für die CSV-Dateien' +lucistatistics_collectdcsv_storerates = 'Werte nicht absolut sondern als Raten speichern' +lucistatistics_collectddf = 'DF Plugin Konfiguration' +lucistatistics_collectddf_desc = 'Das DF-Plugin sammelt Statistiken über den Speicherverbrauch auf verschiedenen Geräten, Mount-Punkten oder Dateisystemtypen.' +lucistatistics_collectddf_enable = 'Plugin aktivieren' +lucistatistics_collectddf_devices = 'Geräte überwachen' +lucistatistics_collectddf_devices_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddf_mountpoints = 'Mount-Punkte überwachen' +lucistatistics_collectddf_mountpoints_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddf_fstypes = 'Datesystemtypen überwachen' +lucistatistics_collectddf_fstypes_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddf_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectddisk = 'Disk Plugin Konfiguration' +lucistatistics_collectddisk_desc = 'Das Disk-Plugin sammelt detaillierte Statistiken über die Auslastung auf ausgewählten Festplatten und Partitionen.' +lucistatistics_collectddisk_enable = 'Plugin aktivieren' +lucistatistics_collectddisk_disks = 'Geräte und Partitionen überwachen' +lucistatistics_collectddisk_disks_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddisk_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectddns = 'DNS Plugin Konfiguration' +lucistatistics_collectddns_desc = 'Das DNS-Plugin sammelt detaillierte Statistiken über DNS-bezogenen Verkehr auf ausgewählten Schnittstellen.' +lucistatistics_collectddns_enable = 'Plugin aktivieren' +lucistatistics_collectddns_interfaces = 'Schnittstellen überwachen' +lucistatistics_collectddns_interfaces_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectddns_ignoresources = 'Quelladressen ignorieren' +lucistatistics_collectddns_ignoresources_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdemail = 'E-Mail Plugin Konfiguration' +lucistatistics_collectdemail_desc = 'Das E-Mail Plugin erstellt einen Unix-Socket welcher benutzt werden kann um E-Mail-Statistiken an den laufenden Collectd-Daemon zu übermitteln. Dieses Plugin ist primär für die Verwendung zusammen mit Mail::SpamAssasin::Plugin::Collectd gedacht, kann aber auch anderweitig verwendet werden.' +lucistatistics_collectdemail_enable = 'Plugin aktivieren' +lucistatistics_collectdemail_socketfile = 'Dateipfad des Unix-Sockets' +lucistatistics_collectdemail_socketgroup = 'Gruppenbesitzer festlegen' +lucistatistics_collectdemail_socketgroup_desc = 'Gruppenname' +lucistatistics_collectdemail_socketperms = 'Dateiberechtigungen des Unix-Sockets' +lucistatistics_collectdemail_socketperms_desc = 'oktal' +lucistatistics_collectdemail_maxconns = 'Maximale Anzahl erlaubter Verbindungen' +lucistatistics_collectdexec = 'Exec Plugin Konfiguration' +lucistatistics_collectdexec_desc = 'Das Exec-Plugin startet externe Kommandos um Werte einzulesen oder um Benachrichtigungen auszulösen falls bestimmte Grenzwerte erreicht werden.' +lucistatistics_collectdexec_enable = 'Plugin aktivieren' +lucistatistics_collectdexecinput = 'Kommando zum Werte einlesen hinzufügen' +lucistatistics_collectdexecinput_desc = 'Hier können externe Kommandos definiert werden, welche durch Collectd gestartet werden um Statistik-Werte einzulesen. Die Werte werden dabei vom STDOUT des aufgerufenen Programmes gelesen.' +lucistatistics_collectdexecinput_cmdline = 'Kommandozeile' +lucistatistics_collectdexecinput_cmduser = 'Als Benutzer ausführen' +lucistatistics_collectdexecinput_cmdgroup = 'Als Gruppe ausführen' +lucistatistics_collectdexecnotify = 'Benachrichtigungskommando hinzufügen' +lucistatistics_collectdexecnotify_desc = 'Hier können externe Kommandos definiert werden, welche durch Collectd gestartet werden sobald konfigurierte Grenzwerte erreicht werden. Die Werte welche die Benachrichtigung ausgelöst haben werden dabei an den STDIN des aufgerufenen Programmes übergeben.' +lucistatistics_collectdexecnotify_cmdline = 'Kommandozeile' +lucistatistics_collectdexecnotify_cmduser = 'Als Benutzer ausführen' +lucistatistics_collectdexecnotify_cmdgroup = 'Als Gruppe ausführen' +lucistatistics_collectdinterface = 'Interface Plugin Konfiguration' +lucistatistics_collectdinterface_desc = 'Das Interface-Plugin sammelt allgemeine Verkehrsstatistiken auf ausgewählten Schnittstellen.' +lucistatistics_collectdinterface_enable = 'Plugin aktivieren' +lucistatistics_collectdinterface_interfaces = 'Schnittstellen überwachen' +lucistatistics_collectdinterface_interfaces_desc = 'Strg gedrückt halten um mehrere Schnittstellen zu wählen' +lucistatistics_collectdinterface_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectdiptables = 'Iptables Plugin Konfiguration' +lucistatistics_collectdiptables_desc = 'Das Iptables-Plugin überwacht ausgewählte Firewall-Regeln und sammelt Werte über die Anzahl der verarbeiteten Pakete und Bytes.' +lucistatistics_collectdiptables_enable = 'Plugin aktivieren' +lucistatistics_collectdiptablesmatch = 'Auswahlregel hinzufügen' +lucistatistics_collectdiptablesmatch_desc = 'Hier werden die Kriterien festgelegt nach welchen die zu überwachenden Firewall-Regeln ausgewählt werden.' +lucistatistics_collectdiptablesmatch_name = 'Name der Regel' +lucistatistics_collectdiptablesmatch_name_desc = 'max. 16 Buchstaben' +lucistatistics_collectdiptablesmatch_table = 'Tabelle' +lucistatistics_collectdiptablesmatch_chain = 'Kette (Chain)' +lucistatistics_collectdiptablesmatch_target = 'Aktion (Target)' +lucistatistics_collectdiptablesmatch_protocol = 'Netzwerkprotokoll' +lucistatistics_collectdiptablesmatch_source = 'Quell-IP-Bereich' +lucistatistics_collectdiptablesmatch_source_desc = 'CIDR-Notation' +lucistatistics_collectdiptablesmatch_destination = 'Ziel-IP-Bereich' +lucistatistics_collectdiptablesmatch_destination_desc = 'CIDR-Notation' +lucistatistics_collectdiptablesmatch_inputif = 'eingehende Schnittstelle' +lucistatistics_collectdiptablesmatch_inputif_desc = 'z.B. br-lan' +lucistatistics_collectdiptablesmatch_outputif = 'ausgehende Schnittstelle' +lucistatistics_collectdiptablesmatch_outputif_desc = 'z.B. br-ff' +lucistatistics_collectdiptablesmatch_options = 'Optionen' +lucistatistics_collectdiptablesmatch_options_desc = 'z.B. reject-with tcp-reset' +lucistatistics_collectdirq = 'IRQ Plugin Konfiguration' +lucistatistics_collectdirq_desc = 'Das IRQ-Plugin überwacht die Anzahl der Aufrufe pro Sekunde für jeden ausgewählten Interrupt. Wird kein Interrupt ausgewählt überwacht das Plugin alle im System vorhandenen Interrupts.' +lucistatistics_collectdirq_enable = 'Plugin aktivieren' +lucistatistics_collectdirq_irqs = 'Interrups überwachen' +lucistatistics_collectdirq_irqs_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdirq_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectdload = 'Load Plugin Konfiguration' +lucistatistics_collectdload_desc = 'Das Load-Plugin sammelt Informationen über die allgemeine Systemlast.' +lucistatistics_collectdload_enable = 'Plugin aktivieren' +lucistatistics_collectdnetlink = 'Netlink Plugin Konfiguration' +lucistatistics_collectdnetlink_desc = 'Das Netlink-Plugin sammelt erweiterte QoS-Informationen wie QDisc-, Class- und Filter-Statistiken auf ausgewählten Schnittstellen.' +lucistatistics_collectdnetlink_enable = 'Plugin aktivieren' +lucistatistics_collectdnetlink_interfaces = 'Schnittstellen einfach überwachen' +lucistatistics_collectdnetlink_interfaces_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_verboseinterfaces = 'Schnittstellen detailliert überwachen' +lucistatistics_collectdnetlink_verboseinterfaces_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_qdiscs = 'Queue Discipline überwachen' +lucistatistics_collectdnetlink_qdiscs_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_classes = 'Shapingklassen überwachen' +lucistatistics_collectdnetlink_classes_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_filters = 'Filterklassen überwachen' +lucistatistics_collectdnetlink_filters_desc = 'Strg gedrückt halten um mehrere zu wählen' +lucistatistics_collectdnetlink_ignoreselected = 'Alle außer Ausgewählte überwachen' +lucistatistics_collectdnetwork = 'Network Plugin Konfiguration' +lucistatistics_collectdnetwork_desc = 'Das Network-Plugin ermöglicht die netzwerkgestützte Kommunikation zwischen verschiedenen Collectd-Instanzen. Collectd kann gleichzeitig im Server- und Client-Modus betrieben werden. Im Client-Modus werden lokal gesammelte Daten an einen Collectd-Server übermittelt, im Server-Modus empfängt die lokale Instanz Daten von anderen Installationen.' +lucistatistics_collectdnetwork_enable = 'Plugin aktivieren' +lucistatistics_collectdnetworklisten = 'Listen-Schnittstelle' +lucistatistics_collectdnetworklisten_desc = 'Diese Sektion legt fest auf welchen Schnittstellen Collectd auf eingehende Verbindungen wartet.' +lucistatistics_collectdnetworklisten_host = 'Listen-Host' +lucistatistics_collectdnetworklisten_host_desc = 'Host-, IP- oder IPv6-Adresse' +lucistatistics_collectdnetworklisten_port = 'Listen-Port' +lucistatistics_collectdnetworklisten_port_desc = '0 - 65535' +lucistatistics_collectdnetworkserver = 'Server-Schnittstellen' +lucistatistics_collectdnetworkserver_desc = 'Diese Sektion legt fest zu welchen Collectd-Servern die lokal gesammelten Daten gesendet werden.' +lucistatistics_collectdnetworkserver_host = 'Server-Host' +lucistatistics_collectdnetworkserver_host_desc = 'Host-, IP- oder IPv6-Adresse' +lucistatistics_collectdnetworkserver_port = 'Server-Port' +lucistatistics_collectdnetworkserver_port_desc = '0 - 65535' +lucistatistics_collectdnetwork_timetolive = 'TTL für Netzwerkpakete' +lucistatistics_collectdnetwork_timetolive_desc = '0 - 255' +lucistatistics_collectdnetwork_forward = 'Weiterleitung zwischen Listen- und Server-Adressen' +lucistatistics_collectdnetwork_cacheflush = 'Cache-Leerungsintervall' +lucistatistics_collectdnetwork_cacheflush_desc = 'Sekunden' +lucistatistics_collectdping = 'Ping Plugin Konfiguration' +lucistatistics_collectdping_desc = 'Das Ping-Plugin sendet ICMP-Echo-Requests an ausgewählte Hosts und misst die Antwortzeiten für jede Adresse.' +lucistatistics_collectdping_enable = 'Plugin aktivieren' +lucistatistics_collectdping_hosts = 'Hosts überwachen' +lucistatistics_collectdping_hosts_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdping_ttl = 'TTL für Ping Pakete' +lucistatistics_collectdping_ttl_desc = '0 - 255' +lucistatistics_collectdProzesse = 'Prozesse Plugin Konfiguration' +lucistatistics_collectdProzesse_desc = 'Das Prozess-Plugin sammelt Informationen wie CPU-Zeit, Speicherzugriffsfehler und Speicherverbrauch ausgewählter Prozesse.' +lucistatistics_collectdProzesse_enable = 'Plugin aktivieren' +lucistatistics_collectdProzesse_processes = 'Prozesse überwachen' +lucistatistics_collectdProzesse_processes_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdrrdtool = 'RRDTool Plugin Konfiguration' +lucistatistics_collectdrrdtool_desc = 'Das RRDTool-Plugin speichert die gesammelten Daten in sogenannten RRD-Datenbanken, der Grundlage für die Diagramm-Bilder.

Warnung: Falsche Werte resultieren in einem sehr hohen Speicherverbrauch im temporären Verzeichnis. Das kann das Gerät unbrauchbar machen, da Systemspeicher für den regulären Betrieb fehlt!' +lucistatistics_collectdrrdtool_enable = 'Plugin aktivieren' +lucistatistics_collectdrrdtool_datadir = 'Speicherverzeichnis' +lucistatistics_collectdrrdtool_stepsize = 'RRD Schrittintervall' +lucistatistics_collectdrrdtool_stepsize_desc = 'Sekunden' +lucistatistics_collectdrrdtool_heartbeat = 'RRD Heartbeatintervall' +lucistatistics_collectdrrdtool_heartbeat_desc = 'Sekunden' +lucistatistics_collectdrrdtool_rrasingle = 'Nur 'average' RRAs erzeugen' +lucistatistics_collectdrrdtool_rrasingle_desc = 'reduziert die RRD Größe' +lucistatistics_collectdrrdtool_rratimespans = 'gespeicherte Zeitspannen' +lucistatistics_collectdrrdtool_rratimespans_desc = 'mehrere mit Leerzeichen trennen' +lucistatistics_collectdrrdtool_rrarows = 'Spalten pro RRA' +lucistatistics_collectdrrdtool_xff = 'RRD XFiles Faktor' +lucistatistics_collectdrrdtool_cachetimeout = 'Zwischenspeicherzeit für gesammelte Daten' +lucistatistics_collectdrrdtool_cachetimeout_desc = 'Sekunden' +lucistatistics_collectdrrdtool_cacheflush = 'Leerungsintervall für Zwischenspeicher' +lucistatistics_collectdrrdtool_cacheflush_desc = 'Sekunden' +lucistatistics_collectdtcpconns = 'TCPConns Plugin Konfiguration' +lucistatistics_collectdtcpconns_desc = 'Das TCPConns-Plugin sammelt Informationen über offene TCP-Verbindungen auf ausgewählten Ports.' +lucistatistics_collectdtcpconns_enable = 'Plugin aktivieren' +lucistatistics_collectdtcpconns_listeningports = 'Alle durch lokale Dienste genutzten Ports überwachen' +lucistatistics_collectdtcpconns_localports = 'lokale Ports überwachen' +lucistatistics_collectdtcpconns_localports_desc = '0 - 65535; mehrere mit Leerzeichen trennen' +lucistatistics_collectdtcpconns_remoteports = 'entfernte Ports überwachen' +lucistatistics_collectdtcpconns_remoteports_desc = '0 - 65535; mehrere mit Leerzeichen trennen' +lucistatistics_collectdunixsock = 'Unixsock Plugin Konfiguration' +lucistatistics_collectdunixsock_desc = 'Das Unixsock-Plugin erstellt einen Unix-Socket über welchen gesammelte Werte aus der laufenden Collectd-Instanz ausgelesen werden können.' +lucistatistics_collectdunixsock_enable = 'Plugin aktivieren' +lucistatistics_collectdunixsock_socketfile = 'Dateipfad des Unix-Sockets' +lucistatistics_collectdunixsock_socketgroup = 'Gruppenbesitzer festlegen' +lucistatistics_collectdunixsock_socketgroup_desc = 'Gruppenname' +lucistatistics_collectdunixsock_socketperms = 'Dateiberechtigungen des Unix-Sockets' +lucistatistics_collectdunixsock_socketperms_desc = 'oktal' +lucistatistics_collectdwireless = 'Wireless Plugin Konfiguration' +lucistatistics_collectdwireless_desc = 'Das Wireless-Plugin sammelt Statistiken über die drahtlose Signalstärke, den Störpegel und die Signalqualität.' +lucistatistics_collectdwireless_enable = 'Plugin aktivieren' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.en.lua new file mode 100644 index 0000000..c12b420 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.en.lua @@ -0,0 +1,212 @@ +stat_statistics = 'Statistics' +stat_desc = 'The statistics package is based on Collectd and uses RRD Tool to render diagram images from collected data.' +stat_systemplugins = 'System plugins' +stat_networkplugins = 'Network plugins' +stat_outputplugins = 'Output plugins' +stat_showtimespan = 'Display timespan »' +stat_graphs = 'Graphs' +stat_collectd = 'Collectd' +stat_cpu = 'Processor' +stat_ping = 'Ping' +stat_iptables = 'Firewall' +stat_netlink = 'Netlink' +stat_processes = 'Processes' +stat_wireless = 'Wireless' +stat_tcpconns = 'TCP Connections' +stat_interface = 'Interfaces' +stat_df = 'Disk Space Usage' +stat_irq = 'Interrupts' +stat_disk = 'Disk Usage' +stat_exec = 'Exec' +stat_rrdtool = 'RRDTool' +stat_network = 'Network' +stat_csv = 'CSV Output' +stat_load = 'System Load' +stat_dns = 'DNS' +stat_email = 'Email' +stat_unixsock = 'UnixSock' +lucistatistics = 'Statistics' +lucistatistics_collectd = 'Collectd Settings' +lucistatistics_collectd_desc = 'Collectd is a small daeomon for collecting data from various sources through different plugins. On this page you can change general settings for the collectd daemon.' +lucistatistics_collectd_hostname = 'Hostname' +lucistatistics_collectd_basedir = 'Base Directory' +lucistatistics_collectd_include = 'Directory for sub-configurations' +lucistatistics_collectd_plugindir = 'Directory for collectd plugins' +lucistatistics_collectd_pidfile = 'Used PID file' +lucistatistics_collectd_typesdb = 'Datasets definition file' +lucistatistics_collectd_interval = 'Data collection interval' +lucistatistics_collectd_interval_desc = 'Seconds' +lucistatistics_collectd_readthreads = 'Number of threads for data collection' +lucistatistics_collectd_fqdnlookup = 'Try to lookup fully qualified hostname' +lucistatistics_collectdcpu = 'CPU Plugin Configuration' +lucistatistics_collectdcpu_desc = 'The cpu plugin collects basic statistics about the processor usage.' +lucistatistics_collectdcpu_enable = 'Enable this plugin' +lucistatistics_collectdcsv = 'CSV Plugin Configuration' +lucistatistics_collectdcsv_desc = 'The csv plugin stores collected data in csv file format for further processing by external programs.' +lucistatistics_collectdcsv_enable = 'Enable this plugin' +lucistatistics_collectdcsv_datadir = 'Storage directory for the csv files' +lucistatistics_collectdcsv_storerates = 'Store data values as rates instead of absolute values' +lucistatistics_collectddf = 'DF Plugin Configuration' +lucistatistics_collectddf_desc = 'The df plugin collects statistics about the disk space usage on different devices, mount points or filesystem types.' +lucistatistics_collectddf_enable = 'Enable this plugin' +lucistatistics_collectddf_devices = 'Monitor devices' +lucistatistics_collectddf_devices_desc = 'multiple separated by space' +lucistatistics_collectddf_mountpoints = 'Monitor mount points' +lucistatistics_collectddf_mountpoints_desc = 'multiple separated by space' +lucistatistics_collectddf_fstypes = 'Monitor filesystem types' +lucistatistics_collectddf_fstypes_desc = 'multiple separated by space' +lucistatistics_collectddf_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectddisk = 'Disk Plugin Configuration' +lucistatistics_collectddisk_desc = 'The disk plugin collects detailled usage statistics for selected partitions or whole disks.' +lucistatistics_collectddisk_enable = 'Enable this plugin' +lucistatistics_collectddisk_disks = 'Monitor disks and partitions' +lucistatistics_collectddisk_disks_desc = 'multiple separated by space' +lucistatistics_collectddisk_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectddns = 'DNS Plugin Configuration' +lucistatistics_collectddns_desc = 'The dns plugin collects detailled statistics about dns related traffic on selected interfaces.' +lucistatistics_collectddns_enable = 'Enable this plugin' +lucistatistics_collectddns_interfaces = 'Monitor interfaces' +lucistatistics_collectddns_interfaces_desc = 'multiple separated by space' +lucistatistics_collectddns_ignoresources = 'Ignore source addresses' +lucistatistics_collectddns_ignoresources_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdemail = 'E-Mail Plugin Configuration' +lucistatistics_collectdemail_desc = 'The email plugin creates a unix socket which can be used to transmit email-statistics to a running collectd daemon. This plugin is primarily intended to be used in conjunction with Mail::SpamAssasin::Plugin::Collectd but can be used in other ways as well.' +lucistatistics_collectdemail_enable = 'Enable this plugin' +lucistatistics_collectdemail_socketfile = 'Filepath of the unix socket' +lucistatistics_collectdemail_socketgroup = 'Group ownership of the unix socket' +lucistatistics_collectdemail_socketgroup_desc = 'group name' +lucistatistics_collectdemail_socketperms = 'File permissions of the unix socket' +lucistatistics_collectdemail_socketperms_desc = 'octal' +lucistatistics_collectdemail_maxconns = 'Maximum allowed connections' +lucistatistics_collectdexec = 'Exec Plugin Configuration' +lucistatistics_collectdexec_desc = 'The exec plugin starts external commands to read values from or to notify external processes when certain threshold values have been reached.' +lucistatistics_collectdexec_enable = 'Enable this plugin' +lucistatistics_collectdexecinput = 'Add command for reading values' +lucistatistics_collectdexecinput_desc = 'Here you can define external commands which will be started by collectd in order to read certain values. The values will be read from stdout.' +lucistatistics_collectdexecinput_cmdline = 'Commandline' +lucistatistics_collectdexecinput_cmduser = 'Run as user' +lucistatistics_collectdexecinput_cmdgroup = 'Run as group' +lucistatistics_collectdexecnotify = 'Add notification command' +lucistatistics_collectdexecnotify_desc = 'Here you can define external commands which will be started by collectd when certain threshold values have been reached. The values leading to invokation will be feeded to the the called programs stdin.' +lucistatistics_collectdexecnotify_cmdline = 'Commandline' +lucistatistics_collectdexecnotify_cmduser = 'Run as user' +lucistatistics_collectdexecnotify_cmdgroup = 'Run as group' +lucistatistics_collectdinterface = 'Interface Plugin Configuration' +lucistatistics_collectdinterface_desc = 'The interface plugin collects traffic statistics on selected interfaces.' +lucistatistics_collectdinterface_enable = 'Enable this plugin' +lucistatistics_collectdinterface_interfaces = 'Monitor interfaces' +lucistatistics_collectdinterface_interfaces_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdinterface_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectdiptables = 'Iptables Plugin Configuration' +lucistatistics_collectdiptables_desc = 'The iptables plugin will monitor selected firewall rules and collect informations about processed bytes and packets per rule.' +lucistatistics_collectdiptables_enable = 'Enable this plugin' +lucistatistics_collectdiptablesmatch = 'Add matching rule' +lucistatistics_collectdiptablesmatch_desc = 'Here you can define various criteria by which the monitored iptables rules are selected.' +lucistatistics_collectdiptablesmatch_name = 'Name of the rule' +lucistatistics_collectdiptablesmatch_name_desc = 'max. 16 chars' +lucistatistics_collectdiptablesmatch_table = 'Table' +lucistatistics_collectdiptablesmatch_chain = 'Chain' +lucistatistics_collectdiptablesmatch_target = 'Action (target)' +lucistatistics_collectdiptablesmatch_protocol = 'Network protocol' +lucistatistics_collectdiptablesmatch_source = 'Source ip range' +lucistatistics_collectdiptablesmatch_source_desc = 'CIDR notation' +lucistatistics_collectdiptablesmatch_destination = 'Destination ip range' +lucistatistics_collectdiptablesmatch_destination_desc = 'CIDR notation' +lucistatistics_collectdiptablesmatch_inputif = 'Incoming interface' +lucistatistics_collectdiptablesmatch_inputif_desc = 'e.g. br-lan' +lucistatistics_collectdiptablesmatch_outputif = 'Outgoing interface' +lucistatistics_collectdiptablesmatch_outputif_desc = 'e.g. br-ff' +lucistatistics_collectdiptablesmatch_options = 'Options' +lucistatistics_collectdiptablesmatch_options_desc = 'e.g. reject-with tcp-reset' +lucistatistics_collectdirq = 'IRQ Plugin Configuration' +lucistatistics_collectdirq_desc = 'The irq plugin will monitor the rate of issues per second for each selected interrupt. If no interrupt is selected then all interrupts are monitored.' +lucistatistics_collectdirq_enable = 'Enable this plugin' +lucistatistics_collectdirq_irqs = 'Monitor interrupts' +lucistatistics_collectdirq_irqs_desc = 'multiple separated by space' +lucistatistics_collectdirq_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectdload = 'Load Plugin Configuration' +lucistatistics_collectdload_desc = 'The load plugin collects statistics about the general system load.' +lucistatistics_collectdload_enable = 'Enable this plugin' +lucistatistics_collectdnetlink = 'Netlink Plugin Configuration' +lucistatistics_collectdnetlink_desc = 'The netlink plugin collects extended informations like qdisc-, class- and filter-statistics for selected interfaces.' +lucistatistics_collectdnetlink_enable = 'Enable this plugin' +lucistatistics_collectdnetlink_interfaces = 'Basic monitoring' +lucistatistics_collectdnetlink_interfaces_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_verboseinterfaces = 'Verbose monitoring' +lucistatistics_collectdnetlink_verboseinterfaces_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_qdiscs = 'Qdisc monitoring' +lucistatistics_collectdnetlink_qdiscs_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_classes = 'Shaping class monitoring' +lucistatistics_collectdnetlink_classes_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_filters = 'Filter class monitoring' +lucistatistics_collectdnetlink_filters_desc = 'hold Ctrl while clicking to select multiple interfaces' +lucistatistics_collectdnetlink_ignoreselected = 'Monitor all except selected ones' +lucistatistics_collectdnetwork = 'Network Plugin Configuration' +lucistatistics_collectdnetwork_desc = 'The network plugin provides network based communication between different collectd instances. Collectd can operate both in client and server mode. In client mode locally collected date is transferred to a collectd server instance, in server mode the local instance receives data from other hosts.' +lucistatistics_collectdnetwork_enable = 'Enable this plugin' +lucistatistics_collectdnetworklisten = 'Listener interfaces' +lucistatistics_collectdnetworklisten_desc = 'This section defines on which interfaces collectd will wait for incoming connections.' +lucistatistics_collectdnetworklisten_host = 'Listen host' +lucistatistics_collectdnetworklisten_host_desc = 'host-, ip- or ip6 address' +lucistatistics_collectdnetworklisten_port = 'Listen port' +lucistatistics_collectdnetworklisten_port_desc = '0 - 65535' +lucistatistics_collectdnetworkserver = 'server interfaces' +lucistatistics_collectdnetworkserver_desc = 'This section defines to which servers the locally collected data is sent to.' +lucistatistics_collectdnetworkserver_host = 'Server host' +lucistatistics_collectdnetworkserver_host_desc = 'host-, ip- or ip6 address' +lucistatistics_collectdnetworkserver_port = 'Server port' +lucistatistics_collectdnetworkserver_port_desc = '0 - 65535' +lucistatistics_collectdnetwork_timetolive = 'TTL for network packets' +lucistatistics_collectdnetwork_timetolive_desc = '0 - 255' +lucistatistics_collectdnetwork_forward = 'Forwarding between listen and server addresses' +lucistatistics_collectdnetwork_cacheflush = 'Cache flush interval' +lucistatistics_collectdnetwork_cacheflush_desc = 'seconds' +lucistatistics_collectdping = 'Ping Plugin Configuration' +lucistatistics_collectdping_desc = 'The ping plugin will send icmp echo replies to selected hosts and measure the roundtrip time for each host.' +lucistatistics_collectdping_enable = 'Enable this plugin' +lucistatistics_collectdping_hosts = 'Monitor hosts' +lucistatistics_collectdping_hosts_desc = 'multiple separated by space' +lucistatistics_collectdping_ttl = 'TTL for ping packets' +lucistatistics_collectdping_ttl_desc = '0 - 255' +lucistatistics_collectdprocesses = 'Processes Plugin Configuration' +lucistatistics_collectdprocesses_desc = 'The processes plugin collects informations like cpu time, page faults and memory usage of selected processes.' +lucistatistics_collectdprocesses_enable = 'Enable this plugin' +lucistatistics_collectdprocesses_processes = 'Monitor processes' +lucistatistics_collectdprocesses_processes_desc = 'multiple separated by space' +lucistatistics_collectdrrdtool = 'RRDTool Plugin Configuration' +lucistatistics_collectdrrdtool_desc = 'The rrdtool plugin stores the collected data in rrd database files, the foundation of the diagrams.

Warning: Setting the wrong values will result in a very high memory consumption in the temporary directory. This can render the device unusable!' +lucistatistics_collectdrrdtool_enable = 'Enable this plugin' +lucistatistics_collectdrrdtool_datadir = 'Storage directory' +lucistatistics_collectdrrdtool_stepsize = 'RRD step interval' +lucistatistics_collectdrrdtool_stepsize_desc = 'seconds' +lucistatistics_collectdrrdtool_heartbeat = 'RRD heart beat interval' +lucistatistics_collectdrrdtool_heartbeat_desc = 'seconds' +lucistatistics_collectdrrdtool_rrasingle = 'Only create average RRAs' +lucistatistics_collectdrrdtool_rrasingle_desc = 'reduces rrd size' +lucistatistics_collectdrrdtool_rratimespans = 'Stored timespans' +lucistatistics_collectdrrdtool_rratimespans_desc = 'seconds; multiple separated by space' +lucistatistics_collectdrrdtool_rrarows = 'Rows per RRA' +lucistatistics_collectdrrdtool_xff = 'RRD XFiles Factor' +lucistatistics_collectdrrdtool_cachetimeout = 'Cache collected data for' +lucistatistics_collectdrrdtool_cachetimeout_desc = 'seconds' +lucistatistics_collectdrrdtool_cacheflush = 'Flush cache after' +lucistatistics_collectdrrdtool_cacheflush_desc = 'seconds' +lucistatistics_collectdtcpconns = 'TCPConns Plugin Configuration' +lucistatistics_collectdtcpconns_desc = 'The tcpconns plugin collects informations about open tcp connections on selected ports.' +lucistatistics_collectdtcpconns_enable = 'Enable this plugin' +lucistatistics_collectdtcpconns_listeningports = 'Monitor all local listen ports' +lucistatistics_collectdtcpconns_localports = 'Monitor local ports' +lucistatistics_collectdtcpconns_localports_desc = '0 - 65535; multiple separated by space' +lucistatistics_collectdtcpconns_remoteports = 'Monitor remote ports' +lucistatistics_collectdtcpconns_remoteports_desc = '0 - 65535; multiple separated by space' +lucistatistics_collectdunixsock = 'Unixsock Plugin Configuration' +lucistatistics_collectdunixsock_desc = 'The unixsock plugin creates a unix socket which can be used to read collected data from a running collectd instance.' +lucistatistics_collectdunixsock_enable = 'Enable this plugin' +lucistatistics_collectdunixsock_socketfile = 'Filepath of the unix socket' +lucistatistics_collectdunixsock_socketgroup = 'Group ownership of the unix socket' +lucistatistics_collectdunixsock_socketgroup_desc = 'group name' +lucistatistics_collectdunixsock_socketperms = 'File permissions of the unix socket' +lucistatistics_collectdunixsock_socketperms_desc = 'octal' +lucistatistics_collectdwireless = 'Wireless Plugin Configuration' +lucistatistics_collectdwireless_desc = 'The wireless plugin collects statistics about wireless signal strength, noise and quality.' +lucistatistics_collectdwireless_enable = 'Enable this plugin' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.pt-br.lua new file mode 100644 index 0000000..e2b5cac --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/statistics.pt-br.lua @@ -0,0 +1,212 @@ +stat_statistics = 'Estatísticas' +stat_desc = 'As estatísticas são baseadas no Collectd e é utilizado o RRD Tool para renderização das imagens à partir dos dados coletados.' +stat_systemplugins = 'Plugis de Sistema' +stat_networkplugins = 'Plugins de rede' +stat_outputplugins = 'Plugins de saída' +stat_showtimespan = 'Mostrar intervalo »' +stat_graphs = 'Gráficos' +stat_collectd = 'Collectd' +stat_cpu = 'Processador' +stat_ping = 'Ping' +stat_iptables = 'Firewall' +stat_netlink = 'Netlink' +stat_processes = 'Processos' +stat_wireless = 'Wireless' +stat_tcpconns = 'Conexões TCP' +stat_interface = 'Interfaces' +stat_df = 'Utilização de espaço em disco' +stat_irq = 'Interrupções' +stat_disk = 'Utilização do Disco' +stat_exec = 'Exec' +stat_rrdtool = 'RRDTool' +stat_network = 'Rede' +stat_csv = 'Formato CSV' +stat_load = 'Carga do Sistema' +stat_dns = 'DNS' +stat_email = 'Email' +stat_unixsock = 'UnixSock' +lucistatistics = 'Estatísticas' +lucistatistics_collectd = 'Configurações do Collectd' +lucistatistics_collectd_desc = 'Collectd é um pequeno daemon que coleta dados de várias fontes através de diferentes plugins. Nesta página você pode alterar as configurações gerais do daemon collectd.' +lucistatistics_collectd_hostname = 'Hostname' +lucistatistics_collectd_basedir = 'Diretório Base' +lucistatistics_collectd_include = 'Diretório para sub-configurações' +lucistatistics_collectd_plugindir = 'Diretório para os plugins do collectd' +lucistatistics_collectd_pidfile = 'Arquivo PID usado' +lucistatistics_collectd_typesdb = 'Arquivo com a definição de dados' +lucistatistics_collectd_interval = 'Intervalo da coleta de dados' +lucistatistics_collectd_interval_desc = 'Segundos' +lucistatistics_collectd_readthreads = 'Número de threads para o coletor de dados' +lucistatistics_collectd_fqdnlookup = 'Tentar encontrar o nome do host completo (FQDN)' +lucistatistics_collectdcpu = 'Configuração do plugin CPU' +lucistatistics_collectdcpu_desc = 'O plugin cpu coleta as estatísticas básicas sobre o uso do processador.' +lucistatistics_collectdcpu_enable = 'Habilitar este plugin' +lucistatistics_collectdcsv = 'Configuração do plugin CSV' +lucistatistics_collectdcsv_desc = 'O plugin csv armazena os dados coletados em um arquivo no formato csv para um futuro processamento por outros programas.' +lucistatistics_collectdcsv_enable = 'Habilitar este plugin' +lucistatistics_collectdcsv_datadir = 'Diretório para armazenamento dos arquivos csv' +lucistatistics_collectdcsv_storerates = 'Armazenar os valores dos dados como taxas em vez de valores absolutos' +lucistatistics_collectddf = 'Configuração do plugin DF' +lucistatistics_collectddf_desc = 'O plugin df coleta estatísticas sobre a utilização de espaço em disco em diferentes dispositivos, pontos de montagem ou tipos de sistemas de arquivos.' +lucistatistics_collectddf_enable = 'Habilitar este plugin' +lucistatistics_collectddf_devices = 'Monitorar dispositivos' +lucistatistics_collectddf_devices_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddf_mountpoints = 'Monitorar pontos de montagem' +lucistatistics_collectddf_mountpoints_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddf_fstypes = 'Monitorar tipos de sistemas de arquivos' +lucistatistics_collectddf_fstypes_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddf_ignoreselected = 'Monitorar tudo exceto os selecionados' +lucistatistics_collectddisk = 'Configuração do plugin Disco' +lucistatistics_collectddisk_desc = 'O plugin disco coleta estatísticas de uso detalhadas das partições selecionadas ou discos inteiros.' +lucistatistics_collectddisk_enable = 'Habilitar este plugin' +lucistatistics_collectddisk_disks = 'Monitoras discos e partições' +lucistatistics_collectddisk_disks_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddisk_ignoreselected = 'Monitorar tudo exceto os selecionados' +lucistatistics_collectddns = 'Configuração do plugin DNS' +lucistatistics_collectddns_desc = 'O plugin dns coleta estatísticas detalhadas sobre o tráfego do dns nas interfaces selecionadas.' +lucistatistics_collectddns_enable = 'Habilitar este plugin' +lucistatistics_collectddns_interfaces = 'Monitorar interfaces' +lucistatistics_collectddns_interfaces_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectddns_ignoresources = 'Ignorar endereços de origem' +lucistatistics_collectddns_ignoresources_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdemail = 'Configuração do plugin E-Mail' +lucistatistics_collectdemail_desc = 'O plugin de email cria um socket unix que pode ser usado para transmitir estatísticas de email o daemon collectd. Este plugin é essencialmente destinado a ser utilizado em conjunto com o plugin Mail::SpamAssasin::Plugin::Collectd mas pode ser utilizado de outras maneiras também.' +lucistatistics_collectdemail_enable = 'Habilitar este plugin' +lucistatistics_collectdemail_socketfile = 'Caminho do arquivo do socket unix' +lucistatistics_collectdemail_socketgroup = 'Grupo dono do socket unix' +lucistatistics_collectdemail_socketgroup_desc = 'nome do grupo' +lucistatistics_collectdemail_socketperms = 'Permissões de arquivo do socket unix' +lucistatistics_collectdemail_socketperms_desc = 'octal' +lucistatistics_collectdemail_maxconns = 'Máximo de conexões permitidas' +lucistatistics_collectdexec = 'Configuração do plugin Exec' +lucistatistics_collectdexec_desc = 'O plugin exec inicia comandos externos para leitura de valores ou notificar processos externos quando um determinado valor limite for atingido.' +lucistatistics_collectdexec_enable = 'Habilitar este plugin' +lucistatistics_collectdexecinput = 'Adicionar comando para leitura de valores' +lucistatistics_collectdexecinput_desc = 'Aqui você pode definir comandos externos que serão iniciados pelo collectd a fim de ler determinados valores. Os valores serão lidos a partir do stdout.' +lucistatistics_collectdexecinput_cmdline = 'Linha de comando' +lucistatistics_collectdexecinput_cmduser = 'Executar como usuário' +lucistatistics_collectdexecinput_cmdgroup = 'Executar como grupo' +lucistatistics_collectdexecnotify = 'Adicionar o comando de notificação' +lucistatistics_collectdexecnotify_desc = 'Aqui você pode definir os comandos externos que serão iniciados pelo collectd quando determinados valores limite forem atingidos. Os valores passados ao comando serão enviados para o stdin.' +lucistatistics_collectdexecnotify_cmdline = 'Linha de comando' +lucistatistics_collectdexecnotify_cmduser = 'Executar como usuário' +lucistatistics_collectdexecnotify_cmdgroup = 'Executar como grupo' +lucistatistics_collectdinterface = 'Configuração do plugin Interface' +lucistatistics_collectdinterface_desc = 'O plugin interface plugin coleta estatísticas sobre o tráfego das interfaces selecionadas.' +lucistatistics_collectdinterface_enable = 'Habilitar este plugin' +lucistatistics_collectdinterface_interfaces = 'Monitorar interfaces' +lucistatistics_collectdinterface_interfaces_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdinterface_ignoreselected = 'Monitorar todas exceto as selecionadas' +lucistatistics_collectdiptables = 'Configuração do plugin Iptables' +lucistatistics_collectdiptables_desc = 'O plugin iptables irá monitorar as regras de firewall selecionadas e coletar informações sobre pacotes e bytes processados pela regra.' +lucistatistics_collectdiptables_enable = 'Habilitar este plugin' +lucistatistics_collectdiptablesmatch = 'Adicionar regra' +lucistatistics_collectdiptablesmatch_desc = 'Aqui você pode definir diversos critérios para as regras iptables selecionadas serem monitoradas.' +lucistatistics_collectdiptablesmatch_name = 'Nome da regra' +lucistatistics_collectdiptablesmatch_name_desc = 'max. 16 caract.' +lucistatistics_collectdiptablesmatch_table = 'Tabela' +lucistatistics_collectdiptablesmatch_chain = 'Cadeia' +lucistatistics_collectdiptablesmatch_target = 'Ação (destino)' +lucistatistics_collectdiptablesmatch_protocol = 'Protocolo de rede' +lucistatistics_collectdiptablesmatch_source = 'IP de origem' +lucistatistics_collectdiptablesmatch_source_desc = 'Notação CIDR' +lucistatistics_collectdiptablesmatch_destination = 'IP de destino' +lucistatistics_collectdiptablesmatch_destination_desc = 'Notação CIDR' +lucistatistics_collectdiptablesmatch_inputif = 'Interface de entrada' +lucistatistics_collectdiptablesmatch_inputif_desc = 'ex. br-lan' +lucistatistics_collectdiptablesmatch_outputif = 'Interface de saída' +lucistatistics_collectdiptablesmatch_outputif_desc = 'ex. br-ff' +lucistatistics_collectdiptablesmatch_options = 'Opções' +lucistatistics_collectdiptablesmatch_options_desc = 'ex. rejeitar-com tcp-reset' +lucistatistics_collectdirq = 'Configuração do plugin IRQ' +lucistatistics_collectdirq_desc = 'O plugin irq irá monitorar a taxa de erros por segundo de cada interrupção selecionada. Se nenhuma interrupção for selecionada então todas as interrupções serão monitoradas.' +lucistatistics_collectdirq_enable = 'Habilitar este plugin' +lucistatistics_collectdirq_irqs = 'Monitorar interrupções' +lucistatistics_collectdirq_irqs_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectdirq_ignoreselected = 'Monitorar todas exceto as selecionadas' +lucistatistics_collectdload = 'Configuração do plugin carga' +lucistatistics_collectdload_desc = 'O plugin carga coleta estatísticas gerais sobre a carga do sistema.' +lucistatistics_collectdload_enable = 'Habilitar este plugin' +lucistatistics_collectdnetlink = 'Configuração do plugin Netlink' +lucistatistics_collectdnetlink_desc = 'O plugin Netlink coleta informações detalhadas como qdisc-, classe- e filtro de estatísticas das interfaces selecionadas.' +lucistatistics_collectdnetlink_enable = 'Habilitar este plugin' +lucistatistics_collectdnetlink_interfaces = 'Monitoramento básico' +lucistatistics_collectdnetlink_interfaces_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_verboseinterfaces = 'Monitoramento no modo verbose' +lucistatistics_collectdnetlink_verboseinterfaces_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_qdiscs = 'Monitoramento do Qdisc' +lucistatistics_collectdnetlink_qdiscs_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_classes = 'Monitoramento das Classes de Shaping' +lucistatistics_collectdnetlink_classes_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_filters = 'Monitoramento das Classes de Filtros' +lucistatistics_collectdnetlink_filters_desc = 'pressione Ctrl enquanto clica para selecionar várias interfaces' +lucistatistics_collectdnetlink_ignoreselected = 'Monitorar todas exceto as selecionadas' +lucistatistics_collectdnetwork = 'Configuração do plugin Rede' +lucistatistics_collectdnetwork_desc = 'O plugin rede fornece informações de rede baseadas na comunicação entre as diferentes instâncias do collectd. O Collectd pode operar tanto no modo cliente quanto no modo servidor. No modo cliente os dados coletados localmente são transferidos para um servidor collectd, no modo de servidor a instância local recebe dados de outros hosts.' +lucistatistics_collectdnetwork_enable = 'Habilitar este plugin' +lucistatistics_collectdnetworklisten = 'Escutar na(s) interface(s)' +lucistatistics_collectdnetworklisten_desc = 'Esta seção define em quais interfaces o collectd irá aguardar para receber conexões.' +lucistatistics_collectdnetworklisten_host = 'Endereço de escuta do Host' +lucistatistics_collectdnetworklisten_host_desc = 'hostname, ip ou ip6' +lucistatistics_collectdnetworklisten_port = 'Porta de escuta' +lucistatistics_collectdnetworklisten_port_desc = '0 - 65535' +lucistatistics_collectdnetworkserver = 'Interfaces do servidor' +lucistatistics_collectdnetworkserver_desc = 'Esta seção define para qual servidor os dados coletados localmente serão enviados.' +lucistatistics_collectdnetworkserver_host = 'IP/Hostname do servidor' +lucistatistics_collectdnetworkserver_host_desc = 'hostname, ip ou ip6' +lucistatistics_collectdnetworkserver_port = 'Porta do servidor' +lucistatistics_collectdnetworkserver_port_desc = '0 - 65535' +lucistatistics_collectdnetwork_timetolive = 'TTL para os pacotes de rede' +lucistatistics_collectdnetwork_timetolive_desc = '0 - 255' +lucistatistics_collectdnetwork_forward = 'Transmissão entre o endereço de escuta e dos servidores' +lucistatistics_collectdnetwork_cacheflush = 'Intervalo de limpeza do cache' +lucistatistics_collectdnetwork_cacheflush_desc = 'segundos' +lucistatistics_collectdping = 'Configuração do plugin Ping' +lucistatistics_collectdping_desc = 'O plugin ping irá enviar pacotes ICMP to tipo echo aos hosts selecionados e medir o tempo de resposta para cada host.' +lucistatistics_collectdping_enable = 'Habilitar este plugin' +lucistatistics_collectdping_hosts = 'Monitorar os hosts' +lucistatistics_collectdping_hosts_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectdping_ttl = 'TTL para os pacotes do ping' +lucistatistics_collectdping_ttl_desc = '0 - 255' +lucistatistics_collectdprocesses = 'Configuração do plugin Processos' +lucistatistics_collectdprocesses_desc = 'O plugin processo coleta informações como o tempo da cpu, página falhas e uso de memória dos processos selecionados.' +lucistatistics_collectdprocesses_enable = 'Habilitar este plugin' +lucistatistics_collectdprocesses_processes = 'Monitorar processos' +lucistatistics_collectdprocesses_processes_desc = 'múltiplos valores, separados por espaço' +lucistatistics_collectdrrdtool = 'Configuração do plugin RRDTool' +lucistatistics_collectdrrdtool_desc = 'O plugin rrdtool armazena os dados coletados no arquivo de banco de dados rrd.

Aviso: A má configuração desses valores, resultará em um valor muito elevado no consumo de memória no diretório temporário. Isso pode tornar o equipamento inutilizável!' +lucistatistics_collectdrrdtool_enable = 'Habilitar este plugin' +lucistatistics_collectdrrdtool_datadir = 'Diretório de armazenamento' +lucistatistics_collectdrrdtool_stepsize = 'Intervalo de atualização' +lucistatistics_collectdrrdtool_stepsize_desc = 'segundos' +lucistatistics_collectdrrdtool_heartbeat = 'Intervalo entre duas atualizações' +lucistatistics_collectdrrdtool_heartbeat_desc = 'segundos' +lucistatistics_collectdrrdtool_rrasingle = 'Somente criar RRAs de média' +lucistatistics_collectdrrdtool_rrasingle_desc = 'reduzir o tamanho do rrd' +lucistatistics_collectdrrdtool_rratimespans = 'Intervalos armazenados' +lucistatistics_collectdrrdtool_rratimespans_desc = 'segundos; vários valores, separar com espaço' +lucistatistics_collectdrrdtool_rrarows = 'Linhas por RRA' +lucistatistics_collectdrrdtool_xff = 'Arquivos RRD XFiles Factor' +lucistatistics_collectdrrdtool_cachetimeout = 'Cache dos dados coletados' +lucistatistics_collectdrrdtool_cachetimeout_desc = 'segundos' +lucistatistics_collectdrrdtool_cacheflush = 'Limpar cache após' +lucistatistics_collectdrrdtool_cacheflush_desc = 'segundos' +lucistatistics_collectdtcpconns = 'Configuração do plugin TCPConns' +lucistatistics_collectdtcpconns_desc = 'O plugin tcpconns coleta informações sobre as conexões TCP abertas das portas selecionadas.' +lucistatistics_collectdtcpconns_enable = 'Habilitar este plugin' +lucistatistics_collectdtcpconns_listeningports = 'Monitorar todas as portas locais' +lucistatistics_collectdtcpconns_localports = 'Monitorar as portas locais' +lucistatistics_collectdtcpconns_localports_desc = '0 - 65535; vários valores, separar com espaço' +lucistatistics_collectdtcpconns_remoteports = 'Monitorar portas remotas' +lucistatistics_collectdtcpconns_remoteports_desc = '0 - 65535; vários valores, separar com espaço' +lucistatistics_collectdunixsock = 'Configuração do plugin Unixsock' +lucistatistics_collectdunixsock_desc = 'O plugin unixsock cria um socket unix, que pode ser usado para ler os dados coletados a partir de uma instância do collectd.' +lucistatistics_collectdunixsock_enable = 'Habilitar este plugin' +lucistatistics_collectdunixsock_socketfile = 'Caminho do arquivo socket unix' +lucistatistics_collectdunixsock_socketgroup = 'Grupo dono do socket unix' +lucistatistics_collectdunixsock_socketgroup_desc = 'nome do grupo' +lucistatistics_collectdunixsock_socketperms = 'Permissões de arquivo do socket unix' +lucistatistics_collectdunixsock_socketperms_desc = 'octal' +lucistatistics_collectdwireless = 'Configuração do plugin Wireless' +lucistatistics_collectdwireless_desc = 'O plugin wireless coleta estatísticas sobre o nível de sinal wireless, o ruído e qualidade.' +lucistatistics_collectdwireless_enable = 'Habilitar este plugin' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.de.lua new file mode 100644 index 0000000..164064b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.de.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Autorisation benötigt' +sysauth_prompt = 'Bitte Benutzernamen und Passwort eingeben.' +sysauth_failed = 'Ungültiger Benutzername und/oder ungültiges Passwort! Bitte nocheinmal versuchen.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.en.lua new file mode 100644 index 0000000..2a8759f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.en.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Authorization Required' +sysauth_prompt = 'Please enter your username and password.' +sysauth_failed = 'Invalid username and/or password! Please try again.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.fr.lua new file mode 100644 index 0000000..341fcfc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.fr.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Authorisation requise' +sysauth_prompt = 'Saisissez votre nom d'utilisateur et mot de passe.' +sysauth_failed = 'Nom d'utilisateur et/ou mot de passe erroné ! Réessayez s'il vous plaît.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.it.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.it.lua new file mode 100644 index 0000000..41200a7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.it.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Autorizzazione richiesta' +sysauth_prompt = 'Per favore inserisci i tuoi username e password.' +sysauth_failed = 'Username o password non validi! Per favore riprova.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.pt-br.lua new file mode 100644 index 0000000..9df9c6a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.pt-br.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Autorização Requerida' +sysauth_prompt = 'Digite seu nome de usuário e senha.' +sysauth_failed = 'Nome de usuário inválido e/ou a senha! Por favor, tente novamente.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.ru.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.ru.lua new file mode 100644 index 0000000..a0d3e1f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/sysauth.ru.lua @@ -0,0 +1,3 @@ +sysauth_head = 'ТребуетÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ' +sysauth_prompt = 'ПожалуйÑта, введите логин и пароль.' +sysauth_failed = 'Ðеверный логин и/или пароль! ПожалуйÑта попробуйте Ñнова.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.de.lua new file mode 100644 index 0000000..5aaafe4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.de.lua @@ -0,0 +1,32 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy ist ein schlanker HTTP(S)-Proxy ohne Zwischenspeicher' +tinyproxy_tinyproxy_allow = 'Proxyzugang erlauben von' +tinyproxy_tinyproxy_anonymous = 'Erlaube Header für anonymen Proxy' +tinyproxy_tinyproxy_bind = 'Ausgehendenden Verkehr an Adresse binden' +tinyproxy_tinyproxy_connectport = 'Ports für CONNECT-Methode' +tinyproxy_tinyproxy_connectport_desc = '0 = deaktiviert, leer = alle' +tinyproxy_tinyproxy_defaulterrorfile = 'Fehlerseite' +tinyproxy_tinyproxy_filter = 'Filterliste' +tinyproxy_tinyproxy_filtercasesensitive = 'Filter unterscheiden Groß-/Kleinschreibung' +tinyproxy_tinyproxy_filterdefaultdeny = 'Filterliste ist eine Whitelist' +tinyproxy_tinyproxy_filterextended = 'Erweiterte reguläre Ausdrücke für Filter' +tinyproxy_tinyproxy_filterurls = 'Filtere URLs statt Domains' +tinyproxy_tinyproxy_listen = 'An Adresse binden' +tinyproxy_tinyproxy_logfile = 'Protokolldatei' +tinyproxy_tinyproxy_loglevel = 'Protokolllevel' +tinyproxy_tinyproxy_maxclients = 'Maximale Anzahl an Clients' +tinyproxy_tinyproxy_maxrequestsperchild = 'Maximale Anfragen pro Prozess' +tinyproxy_tinyproxy_maxspareservers = 'Max. Prozesszahl' +tinyproxy_tinyproxy_minspareservers = 'Min. Prozesszahl' +tinyproxy_tinyproxy_startservers = 'Anfängliche Prozesszahl' +tinyproxy_tinyproxy_statfile = 'Statistikseite' +tinyproxy_tinyproxy_syslog = 'In Systemprotokoll schreiben' +tinyproxy_tinyproxy_timeout = 'Verbindungstimeout' +tinyproxy_tinyproxy_viaproxyname = 'Wert des Via-Headers' +tinyproxy_tinyproxy_xtinyproxy = 'Client-IP übertragen' +tinyproxy_type_proxy = 'Ãœber Proxy' +tinyproxy_type_reject = 'Verbiete Zugriff' +tinyproxy_upstream = 'Zugangskontrolle' +tinyproxy_upstream_target = 'Zielhost' +tinyproxy_upstream_type = 'Methode' +tinyproxy_upstream_via = 'Zugangsproxy' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.en.lua new file mode 100644 index 0000000..2520e38 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.en.lua @@ -0,0 +1,32 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy is a small and fast non-caching HTTP(S)-Proxy' +tinyproxy_tinyproxy_allow = 'Allow access from' +tinyproxy_tinyproxy_anonymous = 'Allowed headers for anonymous proxy' +tinyproxy_tinyproxy_bind = 'Bind outgoing traffic to address' +tinyproxy_tinyproxy_connectport = 'Ports allowed for CONNECT method' +tinyproxy_tinyproxy_connectport_desc = '0 = disabled, empty = all' +tinyproxy_tinyproxy_defaulterrorfile = 'Error document' +tinyproxy_tinyproxy_filter = 'Filter list' +tinyproxy_tinyproxy_filtercasesensitive = 'Case sensitive filters' +tinyproxy_tinyproxy_filterdefaultdeny = 'Filter list is a whitelist' +tinyproxy_tinyproxy_filterextended = 'Extended regular expression filters' +tinyproxy_tinyproxy_filterurls = 'Filter URLs instead of domains' +tinyproxy_tinyproxy_listen = 'Listen on address' +tinyproxy_tinyproxy_logfile = 'Logfile' +tinyproxy_tinyproxy_loglevel = 'Log level' +tinyproxy_tinyproxy_maxclients = 'Maximum number of clients' +tinyproxy_tinyproxy_maxrequestsperchild = 'Maximum requests per thread' +tinyproxy_tinyproxy_maxspareservers = 'Max. spare servers' +tinyproxy_tinyproxy_minspareservers = 'Min. spare servers' +tinyproxy_tinyproxy_startservers = 'Spare servers to start with' +tinyproxy_tinyproxy_statfile = 'Statistic document' +tinyproxy_tinyproxy_syslog = 'Write to syslog' +tinyproxy_tinyproxy_timeout = 'Connection Timeout' +tinyproxy_tinyproxy_viaproxyname = 'Value of Via-Header' +tinyproxy_tinyproxy_xtinyproxy = 'Include client IP' +tinyproxy_type_proxy = 'Via proxy' +tinyproxy_type_reject = 'Reject access' +tinyproxy_upstream = 'Upstream Control' +tinyproxy_upstream_target = 'Target host' +tinyproxy_upstream_type = 'Type' +tinyproxy_upstream_via = 'Upstream Proxy' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.fr.lua new file mode 100644 index 0000000..af7a134 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.fr.lua @@ -0,0 +1,34 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy is a small and fast non-caching HTTP(S)-Proxy' +tinyproxy_tinyproxy_allow = 'Allow access from' +tinyproxy_tinyproxy_anonymous = 'Allowed headers for anonymous proxy' +tinyproxy_tinyproxy_bind = 'Lier le trafic sortant à l'adresse ip' +tinyproxy_tinyproxy_connectport = 'Ports allowed for CONNECT method' +tinyproxy_tinyproxy_connectport_desc = '0 = disabled, empty = all' +tinyproxy_tinyproxy_defaulterrorfile = 'Fichier d'erreur' +tinyproxy_tinyproxy_filter = 'Liste de filtres' +tinyproxy_tinyproxy_filtercasesensitive = 'Case sensitive filters' +tinyproxy_tinyproxy_filterdefaultdeny = 'Filter list is a whitelist' +tinyproxy_tinyproxy_filterextended = 'Extended regular expression filters' +tinyproxy_tinyproxy_filterurls = 'Filter URLs instead of domains' +tinyproxy_tinyproxy_group = 'Groupe' +tinyproxy_tinyproxy_listen = 'Listen on address' +tinyproxy_tinyproxy_logfile = 'Chemin du fichier de log' +tinyproxy_tinyproxy_loglevel = 'Niveau de log' +tinyproxy_tinyproxy_maxclients = 'Nombre maximum de clients' +tinyproxy_tinyproxy_maxrequestsperchild = 'Maximum de connexion par processus' +tinyproxy_tinyproxy_maxspareservers = 'Nombre Maximum de processus serveur' +tinyproxy_tinyproxy_minspareservers = 'Nombre Minimum de processus serveur' +tinyproxy_tinyproxy_startservers = 'Nombre de processus serveur lancés au demarrage' +tinyproxy_tinyproxy_statfile = 'Fichier de statistiques' +tinyproxy_tinyproxy_syslog = 'Écrire dans le journal système (Syslog)' +tinyproxy_tinyproxy_timeout = 'Délai de connexion' +tinyproxy_tinyproxy_user = 'Utilisateur' +tinyproxy_tinyproxy_viaproxyname = 'Valeur de l'entête "VIA" utilisée comme nom d'hôte' +tinyproxy_tinyproxy_xtinyproxy = 'Inclure l'ip du client' +tinyproxy_type_proxy = 'Via proxy' +tinyproxy_type_reject = 'Refuser l'accès' +tinyproxy_upstream = 'Upstream Control' +tinyproxy_upstream_target = 'Hôte de destination' +tinyproxy_upstream_type = 'Type' +tinyproxy_upstream_via = 'Proxy' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.pt-br.lua new file mode 100644 index 0000000..33b664a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/tinyproxy.pt-br.lua @@ -0,0 +1,34 @@ +tinyproxy = 'Tinyproxy' +tinyproxy_desc = 'Tinyproxy é um pequeno e rápido Proxy-HTTP(S) sem suporte à cache' +tinyproxy_tinyproxy_allow = 'Permitir acesso de' +tinyproxy_tinyproxy_anonymous = 'Cabeçalhos permitidos para proxy anônimo' +tinyproxy_tinyproxy_bind = 'Associar o tráfego de saída ao endereço' +tinyproxy_tinyproxy_connectport = 'Portas permitidas para o método CONNECT ' +tinyproxy_tinyproxy_connectport_desc = '0 = desativado, vazio = todas' +tinyproxy_tinyproxy_defaulterrorfile = 'Documento de erro' +tinyproxy_tinyproxy_filter = 'Lista de filtros' +tinyproxy_tinyproxy_filtercasesensitive = 'Filtros "case sensitive"' +tinyproxy_tinyproxy_filterdefaultdeny = 'A lista de filtros é uma lista branca' +tinyproxy_tinyproxy_filterextended = 'Filtros com suporte à expressões regulares' +tinyproxy_tinyproxy_filterurls = 'Filtrar URLs em vez de domínios' +tinyproxy_tinyproxy_listen = 'Escutar no endereço' +tinyproxy_tinyproxy_logfile = 'Arquivo de log' +tinyproxy_tinyproxy_loglevel = 'Nível do log' +tinyproxy_tinyproxy_maxclients = 'Número máximo de clientes' +tinyproxy_tinyproxy_maxrequestsperchild = 'Máximo de solicitações por thread' +tinyproxy_tinyproxy_maxspareservers = 'Max. servidores sobressalentes' +tinyproxy_tinyproxy_minspareservers = 'Min. servidores sobressalentes' +tinyproxy_tinyproxy_startservers = 'Servidores sobressalentes iniciar com' +tinyproxy_tinyproxy_statfile = 'Documento de estatísticas' +tinyproxy_tinyproxy_syslog = 'Escrever para syslog' +tinyproxy_tinyproxy_timeout = 'Timeout de conexão' +tinyproxy_tinyproxy_group = 'Grupo' +tinyproxy_tinyproxy_user = 'Usuário' +tinyproxy_tinyproxy_viaproxyname = 'Valor do cabeçalho "Via-Header"' +tinyproxy_tinyproxy_xtinyproxy = 'Incluir o IP do cliente' +tinyproxy_type_proxy = 'Via proxy' +tinyproxy_type_reject = 'Rejeitar o acesso' +tinyproxy_upstream = 'Controle de Upstream' +tinyproxy_upstream_target = 'Host de destino' +tinyproxy_upstream_type = 'Tipo' +tinyproxy_upstream_via = 'Proxy para Upstream' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.de.lua new file mode 100644 index 0000000..777ae87 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.de.lua @@ -0,0 +1,7 @@ +upnpd = 'Universal Plug & Play' +upnpd_desc = 'UPNP ermöglicht die automatische Konfiguration des Routers durch Clients im lokalen Netzwerk.' +upnpd_config_desc = 'UPNP sollte nur wenn unbedingt nötig aktiviert werden, da es ein Sicherheitsrisiko für das Netzwerk darstellen kann.' +upnpd_config_securemode = 'Sicheren Modus aktivieren' +upnpd_config_logoutput = 'Ausgabe protokollieren' +upnpd_config_download = 'Downlink' +upnpd_config_upload = 'Uplink' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.en.lua new file mode 100644 index 0000000..8e6c825 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.en.lua @@ -0,0 +1,7 @@ +upnpd = 'Universal Plug & Play' +upnpd_desc = 'UPNP allows clients in the local network to automatically configure the router.' +upnpd_config_desc = 'UPNP should only be enabled if absolutely necessary as it can result in high security risks for your network.' +upnpd_config_securemode = 'Enable secure mode' +upnpd_config_logoutput = 'Log output' +upnpd_config_download = 'Downlink' +upnpd_config_upload = 'Uplink' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.pt-br.lua new file mode 100644 index 0000000..cf2c3db --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/upnp.pt-br.lua @@ -0,0 +1,7 @@ +upnpd = 'Plug & Play Universal' +upnpd_desc = 'UPNP permite os clientes da rede local automaticamente configurar o roteador.' +upnpd_config_desc = 'O UPNP deve ser ativado apenas se for absolutamente necessário, pois ele pode resultar em elevados riscos de segurança para sua rede.' +upnpd_config_securemode = 'Enable secure mode' +upnpd_config_logoutput = 'Log de saída' +upnpd_config_download = 'Link para download' +upnpd_config_upload = 'Link para Upload' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.de.lua new file mode 100644 index 0000000..a5f239a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.de.lua @@ -0,0 +1,8 @@ +content_directories = 'Freigabeverzeichnisse' +disable_telnet = 'Telnet-Konsole deaktivieren' +disable_webif = 'Webinterface deaktivieren' +options = 'Optionen' +servername = 'Servername' +settings = 'Einstellungen' +ushare = 'uShare' +ushare_desc = 'uShare' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.en.lua new file mode 100644 index 0000000..834fa91 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.en.lua @@ -0,0 +1,8 @@ +content_directories = 'Content directories' +disable_telnet = 'Disable telnet console' +disable_webif = 'Disable webinterface' +options = 'Options' +servername = 'Servername' +settings = 'Settings' +ushare = 'uShare' +ushare_desc = 'uShare' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.pt-br.lua new file mode 100644 index 0000000..492c4ce --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/ushare.pt-br.lua @@ -0,0 +1,8 @@ +content_directories = 'Diretórios de conteúdo' +disable_telnet = 'Desativar console telnet' +disable_webif = 'Desativar interface web' +options = 'Opções' +servername = 'Nome do servidor' +settings = 'Configurações' +ushare = 'uShare' +ushare_desc = 'uShare' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.de.lua new file mode 100644 index 0000000..b340fd4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.de.lua @@ -0,0 +1,5 @@ +framespersecond = 'Bilder pro Sekunde' +resolution = 'Auflösung' +settings = 'Konfiguration' +uvc_streamer = 'Webcam Stream' +uvc_streamer_desc = 'Linux-UVC Webcam Konfiguration. Im Browser z.B. http://%s:%i/ laden.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.en.lua new file mode 100644 index 0000000..e56eacc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.en.lua @@ -0,0 +1,5 @@ +framespersecond = 'Frames per second' +resolution = 'Resolution' +settings = 'Settings' +uvc_streamer = 'Webcam streaming' +uvc_streamer_desc = 'Configure your Linux-UVC compatible webcam. Point your browser to e.g. http://%s:%i/' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.fr.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.fr.lua new file mode 100644 index 0000000..97523af --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.fr.lua @@ -0,0 +1,5 @@ +framespersecond = 'Images par seconde' +resolution = 'Résolution' +settings = 'Paramètres' +uvc_streamer = 'Webcam streaming' +uvc_streamer_desc = 'Configurez le pilote linux UVC-webcam pour votre webcam. Pointez votre navigateur par exemple surhttp://%s:%i/' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.pt-br.lua new file mode 100644 index 0000000..624a885 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvc_streamer.pt-br.lua @@ -0,0 +1,5 @@ +framespersecond = 'Frames por segundo' +resolution = 'Resolução' +settings = 'Configurações' +uvc_streamer = 'Webcam streaming' +uvc_streamer_desc = 'Configure a sua webcam compatível com o Linux-UVC. Coloque no seu browser por ex. http://%s:%i/' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.de.lua new file mode 100644 index 0000000..7962161 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.de.lua @@ -0,0 +1,39 @@ +uvl_err_uciload = 'Fehler beim Laden der Konfiguration \"%p\": %1' +uvl_err_scheme = 'Fehler in Schema \"%p\":\n%c' +uvl_err_config = 'Fehler in Konfiguration \"%p\":\n%c' +uvl_err_section = 'Fehler in Sektion \"%i\" (%I):\n%c' +uvl_err_option = 'Fehler in Option \"%i\" (%I):\n%c' +uvl_err_reference = 'Option \"%i\" hat eine ungültige Referenz-Spezifikation %1:\n%c' +uvl_err_dependency = 'Nicht erfüllte Abhängigkeiten in %t \"%i\":\n%c' +uvl_err_sme_find = 'Schema \"%p\" nicht in Verzeichnis \"%1\" gefunden' +uvl_err_sme_read = 'Fehlende Dateizugriffsrechte auf \"%1\"' +uvl_err_sme_reqfld = 'Notwendiges Feld \"%1\" fehlt in Schema \"%i\"' +uvl_err_sme_invref = 'Ungültige Referenz \"%1\" verweist auf eine anonyme Sektion' +uvl_err_sme_badref = 'Syntaxfehler in Referenzspezifikation \"%1\"' +uvl_err_sme_baddep = 'Syntaxfehler in Abhängigkeitsbeschreibung \"%1\" von \"%i\"' +uvl_err_sme_badval = 'Syntaxfehler in Validatorspezifikation \"%1\" von \"%i\"' +uvl_err_sme_errval = 'Fehler in externem Validator \"%1\": %2' +uvl_err_sme_vbadpack = 'Option \"%o\" in Schema \"%p\" referenziert unbekanntes Paket \"%1\"' +uvl_err_sme_vbadsect = 'Option \"%o\" in Schema \"%p\" referenziert unbekannte Sektion \"%1\"' +uvl_err_sme_ebadpack = 'Aufzählung \"%v\" in Schema \"%p\" referenziert unbekanntes Paket \"%1\"' +uvl_err_sme_ebadsect = 'Aufzählung \"%v\" in Schema \"%p\" referenziert unbekannte Sektion \"%1\"' +uvl_err_sme_ebadopt = 'Aufzählung \"%v\" in Schema \"%p\" referenziert unbekannte Option \"%1\"' +uvl_err_sme_ebadtype = 'Aufzählung \"%v\" in Schema \"%p\" referenziert Nicht-Aufzählungs-Option \"%p.%s.%o\"' +uvl_err_sme_ebaddef = 'Aufzählung \"%v\" in Schema \"%p\" überschreibt den Standardwert von \"%p.%s.%o\"' +uvl_err_sect_unknown = 'Sektion \"%i\" (%I) nicht in Schema gefunden' +uvl_err_sect_required = 'Benötigte Sektion vom Typ \"%I\" nicht in Konfiguration gefunden' +uvl_err_sect_unique = 'Einzigartige Sektion \"%i\" (%I) kommt mehrfach in der Konfiguration vor' +uvl_err_sect_named = 'Die Sektion vom Typ \"%I\" ist anonym in der Konfiguration gespeichert, muss aber einen Namen haben' +uvl_err_sect_notfound = 'Sektion vom Typ \"%I\" nicht in der Konfiguration gefunden' +uvl_err_opt_unknown = 'Option \"%i\" (%I) nicht im Schema gefunden' +uvl_err_opt_required = 'Die benötigte Option \"%i\" hat keinen Wert gesetzt' +uvl_err_opt_badvalue = 'Der Wert \"%1\" von Option \"%i\" ist nicht in der Aufzählung %2 definiert' +uvl_err_opt_invvalue = 'Der Wert \"%1\" von Option \"%i\" ist kein gültiger \"%2\" Datentyp' +uvl_err_opt_notlist = 'Option \"%i\" ist als Liste definiert aber als einfache Option gespeichert' +uvl_err_opt_datatype = 'Option \"%i\" hat unbekannten Datentyp \"%1\"' +uvl_err_opt_notfound = 'Option \"%i\" nicht in der Konfiguration gefunden' +uvl_err_dep_notequal = 'Abhängigkeit (%1) nicht erfüllt:\nOption \"%i\" ist nicht \"%2\"' +uvl_err_dep_novalue = 'Abhängigkeit (%1) nicht erfüllt:\nOption \"%i\" hat keinen Wert gesetzt' +uvl_err_dep_notvalid = 'Abhängigkeit (%1) nicht erfüllt:\n%c' +uvl_err_dep_recursive = 'Rekursive Abhängkeit in Option \"%i\" gefunden' +uvl_err_dep_badenum = 'Nicht erfüllte Abhängigkeiten in Aufzählung \"%i\":\n%c' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.en.lua new file mode 100644 index 0000000..b0944a2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.en.lua @@ -0,0 +1,39 @@ +uvl_err_uciload = 'Unable to load config \"%p\": %1' +uvl_err_scheme = 'Error in scheme \"%p\":\n%c' +uvl_err_config = 'Error in config \"%p\":\n%c' +uvl_err_section = 'Error in section \"%i\" (%I):\n%c' +uvl_err_option = 'Error in option \"%i\" (%I):\n%c' +uvl_err_reference = 'Option \"%i\" has invalid reference specification %1:\n%c' +uvl_err_dependency = 'In dependency check for %t \"%i\":\n%c' +uvl_err_sme_find = 'Can not find scheme \"%p\" in \"%1\"' +uvl_err_sme_read = 'Can not access file \"%1\"' +uvl_err_sme_reqfld = 'Missing required scheme field \"%1\" in \"%i\"' +uvl_err_sme_invref = 'Illegal reference \"%1\" to an anonymous section' +uvl_err_sme_badref = 'Malformed reference in \"%1\"' +uvl_err_sme_baddep = 'Malformed dependency specification \"%1\" in \"%i\"' +uvl_err_sme_badval = 'Malformed validator specification \"%1\" in \"%i\"' +uvl_err_sme_errval = 'External validator \"%1\" failed: %2' +uvl_err_sme_vbadpack = 'Variable \"%o\" in scheme \"%p\" references unknown package \"%1\"' +uvl_err_sme_vbadsect = 'Variable \"%o\" in scheme \"%p\" references unknown section \"%1\"' +uvl_err_sme_ebadpack = 'Enum \"%v\" in scheme \"%p\" references unknown package \"%1\"' +uvl_err_sme_ebadsect = 'Enum \"%v\" in scheme \"%p\" references unknown section \"%1\"' +uvl_err_sme_ebadopt = 'Enum \"%v\" in scheme \"%p\" references unknown option \"%1\"' +uvl_err_sme_ebadtype = 'Enum \"%v\" in scheme \"%p\" references non-enum option \"%p.%s.%o\"' +uvl_err_sme_ebaddef = 'Enum \"%v\" in scheme \"%p\" redeclares the default value of \"%p.%s.%o\"' +uvl_err_sect_unknown = 'Section \"%i\" (%I) not found in scheme' +uvl_err_sect_required = 'Required section \"%p.%s\" not found in config' +uvl_err_sect_unique = 'Unique section \"%p.%s\" occurs multiple times in config' +uvl_err_sect_named = 'The section of type \"%p.%s\" is stored anonymously in config but must be named' +uvl_err_sect_notfound = 'Section \"%p.%s\" not found in config' +uvl_err_opt_unknown = 'Option \"%i\" (%I) not found in scheme' +uvl_err_opt_required = 'Required option \"%i\" has no value' +uvl_err_opt_badvalue = 'Value \"%1\" of option \"%i\" is not defined in enum %2' +uvl_err_opt_invvalue = 'Value \"%1\" of option \"%i\" does not validate as datatype \"%2\"' +uvl_err_opt_notlist = 'Option \"%i\" is defined as list but stored as plain value' +uvl_err_opt_datatype = 'Option \"%i\" has unknown datatype \"%1\"' +uvl_err_opt_notfound = 'Option \"%p.%s.%o\" not found in config' +uvl_err_dep_notequal = 'Dependency (%1) failed:\noption \"%i\" is not eqal \"%2\"' +uvl_err_dep_novalue = 'Dependency (%1) failed:\noption \"%i\" has no value' +uvl_err_dep_notvalid = 'Dependency (%1) failed:\n%c' +uvl_err_dep_recursive = 'Recursive dependency for option \"%i\" detected' +uvl_err_dep_badenum = 'In dependency check for enum value \"%i\":\n%c' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.pt-br.lua new file mode 100644 index 0000000..baf789a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/uvl.pt-br.lua @@ -0,0 +1,39 @@ +uvl_err_uciload = 'Não foi possível carregar a configuração \"%p\": %1' +uvl_err_scheme = 'Erro no esquema \"%p\":\n%c' +uvl_err_config = 'Erro na configuração \"%p\":\n%c' +uvl_err_section = 'Erro na seção \"%i\" (%I):\n%c' +uvl_err_option = 'Erro na opção \"%i\" (%I):\n%c' +uvl_err_reference = 'Opção \"%i\" tem especificação de referência inválida %1:\n%c' +uvl_err_dependency = 'Na dependência de verificação %t \"%i\":\n%c' +uvl_err_sme_find = 'Não é possível encontrar o esquema \"%p\" in \"%1\"' +uvl_err_sme_read = 'Não é possível acessar o arquivo \"%1\"' +uvl_err_sme_reqfld = 'Faltando campo requerido no esquema: \"%1\" em \"%i\"' +uvl_err_sme_invref = 'Referência \"1%\" ilegal para uma seção anônima' +uvl_err_sme_badref = 'Referência mal elaborada em \"%1\"' +uvl_err_sme_baddep = 'Especificação de dependência mal elaborada: \"%1\" em \"%i\"' +uvl_err_sme_badval = 'Especificação de validador mal elaborada: \"%1\" em \"%i\"' +uvl_err_sme_errval = 'Validador externo \"%1\" falhou: %2' +uvl_err_sme_vbadpack = 'Variável \"%o\" no esquema \"%p\" faz referência para um pacote desconecido \"%1\"' +uvl_err_sme_vbadsect = 'Variável \"%o\" no esquema \"%p\" faz referência para uma seção desconecida \"%1\"' +uvl_err_sme_ebadpack = 'Enum \"%v\" no esquema \"%p\" faz referência para um pacote desconecido \"%1\"' +uvl_err_sme_ebadsect = 'Enum \"%v\" no esquema \"%p\" faz referência para uma seção desconecida \"%1\"' +uvl_err_sme_ebadopt = 'Enum \"%v\" no esquema \"%p\" faz referência para uma opção desconecida \"%1\"' +uvl_err_sme_ebadtype = 'Enum \"%v\" no esquema \"%p\" faz referência para uma opção não-enum \"%p.%s.%o\"' +uvl_err_sme_ebaddef = 'Enum \"%v\" no esquema \"%p\" redeclara o valor padrão de \"%p.%s.%o\"' +uvl_err_sect_unknown = 'Seção \"%i\" (%I) não encontrada no esquema' +uvl_err_sect_required = 'Seção requerida \"%p.%s\" não encontrada na configuração' +uvl_err_sect_unique = 'Seção única \"%p.%s\" ocorre várias vezes na configuração' +uvl_err_sect_named = 'A seção do tipo \"%p.%s\" está armazenada na configuração como anônima, mas deve ser nomeada' +uvl_err_sect_notfound = 'Seção \"%p.%s\" não encontrada na configuração' +uvl_err_opt_unknown = 'Opção \"%i\" (%I) não encontrada no esquema' +uvl_err_opt_required = 'Opção requerida \"%i\" não tem nenhum valor' +uvl_err_opt_badvalue = 'Valor \"%1\" da opção \"%i\" não está definido no enum %2' +uvl_err_opt_invvalue = 'Valor \"%1\" da opção \"%i\" não foi validado como tipo de dados \"%2\"' +uvl_err_opt_notlist = 'Opção \"%i\" está definida como lista, mas armazenada como um valor simples' +uvl_err_opt_datatype = 'Opção \"%i\" tem o tipo de dados desconhecido \"%1\"' +uvl_err_opt_notfound = 'Opção \"%p.%s.%o\" não encontrada na configuração' +uvl_err_dep_notequal = 'Dependência (%1) falhou:\nopção \"%i\" is not eqal à \"%2\"' +uvl_err_dep_novalue = 'Dependência (%1) falhou:\nopção \"%i\" não tem nenhum valor' +uvl_err_dep_notvalid = 'Dependência (%1) falhou:\n%c' +uvl_err_dep_recursive = 'Dependência recursiva para a opção \"%i\" detectada' +uvl_err_dep_badenum = 'Na dependência, verificar pelo valor enum \"%i\":\n%c' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.de.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.de.lua new file mode 100644 index 0000000..3e48b35 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.de.lua @@ -0,0 +1,37 @@ +wifi_auto = 'auto' +wifi_fh = 'Frequenzsprung' +wifi_diversity = 'Diversität' +wifi_txantenna = 'Sendeantenne' +wifi_rxantenna = 'Empfangsantenne' +wifi_distance = 'Distanzoptimierung' +wifi_distance_desc = 'Distanz zum am weitesten entfernten Funkpartner in Meter.' +wifi_macpolicy = 'MAC-Adressfilter' +wifi_whitelist = 'Nur gelistete erlauben' +wifi_blacklist = 'Alle außer gelistete erlauben' +wifi_maclist = 'MAC-Adressliste' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Ländercode' +wifi_maxassoc = 'Verbindungsbegrenzung' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Fragmentierungsschwelle' +wifi_rts = 'RTS/CTS-Schwelle' +wifi_wds = 'WDS' +wifi_wdssep = 'Separates WDS' +wifi_hidden = 'ESSID verstecken' +wifi_isloate = 'Clients isolieren' +wifi_isloate_desc = 'Verhindert Client zu Client Kommunikation' +wifi_bgscan = 'Hintergrundscan' +wifi_rate = 'Ãœbertragungsrate' +wifi_mcast_rate = 'Multicastrate' +wifi_minrate = 'Mindestübertragungsrate' +wifi_maxrate = 'Höchstübertragungsrate' +wifi_compression = 'Kompression' +wifi_turbo = 'Turbo Modus' +wifi_ff = 'Schnelle Frames' +wifi_wmm = 'WMM Modus' +wifi_xr = 'XR-Unterstützung' +wifi_ar = 'AR-Unterstützung' +wifi_nosbeacon = 'Deaktiviere Hardware-Beacon Zeitgeber' +wifi_noprobereq = 'Scan-Anforderungen nicht beantworten' +wifi_wpareq = 'Für WPA-Verschlüsselung muss wpa_supplicant (für Clientmodus) oder hostapd (für AP und Ad-hoc-Modus) installiert sein.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.en.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.en.lua new file mode 100644 index 0000000..4fb286c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.en.lua @@ -0,0 +1,38 @@ +wifi_auto = 'auto' +wifi_fh = 'Frequency Hopping' +wifi_diversity = 'Diversity' +wifi_txantenna = 'Transmitter Antenna' +wifi_rxantenna = 'Receiver Antenna' +wifi_distance = 'Distance Optimization' +wifi_distance_desc = 'Distance to farthest network member in meters.' +wifi_macpolicy = 'MAC-Address Filter' +wifi_whitelist = 'Allow listed only' +wifi_blacklist = 'Allow all except listed' +wifi_maclist = 'MAC-List' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Country Code' +wifi_maxassoc = 'Connection Limit' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Fragmentation Threshold' +wifi_rts = 'RTS/CTS Threshold' +wifi_wds = 'WDS' +wifi_wdssep = 'Separate WDS' +wifi_hidden = 'Hide ESSID' +wifi_isloate = 'Isolate Clients' +wifi_isloate_desc = 'Prevent Client to Client Communication' +wifi_bgscan = 'Background Scan' +wifi_rate = 'Transmission Rate' +wifi_mcast_rate = 'Multicast Rate' +wifi_minrate = 'Minimum Rate' +wifi_maxrate = 'Maximum Rate' +wifi_compression = 'Compression' +wifi_turbo = 'Turbo Mode' +wifi_ff = 'Fast Frames' +wifi_wmm = 'WMM Mode' +wifi_xr = 'XR Support' +wifi_ar = 'AR Support' +wifi_nosbeacon = 'Disable HW-Beacon timer' +wifi_noprobereq = 'Do not send probe responses' +wifi_wpareq = 'WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP and ad-hoc mode) to be installed.' +wifi_keyreq = '40bit/104bit WEP is autodetected based on key length. Use either 5/13 ASCII or 10/26 HEX characters as WEP key. A valid ASCII-based key will be translated into a HEX-based one. WPA(2)-PSK keys should be 64 HEX characters.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.it.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.it.lua new file mode 100644 index 0000000..223ef27 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.it.lua @@ -0,0 +1,37 @@ +wifi_auto = 'auto' +wifi_fh = 'Frequency Hopping' +wifi_diversity = 'Diversity' +wifi_txantenna = 'Antenna trasmettente' +wifi_rxantenna = 'Antenna ricevente' +wifi_distance = 'Ottimizzazione distanza' +wifi_distance_desc = 'Distanza del membro più lontano della rete in metri.' +wifi_macpolicy = 'Filtro dei MAC-Addres' +wifi_whitelist = 'Consenti solo quelli in lista' +wifi_blacklist = 'Consenti tutti tranne quelli in lista' +wifi_maclist = 'Lista MAC' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Codice nazione' +wifi_maxassoc = 'Limite connessioni' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Soglia di frammentazione' +wifi_rts = 'Soglia RTS/CTS' +wifi_wds = 'WDS' +wifi_wdssep = 'WDS separati' +wifi_hidden = 'Nascondi ESSID' +wifi_isloate = 'Isola utenti' +wifi_isloate_desc = 'Impedisci comunicazione fra utenti' +wifi_bgscan = 'Scansione in background' +wifi_rate = 'Velocità di transmissione' +wifi_mcast_rate = 'Velocità multicast' +wifi_minrate = 'Velocità minima' +wifi_maxrate = 'Velocità massima' +wifi_compression = 'Compressione' +wifi_turbo = 'Modalità turbo' +wifi_ff = 'Frame veloci' +wifi_wmm = 'Modalità WMM' +wifi_xr = 'Supporto XR' +wifi_ar = 'Supporto AR' +wifi_nosbeacon = 'Disabilita Timer Beacon HW' +wifi_noprobereq = 'Disabilita Probe-Responses' +wifi_wpareq = 'La crittografia WPA richiede l'installazione di wpa_supplicant (per la modalità client) o hostapd (per la modalità AP o ad-hoc).' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.pt-br.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.pt-br.lua new file mode 100644 index 0000000..52a37b7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/i18n/wifi.pt-br.lua @@ -0,0 +1,37 @@ +wifi_auto = 'automático' +wifi_fh = 'Salto de Frequência' +wifi_diversity = 'Diversidade' +wifi_txantenna = 'Antena de Transmissão' +wifi_rxantenna = 'Antena de Recepção' +wifi_distance = 'Otimização de Distância' +wifi_distance_desc = 'Distância para o último host da rede (em metros).' +wifi_macpolicy = 'Filtro de Endereço-MAC' +wifi_whitelist = 'Permitir somente os listados' +wifi_blacklist = 'Permitir todos, exceto os listados' +wifi_maclist = 'Lista de MAC' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Código do País' +wifi_maxassoc = 'Limite de Conexão' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Fragmentation Threshold' +wifi_rts = 'RTS/CTS Threshold' +wifi_wds = 'WDS' +wifi_wdssep = 'Separar WDS' +wifi_hidden = 'Ocultar ESSID' +wifi_isloate = 'Isolar Clientes' +wifi_isloate_desc = 'Previnir Comunicação de Cliente para Cliente' +wifi_bgscan = 'Scanear em Segundo Plano' +wifi_rate = 'Taxa de Transmissão' +wifi_mcast_rate = 'Taxa de Multicast' +wifi_minrate = 'Taxa Mínima' +wifi_maxrate = 'Taxa Máxima' +wifi_compression = 'Compressão' +wifi_turbo = 'Modo Turbo' +wifi_ff = 'Fast Frames' +wifi_wmm = 'Modo WMM' +wifi_xr = 'Suporte XR' +wifi_ar = 'Suporte AR' +wifi_nosbeacon = 'Disable HW-Beacon timer' +wifi_noprobereq = 'Don not send probe responses' +wifi_wpareq = 'Criptografia-WPA requer wpa_supplicant (para o modo cliente) ou hostapd (para o modo AP e ad-hoc) instalados.' diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/init.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/init.lua new file mode 100644 index 0000000..e500b71 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/init.lua @@ -0,0 +1,34 @@ +--[[ +LuCI - Lua Configuration Interface + +Description: +Main class + +FileId: +$Id: init.lua 4079 2009-01-17 17:59:11Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local require = require + +module "luci" + +local v = require "luci.version" + +__version__ = v.luciversion or "0.9" +__appname__ = v.luciname or "LuCI" diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/ip.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/ip.lua new file mode 100644 index 0000000..4e858b6 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/ip.lua @@ -0,0 +1,632 @@ +--[[ + +LuCI ip calculation libarary +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: ip.lua 3835 2008-11-29 21:37:29Z jow $ + +]]-- + +--- LuCI IP calculation library. +module( "luci.ip", package.seeall ) + +require("bit") +require("luci.util") + +--- Boolean; true if system is little endian +LITTLE_ENDIAN = not luci.util.bigendian() + +--- Boolean; true if system is big endian +BIG_ENDIAN = not LITTLE_ENDIAN + +--- Specifier for IPv4 address family +FAMILY_INET4 = 0x04 + +--- Specifier for IPv6 address family +FAMILY_INET6 = 0x06 + + +local function __bless(x) + return setmetatable( x, { + __index = luci.ip.cidr, + __add = luci.ip.cidr.add, + __sub = luci.ip.cidr.sub, + __lt = luci.ip.cidr.lower, + __eq = luci.ip.cidr.equal, + __le = + function(...) + return luci.ip.cidr.equal(...) or luci.ip.cidr.lower(...) + end + } ) +end + +local function __array16( x, family ) + local list + + if type(x) == "number" then + list = { bit.rshift(x, 16), bit.band(x, 0xFFFF) } + + elseif type(x) == "string" then + if x:find(":") then x = IPv6(x) else x = IPv4(x) end + if x then + assert( x[1] == family, "Can't mix IPv4 and IPv6 addresses" ) + list = { unpack(x[2]) } + end + + elseif type(x) == "table" and type(x[2]) == "table" then + assert( x[1] == family, "Can't mix IPv4 and IPv6 addresses" ) + list = { unpack(x[2]) } + + elseif type(x) == "table" then + list = x + end + + assert( list, "Invalid operand" ) + + return list +end + +local function __mask16(bits) + return bit.lshift( bit.rshift( 0xFFFF, 16 - bits % 16 ), 16 - bits % 16 ) +end + +local function __not16(bits) + return bit.band( bit.bnot( __mask16(bits) ), 0xFFFF ) +end + +local function __maxlen(family) + return ( family == FAMILY_INET4 ) and 32 or 128 +end + +local function __sublen(family) + return ( family == FAMILY_INET4 ) and 30 or 127 +end + + +--- Convert given short value to network byte order on little endian hosts +-- @param x Unsigned integer value between 0x0000 and 0xFFFF +-- @return Byte-swapped value +-- @see htonl +-- @see ntohs +function htons(x) + if LITTLE_ENDIAN then + return bit.bor( + bit.rshift( x, 8 ), + bit.band( bit.lshift( x, 8 ), 0xFF00 ) + ) + else + return x + end +end + +--- Convert given long value to network byte order on little endian hosts +-- @param x Unsigned integer value between 0x00000000 and 0xFFFFFFFF +-- @return Byte-swapped value +-- @see htons +-- @see ntohl +function htonl(x) + if LITTLE_ENDIAN then + return bit.bor( + bit.lshift( htons( bit.band( x, 0xFFFF ) ), 16 ), + htons( bit.rshift( x, 16 ) ) + ) + else + return x + end +end + +--- Convert given short value to host byte order on little endian hosts +-- @class function +-- @name ntohs +-- @param x Unsigned integer value between 0x0000 and 0xFFFF +-- @return Byte-swapped value +-- @see htonl +-- @see ntohs +ntohs = htons + +--- Convert given short value to host byte order on little endian hosts +-- @class function +-- @name ntohl +-- @param x Unsigned integer value between 0x00000000 and 0xFFFFFFFF +-- @return Byte-swapped value +-- @see htons +-- @see ntohl +ntohl = htonl + + +--- Parse given IPv4 address in dotted quad or CIDR notation. If an optional +-- netmask is given as second argument and the IP address is encoded in CIDR +-- notation then the netmask parameter takes precedence. If neither a CIDR +-- encoded prefix nor a netmask parameter is given, then a prefix length of +-- 32 bit is assumed. +-- @param address IPv4 address in dotted quad or CIDR notation +-- @param netmask IPv4 netmask in dotted quad notation (optional) +-- @return luci.ip.cidr instance or nil if given address was invalid +-- @see IPv6 +-- @see Hex +function IPv4(address, netmask) + address = address or "0.0.0.0/0" + + local obj = __bless({ FAMILY_INET4 }) + + local data = {} + local prefix = address:match("/(.+)") + address = address:gsub("/.+","") + + if netmask then + prefix = obj:prefix(netmask) + elseif prefix then + prefix = tonumber(prefix) + if not prefix or prefix < 0 or prefix > 32 then return nil end + else + prefix = 32 + end + + local b1, b2, b3, b4 = address:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$") + + b1 = tonumber(b1) + b2 = tonumber(b2) + b3 = tonumber(b3) + b4 = tonumber(b4) + + if b1 and b1 <= 255 and + b2 and b2 <= 255 and + b3 and b3 <= 255 and + b4 and b4 <= 255 and + prefix + then + table.insert(obj, { b1 * 256 + b2, b3 * 256 + b4 }) + table.insert(obj, prefix) + return obj + end +end + +--- Parse given IPv6 address in full, compressed, mixed or CIDR notation. +-- If an optional netmask is given as second argument and the IP address is +-- encoded in CIDR notation then the netmask parameter takes precedence. +-- If neither a CIDR encoded prefix nor a netmask parameter is given, then a +-- prefix length of 128 bit is assumed. +-- @param address IPv6 address in full/compressed/mixed or CIDR notation +-- @param netmask IPv6 netmask in full/compressed/mixed notation (optional) +-- @return luci.ip.cidr instance or nil if given address was invalid +-- @see IPv4 +-- @see Hex +function IPv6(address, netmask) + address = address or "::/0" + + local obj = __bless({ FAMILY_INET6 }) + + local data = {} + local prefix = address:match("/(.+)") + address = address:gsub("/.+","") + + if netmask then + prefix = obj:prefix(netmask) + elseif prefix then + prefix = tonumber(prefix) + if not prefix or prefix < 0 or prefix > 128 then return nil end + else + prefix = 128 + end + + local borderl = address:sub(1, 1) == ":" and 2 or 1 + local borderh, zeroh, chunk, block + + if #address > 45 then return nil end + + repeat + borderh = address:find(":", borderl, true) + if not borderh then break end + + block = tonumber(address:sub(borderl, borderh - 1), 16) + if block and block <= 0xFFFF then + data[#data+1] = block + else + if zeroh or borderh - borderl > 1 then return nil end + zeroh = #data + 1 + end + + borderl = borderh + 1 + until #data == 7 + + chunk = address:sub(borderl) + if #chunk > 0 and #chunk <= 4 then + block = tonumber(chunk, 16) + if not block or block > 0xFFFF then return nil end + + data[#data+1] = block + elseif #chunk > 4 then + if #data == 7 or #chunk > 15 then return nil end + borderl = 1 + for i=1, 4 do + borderh = chunk:find(".", borderl, true) + if not borderh and i < 4 then return nil end + borderh = borderh and borderh - 1 + + block = tonumber(chunk:sub(borderl, borderh)) + if not block or block > 255 then return nil end + + if i == 1 or i == 3 then + data[#data+1] = block * 256 + else + data[#data] = data[#data] + block + end + + borderl = borderh and borderh + 2 + end + end + + if zeroh then + if #data == 8 then return nil end + while #data < 8 do + table.insert(data, zeroh, 0) + end + end + + if #data == 8 and prefix then + table.insert(obj, data) + table.insert(obj, prefix) + return obj + end +end + +--- Transform given hex-encoded value to luci.ip.cidr instance of specified +-- address family. +-- @param hex String containing hex encoded value +-- @param prefix Prefix length of CIDR instance (optional, default is 32/128) +-- @param family Address family, either luci.ip.FAMILY_INET4 or FAMILY_INET6 +-- @param swap Bool indicating whether to swap byteorder on low endian host +-- @return luci.ip.cidr instance or nil if given value was invalid +-- @see IPv4 +-- @see IPv6 +function Hex( hex, prefix, family, swap ) + family = ( family ~= nil ) and family or FAMILY_INET4 + swap = ( swap == nil ) and true or swap + prefix = prefix or __maxlen(family) + + local len = __maxlen(family) + local tmp = "" + local data = { } + + for i = 1, (len/4) - #hex do tmp = tmp .. '0' end + + if swap and LITTLE_ENDIAN then + for i = #hex, 1, -2 do tmp = tmp .. hex:sub( i - 1, i ) end + else + tmp = tmp .. hex + end + + hex = tmp + + for i = 1, ( len / 4 ), 4 do + local n = tonumber( hex:sub( i, i+3 ), 16 ) + if n then + data[#data+1] = n + else + return nil + end + end + + return __bless({ family, data, prefix }) +end + + +--- LuCI IP Library / CIDR instances +-- @class module +-- @cstyle instance +-- @name luci.ip.cidr +cidr = luci.util.class() + +--- Test whether the instance is a IPv4 address. +-- @return Boolean indicating a IPv4 address type +-- @see cidr.is6 +function cidr.is4( self ) + return self[1] == FAMILY_INET4 +end + +--- Test whether the instance is a IPv6 address. +-- @return Boolean indicating a IPv6 address type +-- @see cidr.is4 +function cidr.is6( self ) + return self[1] == FAMILY_INET6 +end + +--- Return a corresponding string representation of the instance. +-- If the prefix length is lower then the maximum possible prefix length for the +-- corresponding address type then the address is returned in CIDR notation, +-- otherwise the prefix will be left out. +function cidr.string( self ) + local str + if self:is4() then + str = string.format( + "%d.%d.%d.%d", + bit.rshift(self[2][1], 8), bit.band(self[2][1], 0xFF), + bit.rshift(self[2][2], 8), bit.band(self[2][2], 0xFF) + ) + if self[3] < 32 then + str = str .. "/" .. self[3] + end + elseif self:is6() then + str = string.format( "%X:%X:%X:%X:%X:%X:%X:%X", unpack(self[2]) ) + if self[3] < 128 then + str = str .. "/" .. self[3] + end + end + return str +end + +--- Test whether the value of the instance is lower then the given address. +-- This function will throw an exception if the given address has a different +-- family than this instance. +-- @param addr A luci.ip.cidr instance to compare against +-- @return Boolean indicating whether this instance is lower +-- @see cidr.higher +-- @see cidr.equal +function cidr.lower( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + for i = 1, #self[2] do + if self[2][i] ~= addr[2][i] then + return self[2][i] < addr[2][i] + end + end + return false +end + +--- Test whether the value of the instance is higher then the given address. +-- This function will throw an exception if the given address has a different +-- family than this instance. +-- @param addr A luci.ip.cidr instance to compare against +-- @return Boolean indicating whether this instance is higher +-- @see cidr.lower +-- @see cidr.equal +function cidr.higher( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + for i = 1, #self[2] do + if self[2][i] ~= addr[2][i] then + return self[2][i] > addr[2][i] + end + end + return false +end + +--- Test whether the value of the instance is equal to the given address. +-- This function will throw an exception if the given address is a different +-- family than this instance. +-- @param addr A luci.ip.cidr instance to compare against +-- @return Boolean indicating whether this instance is equal +-- @see cidr.lower +-- @see cidr.higher +function cidr.equal( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + for i = 1, #self[2] do + if self[2][i] ~= addr[2][i] then + return false + end + end + return true +end + +--- Return the prefix length of this CIDR instance. +-- @param mask Override instance prefix with given netmask (optional) +-- @return Prefix length in bit +function cidr.prefix( self, mask ) + local prefix = self[3] + + if mask then + prefix = 0 + + local stop = false + local obj = type(mask) ~= "table" + and ( self:is4() and IPv4(mask) or IPv6(mask) ) or mask + + if not obj then return nil end + + for _, word in ipairs(obj[2]) do + if word == 0xFFFF then + prefix = prefix + 16 + else + local bitmask = bit.lshift(1, 15) + while bit.band(word, bitmask) == bitmask do + prefix = prefix + 1 + bitmask = bit.lshift(1, 15 - (prefix % 16)) + end + + break + end + end + end + + return prefix +end + +--- Return a corresponding CIDR representing the network address of this +-- instance. +-- @param bits Override prefix length of this instance (optional) +-- @return CIDR instance containing the network address +-- @see cidr.host +-- @see cidr.broadcast +-- @see cidr.mask +function cidr.network( self, bits ) + local data = { } + bits = bits or self[3] + + for i = 1, math.floor( bits / 16 ) do + data[#data+1] = self[2][i] + end + + if #data < #self[2] then + data[#data+1] = bit.band( self[2][1+#data], __mask16(bits) ) + + for i = #data + 1, #self[2] do + data[#data+1] = 0 + end + end + + return __bless({ self[1], data, __maxlen(self[1]) }) +end + +--- Return a corresponding CIDR representing the host address of this +-- instance. This is intended to extract the host address from larger subnet. +-- @return CIDR instance containing the network address +-- @see cidr.network +-- @see cidr.broadcast +-- @see cidr.mask +function cidr.host( self ) + return __bless({ self[1], self[2], __maxlen(self[1]) }) +end + +--- Return a corresponding CIDR representing the netmask of this instance. +-- @param bits Override prefix length of this instance (optional) +-- @return CIDR instance containing the netmask +-- @see cidr.network +-- @see cidr.host +-- @see cidr.broadcast +function cidr.mask( self, bits ) + local data = { } + bits = bits or self[3] + + for i = 1, math.floor( bits / 16 ) do + data[#data+1] = 0xFFFF + end + + if #data < #self[2] then + data[#data+1] = __mask16(bits) + + for i = #data + 1, #self[2] do + data[#data+1] = 0 + end + end + + return __bless({ self[1], data, __maxlen(self[1]) }) +end + +--- Return CIDR containing the broadcast address of this instance. +-- @return CIDR instance containing the netmask, always nil for IPv6 +-- @see cidr.network +-- @see cidr.host +-- @see cidr.mask +function cidr.broadcast( self ) + -- IPv6 has no broadcast addresses (XXX: assert() instead?) + if self[1] == FAMILY_INET4 then + local data = { unpack(self[2]) } + local offset = math.floor( self[3] / 16 ) + 1 + + if offset <= #data then + data[offset] = bit.bor( data[offset], __not16(self[3]) ) + for i = offset + 1, #data do data[i] = 0xFFFF end + + return __bless({ self[1], data, __maxlen(self[1]) }) + end + end +end + +--- Test whether this instance fully contains the given CIDR instance. +-- @param addr CIDR instance to test against +-- @return Boolean indicating whether this instance contains the given CIDR +function cidr.contains( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + + if self:prefix() <= addr:prefix() then + return self:network() == addr:network(self:prefix()) + end + + return false +end + +--- Add specified amount of hosts to this instance. +-- @param amount Number of hosts to add to this instance +-- @param inplace Boolen indicating whether to alter values inplace (optional) +-- @return CIDR representing the new address or nil on overflow error +-- @see cidr.sub +function cidr.add( self, amount, inplace ) + local data = { unpack(self[2]) } + local shorts = __array16( amount, self[1] ) + + for pos = #data, 1, -1 do + local add = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0 + if ( data[pos] + add ) > 0xFFFF then + data[pos] = ( data[pos] + add ) % 0xFFFF + if pos > 1 then + data[pos-1] = data[pos-1] + ( add - data[pos] ) + else + return nil + end + else + data[pos] = data[pos] + add + end + end + + if inplace then + self[2] = data + return self + else + return __bless({ self[1], data, self[3] }) + end +end + +--- Substract specified amount of hosts from this instance. +-- @param amount Number of hosts to substract from this instance +-- @param inplace Boolen indicating whether to alter values inplace (optional) +-- @return CIDR representing the new address or nil on underflow error +-- @see cidr.add +function cidr.sub( self, amount, inplace ) + local data = { unpack(self[2]) } + local shorts = __array16( amount, self[1] ) + + for pos = #data, 1, -1 do + local sub = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0 + if ( data[pos] - sub ) < 0 then + data[pos] = ( sub - data[pos] ) % 0xFFFF + if pos > 1 then + data[pos-1] = data[pos-1] - ( sub + data[pos] ) + else + return nil + end + else + data[pos] = data[pos] - sub + end + end + + if inplace then + self[2] = data + return self + else + return __bless({ self[1], data, self[3] }) + end +end + +--- Return CIDR containing the lowest available host address within this subnet. +-- @return CIDR containing the host address, nil if subnet is too small +-- @see cidr.maxhost +function cidr.minhost( self ) + if self[3] <= __sublen(self[1]) then + -- 1st is Network Address in IPv4 and Subnet-Router Anycast Adresse in IPv6 + return self:network():add(1, true) + end +end + +--- Return CIDR containing the highest available host address within the subnet. +-- @return CIDR containing the host address, nil if subnet is too small +-- @see cidr.minhost +function cidr.maxhost( self ) + if self[3] <= __sublen(self[1]) then + local data = { unpack(self[2]) } + local offset = math.floor( self[3] / 16 ) + 1 + + data[offset] = bit.bor( data[offset], __not16(self[3]) ) + for i = offset + 1, #data do data[i] = 0xFFFF end + data = __bless({ self[1], data, __maxlen(self[1]) }) + + -- Last address in reserved for Broadcast Address in IPv4 + if data[1] == FAMILY_INET4 then data:sub(1, true) end + + return data + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/json.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/json.lua new file mode 100644 index 0000000..7a5bff1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/json.lua @@ -0,0 +1,538 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: json.lua 3997 2009-01-04 20:09:13Z Cyrus $ + +Decoder: + Info: + null will be decoded to luci.json.null if first parameter of Decoder() is true + + Example: + decoder = luci.json.Decoder() + luci.ltn12.pump.all(luci.ltn12.source.string("decodableJSON"), decoder:sink()) + luci.util.dumptable(decoder:get()) + + Known issues: + does not support unicode conversion \uXXYY with XX != 00 will be ignored + + +Encoder: + Info: + Accepts numbers, strings, nil, booleans as they are + Accepts luci.json.null as replacement for nil + Accepts full associative and full numerically indexed tables + Mixed tables will loose their associative values during conversion + Iterator functions will be encoded as an array of their return values + Non-iterator functions will probably corrupt the encoder + + Example: + encoder = luci.json.Encoder(encodableData) + luci.ltn12.pump.all(encoder:source(), luci.ltn12.sink.file(io.open("someFile", w))) +]]-- + +local util = require "luci.util" +local table = require "table" +local string = require "string" +local coroutine = require "coroutine" + +local assert = assert +local tonumber = tonumber +local tostring = tostring +local error = error +local type = type +local pairs = pairs +local ipairs = ipairs +local next = next + +local getmetatable = getmetatable + +--- LuCI JSON-Library +-- @cstyle instance +module "luci.json" + +--- Null replacement function +-- @return null +function null() + return null +end + +--- Create a new JSON-Encoder. +-- @class function +-- @name Encoder +-- @param data Lua-Object to be encoded. +-- @param buffersize Blocksize of returned data source. +-- @param fastescape Use non-standard escaping (don't escape control chars) +-- @return JSON-Encoder +Encoder = util.class() + +function Encoder.__init__(self, data, buffersize, fastescape) + self.data = data + self.buffersize = buffersize or 512 + self.buffer = "" + self.fastescape = fastescape + + getmetatable(self).__call = Encoder.source +end + +--- Create an LTN12 source providing the encoded JSON-Data. +-- @return LTN12 source +function Encoder.source(self) + local source = coroutine.create(self.dispatch) + return function() + local res, data = coroutine.resume(source, self, self.data, true) + if res then + return data + else + return nil, data + end + end +end + +function Encoder.dispatch(self, data, start) + local parser = self.parsers[type(data)] + + parser(self, data) + + if start then + if #self.buffer > 0 then + coroutine.yield(self.buffer) + end + + coroutine.yield() + end +end + +function Encoder.put(self, chunk) + if self.buffersize < 2 then + corountine.yield(chunk) + else + if #self.buffer + #chunk > self.buffersize then + local written = 0 + local fbuffer = self.buffersize - #self.buffer + + coroutine.yield(self.buffer .. chunk:sub(written + 1, fbuffer)) + written = fbuffer + + while #chunk - written > self.buffersize do + fbuffer = written + self.buffersize + coroutine.yield(chunk:sub(written + 1, fbuffer)) + written = fbuffer + end + + self.buffer = chunk:sub(written + 1) + else + self.buffer = self.buffer .. chunk + end + end +end + +function Encoder.parse_nil(self) + self:put("null") +end + +function Encoder.parse_bool(self, obj) + self:put(obj and "true" or "false") +end + +function Encoder.parse_number(self, obj) + self:put(tostring(obj)) +end + +function Encoder.parse_string(self, obj) + if self.fastescape then + self:put('"' .. obj:gsub('\\', '\\\\'):gsub('"', '\\"') .. '"') + else + self:put('"' .. + obj:gsub('[%c\\"]', + function(char) + return '\\u00%02x' % char:byte() + end + ) + .. '"') + end +end + +function Encoder.parse_iter(self, obj) + if obj == null then + return self:put("null") + end + + if type(obj) == "table" and (#obj == 0 and next(obj)) then + self:put("{") + local first = true + + for key, entry in pairs(obj) do + first = first or self:put(",") + first = first and false + self:parse_string(tostring(key)) + self:put(":") + self:dispatch(entry) + end + + self:put("}") + else + self:put("[") + local first = true + + if type(obj) == "table" then + for i=1, #obj do + first = first or self:put(",") + first = first and nil + self:dispatch(obj[i]) + end + else + for entry in obj do + first = first or self:put(",") + first = first and nil + self:dispatch(entry) + end + end + + self:put("]") + end +end + +Encoder.parsers = { + ['nil'] = Encoder.parse_nil, + ['table'] = Encoder.parse_iter, + ['number'] = Encoder.parse_number, + ['string'] = Encoder.parse_string, + ['boolean'] = Encoder.parse_bool, + ['function'] = Encoder.parse_iter +} + + +--- Create a new JSON-Decoder. +-- @class function +-- @name Decoder +-- @param customnull Use luci.json.null instead of nil for decoding null +-- @return JSON-Decoder +Decoder = util.class() + +function Decoder.__init__(self, customnull) + self.cnull = customnull + getmetatable(self).__call = Decoder.sink +end + +--- Create an LTN12 sink from the decoder object which accepts the JSON-Data. +-- @return LTN12 sink +function Decoder.sink(self) + local sink = coroutine.create(self.dispatch) + return function(...) + return coroutine.resume(sink, self, ...) + end +end + + +--- Get the decoded data packets after the rawdata has been sent to the sink. +-- @return Decoded data +function Decoder.get(self) + return self.data +end + +function Decoder.dispatch(self, chunk, src_err, strict) + local robject, object + local oset = false + + while chunk do + while chunk and #chunk < 1 do + chunk = self:fetch() + end + + assert(not strict or chunk, "Unexpected EOS") + if not chunk then break end + + local char = chunk:sub(1, 1) + local parser = self.parsers[char] + or (char:match("%s") and self.parse_space) + or (char:match("[0-9-]") and self.parse_number) + or error("Unexpected char '%s'" % char) + + chunk, robject = parser(self, chunk) + + if parser ~= self.parse_space then + assert(not oset, "Scope violation: Too many objects") + object = robject + oset = true + + if strict then + return chunk, object + end + end + end + + assert(not src_err, src_err) + assert(oset, "Unexpected EOS") + + self.data = object +end + + +function Decoder.fetch(self) + local tself, chunk, src_err = coroutine.yield() + assert(chunk or not src_err, src_err) + return chunk +end + + +function Decoder.fetch_atleast(self, chunk, bytes) + while #chunk < bytes do + local nchunk = self:fetch() + assert(nchunk, "Unexpected EOS") + chunk = chunk .. nchunk + end + + return chunk +end + + +function Decoder.fetch_until(self, chunk, pattern) + local start = chunk:find(pattern) + + while not start do + local nchunk = self:fetch() + assert(nchunk, "Unexpected EOS") + chunk = chunk .. nchunk + start = chunk:find(pattern) + end + + return chunk, start +end + + +function Decoder.parse_space(self, chunk) + local start = chunk:find("[^%s]") + + while not start do + chunk = self:fetch() + if not chunk then + return nil + end + start = chunk:find("[^%s]") + end + + return chunk:sub(start) +end + + +function Decoder.parse_literal(self, chunk, literal, value) + chunk = self:fetch_atleast(chunk, #literal) + assert(chunk:sub(1, #literal) == literal, "Invalid character sequence") + return chunk:sub(#literal + 1), value +end + + +function Decoder.parse_null(self, chunk) + return self:parse_literal(chunk, "null", self.cnull and null) +end + + +function Decoder.parse_true(self, chunk) + return self:parse_literal(chunk, "true", true) +end + + +function Decoder.parse_false(self, chunk) + return self:parse_literal(chunk, "false", false) +end + + +function Decoder.parse_number(self, chunk) + local chunk, start = self:fetch_until(chunk, "[^0-9eE.+-]") + local number = tonumber(chunk:sub(1, start - 1)) + assert(number, "Invalid number specification") + return chunk:sub(start), number +end + + +function Decoder.parse_string(self, chunk) + local str = "" + local object = nil + assert(chunk:sub(1, 1) == '"', 'Expected "') + chunk = chunk:sub(2) + + while true do + local spos = chunk:find('[\\"]') + if spos then + str = str .. chunk:sub(1, spos - 1) + + local char = chunk:sub(spos, spos) + if char == '"' then -- String end + chunk = chunk:sub(spos + 1) + break + elseif char == "\\" then -- Escape sequence + chunk, object = self:parse_escape(chunk:sub(spos)) + str = str .. object + end + else + str = str .. chunk + chunk = self:fetch() + assert(chunk, "Unexpected EOS while parsing a string") + end + end + + return chunk, str +end + + +function Decoder.parse_escape(self, chunk) + local str = "" + chunk = self:fetch_atleast(chunk:sub(2), 1) + local char = chunk:sub(1, 1) + chunk = chunk:sub(2) + + if char == '"' then + return chunk, '"' + elseif char == "\\" then + return chunk, "\\" + elseif char == "u" then + chunk = self:fetch_atleast(chunk, 4) + local s1, s2 = chunk:sub(1, 2), chunk:sub(3, 4) + s1, s2 = tonumber(s1, 16), tonumber(s2, 16) + assert(s1 and s2, "Invalid Unicode character") + + -- ToDo: Unicode support + return chunk:sub(5), s1 == 0 and string.char(s2) or "" + elseif char == "/" then + return chunk, "/" + elseif char == "b" then + return chunk, "\b" + elseif char == "f" then + return chunk, "\f" + elseif char == "n" then + return chunk, "\n" + elseif char == "r" then + return chunk, "\r" + elseif char == "t" then + return chunk, "\t" + else + error("Unexpected escaping sequence '\\%s'" % char) + end +end + + +function Decoder.parse_array(self, chunk) + chunk = chunk:sub(2) + local array = {} + local nextp = 1 + + local chunk, object = self:parse_delimiter(chunk, "%]") + + if object then + return chunk, array + end + + repeat + chunk, object = self:dispatch(chunk, nil, true) + table.insert(array, nextp, object) + nextp = nextp + 1 + + chunk, object = self:parse_delimiter(chunk, ",%]") + assert(object, "Delimiter expected") + until object == "]" + + return chunk, array +end + + +function Decoder.parse_object(self, chunk) + chunk = chunk:sub(2) + local array = {} + local name + + local chunk, object = self:parse_delimiter(chunk, "}") + + if object then + return chunk, array + end + + repeat + chunk = self:parse_space(chunk) + assert(chunk, "Unexpected EOS") + + chunk, name = self:parse_string(chunk) + + chunk, object = self:parse_delimiter(chunk, ":") + assert(object, "Separator expected") + + chunk, object = self:dispatch(chunk, nil, true) + array[name] = object + + chunk, object = self:parse_delimiter(chunk, ",}") + assert(object, "Delimiter expected") + until object == "}" + + return chunk, array +end + + +function Decoder.parse_delimiter(self, chunk, delimiter) + while true do + chunk = self:fetch_atleast(chunk, 1) + local char = chunk:sub(1, 1) + if char:match("%s") then + chunk = self:parse_space(chunk) + assert(chunk, "Unexpected EOS") + elseif char:match("[%s]" % delimiter) then + return chunk:sub(2), char + else + return chunk, nil + end + end +end + + +Decoder.parsers = { + ['"'] = Decoder.parse_string, + ['t'] = Decoder.parse_true, + ['f'] = Decoder.parse_false, + ['n'] = Decoder.parse_null, + ['['] = Decoder.parse_array, + ['{'] = Decoder.parse_object +} + + +--- Create a new Active JSON-Decoder. +-- @class function +-- @name ActiveDecoder +-- @param customnull Use luci.json.null instead of nil for decoding null +-- @return Active JSON-Decoder +ActiveDecoder = util.class(Decoder) + +function ActiveDecoder.__init__(self, source, customnull) + Decoder.__init__(self, customnull) + self.source = source + self.chunk = nil + getmetatable(self).__call = self.get +end + + +--- Fetches one JSON-object from given source +-- @return Decoded object +function ActiveDecoder.get(self) + local chunk, src_err, object + if not self.chunk then + chunk, src_err = self.source() + else + chunk = self.chunk + end + + self.chunk, object = self:dispatch(chunk, src_err, true) + return object +end + + +function ActiveDecoder.fetch(self) + local chunk, src_err = self.source() + assert(chunk or not src_err, src_err) + return chunk +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpc.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpc.lua new file mode 100644 index 0000000..177383d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpc.lua @@ -0,0 +1,94 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: jsonrpc.lua 3000 2008-08-29 12:27:54Z Cyrus $ +]]-- + +module("luci.jsonrpc", package.seeall) +require "luci.json" + +function resolve(mod, method) + local path = luci.util.split(method, ".") + + for j=1, #path-1 do + if not type(mod) == "table" then + break + end + mod = rawget(mod, path[j]) + if not mod then + break + end + end + mod = type(mod) == "table" and rawget(mod, path[#path]) or nil + if type(mod) == "function" then + return mod + end +end + +function handle(tbl, rawsource, ...) + local decoder = luci.json.Decoder() + local stat = luci.ltn12.pump.all(rawsource, decoder:sink()) + local json = decoder:get() + local response + local success = false + + if stat then + if type(json.method) == "string" + and (not json.params or type(json.params) == "table") then + local method = resolve(tbl, json.method) + if method then + response = reply(json.jsonrpc, json.id, + proxy(method, unpack(json.params or {}))) + else + response = reply(json.jsonrpc, json.id, + nil, {code=-32601, message="Method not found."}) + end + else + response = reply(json.jsonrpc, json.id, + nil, {code=-32600, message="Invalid request."}) + end + else + response = reply("2.0", nil, + nil, {code=-32700, message="Parse error."}) + end + + return luci.json.Encoder(response, ...):source() +end + +function reply(jsonrpc, id, res, err) + require "luci.json" + id = id or luci.json.null + + -- 1.0 compatibility + if jsonrpc ~= "2.0" then + jsonrpc = nil + res = res or luci.json.null + err = err or luci.json.null + end + + return {id=id, result=res, error=err, jsonrpc=jsonrpc} +end + +function proxy(method, ...) + local res = {luci.util.copcall(method, ...)} + local stat = table.remove(res, 1) + + if not stat then + return nil, {code=-32602, message="Invalid params.", data=table.remove(res, 1)} + else + if #res <= 1 then + return res[1] or luci.json.null + else + return res + end + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uci.lua new file mode 100644 index 0000000..7cd7f8e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uci.lua @@ -0,0 +1,94 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: uci.lua 3132 2008-09-05 19:27:19Z Cyrus $ +]]-- + +local uci = require "luci.model.uci".cursor() +local ucis = require "luci.model.uci".cursor_state() +local table = require "table" + + +module "luci.jsonrpcbind.uci" +_M, _PACKAGE, _NAME = nil, nil, nil + +function add(config, ...) + uci:load(config) + local stat = uci:add(config, ...) + return uci:save(config) and stat +end + +function apply(config) + return uci:apply(config) +end + +function changes(...) + return uci:changes(...) +end + +function commit(config) + return uci:load(config) and uci:commit(config) +end + +function delete(config, ...) + uci:load(config) + return uci:delete(config, ...) and uci:save(config) +end + +function delete_all(config, ...) + uci:load(config) + return uci:delete_all(config, ...) and uci:save(config) +end + +function foreach(config, stype) + uci:load(config) + local sections = {} + + return uci:foreach(config, stype, function(section) + table.insert(sections, section) + end) and sections +end + +function get(config, ...) + uci:load(config) + return uci:get(config, ...) +end + +function get_all(config, ...) + uci:load(config) + return uci:get_all(config, ...) +end + +function get_state(config, ...) + ucis:load(config) + return ucis:get(config, ...) +end + +function revert(config) + return uci:load(config) and uci:revert(config) +end + +function section(config, ...) + uci:load(config) + return uci:section(config, ...) and uci:save(config) +end + +function set(config, ...) + uci:load(config) + return uci:set(config, ...) and uci:save(config) +end + +function tset(config, ...) + uci:load(config) + return uci:tset(config, ...) and uci:save(config) +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uvl.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uvl.lua new file mode 100644 index 0000000..b06c3e2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/jsonrpcbind/uvl.lua @@ -0,0 +1,41 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: uvl.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local uvl = require "luci.uvl".UVL() +local table = require "table" + +module "luci.jsonrpcbind.uvl" +_M, _PACKAGE, _NAME = nil, nil, nil + + +function get_scheme(...) + return uvl:get_scheme(...) +end + +function validate(...) + return {uvl:validate(...)} +end + +function validate_config(...) + return {uvl:validate_config(...)} +end + +function validate_section(...) + return {uvl:validate_section(...)} +end + +function validate_option(...) + return {uvl:validate_option(...)} +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk.lua new file mode 100644 index 0000000..7117c75 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk.lua @@ -0,0 +1,41 @@ +module("luci.lpk", package.seeall) +require("luci.lpk.util") +require("luci.lpk.core") + +__appname__ = "LuCI »lpk« Package Manager" +__version__ = "0.1" +__authors__ = "Steven Barth, Jo-Philipp Wich" +__cpyrght__ = string.format("Copyright (c) 2008 %s", __authors__) + + +options, arguments = luci.lpk.util.getopt(arg) +config = luci.util.dtable() +machine = luci.lpk.core.Machine() + +local cfgdump = loadfile("/etc/lpk.conf") +if cfgdump then + setfenv(cfgdump, config) + pcall(cfgdump) +end + +if #arguments < 1 then + luci.lpk.util.splash() +else + local task, error = machine:task(table.remove(arguments, 1), + unpack(arguments)) + + if task then + local stat, error = task:perform() + if not stat then + luci.util.perror(error or task.register.errstr or "Unknown Error") + os.exit(task.register.error or 1) + end + else + luci.util.perror((error or "Unknown Error") .. "\n") + luci.lpk.util.splash() + os.exit(1) + end +end + + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core.lua new file mode 100644 index 0000000..97de4fa --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core.lua @@ -0,0 +1,107 @@ +module("luci.lpk.core", package.seeall) +require("luci.util") + +Task = luci.util.class() + +function Task.__init__(self, machine, register, start) + self.machine = machine + + -- The queue that has to be processed + self.work = {start} + + -- The queue that has to be processed in case of rollback + self.done = {} + + -- The Task register + self.register = register +end + +function Task.rollback(self) + if #self.done < 1 then + return false + end + + local state = table.remove(self.done) + if not state.rollback then + return true + end + + local ret, err = pcall(state.rollback, state, self.register) + + if ret then + return true + else + return false, err + end +end + +function Task.step(self) + local state = table.remove(self.work) + local ret, next = pcall(state.process, self.register) + + if ret then + if next then + local nstate = self.machine:state(next) + if nstate then + table.insert(self.work, state) + table.insert(self.work, nstate) + else + self.register.error = 2 + self.register.errstr = "Unknown state: " .. next + return false + end + else + table.insert(self.done, state) + end + + return #self.work > 0 + else + self.register.error = next + return false + end +end + +function Task.perform(self) + while self:step() do + end + + if not self.register.error then + return true + else + local stat, err + repeat + stat, err = self:rollback() + until not stat + + if err then + self.register.errstr = err + self.register.error = 2 + end + + return false + end +end + + +Machine = luci.util.class() + +function Machine.__init__(self, namespace) + self.namespace = namespace or _NAME +end + +function Machine.state(self, name) + local ret, state = pcall(require, self.namespace .. "." .. name) + return ret and state +end + +function Machine.task(self, name, ...) + local start = self:state(name) + + if type(start) ~= "table" or not start.entry then + return false, "No such command: " .. name + end + + local register = {} + + return start.entry(register, ...) and Task(self, register, start) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/download.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/download.lua new file mode 100644 index 0000000..7b30647 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/download.lua @@ -0,0 +1 @@ +module("luci.lpk.core.download", package.seeall) diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/install.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/install.lua new file mode 100644 index 0000000..434f618 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/install.lua @@ -0,0 +1,16 @@ +module("luci.lpk.core.install", package.seeall) + +function entry(register, ...) + print("Requested install of " .. table.concat(arg, ", ")) + return true +end + +function process(register) + register.sometext = "Test" + if not register.retrieved then + print("Step down to retrieve") + return "retrieve" + else + print("Coming up again") + end +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/resolve.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/resolve.lua new file mode 100644 index 0000000..e69de29 diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/retrieve.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/retrieve.lua new file mode 100644 index 0000000..6176a94 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/retrieve.lua @@ -0,0 +1,7 @@ +module("luci.lpk.core.retrieve", package.seeall) + +function process(register) + print "Now in retrieve" + print (register.sometext) + register.retrieved = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/unpack.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/core/unpack.lua new file mode 100644 index 0000000..e69de29 diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/util.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/util.lua new file mode 100644 index 0000000..95bdb96 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/lpk/util.lua @@ -0,0 +1,59 @@ +module("luci.lpk.util", package.seeall) + +function getopt( arg, options ) + options = options or "" + local tab = {} + local args = {} + for k, v in ipairs(arg) do + if v:sub(1, 2) == "--" then + local x = v:find( "=", 1, true ) + if x then + tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 ) + else + tab[ v:sub( 3 ) ] = true + end + elseif v:sub( 1, 1 ) == "-" then + local y = 2 + local l = #v + local jopt + while ( y <= l ) do + jopt = v:sub( y, y ) + if options:find( jopt, 1, true ) then + if y < l then + tab[ jopt ] = v:sub( y+1 ) + y = l + else + tab[ jopt ] = arg[ k + 1 ] + arg[ k + 1 ] = "" + end + else + tab[ jopt ] = true + end + y = y + 1 + end + elseif #v > 0 then + table.insert(args, v) + end + end + return tab, args +end + +function splash() + require("luci.lpk") + luci.util.perror(string.format("%s v%s\n%s", + luci.lpk.__appname__, luci.lpk.__version__, luci.lpk.__cpyrght__)) + luci.util.perror([[ + +Usage: + lpk [options] [arguments] + lpk [options] install|remove pkg1 [pkg2] [...] [pkgn] + +Commands: + install - Install packages + remove - Remove packages + purge - Remove packages and their configuration files + +Options: + --force-depends - Ignore unresolvable dependencies +]]) +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/ltn12.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/ltn12.lua new file mode 100644 index 0000000..f258cef --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/ltn12.lua @@ -0,0 +1,391 @@ +--[[ +LuaSocket 2.0.2 license +Copyright � 2004-2007 Diego Nehab + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +]]-- +--[[ + Changes made by LuCI project: + * Renamed to luci.ltn12 to avoid collisions with luasocket + * Added inline documentation +]]-- +----------------------------------------------------------------------------- +-- LTN12 - Filters, sources, sinks and pumps. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: ltn12.lua 3246 2008-09-12 07:48:36Z Cyrus $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module +----------------------------------------------------------------------------- +local string = require("string") +local table = require("table") +local base = _G + +--- Diego Nehab's LTN12 - Filters, sources, sinks and pumps. +-- See http://lua-users.org/wiki/FiltersSourcesAndSinks for design concepts +module("luci.ltn12") + +filter = {} +source = {} +sink = {} +pump = {} + +-- 2048 seems to be better in windows... +BLOCKSIZE = 2048 +_VERSION = "LTN12 1.0.1" + +----------------------------------------------------------------------------- +-- Filter stuff +----------------------------------------------------------------------------- + +--- LTN12 Filter constructors +-- @class module +-- @name luci.ltn12.filter + +--- Return a high level filter that cycles a low-level filter +-- by passing it each chunk and updating a context between calls. +-- @param low Low-level filter +-- @param ctx Context +-- @param extra Extra argument passed to the low-level filter +-- @return LTN12 filter +function filter.cycle(low, ctx, extra) + base.assert(low) + return function(chunk) + local ret + ret, ctx = low(ctx, chunk, extra) + return ret + end +end + +--- Chain a bunch of filters together. +-- (thanks to Wim Couwenberg) +-- @param ... filters to be chained +-- @return LTN12 filter +function filter.chain(...) + local n = table.getn(arg) + local top, index = 1, 1 + local retry = "" + return function(chunk) + retry = chunk and retry + while true do + if index == top then + chunk = arg[index](chunk) + if chunk == "" or top == n then return chunk + elseif chunk then index = index + 1 + else + top = top+1 + index = top + end + else + chunk = arg[index](chunk or "") + if chunk == "" then + index = index - 1 + chunk = retry + elseif chunk then + if index == n then return chunk + else index = index + 1 end + else base.error("filter returned inappropriate nil") end + end + end + end +end + +----------------------------------------------------------------------------- +-- Source stuff +----------------------------------------------------------------------------- + +--- LTN12 Source constructors +-- @class module +-- @name luci.ltn12.source + +-- create an empty source +local function empty() + return nil +end + +--- Create an empty source. +-- @return LTN12 source +function source.empty() + return empty +end + +--- Return a source that just outputs an error. +-- @param err Error object +-- @return LTN12 source +function source.error(err) + return function() + return nil, err + end +end + +--- Create a file source. +-- @param handle File handle ready for reading +-- @param io_err IO error object +-- @return LTN12 source +function source.file(handle, io_err) + if handle then + return function() + local chunk = handle:read(BLOCKSIZE) + if not chunk then handle:close() end + return chunk + end + else return source.error(io_err or "unable to open file") end +end + +--- Turn a fancy source into a simple source. +-- @param src fancy source +-- @return LTN12 source +function source.simplify(src) + base.assert(src) + return function() + local chunk, err_or_new = src() + src = err_or_new or src + if not chunk then return nil, err_or_new + else return chunk end + end +end + +--- Create a string source. +-- @param s Data +-- @return LTN12 source +function source.string(s) + if s then + local i = 1 + return function() + local chunk = string.sub(s, i, i+BLOCKSIZE-1) + i = i + BLOCKSIZE + if chunk ~= "" then return chunk + else return nil end + end + else return source.empty() end +end + +--- Creates rewindable source. +-- @param src LTN12 source to be made rewindable +-- @return LTN12 source +function source.rewind(src) + base.assert(src) + local t = {} + return function(chunk) + if not chunk then + chunk = table.remove(t) + if not chunk then return src() + else return chunk end + else + t[#t+1] = chunk + end + end +end + +--- Chain a source and a filter together. +-- @param src LTN12 source +-- @param f LTN12 filter +-- @return LTN12 source +function source.chain(src, f) + base.assert(src and f) + local last_in, last_out = "", "" + local state = "feeding" + local err + return function() + if not last_out then + base.error('source is empty!', 2) + end + while true do + if state == "feeding" then + last_in, err = src() + if err then return nil, err end + last_out = f(last_in) + if not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + elseif last_out ~= "" then + state = "eating" + if last_in then last_in = "" end + return last_out + end + else + last_out = f(last_in) + if last_out == "" then + if last_in == "" then + state = "feeding" + else + base.error('filter returned ""') + end + elseif not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + else + return last_out + end + end + end + end +end + +--- Create a source that produces contents of several sources. +-- Sources will be used one after the other, as if they were concatenated +-- (thanks to Wim Couwenberg) +-- @param ... LTN12 sources +-- @return LTN12 source +function source.cat(...) + local src = table.remove(arg, 1) + return function() + while src do + local chunk, err = src() + if chunk then return chunk end + if err then return nil, err end + src = table.remove(arg, 1) + end + end +end + +----------------------------------------------------------------------------- +-- Sink stuff +----------------------------------------------------------------------------- + +--- LTN12 sink constructors +-- @class module +-- @name luci.ltn12.sink + +--- Create a sink that stores into a table. +-- @param t output table to store into +-- @return LTN12 sink +function sink.table(t) + t = t or {} + local f = function(chunk, err) + if chunk then t[#t+1] = chunk end + return 1 + end + return f, t +end + +--- Turn a fancy sink into a simple sink. +-- @param snk fancy sink +-- @return LTN12 sink +function sink.simplify(snk) + base.assert(snk) + return function(chunk, err) + local ret, err_or_new = snk(chunk, err) + if not ret then return nil, err_or_new end + snk = err_or_new or snk + return 1 + end +end + +--- Create a file sink. +-- @param handle file handle to write to +-- @param io_err IO error +-- @return LTN12 sink +function sink.file(handle, io_err) + if handle then + return function(chunk, err) + if not chunk then + handle:close() + return 1 + else return handle:write(chunk) end + end + else return sink.error(io_err or "unable to open file") end +end + +-- creates a sink that discards data +local function null() + return 1 +end + +--- Create a sink that discards data. +-- @return LTN12 sink +function sink.null() + return null +end + +--- Create a sink that just returns an error. +-- @param err Error object +-- @return LTN12 sink +function sink.error(err) + return function() + return nil, err + end +end + +--- Chain a sink with a filter. +-- @param f LTN12 filter +-- @param snk LTN12 sink +-- @return LTN12 sink +function sink.chain(f, snk) + base.assert(f and snk) + return function(chunk, err) + if chunk ~= "" then + local filtered = f(chunk) + local done = chunk and "" + while true do + local ret, snkerr = snk(filtered, err) + if not ret then return nil, snkerr end + if filtered == done then return 1 end + filtered = f(done) + end + else return 1 end + end +end + +----------------------------------------------------------------------------- +-- Pump stuff +----------------------------------------------------------------------------- + +--- LTN12 pump functions +-- @class module +-- @name luci.ltn12.pump + +--- Pump one chunk from the source to the sink. +-- @param src LTN12 source +-- @param snk LTN12 sink +-- @return Chunk of data or nil if an error occured +-- @return Error object +function pump.step(src, snk) + local chunk, src_err = src() + local ret, snk_err = snk(chunk, src_err) + if chunk and ret then return 1 + else return nil, src_err or snk_err end +end + +--- Pump all data from a source to a sink, using a step function. +-- @param src LTN12 source +-- @param snk LTN12 sink +-- @param step step function (optional) +-- @return 1 if the operation succeeded otherwise nil +-- @return Error object +function pump.all(src, snk, step) + base.assert(src and snk) + step = step or pump.step + while true do + local ret, err = step(src, snk) + if not ret then + if err then return nil, err + else return 1 end + end + end +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_index/luci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_index/luci.lua new file mode 100644 index 0000000..bba0cf3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_index/luci.lua @@ -0,0 +1,52 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: luci.lua 4038 2009-01-14 23:48:51Z Cyrus $ +]]-- +require("luci.config") +m = Map("luci", translate("webui"), translate("a_i_luci1", + "Hier können Eigenschaften und die Funktionalität der Oberfläche angepasst werden.")) + +-- force reload of global luci config namespace to reflect the changes +function m.commit_handler(self) + package.loaded["luci.config"] = nil + require("luci.config") +end + + +c = m:section(NamedSection, "main", "core", translate("general")) + +l = c:option(ListValue, "lang", translate("language")) +l:value("auto") + +local i18ndir = luci.i18n.i18ndir .. "default." +for k, v in pairs(luci.config.languages) do + if k:sub(1, 1) ~= "." and luci.fs.access(i18ndir .. k:gsub("_", "-") .. ".lua") then + l:value(k, v) + end +end + +t = c:option(ListValue, "mediaurlbase", translate("design")) +for k, v in pairs(luci.config.themes) do + if k:sub(1, 1) ~= "." then + t:value(v, k) + end +end + +u = m:section(NamedSection, "uci_oncommit", "event", translate("a_i_ucicommit"), + translate("a_i_ucicommit1")) +u.dynamic = true + +f = m:section(NamedSection, "flash_keep", "extern", translate("a_i_keepflash"), + translate("a_i_keepflash1")) +f.dynamic = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/conntrack.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/conntrack.lua new file mode 100644 index 0000000..4daab8a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/conntrack.lua @@ -0,0 +1,49 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: conntrack.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +f = SimpleForm("conntrack", translate("a_n_conntrack"), translate("a_n_conntrack_desc")) +f.reset = false +f.submit = false + +t = f:section(Table, luci.sys.net.arptable(), "ARP") +t:option(DummyValue, "IP address", translate("ipaddress")) +t:option(DummyValue, "HW address", translate("macaddress")) +t:option(DummyValue, "Device", translate("interface")) + +t = f:section(Table, luci.sys.net.conntrack() or {}, translate("a_n_conntrack")) +l3 = t:option(DummyValue, "layer3", translate("network")) +function l3.cfgvalue(self, ...) + return DummyValue.cfgvalue(self, ...):upper() +end + + +l4 = t:option(DummyValue, "layer4", translate("protocol")) +function l4.cfgvalue(self, ...) + return DummyValue.cfgvalue(self, ...):upper() +end + +s = t:option(DummyValue, "src", translate("source")) +function s.cfgvalue(self, section) + return "%s:%s" % { self.map:get(section, "src"), + self.map:get(section, "sport") or "*" } +end + +d = t:option(DummyValue, "dst", translate("destination")) +function d.cfgvalue(self, section) + return "%s:%s" % { self.map:get(section, "dst"), + self.map:get(section, "dport") or "*" } +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcp.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcp.lua new file mode 100644 index 0000000..c366f02 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcp.lua @@ -0,0 +1,72 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dhcp.lua 3796 2008-11-18 12:29:25Z Cyrus $ +]]-- +require("luci.tools.webadmin") +require("luci.model.uci") +require("luci.util") + +m = Map("dhcp", "DHCP") + +s = m:section(TypedSection, "dhcp", "") +s.addremove = true +s.anonymous = true + +iface = s:option(ListValue, "interface", translate("interface")) +luci.tools.webadmin.cbi_add_networks(iface) + +local uci = luci.model.uci.cursor() +uci:foreach("network", "interface", + function (section) + if section[".name"] ~= "loopback" then + iface.default = iface.default or section[".name"] + s:depends("interface", section[".name"]) + end + end) + +uci:foreach("network", "alias", + function (section) + iface:value(section[".name"]) + s:depends("interface", section[".name"]) + end) + +s:option(Value, "start", translate("start")).rmempty = true + +s:option(Value, "limit", translate("limit")).rmempty = true + +s:option(Value, "leasetime").rmempty = true + +local dd = s:option(Flag, "dynamicdhcp") +dd.rmempty = false +function dd.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "1" +end + +s:option(Value, "name", translate("name")).optional = true + +ignore = s:option(Flag, "ignore") +ignore.optional = true + +s:option(Value, "netmask", translate("netmask")).optional = true + +s:option(Flag, "force").optional = true + +s:option(DynamicList, "dhcp_option").optional = true + + +for i, n in ipairs(s.children) do + if n ~= iface and n ~= ignore then + n:depends("ignore", "") + end +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcpleases.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcpleases.lua new file mode 100644 index 0000000..7a39b85 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/dhcpleases.lua @@ -0,0 +1,61 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dhcpleases.lua 2960 2008-08-26 23:00:44Z Cyrus $ +]]-- +require("luci.sys") +require("luci.tools.webadmin") +m2 = Map("luci_ethers", translate("dhcp_leases")) + +local leasefn, leasefp, leases +luci.model.uci.cursor():foreach("dhcp", "dnsmasq", + function(section) + leasefn = section.leasefile + end +) +local leasefp = leasefn and luci.fs.access(leasefn) and io.lines(leasefn) +if leasefp then + leases = {} + for lease in leasefp do + table.insert(leases, luci.util.split(lease, " ")) + end +end + +if leases then + v = m2:section(Table, leases, translate("dhcp_leases_active")) + ip = v:option(DummyValue, 3, translate("ipaddress")) + + mac = v:option(DummyValue, 2, translate("macaddress")) + + ltime = v:option(DummyValue, 1, translate("dhcp_timeremain")) + function ltime.cfgvalue(self, ...) + local value = DummyValue.cfgvalue(self, ...) + return luci.tools.webadmin.date_format( + os.difftime(tonumber(value), os.time()) + ) + end +end + +s = m2:section(TypedSection, "static_lease", translate("luci_ethers")) +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" + +mac = s:option(Value, "macaddr", translate("macaddress")) +ip = s:option(Value, "ipaddr", translate("ipaddress")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + ip:value(dataset["IP address"]) + mac:value(dataset["HW address"], + dataset["HW address"] .. " (" .. dataset["IP address"] .. ")") +end + + +return m2 diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/hosts.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/hosts.lua new file mode 100644 index 0000000..024625c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/hosts.lua @@ -0,0 +1,33 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: hosts.lua 3172 2008-09-06 23:29:58Z jow $ +]]-- + +require("luci.sys") +require("luci.util") +m = Map("luci_hosts", translate("hostnames")) + +s = m:section(TypedSection, "host", translate("hostnames_entries")) +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" + +hn = s:option(Value, "hostname", translate("hostnames_hostname")) +ip = s:option(Value, "ipaddr", translate("hostnames_address")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + ip:value( + dataset["IP address"], + "%s (%s)" %{ dataset["IP address"], dataset["HW address"] } + ) +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/ifaces.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/ifaces.lua new file mode 100644 index 0000000..ca98216 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/ifaces.lua @@ -0,0 +1,343 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ifaces.lua 4114 2009-01-25 12:16:33Z Cyrus $ +]]-- + +require("luci.tools.webadmin") +arg[1] = arg[1] or "" + +local has_3g = luci.fs.mtime("/usr/bin/gcom") +local has_pptp = luci.fs.mtime("/usr/sbin/pptp") +local has_pppd = luci.fs.mtime("/usr/sbin/pppd") +local has_pppoe = luci.fs.glob("/usr/lib/pppd/*/rp-pppoe.so") +local has_pppoa = luci.fs.glob("/usr/lib/pppd/*/pppoatm.so") + +m = Map("network", translate("interfaces"), translate("a_n_ifaces1")) + +s = m:section(NamedSection, arg[1], "interface") +s.addremove = true + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "network") + +p = s:option(ListValue, "proto", translate("protocol")) +p.override_scheme = true +p.default = "static" +p:value("static", translate("static")) +p:value("dhcp", "DHCP") +if has_pppd then p:value("ppp", "PPP") end +if has_pppoe then p:value("pppoe", "PPPoE") end +if has_pppoa then p:value("pppoa", "PPPoA") end +if has_3g then p:value("3g", "UMTS/3G") end +if has_pptp then p:value("pptp", "PPTP") end +p:value("none", translate("none")) + +if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then + p.description = translate("network_interface_prereq") +end + +br = s:option(Flag, "type", translate("a_n_i_bridge"), translate("a_n_i_bridge1")) +br.enabled = "bridge" +br.rmempty = true + +ifname = s:option(Value, "ifname", translate("interface")) +ifname.rmempty = true +for i,d in ipairs(luci.sys.net.devices()) do + if d ~= "lo" then + ifname:value(d) + end +end + +local zones = luci.tools.webadmin.network_get_zones(arg[1]) +if zones then + if #zones == 0 then + m:chain("firewall") + + fwzone = s:option(Value, "_fwzone", + translate("network_interface_fwzone"), + translate("network_interface_fwzone_desc")) + fwzone.rmempty = true + fwzone:value("", "- " .. translate("none") .. " -") + fwzone:value(arg[1]) + m.uci:load("firewall") + m.uci:foreach("firewall", "zone", + function (section) + fwzone:value(section.name) + end + ) + + function fwzone.write(self, section, value) + local zone = luci.tools.webadmin.firewall_find_zone(value) + local stat + + if not zone then + stat = m.uci:section("firewall", "zone", nil, { + name = value, + network = section + }) + else + local net = m.uci:get("firewall", zone, "network") + net = (net or value) .. " " .. section + stat = m.uci:set("firewall", zone, "network", net) + end + + if stat then + self.render = function() end + end + end + else + fwzone = s:option(DummyValue, "_fwzone", translate("zone")) + fwzone.value = table.concat(zones, ", ") + end + fwzone.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "zones") + m.uci:unload("firewall") +end + +ipaddr = s:option(Value, "ipaddr", translate("ipaddress")) +ipaddr.rmempty = true +ipaddr:depends("proto", "static") + +nm = s:option(Value, "netmask", translate("netmask")) +nm.rmempty = true +nm:depends("proto", "static") +nm:value("255.255.255.0") +nm:value("255.255.0.0") +nm:value("255.0.0.0") + +gw = s:option(Value, "gateway", translate("gateway")) +gw:depends("proto", "static") +gw.rmempty = true + +bcast = s:option(Value, "bcast", translate("broadcast")) +bcast:depends("proto", "static") +bcast.optional = true + +ip6addr = s:option(Value, "ip6addr", translate("ip6address"), translate("cidr6")) +ip6addr.optional = true +ip6addr:depends("proto", "static") + +ip6gw = s:option(Value, "ip6gw", translate("gateway6")) +ip6gw:depends("proto", "static") +ip6gw.optional = true + +dns = s:option(Value, "dns", translate("dnsserver")) +dns.optional = true + +mtu = s:option(Value, "mtu", "MTU") +mtu.optional = true +mtu.isinteger = true + +mac = s:option(Value, "macaddr", translate("macaddress")) +mac.optional = true + + +srv = s:option(Value, "server", translate("network_interface_server")) +srv:depends("proto", "pptp") +srv.rmempty = true + +if has_3g then + service = s:option(ListValue, "service", translate("network_interface_service")) + service:value("", translate("cbi_select")) + service:value("umts", "UMTS/GPRS") + service:value("cdma", "CDMA") + service:value("evdo", "EV-DO") + service:depends("proto", "3g") + service.rmempty = true + + apn = s:option(Value, "apn", translate("network_interface_apn")) + apn:depends("proto", "3g") + + pincode = s:option(Value, "pincode", + translate("network_interface_pincode"), + translate("network_interface_pincode_desc") + ) + pincode:depends("proto", "3g") +end + +if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then + user = s:option(Value, "username", translate("username")) + user.rmempty = true + user:depends("proto", "pptp") + user:depends("proto", "pppoe") + user:depends("proto", "pppoa") + user:depends("proto", "ppp") + user:depends("proto", "3g") + + pass = s:option(Value, "password", translate("password")) + pass.rmempty = true + pass.password = true + pass:depends("proto", "pptp") + pass:depends("proto", "pppoe") + pass:depends("proto", "pppoa") + pass:depends("proto", "ppp") + pass:depends("proto", "3g") + + ka = s:option(Value, "keepalive", + translate("network_interface_keepalive"), + translate("network_interface_keepalive_desc") + ) + ka.optional = true + ka:depends("proto", "pptp") + ka:depends("proto", "pppoe") + ka:depends("proto", "pppoa") + ka:depends("proto", "ppp") + ka:depends("proto", "3g") + + demand = s:option(Value, "demand", + translate("network_interface_demand"), + translate("network_interface_demand_desc") + ) + demand.optional = true + demand:depends("proto", "pptp") + demand:depends("proto", "pppoe") + demand:depends("proto", "pppoa") + demand:depends("proto", "ppp") + demand:depends("proto", "3g") +end + +if has_pppoa then + encaps = s:option(ListValue, "encaps", translate("network_interface_encaps")) + encaps.optional = false + encaps:depends("proto", "pppoa") + encaps:value("", translate("cbi_select")) + encaps:value("vc", "VC") + encaps:value("llc", "LLC") + + vpi = s:option(Value, "vpi", "VPI") + vpi.optional = false + vpi:depends("proto", "pppoa") + + vci = s:option(Value, "vci", "VCI") + vci.optional = false + vci:depends("proto", "pppoa") +end + +if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then + device = s:option(Value, "device", + translate("network_interface_device"), + translate("network_interface_device_desc") + ) + device:depends("proto", "ppp") + device:depends("proto", "3g") + + defaultroute = s:option(Flag, "defaultroute", + translate("network_interface_defaultroute"), + translate("network_interface_defaultroute_desc") + ) + defaultroute:depends("proto", "ppp") + defaultroute:depends("proto", "pppoa") + defaultroute:depends("proto", "pppoe") + defaultroute:depends("proto", "pptp") + defaultroute:depends("proto", "3g") + defaultroute.rmempty = false + function defaultroute.cfgvalue(...) + return ( AbstractValue.cfgvalue(...) or '1' ) + end + + peerdns = s:option(Flag, "peerdns", + translate("network_interface_peerdns"), + translate("network_interface_peerdns_desc") + ) + peerdns:depends("proto", "ppp") + peerdns:depends("proto", "pppoa") + peerdns:depends("proto", "pppoe") + peerdns:depends("proto", "pptp") + peerdns:depends("proto", "3g") + peerdns.rmempty = false + function peerdns.cfgvalue(...) + return ( AbstractValue.cfgvalue(...) or '1' ) + end + + ipv6 = s:option(Flag, "ipv6", translate("network_interface_ipv6") ) + ipv6:depends("proto", "ppp") + ipv6:depends("proto", "pppoa") + ipv6:depends("proto", "pppoe") + ipv6:depends("proto", "pptp") + ipv6:depends("proto", "3g") + + connect = s:option(Value, "connect", + translate("network_interface_connect"), + translate("network_interface_connect_desc") + ) + connect.optional = true + connect:depends("proto", "ppp") + connect:depends("proto", "pppoe") + connect:depends("proto", "pppoa") + connect:depends("proto", "pptp") + connect:depends("proto", "3g") + + disconnect = s:option(Value, "disconnect", + translate("network_interface_disconnect"), + translate("network_interface_disconnect_desc") + ) + disconnect.optional = true + disconnect:depends("proto", "ppp") + disconnect:depends("proto", "pppoe") + disconnect:depends("proto", "pppoa") + disconnect:depends("proto", "pptp") + disconnect:depends("proto", "3g") + + pppd_options = s:option(Value, "pppd_options", + translate("network_interface_pppd_options"), + translate("network_interface_pppd_options_desc") + ) + pppd_options.optional = true + pppd_options:depends("proto", "ppp") + pppd_options:depends("proto", "pppoa") + pppd_options:depends("proto", "pppoe") + pppd_options:depends("proto", "pptp") + pppd_options:depends("proto", "3g") + + maxwait = s:option(Value, "maxwait", + translate("network_interface_maxwait"), + translate("network_interface_maxwait_desc") + ) + maxwait.optional = true + maxwait:depends("proto", "3g") +end + +s2 = m:section(TypedSection, "alias", translate("aliases")) +s2.addremove = true + +s2:depends("interface", arg[1]) +s2.defaults.interface = arg[1] + + +s2.defaults.proto = "static" + +ipaddr = s2:option(Value, "ipaddr", translate("ipaddress")) +ipaddr.rmempty = true + +nm = s2:option(Value, "netmask", translate("netmask")) +nm.rmempty = true +nm:value("255.255.255.0") +nm:value("255.255.0.0") +nm:value("255.0.0.0") + +gw = s2:option(Value, "gateway", translate("gateway")) +gw.rmempty = true + +bcast = s2:option(Value, "bcast", translate("broadcast")) +bcast.optional = true + +ip6addr = s2:option(Value, "ip6addr", translate("ip6address"), translate("cidr6")) +ip6addr.optional = true + +ip6gw = s2:option(Value, "ip6gw", translate("gateway6")) +ip6gw.optional = true + +dns = s2:option(Value, "dns", translate("dnsserver")) +dns.optional = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/network.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/network.lua new file mode 100644 index 0000000..89e13a5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/network.lua @@ -0,0 +1,128 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: network.lua 3650 2008-10-29 19:40:40Z jow $ +]]-- +require("luci.sys") +require("luci.tools.webadmin") + +local netstate = luci.model.uci.cursor_state():get_all("network") +m = Map("network", translate("interfaces")) + +local created +local netstat = luci.sys.net.deviceinfo() + +s = m:section(TypedSection, "interface", "") +s.addremove = true +s.extedit = luci.dispatcher.build_url("admin", "network", "network") .. "/%s" +s.template = "cbi/tblsection" +s.override_scheme = true + +function s.filter(self, section) + return section ~= "loopback" and section +end + +function s.create(self, section) + if TypedSection.create(self, section) then + created = section + else + self.invalid_cts = true + end +end + +function s.parse(self, ...) + TypedSection.parse(self, ...) + if created then + m.uci:save("network") + luci.http.redirect(luci.dispatcher.build_url("admin", "network", "network") + .. "/" .. created) + end +end + +up = s:option(Flag, "up") +function up.cfgvalue(self, section) + return netstate[section] and netstate[section].up or "0" +end + +function up.write(self, section, value) + local call + if value == "1" then + call = "ifup" + elseif value == "0" then + call = "ifdown" + end + os.execute(call .. " " .. section .. " >/dev/null 2>&1") +end + +ifname = s:option(DummyValue, "ifname", translate("device")) +function ifname.cfgvalue(self, section) + return netstate[section] and netstate[section].ifname +end + +ifname.titleref = luci.dispatcher.build_url("admin", "network", "vlan") + + +if luci.model.uci.cursor():load("firewall") then + zone = s:option(DummyValue, "_zone", translate("zone")) + zone.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "zones") + + function zone.cfgvalue(self, section) + local zones = luci.tools.webadmin.network_get_zones(section) + return zones and table.concat(zones, ", ") or "-" + end +end + +hwaddr = s:option(DummyValue, "_hwaddr") +function hwaddr.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") or "" + return luci.fs.readfile("/sys/class/net/" .. ix .. "/address") + or luci.util.exec("ifconfig " .. ix):match(" ([A-F0-9:]+)%s*\n") + or "n/a" + +end + + +ipaddr = s:option(DummyValue, "ipaddr", translate("addresses")) +function ipaddr.cfgvalue(self, section) + local addr = luci.tools.webadmin.network_get_addresses(section) + return table.concat(addr, ", ") +end + +txrx = s:option(DummyValue, "_txrx") + +function txrx.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][1] + rx = rx and luci.tools.webadmin.byte_format(tonumber(rx)) or "-" + + local tx = netstat and netstat[ix] and netstat[ix][9] + tx = tx and luci.tools.webadmin.byte_format(tonumber(tx)) or "-" + + return string.format("%s / %s", tx, rx) +end + +errors = s:option(DummyValue, "_err") + +function errors.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][3] + local tx = netstat and netstat[ix] and netstat[ix][11] + + rx = rx and tostring(rx) or "-" + tx = tx and tostring(tx) or "-" + + return string.format("%s / %s", tx, rx) +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/routes.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/routes.lua new file mode 100644 index 0000000..73732f8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/routes.lua @@ -0,0 +1,120 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: routes.lua 3888 2008-12-10 21:46:22Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("network", translate("a_n_routes"), translate("a_n_routes1")) + +local routes6 = luci.sys.net.routes6() +local bit = require "bit" + +if not arg or not arg[1] then + local routes = luci.sys.net.routes() + + v = m:section(Table, routes, translate("a_n_routes_kernel4")) + + net = v:option(DummyValue, "iface", translate("network")) + function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes[section].device) + or routes[section].device + end + + target = v:option(DummyValue, "target", translate("target")) + function target.cfgvalue(self, section) + return routes[section].dest:network():string() + end + + netmask = v:option(DummyValue, "netmask", translate("netmask")) + function netmask.cfgvalue(self, section) + return routes[section].dest:mask():string() + end + + gateway = v:option(DummyValue, "gateway", translate("gateway")) + function gateway.cfgvalue(self, section) + return routes[section].gateway:string() + end + + metric = v:option(DummyValue, "metric", translate("metric")) + function metric.cfgvalue(self, section) + return routes[section].metric + end + + if routes6 then + v = m:section(Table, routes6, translate("a_n_routes_kernel6")) + + net = v:option(DummyValue, "iface", translate("network")) + function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes6[section].device) + or routes6[section].device + end + + target = v:option(DummyValue, "target", translate("target")) + function target.cfgvalue(self, section) + return routes6[section].dest:string() + end + + gateway = v:option(DummyValue, "gateway", translate("gateway6")) + function gateway.cfgvalue(self, section) + return routes6[section].source:string() + end + + metric = v:option(DummyValue, "metric", translate("metric")) + function metric.cfgvalue(self, section) + local metr = routes6[section].metric + local lower = bit.band(metr, 0xffff) + local higher = bit.rshift(bit.band(metr, 0xffff0000), 16) + return "%04X%04X" % {higher, lower} + end + end +end + + +s = m:section(TypedSection, "route", translate("a_n_routes_static4")) +s.addremove = true +s.anonymous = true + +s.template = "cbi/tblsection" + +iface = s:option(ListValue, "interface", translate("interface")) +luci.tools.webadmin.cbi_add_networks(iface) + +if not arg or not arg[1] then + net.titleref = iface.titleref +end + +s:option(Value, "target", translate("target"), translate("a_n_r_target1")) + +s:option(Value, "netmask", translate("netmask"), translate("a_n_r_netmask1")).rmemepty = true + +s:option(Value, "gateway", translate("gateway")) + +if routes6 then + s = m:section(TypedSection, "route6", translate("a_n_routes_static6")) + s.addremove = true + s.anonymous = true + + s.template = "cbi/tblsection" + + iface = s:option(ListValue, "interface", translate("interface")) + luci.tools.webadmin.cbi_add_networks(iface) + + if not arg or not arg[1] then + net.titleref = iface.titleref + end + + s:option(Value, "target", translate("target"), translate("a_n_r_target6")) + + s:option(Value, "gateway", translate("gateway6")).rmempty = true +end + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/vlan.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/vlan.lua new file mode 100644 index 0000000..eb14148 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/vlan.lua @@ -0,0 +1,22 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: vlan.lua 2808 2008-08-14 11:49:36Z Cyrus $ +]]-- +m = Map("network", translate("a_n_switch"), translate("a_n_switch1")) + +s = m:section(TypedSection, "switch", "") + +for i = 0, 15 do + s:option(Value, "vlan"..i, "ethX."..i).optional = true +end + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wifi.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wifi.lua new file mode 100644 index 0000000..66fd3b8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wifi.lua @@ -0,0 +1,373 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: wifi.lua 4224 2009-02-04 19:20:23Z Cyrus $ +]]-- +require("luci.tools.webadmin") +arg[1] = arg[1] or "" + +m = Map("wireless", translate("networks"), translate("a_w_networks1")) + +s = m:section(NamedSection, arg[1], "wifi-device", translate("device") .. " " .. arg[1]) +s.addremove = false + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "wireless") + + +en = s:option(Flag, "disabled", translate("enable")) +en.enabled = "0" +en.disabled = "1" +en.rmempty = false + +function en.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" +end + +s:option(DummyValue, "type", translate("type")) +local hwtype = m:get(arg[1], "type") +-- NanoFoo +local nsantenna = m:get(arg[1], "antenna") + +ch = s:option(Value, "channel", translate("a_w_channel")) +for i=1, 14 do + ch:value(i, i .. " (2.4 GHz)") +end +for i=36, 64, 4 do + ch:value(i, i .. " (5 GHz)") +end +for i=100, 140, 4 do + ch:value(i, i .. " (5 GHz)") +end +ch:value(147, 147 .. " (5 GHz)") +ch:value(151, 151 .. " (5 GHz)") +ch:value(155, 155 .. " (5 GHz)") +ch:value(167, 167 .. " (5 GHz)") + +s:option(Value, "txpower", translate("a_w_txpwr"), "dBm").rmempty = true + + +------------------- MAC80211 Device ------------------ + +if hwtype == "mac80211" then + +end + + +------------------- Madwifi Device ------------------ + +if hwtype == "atheros" then + mode = s:option(ListValue, "hwmode", translate("mode")) + mode:value("", translate("wifi_auto")) + mode:value("11b", "802.11b") + mode:value("11g", "802.11g") + mode:value("11a", "802.11a") + mode:value("11bg", "802.11b+g") + mode:value("11gdt", "802.11adt") + mode:value("11adt", "802.11adt") + mode:value("fh", translate("wifi_fh")) + + s:option(Flag, "diversity", translate("wifi_diversity")).rmempty = false + + if not nsantenna then + s:option(Value, "txantenna", translate("wifi_txantenna")).optional = true + s:option(Value, "rxantenna", translate("wifi_rxantenna")).optional = true + else -- NanoFoo + local ant = s:option(ListValue, "antenna", translate("wifi_txantenna")) + ant:value("auto") + ant:value("vertical") + ant:value("horizontal") + ant:value("external") + end + s:option(Value, "distance", translate("wifi_distance"), + translate("wifi_distance_desc")).optional = true + + --s:option(Flag, "nosbeacon", translate("wifi_nosbeacon")).optional = true +end + + + +------------------- Broadcom Device ------------------ + +if hwtype == "broadcom" then + mp = s:option(ListValue, "macfilter", translate("wifi_macpolicy")) + mp.optional = true + mp:value("") + mp:value("allow", translate("wifi_whitelist")) + mp:value("deny", translate("wifi_blacklist")) + ml = s:option(DynamicList, "maclist", translate("wifi_maclist")) + ml:depends({macfilter="allow"}) + ml:depends({macfilter="deny"}) + + s:option(Value, "txantenna", translate("wifi_txantenna")).optional = true + s:option(Value, "rxantenna", translate("wifi_rxantenna")).optional = true + + s:option(Flag, "frameburst", translate("wifi_bursting")).optional = true + + s:option(Value, "distance", translate("wifi_distance")).optional = true + --s:option(Value, "slottime", translate("wifi_slottime")).optional = true + + s:option(Value, "country", translate("wifi_country")).optional = true + s:option(Value, "maxassoc", translate("wifi_maxassoc")).optional = true +end + + +----------------------- Interface ----------------------- + +s = m:section(TypedSection, "wifi-iface", translate("interfaces")) +s.addremove = true +s.anonymous = true +s:depends("device", arg[1]) +s.defaults.device = arg[1] + +s:option(Value, "ssid", translate("wifi_essid")) + +network = s:option(Value, "network", translate("network"), translate("a_w_network1")) +network.rmempty = true +network:value("") +network.combobox_manual = translate("a_w_netmanual") +luci.tools.webadmin.cbi_add_networks(network) + +function network.write(self, section, value) + if not m.uci:get("network", value) then + -- avoid "value not defined in enum" because network is not known yet + s.override_scheme = true + + m:chain("network") + m.uci:set("network", value, "interface") + Value.write(self, section, value) + else + if m.uci:get("network", value) == "interface" then + Value.write(self, section, value) + end + end +end + + +mode = s:option(ListValue, "mode", translate("mode")) +mode.override_values = true +mode:value("ap", translate("a_w_ap")) +mode:value("adhoc", translate("a_w_adhoc")) +mode:value("sta", translate("a_w_client")) + +bssid = s:option(Value, "bssid", translate("wifi_bssid")) + + +-------------------- MAC80211 Interface ---------------------- + +if hwtype == "mac80211" then + mode:value("ahdemo", translate("a_w_ahdemo")) + mode:value("monitor", translate("a_w_monitor")) + bssid:depends({mode="adhoc"}) + + s:option(Value, "frag", translate("wifi_frag")).optional = true + s:option(Value, "rts", translate("wifi_rts")).optional = true +end + + + +-------------------- Madwifi Interface ---------------------- + +if hwtype == "atheros" then + mode:value("ahdemo", translate("a_w_ahdemo")) + mode:value("monitor", translate("a_w_monitor")) + + bssid:depends({mode="adhoc"}) + bssid:depends({mode="ahdemo"}) + + wds = s:option(Flag, "wds", translate("a_w_wds")) + wds:depends({mode="ap"}) + wds:depends({mode="sta"}) + wds.rmempty = true + wdssep = s:option(Flag, "wdssep", translate("wifi_wdssep")) + wdssep:depends({mode="ap", wds="1"}) + wdssep.optional = true + + s:option(Flag, "doth", "802.11h").optional = true + hidden = s:option(Flag, "hidden", translate("wifi_hidden")) + hidden:depends({mode="ap"}) + hidden:depends({mode="adhoc"}) + hidden:depends({mode="wds"}) + hidden.optional = true + isolate = s:option(Flag, "isolate", translate("wifi_isolate"), + translate("wifi_isolate_desc")) + isolate:depends({mode="ap"}) + isolate.optional = true + s:option(Flag, "bgscan", translate("wifi_bgscan")).optional = true + + mp = s:option(ListValue, "macpolicy", translate("wifi_macpolicy")) + mp.optional = true + mp:value("") + mp:value("deny", translate("wifi_whitelist")) + mp:value("allow", translate("wifi_blacklist")) + ml = s:option(DynamicList, "maclist", translate("wifi_maclist")) + ml:depends({macpolicy="allow"}) + ml:depends({macpolicy="deny"}) + + s:option(Value, "rate", translate("wifi_rate")).optional = true + s:option(Value, "mcast_rate", translate("wifi_mcast_rate")).optional = true + s:option(Value, "frag", translate("wifi_frag")).optional = true + s:option(Value, "rts", translate("wifi_rts")).optional = true + s:option(Value, "minrate", translate("wifi_minrate")).optional = true + s:option(Value, "maxrate", translate("wifi_maxrate")).optional = true + s:option(Flag, "compression", translate("wifi_compression")).optional = true + + s:option(Flag, "bursting", translate("wifi_bursting")).optional = true + s:option(Flag, "turbo", translate("wifi_turbo")).optional = true + s:option(Value, "ff", translate("wifi_ff")).optional = true + + s:option(Flag, "wmm", translate("wifi_wmm")).optional = true + s:option(Flag, "xr", translate("wifi_xr")).optional = true + s:option(Flag, "ar", translate("wifi_ar")).optional = true + + local swm = s:option(Flag, "sw_merge", translate("wifi_nosbeacon")) + swm:depends({mode="adhoc"}) + swm.optional = true + + local nos = s:option(Flag, "nosbeacon", translate("wifi_nosbeacon")) + nos:depends({mode="sta"}) + nos.optional = true + + local probereq = s:option(Flag, "probereq", translate("wifi_noprobereq")) + probereq.optional = true + probereq.enabled = "0" + probereq.disabled = "1" +end + + +-------------------- Broadcom Interface ---------------------- + +if hwtype == "broadcom" then + mode:value("wds", translate("a_w_wds")) + mode:value("monitor", translate("a_w_monitor")) + + hidden = s:option(Flag, "hidden", translate("wifi_hidden")) + hidden:depends({mode="ap"}) + hidden:depends({mode="adhoc"}) + hidden:depends({mode="wds"}) + hidden.optional = true + + isolate = s:option(Flag, "isolate", translate("wifi_isolate"), + translate("wifi_isolate_desc")) + isolate:depends({mode="ap"}) + isolate.optional = true + + bssid:depends({mode="wds"}) + bssid:depends({mode="adhoc"}) +end + + + +------------------- WiFI-Encryption ------------------- + +encr = s:option(ListValue, "encryption", translate("encryption")) +encr.override_values = true +encr:depends({mode="ap"}) +encr:depends({mode="sta"}) +encr:depends({mode="adhoc"}) +encr:depends({mode="ahdemo"}) +encr:depends({mode="wds"}) + +encr:value("none", "No Encryption") +encr:value("wep", "WEP") + +if hwtype == "atheros" or hwtype == "mac80211" then + local supplicant = luci.fs.mtime("/usr/sbin/wpa_supplicant") + local hostapd = luci.fs.mtime("/usr/sbin/hostapd") + + if hostapd and supplicant then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") + encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="sta"}) + encr:value("wpa2i", "WPA2-EAP", {mode="ap"}, {mode="sta"}) + elseif hostapd and not supplicant then + encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="adhoc"}, {mode="ahdemo"}) + encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="adhoc"}, {mode="ahdemo"}) + encr:value("wpa", "WPA-EAP", {mode="ap"}) + encr:value("wpa2i", "WPA2-EAP", {mode="ap"}) + encr.description = translate("wifi_wpareq") + elseif not hostapd and supplicant then + encr:value("psk", "WPA-PSK", {mode="sta"}) + encr:value("psk2", "WPA2-PSK", {mode="sta"}) + encr:value("wpa", "WPA-EAP", {mode="sta"}) + encr:value("wpa2i", "WPA2-EAP", {mode="sta"}) + encr.description = translate("wifi_wpareq") + else + encr.description = translate("wifi_wpareq") + end +elseif hwtype == "broadcom" then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") +end + +encr:depends("mode", "ap") +encr:depends("mode", "sta") +encr:depends("mode", "wds") + +server = s:option(Value, "server", translate("a_w_radiussrv")) +server:depends({mode="ap", encryption="wpa"}) +server:depends({mode="ap", encryption="wpa2i"}) +server.rmempty = true + +port = s:option(Value, "port", translate("a_w_radiusport")) +port:depends({mode="ap", encryption="wpa"}) +port:depends({mode="ap", encryption="wpa2i"}) +port.rmempty = true + +key = s:option(Value, "key", translate("key")) +key:depends("encryption", "wep") +key:depends("encryption", "psk") +key:depends({mode="ap", encryption="wpa"}) +key:depends("encryption", "psk2") +key:depends({mode="ap", encryption="wpa2i"}) +key.rmempty = true + +if hwtype == "atheros" or hwtype == "mac80211" then + nasid = s:option(Value, "nasid", translate("a_w_nasid")) + nasid:depends({mode="ap", encryption="wpa"}) + nasid:depends({mode="ap", encryption="wpa2i"}) + nasid.rmempty = true + + eaptype = s:option(ListValue, "eap_type", translate("a_w_eaptype")) + eaptype:value("TLS") + eaptype:value("PEAP") + eaptype:depends({mode="sta", encryption="wpa"}) + eaptype:depends({mode="sta", encryption="wpa2i"}) + + cacert = s:option(FileUpload, "ca_cert", translate("a_w_cacert")) + cacert:depends({mode="sta", encryption="wpa"}) + cacert:depends({mode="sta", encryption="wpa2i"}) + + privkey = s:option(FileUpload, "priv_key", translate("a_w_tlsprivkey")) + privkey:depends({mode="sta", eap_type="TLS", encryption="wpa2i"}) + privkey:depends({mode="sta", eap_type="TLS", encryption="wpa"}) + + privkeypwd = s:option(Value, "priv_key_pwd", translate("a_w_tlsprivkeypwd")) + privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa2i"}) + privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa"}) + + + auth = s:option(Value, "auth", translate("a_w_peapauth")) + auth:depends({mode="sta", eap_type="PEAP", encryption="wpa2i"}) + auth:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) + + identity = s:option(Value, "identity", translate("a_w_peapidentity")) + identity:depends({mode="sta", eap_type="PEAP", encryption="wpa2i"}) + identity:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) + + password = s:option(Value, "password", translate("a_w_peappassword")) + password:depends({mode="sta", eap_type="PEAP", encryption="wpa2i"}) + password:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) +end + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wireless.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wireless.lua new file mode 100644 index 0000000..198d410 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_network/wireless.lua @@ -0,0 +1,134 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: wireless.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +require("luci.sys") +require("luci.tools.webadmin") + +local wireless = luci.model.uci.cursor_state():get_all("wireless") +local wifidata = luci.sys.wifi.getiwconfig() +local ifaces = {} + +for k, v in pairs(wireless) do + if v[".type"] == "wifi-iface" then + table.insert(ifaces, v) + end +end + + +m = SimpleForm("wireless", translate("wifi")) + +s = m:section(Table, ifaces, translate("networks")) + +function s.extedit(self, section) + local device = self.map:get(section, "device") or "" + return luci.dispatcher.build_url(unpack(luci.dispatcher.context.requested.path)) .. "/" .. device +end + +link = s:option(DummyValue, "_link", translate("link")) +function link.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Link Quality"] or "-" +end + +essid = s:option(DummyValue, "ssid", "ESSID") + +bssid = s:option(DummyValue, "_bsiid", "BSSID") +function bssid.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return (wifidata[ifname] and (wifidata[ifname].Cell + or wifidata[ifname]["Access Point"])) or "-" +end + +channel = s:option(DummyValue, "channel", translate("channel")) +function channel.cfgvalue(self, section) + return wireless[self.map:get(section, "device")].channel +end + +protocol = s:option(DummyValue, "_mode", translate("protocol")) +function protocol.cfgvalue(self, section) + local mode = wireless[self.map:get(section, "device")].mode + return mode and "802." .. mode +end + +mode = s:option(DummyValue, "mode", translate("mode")) +encryption = s:option(DummyValue, "encryption", translate("iwscan_encr")) + +power = s:option(DummyValue, "_power", translate("power")) +function power.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Tx-Power"] or "-" +end + +scan = s:option(Button, "_scan", translate("scan")) +scan.inputstyle = "find" + +function scan.cfgvalue(self, section) + return self.map:get(section, "ifname") or false +end + +t2 = m:section(Table, {}, translate("iwscan"), translate("iwscan1")) + +function scan.write(self, section) + t2.render = t2._render + local ifname = self.map:get(section, "ifname") + luci.util.update(t2.data, luci.sys.wifi.iwscan(ifname)) +end + +t2._render = t2.render +t2.render = function() end + +t2:option(DummyValue, "Quality", translate("iwscan_link")) +essid = t2:option(DummyValue, "ESSID", "ESSID") +function essid.cfgvalue(self, section) + return luci.util.pcdata(self.map:get(section, "ESSID")) +end + +t2:option(DummyValue, "Address", "BSSID") +t2:option(DummyValue, "Mode", translate("mode")) +chan = t2:option(DummyValue, "channel", translate("channel")) +function chan.cfgvalue(self, section) + return self.map:get(section, "Channel") + or self.map:get(section, "Frequency") + or "-" +end + +t2:option(DummyValue, "Encryption key", translate("iwscan_encr")) + +t2:option(DummyValue, "Signal level", translate("iwscan_signal")) + +t2:option(DummyValue, "Noise level", translate("iwscan_noise")) + + +s2 = m:section(SimpleSection, translate("a_w_create")) +create = s2:option(ListValue, "create", translate("device")) +create:value("", translate("cbi_select")) +for k, v in pairs(wireless) do + if v[".type"] == "wifi-device" then + create:value(k) + end +end + +function create.write(self, section, value) + local uci = luci.model.uci.cursor() + uci:load("wireless") + uci:section("wireless", "wifi-iface", nil, {device=value}) + uci:save("wireless") + luci.http.redirect(luci.dispatcher.build_url(unpack(luci.dispatcher.context.requested.path)) .. "/" .. value) +end + +function create.cbid(self, section) + return "priv.cbid.create" +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/crontab.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/crontab.lua new file mode 100644 index 0000000..5be5fd1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/crontab.lua @@ -0,0 +1,35 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: crontab.lua 4106 2009-01-20 11:33:33Z Cyrus $ +]]-- +local cronfile = "/etc/crontabs/root" + +f = SimpleForm("crontab", translate("a_s_crontab"), translate("a_s_crontab1")) + +t = f:field(TextValue, "crons") +t.rmempty = true +t.rows = 10 +function t.cfgvalue() + return luci.fs.readfile(cronfile) or "" +end + +function f.handle(self, state, data) + if state == FORM_VALID then + if data.crons then + luci.fs.writefile(cronfile, data.crons:gsub("\r\n", "\n")) + end + end + return true +end + +return f diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dnsmasq.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dnsmasq.lua new file mode 100644 index 0000000..afdf075 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dnsmasq.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dnsmasq.lua 3595 2008-10-17 16:20:01Z Cyrus $ +]]-- +m = Map("dhcp", "Dnsmasq") + +s = m:section(TypedSection, "dnsmasq", translate("settings")) +s.anonymous = true + +s:option(Flag, "domainneeded") +s:option(Flag, "authoritative") +s:option(Flag, "boguspriv") +s:option(Flag, "filterwin2k") +s:option(Flag, "localise_queries") +s:option(Value, "local") +s:option(Value, "domain") +s:option(Flag, "expandhosts") +s:option(Flag, "nonegcache") +s:option(Flag, "readethers") +s:option(Value, "leasefile") +s:option(Value, "resolvfile") +s:option(Flag, "nohosts").optional = true +s:option(Flag, "strictorder").optional = true +s:option(Flag, "logqueries").optional = true +s:option(Flag, "noresolv").optional = true +s:option(Value, "dnsforwardmax").optional = true +s:option(Value, "port").optional = true +s:option(Value, "ednspacket_max").optional = true +s:option(Value, "dhcpleasemax").optional = true +s:option(Value, "addnhosts").optional = true +s:option(Value, "queryport").optional = true +s:option(Flag, "enable_tftp").optional = true +s:option(Value, "tftp_root").optional = true +s:option(Value, "dhcp_boot").optional = true + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dropbear.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dropbear.lua new file mode 100644 index 0000000..30f7325 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/dropbear.lua @@ -0,0 +1,27 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dropbear.lua 4150 2009-01-26 02:10:02Z jow $ +]]-- +m = Map("dropbear", "Dropbear SSHd", translate("a_srv_dropbear1")) + +s = m:section(TypedSection, "dropbear", "") +s.anonymous = true + +port = s:option(Value, "Port", translate("port")) +port.isinteger = true + +pwauth = s:option(Flag, "PasswordAuth", translate("a_srv_d_pwauth"), translate("a_srv_d_pwauth1")) +pwauth.enabled = 'on' +pwauth.disabled = 'off' +pwauth.rmempty = false + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/httpd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/httpd.lua new file mode 100644 index 0000000..5541959 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/httpd.lua @@ -0,0 +1,31 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: httpd.lua 3402 2008-09-23 17:29:05Z jow $ +]]-- +m = Map("httpd", "Busybox HTTPd", translate("a_srv_http1")) + +s = m:section(TypedSection, "httpd", "") +s.anonymous = true +s.addremove = true + +port = s:option(Value, "port", translate("port")) +port.isinteger = true + +s:option(Value, "home", translate("a_srv_http_root")) + +config = s:option(Value, "c_file", translate("configfile"), translate("a_srv_http_config1")) +config.rmempty = true + +realm = s:option(Value, "realm", translate("a_srv_http_authrealm"), translate("a_srv_http_authrealm1")) +realm.rmempty = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/lucittpd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/lucittpd.lua new file mode 100644 index 0000000..3599f59 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_services/lucittpd.lua @@ -0,0 +1,25 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: lucittpd.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +m = Map("lucittpd", "LuCIttpd", translate("a_srv_lucittpd")) + +s = m:section(NamedSection, "lucittpd", "lucittpd", "") + +s:option(Value, "port", translate("port")) +s:option(Value, "root", translate("a_srv_http_root")) +s:option(Value, "path", translate("a_srv_http_path")) +s:option(Flag, "keepalive", translate("a_srv_http_keepalive")) +s:option(Value, "timeout", translate("a_srv_http_timeout")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/buttons.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/buttons.lua new file mode 100644 index 0000000..d32f8fa --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/buttons.lua @@ -0,0 +1,31 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: buttons.lua 2880 2008-08-17 23:47:38Z jow $ +]]-- +m = Map("system", translate("buttons"), translate("buttons_desc")) + +s = m:section(TypedSection, "button", "") +s.anonymous = true +s.addremove = true + +s:option(Value, "button") + +act = s:option(ListValue, "action") +act:value("released") + +s:option(Value, "handler") + +min = s:option(Value, "min") +min.rmempty = true + +max = s:option(Value, "max") +max.rmempty = true diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/fstab.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/fstab.lua new file mode 100644 index 0000000..30409a4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/fstab.lua @@ -0,0 +1,86 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: fstab.lua 3329 2008-09-16 02:01:05Z jow $ +]]-- +require("luci.tools.webadmin") + +local fs = require "luci.fs" +local devices = {} +luci.util.update(devices, fs.glob("/dev/sd*") or {}) +luci.util.update(devices, fs.glob("/dev/hd*") or {}) +luci.util.update(devices, fs.glob("/dev/scd*") or {}) +luci.util.update(devices, fs.glob("/dev/mmc*") or {}) + +local size = {} +for i, dev in ipairs(devices) do + local s = tonumber((luci.fs.readfile("/sys/class/block/%s/size" % dev:sub(6)))) + size[dev] = s and math.floor(s / 2048) +end + + +m = Map("fstab", translate("a_s_fstab")) + +local mounts = luci.sys.mounts() + +v = m:section(Table, mounts, translate("a_s_fstab_active")) + +fs = v:option(DummyValue, "fs", translate("filesystem")) + +mp = v:option(DummyValue, "mountpoint", translate("a_s_fstab_mountpoint")) + +avail = v:option(DummyValue, "avail", translate("a_s_fstab_avail")) +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("a_s_fstab_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 + + + +mount = m:section(TypedSection, "mount", translate("a_s_fstab_mountpoints"), translate("a_s_fstab_mountpoints1")) +mount.anonymous = true +mount.addremove = true +mount.template = "cbi/tblsection" + +mount:option(Flag, "enabled", translate("enable")) +dev = mount:option(Value, "device", translate("device"), translate("a_s_fstab_device1")) +for i, d in ipairs(devices) do + dev:value(d, size[d] and "%s (%s MB)" % {d, size[d]}) +end + +mount:option(Value, "target", translate("a_s_fstab_mountpoint")) +mount:option(Value, "fstype", translate("filesystem"), translate("a_s_fstab_fs1")) +mount:option(Value, "options", translate("options"), translatef("manpage", "siehe '%s' manpage", "mount")) + + +swap = m:section(TypedSection, "swap", "SWAP", translate("a_s_fstab_swap1")) +swap.anonymous = true +swap.addremove = true +swap.template = "cbi/tblsection" + +swap:option(Flag, "enabled", translate("enable")) +dev = swap:option(Value, "device", translate("device"), translate("a_s_fstab_device1")) +for i, d in ipairs(devices) do + dev:value(d, size[d] and "%s (%s MB)" % {d, size[d]}) +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/ipkg.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/ipkg.lua new file mode 100644 index 0000000..f941efc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/ipkg.lua @@ -0,0 +1,35 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ipkg.lua 4106 2009-01-20 11:33:33Z Cyrus $ +]]-- +local ipkgfile = "/etc/opkg.conf" + +f = SimpleForm("ipkgconf", translate("a_s_p_ipkg")) + +t = f:field(TextValue, "lines") +t.rows = 10 +function t.cfgvalue() + return luci.fs.readfile(ipkgfile) or "" +end + +function t.write(self, section, data) + return luci.fs.writefile(ipkgfile, data:gsub("\r\n", "\n")) +end + +f:append(Template("admin_system/ipkg")) + +function f.handle(self, state, data) + return true +end + +return f diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/leds.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/leds.lua new file mode 100644 index 0000000..b6a911f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/leds.lua @@ -0,0 +1,86 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: leds.lua 2880 2008-08-17 23:47:38Z jow $ +]]-- +m = Map("system", translate("leds"), translate("leds_desc")) + +local sysfs_path = "/sys/class/leds/" +local leds = {} + +if luci.fs.access(sysfs_path) then + for k, v in pairs(luci.fs.dir(sysfs_path)) do + if v ~= "." and v ~= ".." then + table.insert(leds, v) + end + end +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") + + +sysfs = s:option(ListValue, "sysfs") +for k, v in ipairs(leds) do + sysfs:value(v) +end + +s:option(Flag, "default").rmempty = true + + +trigger = s:option(ListValue, "trigger") + +local triggers = luci.fs.readfile(sysfs_path .. leds[1] .. "/trigger") +for t in triggers:gmatch("[%w-]+") do + trigger:value(t, translate("system_led_trigger_" .. t:gsub("-", ""))) +end + + +delayon = s:option(Value, "delayon") +delayon:depends("trigger", "timer") + +delayoff = s:option(Value, "delayoff") +delayoff:depends("trigger", "timer") + + +dev = s:option(ListValue, "dev") +dev.rmempty = true +dev:value("") +dev:depends("trigger", "netdev") +for k, v in pairs(luci.sys.net.devices()) do + if v ~= "lo" then + dev:value(v) + end +end + + +mode = s:option(MultiValue, "mode") +mode.rmempty = true +mode:depends("trigger", "netdev") +mode:value("link", translate("system_led_mode_link")) +mode:value("tx", translate("system_led_mode_tx")) +mode:value("rx", translate("system_led_mode_rx")) + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/passwd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/passwd.lua new file mode 100644 index 0000000..f078dd5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/passwd.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: passwd.lua 3864 2008-12-07 13:44:25Z Cyrus $ +]]-- +f = SimpleForm("password", translate("a_s_changepw"), translate("a_s_changepw1")) + +pw1 = f:field(Value, "pw1", translate("password")) +pw1.password = true +pw1.rmempty = false + +pw2 = f:field(Value, "pw2", translate("confirmation")) +pw2.password = true +pw2.rmempty = false + +function pw2.validate(self, value, section) + return pw1:formvalue(section) == value and value +end + +function f.handle(self, state, data) + if state == FORM_VALID then + local stat = luci.sys.user.setpasswd("root", data.pw1) == 0 + + if stat then + f.message = translate("a_s_changepw_changed") + else + f.errmessage = translate("unknownerror") + end + + data.pw1 = nil + data.pw2 = nil + end + return true +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/processes.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/processes.lua new file mode 100644 index 0000000..8aa2be8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/processes.lua @@ -0,0 +1,44 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: processes.lua 2880 2008-08-17 23:47:38Z jow $ +]]-- +f = SimpleForm("processes", translate("process_head"), translate("process_descr")) +f.reset = false +f.submit = false + +t = f:section(Table, luci.sys.process.list()) +t:option(DummyValue, "PID", translate("process_pid")) +t:option(DummyValue, "USER", translate("process_owner")) +t:option(DummyValue, "COMMAND", translate("process_command")) +t:option(DummyValue, "%CPU", translate("process_cpu")) +t:option(DummyValue, "%MEM", translate("process_mem")) + +hup = t:option(Button, "_hup", translate("process_hup")) +hup.inputstyle = "reload" +function hup.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 1) +end + +term = t:option(Button, "_term", translate("process_term")) +term.inputstyle = "remove" +function term.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 15) +end + +kill = t:option(Button, "_kill", translate("process_kill")) +kill.inputstyle = "reset" +function kill.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 9) +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/sshkeys.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/sshkeys.lua new file mode 100644 index 0000000..bae8116 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/sshkeys.lua @@ -0,0 +1,35 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: sshkeys.lua 4106 2009-01-20 11:33:33Z Cyrus $ +]]-- +local keyfile = "/etc/dropbear/authorized_keys" + +f = SimpleForm("sshkeys", translate("a_s_sshkeys"), translate("a_s_sshkeys1")) + +t = f:field(TextValue, "keys") +t.rmempty = true +t.rows = 10 +function t.cfgvalue() + return luci.fs.readfile(keyfile) or "" +end + +function f.handle(self, state, data) + if state == FORM_VALID then + if data.keys then + luci.fs.writefile(keyfile, data.keys:gsub("\r\n", "\n")) + end + end + return true +end + +return f diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/system.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/system.lua new file mode 100644 index 0000000..b3a01f3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/admin_system/system.lua @@ -0,0 +1,73 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: system.lua 3736 2008-11-06 23:10:43Z jow $ +]]-- + +require("luci.sys") +require("luci.sys.zoneinfo") +require("luci.tools.webadmin") + +m = Map("system", translate("system"), translate("a_s_desc")) + +s = m:section(TypedSection, "system", "") +s.anonymous = true + +local system, model, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo() +local uptime = luci.sys.uptime() + +s:option(DummyValue, "_system", translate("system")).value = system +s:option(DummyValue, "_cpu", translate("m_i_processor")).value = model + +local load1, load5, load15 = luci.sys.loadavg() +s:option(DummyValue, "_la", translate("load")).value = + string.format("%.2f, %.2f, %.2f", load1, load5, load15) + +s:option(DummyValue, "_memtotal", translate("m_i_memory")).value = + string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)", + tonumber(memtotal) / 1024, + 100 * memcached / memtotal, + translate("mem_cached") or "", + 100 * membuffers / memtotal, + translate("mem_buffered") or "", + 100 * memfree / memtotal, + translate("mem_free") or "") + +s:option(DummyValue, "_systime", translate("m_i_systemtime")).value = + os.date("%c") + +s:option(DummyValue, "_uptime", translate("m_i_uptime")).value = + luci.tools.webadmin.date_format(tonumber(uptime)) + +s:option(Value, "hostname", translate("hostname")) + +tz = s:option(ListValue, "zonename", translate("timezone")) +tz:value("UTC") + +for i, zone in ipairs(luci.sys.zoneinfo.TZ) do + tz:value(zone[1]) +end + +function tz.write(self, section, value) + local function lookup_zone(title) + for _, zone in ipairs(luci.sys.zoneinfo.TZ) do + if zone[1] == title then return zone[2] end + end + end + + AbstractValue.write(self, section, value) + self.map.uci:set("system", section, "timezone", lookup_zone(value) or "GMT0") +end + +s:option(Value, "log_size", nil, "kiB").optional = true +s:option(Value, "log_ip").optional = true +s:option(Value, "conloglevel").optional = true +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddns.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddns.lua new file mode 100644 index 0000000..b1877d8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddns.lua @@ -0,0 +1,74 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ddns.lua 3643 2008-10-29 05:34:34Z jow $ +]]-- +require("luci.tools.webadmin") +m = Map("ddns", translate("ddns"), translate("ddns_desc")) + +s = m:section(TypedSection, "service", "") +s.addremove = true + +s:option(Flag, "enabled", translate("enable")) + +svc = s:option(ListValue, "service_name", translate("service")) +svc.rmempty = true +svc:value("") +svc:value("dyndns.org") +svc:value("changeip.com") +svc:value("zoneedit.com") +svc:value("no-ip.com") +svc:value("freedns.afraid.org") + +s:option(Value, "domain", translate("hostname")).rmempty = true +s:option(Value, "username", translate("username")).rmempty = true +pw = s:option(Value, "password", translate("password")) +pw.rmempty = true +pw.password = true + +src = s:option(ListValue, "ip_source") +src:value("network", translate("network")) +src:value("interface", translate("interface")) +src:value("web", "URL") + +iface = s:option(ListValue, "ip_network", translate("network")) +iface:depends("ip_source", "network") +iface.rmempty = true +luci.tools.webadmin.cbi_add_networks(iface) + +iface = s:option(ListValue, "ip_interface", translate("interface")) +iface:depends("ip_source", "interface") +iface.rmempty = true +for k, v in pairs(luci.sys.net.devices()) do + iface:value(v) +end + +web = s:option(Value, "ip_url", "URL") +web:depends("ip_source", "web") +web.rmempty = true + +s:option(Value, "update_url").optional = true + +s:option(Value, "check_interval").default = 10 +unit = s:option(ListValue, "check_unit") +unit.default = "minutes" +unit:value("minutes", "min") +unit:value("hours", "h") + +s:option(Value, "force_interval").default = 72 +unit = s:option(ListValue, "force_unit") +unit.default = "hours" +unit:value("minutes", "min") +unit:value("hours", "h") + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddnsmini.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddnsmini.lua new file mode 100644 index 0000000..8a898a9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ddns/ddnsmini.lua @@ -0,0 +1,52 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ddnsmini.lua 3643 2008-10-29 05:34:34Z jow $ +]]-- +m = Map("ddns", translate("ddns"), translate("ddns_desc")) + +s = m:section(TypedSection, "service", "") +s.addremove = true + +s:option(Flag, "enabled", translate("enable")) + +svc = s:option(ListValue, "service_name", translate("service")) +svc.rmempty = true +svc:value("dyndns.org") +svc:value("changeip.com") +svc:value("zoneedit.com") +svc:value("no-ip.com") +svc:value("freedns.afraid.org") + +s:option(Value, "domain", translate("hostname")).rmempty = true +s:option(Value, "username", translate("username")).rmempty = true +pw = s:option(Value, "password", translate("password")) +pw.rmempty = true +pw.password = true + +s.defaults.ip_source = "network" +s.defaults.ip_network = "wan" + +s:option(Value, "check_interval").default = 10 +unit = s:option(ListValue, "check_unit") +unit.default = "minutes" +unit:value("minutes", "min") +unit:value("hours", "h") + +s:option(Value, "force_interval").default = 72 +unit = s:option(ListValue, "force_unit") +unit.default = "hours" +unit:value("minutes", "min") +unit:value("hours", "h") + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ffwizard.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ffwizard.lua new file mode 100644 index 0000000..f93f0c1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ffwizard.lua @@ -0,0 +1,391 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ffwizard.lua 4187 2009-01-30 15:07:36Z jow $ + +]]-- + + +local uci = require "luci.model.uci".cursor() +local tools = require "luci.tools.ffwizard" +local util = require "luci.util" +local sys = require "luci.sys" + + +-------------------- View -------------------- +f = SimpleForm("ffwizward", "Freifunkassistent", + "Dieser Assistent unterstüzt bei der Einrichtung des Routers für das Freifunknetz.") + + +dev = f:field(ListValue, "device", "WLAN-Gerät") +uci:foreach("wireless", "wifi-device", + function(section) + dev:value(section[".name"]) + end) + + +main = f:field(Flag, "wifi", "Freifunkzugang einrichten") + +net = f:field(Value, "net", "Freifunknetz", "1. Teil der IP-Adresse") +net.rmempty = true +net:depends("wifi", "1") +uci:foreach("freifunk", "community", function(s) + net:value(s[".name"], "%s (%s)" % {s.name, s.prefix}) +end) + +function net.cfgvalue(self, section) + return uci:get("freifunk", "wizard", "net") +end +function net.write(self, section, value) + uci:set("freifunk", "wizard", "net", value) + uci:save("freifunk") +end + + +subnet = f:field(Value, "subnet", "Subnetz (Projekt)", "2. Teil der IP-Adresse") +subnet.rmempty = true +subnet:depends("wifi", "1") +function subnet.cfgvalue(self, section) + return uci:get("freifunk", "wizard", "subnet") +end +function subnet.write(self, section, value) + uci:set("freifunk", "wizard", "subnet", value) + uci:save("freifunk") +end + +node = f:field(Value, "node", "Knoten", "3. Teil der IP-Adresse") +node.rmempty = true +node:depends("wifi", "1") +for i=1, 51 do + node:value(i) +end +function node.cfgvalue(self, section) + return uci:get("freifunk", "wizard", "node") +end +function node.write(self, section, value) + uci:set("freifunk", "wizard", "node", value) + uci:save("freifunk") +end + +client = f:field(Flag, "client", "WLAN-DHCP anbieten") +client:depends("wifi", "1") +client.rmempty = true + + +olsr = f:field(Flag, "olsr", "OLSR einrichten") +olsr.rmempty = true + +share = f:field(Flag, "sharenet", "Eigenen Internetzugang freigeben") +share.rmempty = true + + + +-------------------- Control -------------------- +function f.handle(self, state, data) + if state == FORM_VALID then + luci.http.redirect(luci.dispatcher.build_url("admin", "uci", "changes")) + return false + elseif state == FORM_INVALID then + self.errmessage = "Ungültige Eingabe: Bitte die Formularfelder auf Fehler prüfen." + end + return true +end + +local function _strip_internals(tbl) + tbl = tbl or {} + for k, v in pairs(tbl) do + if k:sub(1, 1) == "." then + tbl[k] = nil + end + end + return tbl +end + +-- Configure Freifunk checked +function main.write(self, section, value) + if value == "0" then + return + end + + local device = dev:formvalue(section) + local community, external + + -- Collect IP-Address + local inet = net:formvalue(section) + local isubnet = subnet:formvalue(section) + local inode = node:formvalue(section) + + -- Invalidate fields + if not inet then + net.tag_missing[section] = true + else + community = inet + external = uci:get("freifunk", community, "external") or "" + inet = uci:get("freifunk", community, "prefix") or inet + end + if not isubnet then + subnet.tag_missing[section] = true + end + if not inode then + node.tag_missing[section] = true + end + + if not inet or not isubnet or not inode then + return + end + + local ip = "%s.%s.%s" % {inet, isubnet, inode} + + + -- Cleanup + tools.wifi_delete_ifaces(device) + tools.network_remove_interface(device) + tools.firewall_zone_remove_interface("freifunk", device) + + -- Tune community settings + if community and uci:get("freifunk", community) then + uci:tset("freifunk", "community", uci:get_all("freifunk", community)) + end + + -- Tune wifi device + local devconfig = uci:get_all("freifunk", "wifi_device") + util.update(devconfig, uci:get_all(external, "wifi_device") or {}) + uci:tset("wireless", device, devconfig) + + -- Create wifi iface + local ifconfig = uci:get_all("freifunk", "wifi_iface") + util.update(ifconfig, uci:get_all(external, "wifi_iface") or {}) + ifconfig.device = device + ifconfig.network = device + ifconfig.ssid = uci:get("freifunk", community, "ssid") + uci:section("wireless", "wifi-iface", nil, ifconfig) + + -- Save wifi + uci:save("wireless") + + -- Create firewall zone and add default rules (first time) + local newzone = tools.firewall_create_zone("freifunk", "REJECT", "ACCEPT", "REJECT", true) + if newzone then + uci:foreach("freifunk", "fw_forwarding", function(section) + uci:section("firewall", "forwarding", nil, section) + end) + uci:foreach(external, "fw_forwarding", function(section) + uci:section("firewall", "forwarding", nil, section) + end) + + uci:foreach("freifunk", "fw_rule", function(section) + uci:section("firewall", "rule", nil, section) + end) + uci:foreach(external, "fw_rule", function(section) + uci:section("firewall", "rule", nil, section) + end) + end + + -- Enforce firewall include + local has_include = false + uci:foreach("firewall", "include", + function(section) + if section.path == "/etc/firewall.freifunk" then + has_include = true + end + end) + + if not has_include then + uci:section("firewall", "include", nil, + { path = "/etc/firewall.freifunk" }) + end + + -- Allow state: invalid packets + uci:foreach("firewall", "defaults", + function(section) + uci:set("firewall", section[".name"], "drop_invalid", "0") + end) + + -- Prepare advanced config + local has_advanced = false + uci:foreach("firewall", "advanced", + function(section) has_advanced = true end) + + if not has_advanced then + uci:section("firewall", "advanced", nil, + { tcp_ecn = "0" }) + end + + uci:save("firewall") + + + -- Create network interface + local netconfig = uci:get_all("freifunk", "interface") + util.update(netconfig, uci:get_all(external, "interface") or {}) + netconfig.proto = "static" + netconfig.ipaddr = ip + uci:section("network", "interface", device, netconfig) + + uci:save("network") + + tools.firewall_zone_add_interface("freifunk", device) + + + -- Set hostname + local new_hostname = ip:gsub("%.", "-") + local old_hostname = sys.hostname() + + if old_hostname == "OpenWrt" or old_hostname:match("^%d+-%d+-%d+-%d+$") then + uci:foreach("system", "system", + function(s) + uci:set("system", s['.name'], "hostname", new_hostname) + end) + + luci.fs.writefile( "/proc/sys/kernel/hostname", new_hostname.."\n" ) + uci:save("system") + end +end + + +function olsr.write(self, section, value) + if value == "0" then + return + end + + + local device = dev:formvalue(section) + + local community = net:formvalue(section) + local external = community and uci:get("freifunk", community, "external") or "" + + -- Configure nameservice + local hostname + uci:foreach("system", "system", function(s) hostname = s.hostname end) + + if hostname then + uci:foreach("olsrd", "LoadPlugin", + function(s) + if s.library == "olsrd_nameservice.so.0.3" then + uci:set("olsrd", s['.name'], "name", hostname) + end + end) + end + + -- Delete old interface + uci:delete_all("olsrd", "Interface", {interface=device}) + + -- Write new interface + local olsrbase = uci:get_all("freifunk", "olsr_interface") + util.update(olsrbase, uci:get_all(external, "olsr_interface") or {}) + olsrbase.interface = device + olsrbase.ignore = "0" + uci:section("olsrd", "Interface", nil, olsrbase) + uci:save("olsrd") + + -- Import hosts + uci:foreach("dhcp", "dnsmasq", function(s) + uci:set("dhcp", s[".name"], "addnhosts", "/var/etc/hosts.olsr") + end) + uci:save("dhcp") +end + + +function share.write(self, section, value) + uci:delete_all("firewall", "forwarding", {src="freifunk", dest="wan"}) + uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw_plain.so.0.4"}) + + if value == "1" then + uci:section("firewall", "forwarding", nil, {src="freifunk", dest="wan"}) + uci:section("olsrd", "LoadPlugin", nil, {library="olsrd_dyn_gw_plain.so.0.4"}) + end + uci:save("firewall") + uci:save("olsrd") +end + + +function client.write(self, section, value) + if value == "0" then + return + end + + local device = dev:formvalue(section) + + -- Collect IP-Address + local inet = net:formvalue(section) + local isubnet = subnet:formvalue(section) + local inode = node:formvalue(section) + + if not inet or not isubnet or not inode then + return + end + local community = inet + local external = community and uci:get("freifunk", community, "external") or "" + inet = uci:get("freifunk", community, "prefix") or inet + + local dhcpbeg = 48 + tonumber(inode) * 4 + local dclient = "%s.%s.%s" % {inet:gsub("^[0-9]+", "10"), isubnet, dhcpbeg} + local limit = dhcpbeg < 252 and 3 or 2 + + -- Delete old alias + uci:delete("network", device .. "dhcp") + + -- Create alias + local aliasbase = uci:get_all("freifunk", "alias") + util.update(aliasbase, uci:get_all(external, "alias") or {}) + aliasbase.interface = device + aliasbase.ipaddr = dclient + aliasbase.proto = "static" + uci:section("network", "alias", device .. "dhcp", aliasbase) + uci:save("network") + + + -- Create dhcp + local dhcpbase = uci:get_all("freifunk", "dhcp") + util.update(dhcpbase, uci:get_all(external, "dhcp") or {}) + dhcpbase.interface = device .. "dhcp" + dhcpbase.start = dhcpbeg + dhcpbase.limit = limit + + uci:section("dhcp", "dhcp", device .. "dhcp", dhcpbase) + uci:save("dhcp") + + uci:delete_all("firewall", "rule", { + src="freifunk", + proto="udp", + src_port="68", + dest_port="67" + }) + uci:section("firewall", "rule", nil, { + src="freifunk", + proto="udp", + src_port="68", + dest_port="67", + target="ACCEPT" + }) + uci:delete_all("firewall", "rule", { + src="freifunk", + proto="tcp", + dest_port="8082", + }) + uci:section("firewall", "rule", nil, { + src="freifunk", + proto="tcp", + dest_port="8082", + target="ACCEPT" + }) + + + + -- Delete old splash + uci:delete_all("luci_splash", "iface", {net=device, zone="freifunk"}) + + -- Register splash + uci:section("luci_splash", "iface", nil, {net=device, zone="freifunk"}) + uci:save("luci_splash") +end + +return f diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/contact.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/contact.lua new file mode 100644 index 0000000..5dd8835 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/contact.lua @@ -0,0 +1,34 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: contact.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +luci.i18n.loadc("freifunk") + +m = Map("freifunk", translate("contact"), translate("contact1")) + +c = m:section(NamedSection, "contact", "public", "") + +c:option(Value, "nickname", translate("ff_nickname")) +c:option(Value, "name", translate("ff_name")) +c:option(Value, "mail", translate("ff_mail"), translate("ff_mail1")) +c:option(Value, "phone", translate("ff_phone")) +c:option(Value, "location", translate("ff_location")) +c:option(Value, "note", translate("ff_note")) + +m2 = Map("system", translate("geo")) + +s = m2:section(TypedSection, "system", "") +s:option(Value, "latitude", translate("latitude", "Breite")).rmempty = true +s:option(Value, "longitude", translate("longitude", "Länge")).rmempty = true + +return m, m2 diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/freifunk.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/freifunk.lua new file mode 100644 index 0000000..fa789d9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/freifunk.lua @@ -0,0 +1,24 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: freifunk.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +m = Map("freifunk", "Freifunk") + +c = m:section(NamedSection, "community", "public", "Gemeinschaft", [[Dies sind die Grundeinstellungen +für die lokale Freifunkgemeinschaft. Diese Werte wirken sich NICHT auf die Konfiguration +des Routers aus, sondern definieren nur die Vorgaben für den Freifunkassistenten.]]) +c:option(Value, "name", "Gemeinschaft") +c:option(Value, "homepage", "Webseite") +c:option(Value, "ssid", "ESSID") +c:option(Value, "prefix", "Netzprefix") + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/public_status.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/public_status.lua new file mode 100644 index 0000000..8180bfe --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/freifunk/public_status.lua @@ -0,0 +1,216 @@ +require "luci.sys" +require "luci.tools.webadmin" + +local bit = require "bit" +local uci = luci.model.uci.cursor_state() + +local ffzone = luci.tools.webadmin.firewall_find_zone("freifunk") +local ffznet = ffzone and uci:get("firewall", ffzone, "network") +local ffwifs = ffznet and luci.util.split(ffznet, " ") or {} + +-- System -- + +f = SimpleForm("system", "System") +f.submit = false +f.reset = false +local system, model, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo() +local uptime = luci.sys.uptime() + +f:field(DummyValue, "_system", translate("system")).value = system +f:field(DummyValue, "_cpu", translate("m_i_processor")).value = model + +local load1, load5, load15 = luci.sys.loadavg() +f:field(DummyValue, "_la", translate("load")).value = +string.format("%.2f, %.2f, %.2f", load1, load5, load15) + +f:field(DummyValue, "_memtotal", translate("m_i_memory")).value = +string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)", + tonumber(memtotal) / 1024, + 100 * memcached / memtotal, + translate("mem_cached") or "", + 100 * membuffers / memtotal, + translate("mem_buffered") or "", + 100 * memfree / memtotal, + translate("mem_free") or "") + +f:field(DummyValue, "_systime", translate("m_i_systemtime")).value = +os.date("%c") + +f:field(DummyValue, "_uptime", translate("m_i_uptime")).value = +luci.tools.webadmin.date_format(tonumber(uptime)) + + +-- Wireless -- + +local wireless = uci:get_all("wireless") +local wifidata = luci.sys.wifi.getiwconfig() +local ifaces = {} + +for k, v in pairs(wireless) do + if v[".type"] == "wifi-iface" and ( + luci.util.contains(ffwifs, v.device) or + ( #ffwifs == 0 and (not v.encryption or v.encryption == "none") ) ) + then + table.insert(ifaces, v) + end +end + + +m = SimpleForm("wireless", "Freifunk WLAN") +m.submit = false +m.reset = false + +s = m:section(Table, ifaces, translate("networks")) + +link = s:option(DummyValue, "_link", translate("link")) +function link.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Link Quality"] or "-" +end + +essid = s:option(DummyValue, "ssid", "ESSID") + +bssid = s:option(DummyValue, "_bsiid", "BSSID") +function bssid.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return (wifidata[ifname] and (wifidata[ifname].Cell + or wifidata[ifname]["Access Point"])) or "-" +end + +channel = s:option(DummyValue, "channel", translate("channel")) + function channel.cfgvalue(self, section) + return wireless[self.map:get(section, "device")].channel +end + +protocol = s:option(DummyValue, "_mode", translate("protocol")) +function protocol.cfgvalue(self, section) + local mode = wireless[self.map:get(section, "device")].mode + return mode and "802." .. mode +end + +mode = s:option(DummyValue, "mode", translate("mode")) +encryption = s:option(DummyValue, "encryption", translate("iwscan_encr")) + +power = s:option(DummyValue, "_power", translate("power")) +function power.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Tx-Power"] or "-" +end + +scan = s:option(Button, "_scan", translate("scan")) +scan.inputstyle = "find" + +function scan.cfgvalue(self, section) + return self.map:get(section, "ifname") or false +end + +t2 = m:section(Table, {}, translate("iwscan"), translate("iwscan1")) + +function scan.write(self, section) + t2.render = t2._render + local ifname = self.map:get(section, "ifname") + luci.util.update(t2.data, luci.sys.wifi.iwscan(ifname)) +end + +t2._render = t2.render +t2.render = function() end + +t2:option(DummyValue, "Quality", translate("iwscan_link")) +essid = t2:option(DummyValue, "ESSID", "ESSID") +function essid.cfgvalue(self, section) + return luci.util.pcdata(self.map:get(section, "ESSID")) +end + +t2:option(DummyValue, "Address", "BSSID") +t2:option(DummyValue, "Mode", translate("mode")) +chan = t2:option(DummyValue, "channel", translate("channel")) +function chan.cfgvalue(self, section) + return self.map:get(section, "Channel") + or self.map:get(section, "Frequency") + or "-" +end + +t2:option(DummyValue, "Encryption key", translate("iwscan_encr")) + +t2:option(DummyValue, "Signal level", translate("iwscan_signal")) + +t2:option(DummyValue, "Noise level", translate("iwscan_noise")) + + +-- Routes -- +r = SimpleForm("routes", "Standardrouten") +r.submit = false +r.reset = false + +local routes = {} +for i, route in ipairs(luci.sys.net.routes()) do + if route.dest:prefix() == 0 then + routes[#routes+1] = route + end +end + +v = r:section(Table, routes) + +net = v:option(DummyValue, "iface", translate("network")) +function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes[section].device) + or routes[section].device +end + +target = v:option(DummyValue, "target", translate("target")) +function target.cfgvalue(self, section) + return routes[section].dest:network():string() +end + +netmask = v:option(DummyValue, "netmask", translate("netmask")) +function netmask.cfgvalue(self, section) + return routes[section].dest:mask():string() +end + +gateway = v:option(DummyValue, "gateway", translate("gateway")) +function gateway.cfgvalue(self, section) + return routes[section].gateway:string() +end + +metric = v:option(DummyValue, "metric", translate("metric")) +function metric.cfgvalue(self, section) + return routes[section].metric +end + + +local routes6 = {} +for i, route in ipairs(luci.sys.net.routes6() or {}) do + if route.dest:prefix() == 0 then + routes6[#routes6+1] = route + end +end + +if #routes6 > 0 then + v6 = r:section(Table, routes6) + + net = v6:option(DummyValue, "iface", translate("network")) + function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes[section].device) + or routes6[section].device + end + + target = v6:option(DummyValue, "target", translate("target")) + function target.cfgvalue(self, section) + return routes6[section].dest:string() + end + + gateway = v6:option(DummyValue, "gateway6", translate("gateway6")) + function gateway.cfgvalue(self, section) + return routes6[section].source:string() + end + + metric = v6:option(DummyValue, "metric", translate("metric")) + function metric.cfgvalue(self, section) + local metr = routes6[section].metric + local lower = bit.band(metr, 0xffff) + local higher = bit.rshift(bit.band(metr, 0xffff0000), 16) + return "%04X%04X" % {higher, lower} + end +end + +return f, m, r diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/hd_idle.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/hd_idle.lua new file mode 100644 index 0000000..32ca85b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/hd_idle.lua @@ -0,0 +1,41 @@ +--[[ + +LuCI hd-idle +(c) 2008 Yanira + +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: hd_idle.lua 3503 2008-10-03 16:49:00Z jow $ + +]]-- + +require("luci.fs") + +m = Map("hd-idle", translate("hd_idle"), translate("hd_idle_desc")) + +s = m:section(TypedSection, "hd-idle", translate("settings")) +s.anonymous = true + +s:option(Flag, "enabled", translate("enable", "Enable")) + +disk = s:option(Value, "disk", translate("disk")) +disk.rmempty = true +for _, dev in ipairs(luci.fs.glob("/dev/[sh]d[a-z]")) do + disk:value(luci.fs.basename(dev)) +end + +s:option(Value, "idle_time_interval", translate("idle_time_interval")).default = 10 +s.rmempty = true +unit = s:option(ListValue, "idle_time_unit", translate("idle_time_unit")) +unit.default = "minutes" +unit:value("minutes", "min") +unit:value("hours", "h") +unit.rmempty = true + +s:option(Flag, "enable_debug", translate("enable_debug")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/init/init.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/init/init.lua new file mode 100644 index 0000000..0523fe9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/init/init.lua @@ -0,0 +1,58 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: init.lua 3528 2008-10-06 20:09:06Z jow $ +]]-- + +require("luci.sys") +require("luci.util") + +local inits = { } + +for _, name in ipairs(luci.sys.init.names()) do + local index = luci.sys.init.index(name) + local enabled = luci.sys.init.enabled(name) + + inits["%02i.%s" % { index, name }] = { + name = name, + index = tostring(index), + enabled = enabled + } +end + + +m = SimpleForm("initmgr", translate("initmgr"), translate("initmgr_desc")) +m.reset = false + +s = m:section(Table, inits) + +i = s:option(DummyValue, "index", translate("initmgr_index")) +n = s:option(DummyValue, "name", translate("initmgr_name")) + +e = s:option(Flag, "enabled", translate("initmgr_enabled")) + +e.cfgvalue = function(self, section) + return inits[section].enabled and "1" or "0" +end + +e.write = function(self, section, value) + if value == "1" and not inits[section].enabled then + inits[section].enabled = true + return luci.sys.init.enable(inits[section].name) + elseif value == "0" and inits[section].enabled then + inits[section].enabled = false + return luci.sys.init.disable(inits[section].name) + end + return true +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/miniportfw.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/miniportfw.lua new file mode 100644 index 0000000..8d27375 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/miniportfw.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: miniportfw.lua 3070 2008-09-02 11:27:00Z Cyrus $ +]]-- +require("luci.sys") +m = Map("firewall", translate("fw_portfw"), translate("fw_portfw1")) + + +s = m:section(TypedSection, "redirect", "") +s:depends("src", "wan") +s.defaults.src = "wan" + +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true + +name = s:option(Value, "_name", translate("name"), translate("cbi_optional")) +name.size = 10 + +proto = s:option(ListValue, "proto", translate("protocol")) +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("tcpudp", "TCP+UDP") + +dport = s:option(Value, "src_dport") +dport.size = 5 + +to = s:option(Value, "dest_ip") +for i, dataset in ipairs(luci.sys.net.arptable()) do + to:value(dataset["IP address"]) +end + +toport = s:option(Value, "dest_port") +toport.size = 5 + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/redirect.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/redirect.lua new file mode 100644 index 0000000..12a738e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/redirect.lua @@ -0,0 +1,50 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: redirect.lua 3500 2008-10-03 16:23:43Z Cyrus $ +]]-- +require("luci.sys") +m = Map("firewall", translate("fw_redirect"), translate("fw_redirect_desc")) + + +s = m:section(TypedSection, "redirect", "") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true +s.extedit = luci.dispatcher.build_url("admin", "network", "firewall", "redirect", "%s") + +name = s:option(Value, "_name", translate("name"), translate("cbi_optional")) +name.size = 10 + +iface = s:option(ListValue, "src", translate("fw_zone")) +iface.default = "wan" +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + end) + +proto = s:option(ListValue, "proto", translate("protocol")) +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("tcpudp", "TCP+UDP") + +dport = s:option(Value, "src_dport") +dport.size = 5 + +to = s:option(Value, "dest_ip") +for i, dataset in ipairs(luci.sys.net.arptable()) do + to:value(dataset["IP address"]) +end + +toport = s:option(Value, "dest_port") +toport.size = 5 + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/rrule.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/rrule.lua new file mode 100644 index 0000000..d9222ec --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/rrule.lua @@ -0,0 +1,69 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: rrule.lua 4200 2009-01-30 18:57:14Z Cyrus $ +]]-- +require("luci.sys") +arg[1] = arg[1] or "" + +m = Map("firewall", translate("fw_redirect"), translate("fw_redirect_desc")) + + +s = m:section(NamedSection, arg[1], "redirect", "") +s.anonymous = true +s.addremove = false + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "redirect") + +name = s:option(Value, "_name", translate("name")) +name.rmempty = true +name.size = 10 + +iface = s:option(ListValue, "src", translate("fw_zone")) +iface.default = "wan" +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + end) + +s:option(Value, "src_ip", translate("firewall_redirect_srcip")).optional = true +s:option(Value, "src_mac", translate("firewall_redirect_srcmac")).optional = true + +sport = s:option(Value, "src_port", translate("firewall_rule_srcport")) +sport:depends("proto", "tcp") +sport:depends("proto", "udp") +sport:depends("proto", "tcpudp") + +proto = s:option(ListValue, "proto", translate("protocol")) +proto.optional = true +proto:value("") +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("tcpudp", "TCP+UDP") + +dport = s:option(Value, "src_dport", translate("firewall_redirect_srcdport")) +dport.size = 5 +dport:depends("proto", "tcp") +dport:depends("proto", "udp") +dport:depends("proto", "tcpudp") + +to = s:option(Value, "dest_ip", translate("firewall_redirect_destip")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + to:value(dataset["IP address"]) +end + +toport = s:option(Value, "dest_port", translate("firewall_redirect_destport")) +toport.optional = true +toport.size = 5 + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/traffic.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/traffic.lua new file mode 100644 index 0000000..994e3de --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/traffic.lua @@ -0,0 +1,82 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: traffic.lua 4181 2009-01-29 15:04:16Z Cyrus $ +]]-- + +m = Map("firewall", translate("fw_traffic")) +s = m:section(TypedSection, "forwarding", translate("fw_forwarding"), translate("fw_forwarding1")) +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true + +iface = s:option(ListValue, "src", translate("fw_src")) +oface = s:option(ListValue, "dest", translate("fw_dest")) +s:option(Flag, "mtu_fix", translate("fw_mtufix")) + +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + oface:value(section.name) + end) + + + +s = m:section(TypedSection, "rule") +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" +s.extedit = luci.dispatcher.build_url("admin", "network", "firewall", "rule", "%s") +s.defaults.target = "ACCEPT" + +local created = nil + +function s.create(self, section) + created = TypedSection.create(self, section) +end + +function s.parse(self, ...) + TypedSection.parse(self, ...) + if created then + m.uci:save("firewall") + luci.http.redirect(luci.dispatcher.build_url( + "admin", "network", "firewall", "rule", created + )) + end +end + +s:option(DummyValue, "_name", translate("name")) +s:option(DummyValue, "proto", translate("protocol")) + +src = s:option(DummyValue, "src", translate("fw_src")) +function src.cfgvalue(self, s) + return "%s:%s:%s" % { + self.map:get(s, "src") or "*", + self.map:get(s, "src_ip") or "0.0.0.0/0", + self.map:get(s, "src_port") or "*" + } +end + +dest = s:option(DummyValue, "dest", translate("fw_dest")) +function dest.cfgvalue(self, s) + return "%s:%s:%s" % { + self.map:get(s, "dest") or translate("device", "device"), + self.map:get(s, "dest_ip") or "0.0.0.0/0", + self.map:get(s, "dest_port") or "*" + } +end + + +s:option(DummyValue, "target") + + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/trule.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/trule.lua new file mode 100644 index 0000000..cda4e52 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/trule.lua @@ -0,0 +1,72 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: trule.lua 4012 2009-01-09 10:05:59Z Cyrus $ +]]-- +arg[1] = arg[1] or "" +m = Map("firewall", translate("firewall_rule"), translate("firewall_rule_desc")) + +s = m:section(NamedSection, arg[1], "rule", "") +s.anonymous = true +s.addremove = false + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "rule") + + +name = s:option(Value, "_name", translate("name")..translate("cbi_optional")) +name.rmempty = true + +iface = s:option(ListValue, "src", translate("fw_src")) +iface.rmempty = true + +oface = s:option(ListValue, "dest", translate("fw_dest")) +oface:value("", translate("device", "device")) +oface.rmempty = true + +luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + iface:value(section.name) + oface:value(section.name) + end) + +proto = s:option(Value, "proto", translate("protocol")) +proto.optional = true +proto:value("") +proto:value("tcpudp", "TCP+UDP") +proto:value("tcp", "TCP") +proto:value("udp", "UDP") +proto:value("icmp", "ICMP") + +s:option(Value, "src_ip", translate("firewall_rule_srcip")).optional = true +s:option(Value, "dest_ip", translate("firewall_rule_destip")).optional = true +s:option(Value, "src_mac", translate("firewall_rule_srcmac")).optional = true + +sport = s:option(Value, "src_port", translate("firewall_rule_srcport")) +sport:depends("proto", "tcp") +sport:depends("proto", "udp") +sport:depends("proto", "tcpudp") + +dport = s:option(Value, "dest_port", translate("firewall_rule_destport")) +dport:depends("proto", "tcp") +dport:depends("proto", "udp") +dport:depends("proto", "tcpudp") + +jump = s:option(ListValue, "target", translate("firewall_rule_target")) +jump.rmempty = true +jump.default = "ACCEPT" +jump:value("DROP", translate("fw_drop")) +jump:value("ACCEPT", translate("fw_accept")) +jump:value("REJECT", translate("fw_reject")) + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/zones.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/zones.lua new file mode 100644 index 0000000..a07149f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_fw/zones.lua @@ -0,0 +1,71 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: zones.lua 4051 2009-01-16 20:29:47Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("firewall", translate("fw_fw"), translate("fw_fw1")) + +s = m:section(TypedSection, "defaults") +s.anonymous = true + +s:option(Flag, "syn_flood") + +local di = s:option(Flag, "drop_invalid", translate("fw_dropinvalid")) +di.rmempty = false +function di.cfgvalue(...) + return AbstractValue.cfgvalue(...) or "1" +end + +p = {} +p[1] = s:option(ListValue, "input") +p[2] = s:option(ListValue, "output") +p[3] = s:option(ListValue, "forward") + +for i, v in ipairs(p) do + v:value("REJECT", translate("fw_reject")) + v:value("DROP", translate("fw_drop")) + v:value("ACCEPT", translate("fw_accept")) +end + + +s = m:section(TypedSection, "zone", translate("fw_zones")) +s.template = "cbi/tblsection" +s.anonymous = true +s.addremove = true + +name = s:option(Value, "name", translate("name")) +name.size = 8 + +p = {} +p[1] = s:option(ListValue, "input") +p[2] = s:option(ListValue, "output") +p[3] = s:option(ListValue, "forward") + +for i, v in ipairs(p) do + v:value("REJECT", translate("fw_reject")) + v:value("DROP", translate("fw_drop")) + v:value("ACCEPT", translate("fw_accept")) +end + +s:option(Flag, "masq") + +net = s:option(MultiValue, "network") +net.widget = "select" +net.rmempty = true +luci.tools.webadmin.cbi_add_networks(net) + +function net.cfgvalue(self, section) + local value = MultiValue.cfgvalue(self, section) + return value or name:cfgvalue(section) +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/collectd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/collectd.lua new file mode 100644 index 0000000..2b03eaa --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/collectd.lua @@ -0,0 +1,74 @@ +--[[ + +Luci configuration model for statistics - general collectd configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: collectd.lua 2317 2008-06-08 14:19:26Z jow $ + +]]-- + +require("luci.sys") + + +--[[ +m = Map("luci_statistics", "Collector Daemon", +Collectd ist ein kleiner und flexibler Dienst zum Sammeln und Abfragen von Daten +aus verschieden Quellen. Zur weiteren Verarbeitung werden die Daten in RRD Datenbanken +gespeichert oder per Multicast Relaying über das Netzwerk versendet.) +]]-- +m = Map("luci_statistics") + +-- general config section +s = m:section( NamedSection, "collectd", "luci_statistics" ) + +-- general.hostname (Hostname) +hostname = s:option( Value, "Hostname" ) +hostname.default = luci.sys.hostname() +hostname.optional = true + +-- general.basedir (BaseDir) +basedir = s:option( Value, "BaseDir" ) +basedir.default = "/var/run/collectd" + +-- general.include (Include) +include = s:option( Value, "Include" ) +include.default = "/etc/collectd/conf.d/*.conf" + +-- general.plugindir (PluginDir) +plugindir = s:option( Value, "PluginDir" ) +plugindir.default = "/usr/lib/collectd/" + +-- general.pidfile (PIDFile) +pidfile = s:option( Value, "PIDFile" ) +pidfile.default = "/var/run/collectd.pid" + +-- general.typesdb (TypesDB) +typesdb = s:option( Value, "TypesDB" ) +typesdb.default = "/etc/collectd/types.db" + +-- general.interval (Interval) +interval = s:option( Value, "Interval" ) +interval.default = 60 +interval.isnumber = true + +-- general.readthreads (ReadThreads) +readthreads = s:option( Value, "ReadThreads" ) +readthreads.default = 5 +readthreads.isnumber = true + +-- general.fqdnlookup (FQDNLookup) +fqdnlookup = s:option( Flag, "FQDNLookup" ) +fqdnlookup.enabled = "true" +fqdnlookup.disabled = "false" +fqdnlookup.default = "false" +fqdnlookup.optional = true +fqdnlookup:depends( "Hostname", "" ) + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/cpu.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/cpu.lua new file mode 100644 index 0000000..5744411 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/cpu.lua @@ -0,0 +1,25 @@ +--[[ + +Luci configuration model for statistics - collectd cpu plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: cpu.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_cpu config section +s = m:section( NamedSection, "collectd_cpu", "luci_statistics" ) + +-- collectd_cpu.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/csv.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/csv.lua new file mode 100644 index 0000000..d3d00b2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/csv.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd csv plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: csv.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_csv config section +s = m:section( NamedSection, "collectd_csv", "luci_statistics" ) + +-- collectd_csv.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_csv.datadir (DataDir) +datadir = s:option( Value, "DataDir" ) +datadir.default = "127.0.0.1" +datadir:depends( "enable", 1 ) + +-- collectd_csv.storerates (StoreRates) +storerates = s:option( Flag, "StoreRates" ) +storerates.default = 0 +storerates:depends( "enable", 1 ) + +return m + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/df.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/df.lua new file mode 100644 index 0000000..7cc4860 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/df.lua @@ -0,0 +1,48 @@ +--[[ + +Luci configuration model for statistics - collectd df plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: df.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_df config section +s = m:section( NamedSection, "collectd_df", "luci_statistics" ) + +-- collectd_df.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_df.devices (Device) +devices = s:option( Value, "Devices" ) +devices.default = "/dev/mtdblock/4" +devices.optional = true +devices:depends( "enable", 1 ) + +-- collectd_df.mountpoints (MountPoint) +mountpoints = s:option( Value, "MountPoints" ) +mountpoints.default = "/jffs" +mountpoints.optional = true +mountpoints:depends( "enable", 1 ) + +-- collectd_df.fstypes (FSType) +fstypes = s:option( Value, "FSTypes" ) +fstypes.default = "tmpfs" +fstypes.optional = true +fstypes:depends( "enable", 1 ) + +-- collectd_df.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/disk.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/disk.lua new file mode 100644 index 0000000..8ca6de2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/disk.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd disk plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: disk.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_disk config section +s = m:section( NamedSection, "collectd_disk", "luci_statistics" ) + +-- collectd_disk.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_disk.disks (Disk) +devices = s:option( Value, "Disks" ) +devices.default = "hda1 hdb" +devices.rmempty = true +devices:depends( "enable", 1 ) + +-- collectd_disk.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/dns.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/dns.lua new file mode 100644 index 0000000..bd65e0b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/dns.lua @@ -0,0 +1,43 @@ +--[[ + +Luci configuration model for statistics - collectd dns plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: dns.lua 3648 2008-10-29 19:11:54Z jow $ + +]]-- + +require("luci.sys") + + +m = Map("luci_statistics") + +-- collectd_dns config section +s = m:section( NamedSection, "collectd_dns", "luci_statistics" ) + +-- collectd_dns.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_dns.interfaces (Interface) +interfaces = s:option( MultiValue, "Interfaces" ) +interfaces.widget = "select" +interfaces.size = 5 +interfaces:depends( "enable", 1 ) +interfaces:value("any") +for k, v in pairs(luci.sys.net.devices()) do + interfaces:value(v) +end + +-- collectd_dns.ignoresources (IgnoreSource) +ignoresources = s:option( Value, "IgnoreSources" ) +ignoresources.default = "127.0.0.1" +ignoresources:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/email.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/email.lua new file mode 100644 index 0000000..46c7863 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/email.lua @@ -0,0 +1,52 @@ +--[[ + +Luci configuration model for statistics - collectd email plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: email.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_email config section +s = m:section( NamedSection, "collectd_email", "luci_statistics" ) + +-- collectd_email.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_email.socketfile (SocketFile) +socketfile = s:option( Value, "SocketFile" ) +socketfile.default = "/var/run/collect-email.sock" +socketfile:depends( "enable", 1 ) + +-- collectd_email.socketgroup (SocketGroup) +socketgroup = s:option( Value, "SocketGroup" ) +socketgroup.default = "nobody" +socketgroup.rmempty = true +socketgroup.optional = true +socketgroup:depends( "enable", 1 ) + +-- collectd_email.socketperms (SocketPerms) +socketperms = s:option( Value, "SocketPerms" ) +socketperms.default = "0770" +socketperms.rmempty = true +socketperms.optional = true +socketperms:depends( "enable", 1 ) + +-- collectd_email.maxconns (MaxConns) +maxconns = s:option( Value, "MaxConns" ) +maxconns.default = 5 +maxconns.isinteger = true +maxconns.rmempty = true +maxconns.optional = true +maxconns:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/exec.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/exec.lua new file mode 100644 index 0000000..4e47712 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/exec.lua @@ -0,0 +1,70 @@ +--[[ + +Luci configuration model for statistics - collectd exec plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: exec.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_exec config section +s = m:section( NamedSection, "collectd_exec", "luci_statistics" ) + +-- collectd_exec.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + + +-- collectd_exec_input config section (Exec directives) +exec = m:section( TypedSection, "collectd_exec_input" ) +exec.addremove = true +exec.anonymous = true + +-- collectd_exec_input.cmdline +exec_cmdline = exec:option( Value, "cmdline" ) +exec_cmdline.default = "/usr/bin/stat-dhcpusers" + +-- collectd_exec_input.cmdline +exec_cmduser = exec:option( Value, "cmduser" ) +exec_cmduser.default = "nobody" +exec_cmduser.rmempty = true +exec_cmduser.optional = true + +-- collectd_exec_input.cmdline +exec_cmdgroup = exec:option( Value, "cmdgroup" ) +exec_cmdgroup.default = "nogroup" +exec_cmdgroup.rmempty = true +exec_cmdgroup.optional = true + + +-- collectd_exec_notify config section (NotifyExec directives) +notify = m:section( TypedSection, "collectd_exec_notify" ) +notify.addremove = true +notify.anonymous = true + +-- collectd_notify_input.cmdline +notify_cmdline = notify:option( Value, "cmdline" ) +notify_cmdline.default = "/usr/bin/stat-dhcpusers" + +-- collectd_notify_input.cmdline +notify_cmduser = notify:option( Value, "cmduser" ) +notify_cmduser.default = "nobody" +notify_cmduser.rmempty = true +notify_cmduser.optional = true + +-- collectd_notify_input.cmdline +notify_cmdgroup = notify:option( Value, "cmdgroup" ) +notify_cmdgroup.default = "nogroup" +notify_cmdgroup.rmempty = true +notify_cmdgroup.optional = true + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/interface.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/interface.lua new file mode 100644 index 0000000..40b843d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/interface.lua @@ -0,0 +1,42 @@ +--[[ + +Luci configuration model for statistics - collectd interface plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: interface.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +require("luci.sys") + + +m = Map("luci_statistics") + +-- collectd_interface config section +s = m:section( NamedSection, "collectd_interface", "luci_statistics" ) + +-- collectd_interface.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_interface.interfaces (Interface) +interfaces = s:option( MultiValue, "Interfaces" ) +interfaces.widget = "select" +interfaces.size = 5 +interfaces:depends( "enable", 1 ) +for k, v in pairs(luci.sys.net.devices()) do + interfaces:value(v) +end + +-- collectd_interface.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/iptables.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/iptables.lua new file mode 100644 index 0000000..865b32d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/iptables.lua @@ -0,0 +1,116 @@ +--[[ + +Luci configuration model for statistics - collectd iptables plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: iptables.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +require("luci.sys.iptparser") + +ip = luci.sys.iptparser.IptParser() +chains = { } +targets = { } + +for i, rule in ipairs( ip:find() ) do + chains[rule.chain] = true + targets[rule.target] = true +end + + +m = Map("luci_statistics") + +-- collectd_iptables config section +s = m:section( NamedSection, "collectd_iptables", "luci_statistics" ) + +-- collectd_iptables.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + + +-- collectd_iptables_match config section (Chain directives) +rule = m:section( TypedSection, "collectd_iptables_match" ) +rule.addremove = true +rule.anonymous = true + + +-- collectd_iptables_match.name +rule_table = rule:option( Value, "name" ) + +-- collectd_iptables_match.table +rule_table = rule:option( ListValue, "table" ) +rule_table.default = "filter" +rule_table.rmempty = true +rule_table.optional = true +rule_table:value("") +rule_table:value("filter") +rule_table:value("nat") +rule_table:value("mangle") + + +-- collectd_iptables_match.chain +rule_chain = rule:option( ListValue, "chain" ) +rule_chain.rmempty = true +rule_chain.optional = true +rule_chain:value("") + +for chain, void in pairs( chains ) do + rule_chain:value( chain ) +end + + +-- collectd_iptables_match.target +rule_target = rule:option( ListValue, "target" ) +rule_target.rmempty = true +rule_target.optional = true +rule_target:value("") + +for target, void in pairs( targets ) do + rule_target:value( target ) +end + + +-- collectd_iptables_match.protocol +rule_protocol = rule:option( ListValue, "protocol" ) +rule_protocol.rmempty = true +rule_protocol.optional = true +rule_protocol:value("") +rule_protocol:value("tcp") +rule_protocol:value("udp") +rule_protocol:value("icmp") + +-- collectd_iptables_match.source +rule_source = rule:option( Value, "source" ) +rule_source.default = "0.0.0.0/0" +rule_source.rmempty = true +rule_source.optional = true + +-- collectd_iptables_match.destination +rule_destination = rule:option( Value, "destination" ) +rule_destination.default = "0.0.0.0/0" +rule_destination.rmempty = true +rule_destination.optional = true + +-- collectd_iptables_match.inputif +rule_inputif = rule:option( Value, "inputif" ) +rule_inputif.rmempty = true +rule_inputif.optional = true + +-- collectd_iptables_match.outputif +rule_outputif = rule:option( Value, "outputif" ) +rule_outputif.rmempty = true +rule_outputif.optional = true + +-- collectd_iptables_match.options +rule_options = rule:option( Value, "options" ) +rule_options.rmempty = true +rule_options.optional = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/irq.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/irq.lua new file mode 100644 index 0000000..41f09a7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/irq.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd irq plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: irq.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_irq config section +s = m:section( NamedSection, "collectd_irq", "luci_statistics" ) + +-- collectd_irq.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_irq.irqs (Irq) +irqs = s:option( Value, "Irqs" ) +irqs.optional = true +irqs:depends( "enable", 1 ) + +-- collectd_irq.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected.optional = "true" +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/load.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/load.lua new file mode 100644 index 0000000..ae97d7f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/load.lua @@ -0,0 +1,25 @@ +--[[ + +Luci configuration model for statistics - collectd load plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: load.lua 2329 2008-06-08 21:51:55Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_wireless config section +s = m:section( NamedSection, "collectd_load", "luci_statistics" ) + +-- collectd_wireless.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/netlink.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/netlink.lua new file mode 100644 index 0000000..b7e8d34 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/netlink.lua @@ -0,0 +1,90 @@ +--[[ + +Luci configuration model for statistics - collectd netlink plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: netlink.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +require("luci.sys") + +local devices = luci.sys.net.devices() + + +m = Map("luci_statistics") + +-- collectd_netlink config section +s = m:section( NamedSection, "collectd_netlink", "luci_statistics" ) + +-- collectd_netlink.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_netlink.interfaces (Interface) +interfaces = s:option( MultiValue, "Interfaces" ) +interfaces.widget = "select" +interfaces.optional = true +interfaces.size = #devices + 1 +interfaces:depends( "enable", 1 ) +interfaces:value("") +for i, v in ipairs(devices) do + interfaces:value(v) +end + +-- collectd_netlink.verboseinterfaces (VerboseInterface) +verboseinterfaces = s:option( MultiValue, "VerboseInterfaces" ) +verboseinterfaces.widget = "select" +verboseinterfaces.optional = true +verboseinterfaces.size = #devices + 1 +verboseinterfaces:depends( "enable", 1 ) +verboseinterfaces:value("") +for i, v in ipairs(devices) do + verboseinterfaces:value(v) +end + +-- collectd_netlink.qdiscs (QDisc) +qdiscs = s:option( MultiValue, "QDiscs" ) +qdiscs.widget = "select" +qdiscs.optional = true +qdiscs.size = #devices + 1 +qdiscs:depends( "enable", 1 ) +qdiscs:value("") +for i, v in ipairs(devices) do + qdiscs:value(v) +end + +-- collectd_netlink.classes (Class) +classes = s:option( MultiValue, "Classes" ) +classes.widget = "select" +classes.optional = true +classes.size = #devices + 1 +classes:depends( "enable", 1 ) +classes:value("") +for i, v in ipairs(devices) do + classes:value(v) +end + +-- collectd_netlink.filters (Filter) +filters = s:option( MultiValue, "Filters" ) +filters.widget = "select" +filters.optional = true +filters.size = #devices + 1 +filters:depends( "enable", 1 ) +filters:value("") +for i, v in ipairs(devices) do + filters:value(v) +end + +-- collectd_netlink.ignoreselected (IgnoreSelected) +ignoreselected = s:option( Flag, "IgnoreSelected" ) +ignoreselected.default = 0 +ignoreselected:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/network.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/network.lua new file mode 100644 index 0000000..7364e89 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/network.lua @@ -0,0 +1,79 @@ +--[[ + +Luci configuration model for statistics - collectd network plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: network.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + + +m = Map("luci_statistics") + +-- collectd_network config section +s = m:section( NamedSection, "collectd_network", "luci_statistics" ) + +-- collectd_network.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + + +-- collectd_network_listen config section (Listen) +listen = m:section( TypedSection, "collectd_network_listen" ) +listen.addremove = true +listen.anonymous = true + +-- collectd_network_listen.host +listen_host = listen:option( Value, "host" ) +listen_host.default = "0.0.0.0" + +-- collectd_network_listen.port +listen_port = listen:option( Value, "port" ) +listen_port.default = 25826 +listen_port.isinteger = true +listen_port.optional = true + + +-- collectd_network_server config section (Server) +server = m:section( TypedSection, "collectd_network_server" ) +server.addremove = true +server.anonymous = true + +-- collectd_network_server.host +server_host = server:option( Value, "host" ) +server_host.default = "0.0.0.0" + +-- collectd_network_server.port +server_port = server:option( Value, "port" ) +server_port.default = 25826 +server_port.isinteger = true +server_port.optional = true + +-- collectd_network.timetolive (TimeToLive) +ttl = s:option( Value, "TimeToLive" ) +ttl.default = 128 +ttl.isinteger = true +ttl.optional = true +ttl:depends( "enable", 1 ) + +-- collectd_network.forward (Forward) +forward = s:option( Flag, "Forward" ) +forward.default = 0 +forward.optional = true +forward:depends( "enable", 1 ) + +-- collectd_network.cacheflush (CacheFlush) +cacheflush = s:option( Value, "CacheFlush" ) +cacheflush.default = 86400 +cacheflush.isinteger = true +cacheflush.optional = true +cacheflush:depends( "enable", 1 ) + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/ping.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/ping.lua new file mode 100644 index 0000000..0bcb264 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/ping.lua @@ -0,0 +1,36 @@ +--[[ + +Luci configuration model for statistics - collectd ping plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ping.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_ping config section +s = m:section( NamedSection, "collectd_ping", "luci_statistics" ) + +-- collectd_ping.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_ping.hosts (Host) +hosts = s:option( Value, "Hosts" ) +hosts.default = "127.0.0.1" +hosts:depends( "enable", 1 ) + +-- collectd_ping.ttl (TTL) +ttl = s:option( Value, "TTL" ) +ttl.isinteger = true +ttl.default = 128 +ttl:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/processes.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/processes.lua new file mode 100644 index 0000000..08386c5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/processes.lua @@ -0,0 +1,30 @@ +--[[ + +Luci configuration model for statistics - collectd processes plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: processes.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_processes config section +s = m:section( NamedSection, "collectd_processes", "luci_statistics" ) + +-- collectd_processes.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_processes.processes (Process) +processes = s:option( Value, "Processes" ) +processes.default = "olsrd bmxd httpd dnsmasq dropbear tinc" +processes:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/rrdtool.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/rrdtool.lua new file mode 100644 index 0000000..9f51794 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/rrdtool.lua @@ -0,0 +1,94 @@ +--[[ + +Luci configuration model for statistics - collectd rrdtool plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: rrdtool.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_rrdtool config section +s = m:section( NamedSection, "collectd_rrdtool", "luci_statistics" ) + +-- collectd_rrdtool.enable +enable = s:option( Flag, "enable" ) +enable.default = 1 + +-- collectd_rrdtool.datadir (DataDir) +datadir = s:option( Value, "DataDir" ) +datadir.default = "/tmp" +datadir.rmempty = true +datadir.optional = true +datadir:depends( "enable", 1 ) + +-- collectd_rrdtool.stepsize (StepSize) +stepsize = s:option( Value, "StepSize" ) +stepsize.default = 30 +stepsize.isinteger = true +stepsize.rmempty = true +stepsize.optional = true +stepsize:depends( "enable", 1 ) + +-- collectd_rrdtool.heartbeat (HeartBeat) +heartbeat = s:option( Value, "HeartBeat" ) +heartbeat.default = 60 +heartbeat.isinteger = true +heartbeat.rmempty = true +heartbeat.optional = true +heartbeat:depends( "enable", 1 ) + +-- collectd_rrdtool.rrasingle (RRASingle) +rrasingle = s:option( Flag, "RRASingle" ) +rrasingle.default = true +rrasingle.rmempty = true +rrasingle.optional = true +rrasingle:depends( "enable", 1 ) + +-- collectd_rrdtool.rratimespans (RRATimespan) +rratimespans = s:option( Value, "RRATimespans" ) +rratimespans.default = "600 86400 604800 2678400 31622400" +rratimespans.rmempty = true +rratimespans.optional = true +rratimespans:depends( "enable", 1 ) + +-- collectd_rrdtool.rrarows (RRARows) +rrarows = s:option( Value, "RRARows" ) +rrarows.isinteger = true +rrarows.default = 100 +rrarows.rmempty = true +rrarows.optional = true +rrarows:depends( "enable", 1 ) + +-- collectd_rrdtool.xff (XFF) +xff = s:option( Value, "XFF" ) +xff.default = 0.1 +xff.isnumber = true +xff.rmempty = true +xff.optional = true +xff:depends( "enable", 1 ) + +-- collectd_rrdtool.cachetimeout (CacheTimeout) +cachetimeout = s:option( Value, "CacheTimeout" ) +cachetimeout.isinteger = true +cachetimeout.default = 100 +cachetimeout.rmempty = true +cachetimeout.optional = true +cachetimeout:depends( "enable", 1 ) + +-- collectd_rrdtool.cacheflush (CacheFlush) +cacheflush = s:option( Value, "CacheFlush" ) +cacheflush.isinteger = true +cacheflush.default = 100 +cacheflush.rmempty = true +cacheflush.optional = true +cacheflush:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/tcpconns.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/tcpconns.lua new file mode 100644 index 0000000..281e581 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/tcpconns.lua @@ -0,0 +1,40 @@ +--[[ + +Luci configuration model for statistics - collectd tcpconns plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: tcpconns.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_tcpconns config section +s = m:section( NamedSection, "collectd_tcpconns", "luci_statistics" ) + +-- collectd_tcpconns.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_tcpconns.listeningports (ListeningPorts) +listeningports = s:option( Flag, "ListeningPorts" ) +listeningports.default = 1 +listeningports:depends( "enable", 1 ) + +-- collectd_tcpconns.localports (LocalPort) +localports = s:option( Value, "LocalPorts" ) +localports.optional = true +localports:depends( "enable", 1 ) + +-- collectd_tcpconns.remoteports (RemotePort) +remoteports = s:option( Value, "RemotePorts" ) +remoteports.optional = true +remoteports:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/unixsock.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/unixsock.lua new file mode 100644 index 0000000..f812200 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/unixsock.lua @@ -0,0 +1,44 @@ +--[[ + +Luci configuration model for statistics - collectd unixsock plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: unixsock.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_unixsock config section +s = m:section( NamedSection, "collectd_unixsock", "luci_statistics" ) + +-- collectd_unixsock.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +-- collectd_unixsock.socketfile (SocketFile) +socketfile = s:option( Value, "SocketFile" ) +socketfile.default = "/var/run/collect-query.socket" +socketfile:depends( "enable", 1 ) + +-- collectd_unixsock.socketgroup (SocketGroup) +socketgroup = s:option( Value, "SocketGroup" ) +socketgroup.default = "nobody" +socketgroup.rmempty = true +socketgroup.optional = true +socketgroup:depends( "enable", 1 ) + +-- collectd_unixsock.socketperms (SocketPerms) +socketperms = s:option( Value, "SocketPerms" ) +socketperms.default = "0770" +socketperms.rmempty = true +socketperms.optional = true +socketperms:depends( "enable", 1 ) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/wireless.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/wireless.lua new file mode 100644 index 0000000..7590dcd --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/luci_statistics/wireless.lua @@ -0,0 +1,25 @@ +--[[ + +Luci configuration model for statistics - collectd wireless plugin configuration +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: wireless.lua 2226 2008-06-01 23:52:07Z jow $ + +]]-- + +m = Map("luci_statistics") + +-- collectd_wireless config section +s = m:section( NamedSection, "collectd_wireless", "luci_statistics" ) + +-- collectd_wireless.enable +enable = s:option( Flag, "enable" ) +enable.default = 0 + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/dhcp.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/dhcp.lua new file mode 100644 index 0000000..56b4ede --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/dhcp.lua @@ -0,0 +1,105 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: dhcp.lua 3675 2008-10-31 09:36:00Z Cyrus $ +]]-- +require("luci.model.uci") +require("luci.sys") +require("luci.tools.webadmin") + +m = Map("dhcp", "DHCP") + +s = m:section(TypedSection, "dhcp", "DHCP-Server") +s.anonymous = true +s.addremove = false +s.dynamic = false + +s:depends("interface", "lan") + +enable = s:option(ListValue, "ignore", translate("enable"), "") +enable:value(0, translate("enable")) +enable:value(1, translate("disable")) + +start = s:option(Value, "start", translate("m_n_d_firstaddress")) +start.rmempty = true +start:depends("ignore", "0") + + +limit = s:option(Value, "limit", translate("m_n_d_numleases"), "") +limit:depends("ignore", "0") + +function limit.cfgvalue(self, section) + local value = Value.cfgvalue(self, section) + + if value then + return tonumber(value) + 1 + end +end + +function limit.write(self, section, value) + value = tonumber(value) - 1 + return Value.write(self, section, value) +end + +limit.rmempty = true + +time = s:option(Value, "leasetime") +time:depends("ignore", "0") +time.rmempty = true + + + +m2 = Map("luci_ethers", translate("dhcp_leases")) + +local leasefn, leasefp, leases +luci.model.uci.cursor():foreach("dhcp", "dnsmasq", + function(section) + leasefn = section.leasefile + end +) +local leasefp = leasefn and luci.fs.access(leasefn) and io.lines(leasefn) +if leasefp then + leases = {} + for lease in leasefp do + table.insert(leases, luci.util.split(lease, " ")) + end +end + +if leases then + v = m2:section(Table, leases, translate("dhcp_leases_active")) + ip = v:option(DummyValue, 3, translate("ipaddress")) + + mac = v:option(DummyValue, 2, translate("macaddress")) + + ltime = v:option(DummyValue, 1, translate("dhcp_timeremain")) + function ltime.cfgvalue(self, ...) + local value = DummyValue.cfgvalue(self, ...) + return luci.tools.webadmin.date_format( + os.difftime(tonumber(value), os.time()) + ) + end +end + +s = m2:section(TypedSection, "static_lease", translate("luci_ethers")) +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" + +mac = s:option(Value, "macaddr", translate("macaddress")) +ip = s:option(Value, "ipaddr", translate("ipaddress")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + ip:value(dataset["IP address"]) + mac:value(dataset["HW address"], + dataset["HW address"] .. " (" .. dataset["IP address"] .. ")") +end + +return m, m2 \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/index.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/index.lua new file mode 100644 index 0000000..34e3555 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/index.lua @@ -0,0 +1,14 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: index.lua 2891 2008-08-18 08:43:48Z Cyrus $ +]]-- +return Template("mini/index") diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/luci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/luci.lua new file mode 100644 index 0000000..627f6de --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/luci.lua @@ -0,0 +1,37 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: luci.lua 4038 2009-01-14 23:48:51Z Cyrus $ +]]-- +require("luci.config") +m = Map("luci", translate("webui"), translate("a_i_luci1")) + +-- force reload of global luci config namespace to reflect the changes +function m.commit_handler(self) + package.loaded["luci.config"] = nil + require("luci.config") +end + + +c = m:section(NamedSection, "main", "core", translate("general")) + +l = c:option(ListValue, "lang", translate("language")) +l:value("auto") + +local i18ndir = luci.i18n.i18ndir .. "default." +for k, v in pairs(luci.config.languages) do + if k:sub(1, 1) ~= "." and luci.fs.access(i18ndir .. k:gsub("_", "-") .. ".lua") then + l:value(k, v) + end +end + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/network.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/network.lua new file mode 100644 index 0000000..3cbc86c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/network.lua @@ -0,0 +1,196 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: network.lua 4171 2009-01-27 20:50:28Z Cyrus $ +]]-- + +require("luci.tools.webadmin") +require("luci.sys") +require("luci.fs") + +local has_pptp = luci.fs.mtime("/usr/sbin/pptp") +local has_pppoe = luci.fs.glob("/usr/lib/pppd/*/rp-pppoe.so") + +local network = luci.model.uci.cursor_state():get_all("network") + +local netstat = luci.sys.net.deviceinfo() +local ifaces = {} + +for k, v in pairs(network) do + if v[".type"] == "interface" and k ~= "loopback" then + table.insert(ifaces, v) + end +end + +m = Map("network", translate("network")) +s = m:section(Table, ifaces, translate("status")) +s.parse = function() end + +s:option(DummyValue, ".name", translate("network")) + +hwaddr = s:option(DummyValue, "_hwaddr", + translate("network_interface_hwaddr"), translate("network_interface_hwaddr_desc")) +function hwaddr.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") or "" + return luci.fs.readfile("/sys/class/net/" .. ix .. "/address") + or luci.util.exec("ifconfig " .. ix):match(" ([A-F0-9:]+)%s*\n") + or "n/a" +end + + +s:option(DummyValue, "ipaddr", translate("ipaddress")) + +s:option(DummyValue, "netmask", translate("netmask")) + + +txrx = s:option(DummyValue, "_txrx", + translate("network_interface_txrx"), translate("network_interface_txrx_desc")) + +function txrx.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][1] + rx = rx and luci.tools.webadmin.byte_format(tonumber(rx)) or "-" + + local tx = netstat and netstat[ix] and netstat[ix][9] + tx = tx and luci.tools.webadmin.byte_format(tonumber(tx)) or "-" + + return string.format("%s / %s", tx, rx) +end + +errors = s:option(DummyValue, "_err", + translate("network_interface_err"), translate("network_interface_err_desc")) + +function errors.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][3] + local tx = netstat and netstat[ix] and netstat[ix][11] + + rx = rx and tostring(rx) or "-" + tx = tx and tostring(tx) or "-" + + return string.format("%s / %s", tx, rx) +end + + + +s = m:section(NamedSection, "lan", "interface", translate("m_n_local")) +s.addremove = false +s:option(Value, "ipaddr", translate("ipaddress")) + +nm = s:option(Value, "netmask", translate("netmask")) +nm:value("255.255.255.0") +nm:value("255.255.0.0") +nm:value("255.0.0.0") + +gw = s:option(Value, "gateway", translate("gateway") .. translate("cbi_optional")) +gw.rmempty = true +dns = s:option(Value, "dns", translate("dnsserver") .. translate("cbi_optional")) +dns.rmempty = true + + +s = m:section(NamedSection, "wan", "interface", translate("m_n_inet")) +s.addremove = false +p = s:option(ListValue, "proto", translate("protocol")) +p.override_values = true +p:value("none", "disabled") +p:value("static", translate("manual", "manual")) +p:value("dhcp", translate("automatic", "automatic")) +if has_pppoe then p:value("pppoe", "PPPoE") end +if has_pptp then p:value("pptp", "PPTP") end + +function p.write(self, section, value) + -- Always set defaultroute to PPP and use remote dns + -- Overwrite a bad variable behaviour in OpenWrt + if value == "pptp" or value == "pppoe" then + self.map:set(section, "peerdns", "1") + self.map:set(section, "defaultroute", "1") + end + return ListValue.write(self, section, value) +end + +if not ( has_pppoe and has_pptp ) then + p.description = translate("network_interface_prereq_mini") +end + + +ip = s:option(Value, "ipaddr", translate("ipaddress")) +ip:depends("proto", "static") + +nm = s:option(Value, "netmask", translate("netmask")) +nm:depends("proto", "static") + +gw = s:option(Value, "gateway", translate("gateway")) +gw:depends("proto", "static") +gw.rmempty = true + +dns = s:option(Value, "dns", translate("dnsserver")) +dns:depends("proto", "static") +dns.rmempty = true + +usr = s:option(Value, "username", translate("username")) +usr:depends("proto", "pppoe") +usr:depends("proto", "pptp") + +pwd = s:option(Value, "password", translate("password")) +pwd.password = true +pwd:depends("proto", "pppoe") +pwd:depends("proto", "pptp") + + +-- Allow user to set MSS correction here if the UCI firewall is installed +-- This cures some cancer for providers with pre-war routers +if luci.fs.access("/etc/config/firewall") then + mssfix = s:option(Flag, "_mssfix", + translate("m_n_mssfix"), translate("m_n_mssfix_desc")) + mssfix.rmempty = false + + function mssfix.cfgvalue(self) + local value + m.uci:foreach("firewall", "forwarding", function(s) + if s.src == "lan" and s.dest == "wan" then + value = s.mtu_fix + end + end) + return value + end + + function mssfix.write(self, section, value) + m.uci:foreach("firewall", "forwarding", function(s) + if s.src == "lan" and s.dest == "wan" then + m.uci:set("firewall", s[".name"], "mtu_fix", value) + m:chain("firewall") + end + end) + end +end + +kea = s:option(Flag, "keepalive", translate("m_n_keepalive")) +kea:depends("proto", "pppoe") +kea:depends("proto", "pptp") +kea.rmempty = true +kea.enabled = "10" + + +cod = s:option(Value, "demand", translate("m_n_dialondemand"), "s") +cod:depends("proto", "pppoe") +cod:depends("proto", "pptp") +cod.rmempty = true + +srv = s:option(Value, "server", translate("m_n_pptp_server")) +srv:depends("proto", "pptp") +srv.rmempty = true + + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/passwd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/passwd.lua new file mode 100644 index 0000000..f078dd5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/passwd.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: passwd.lua 3864 2008-12-07 13:44:25Z Cyrus $ +]]-- +f = SimpleForm("password", translate("a_s_changepw"), translate("a_s_changepw1")) + +pw1 = f:field(Value, "pw1", translate("password")) +pw1.password = true +pw1.rmempty = false + +pw2 = f:field(Value, "pw2", translate("confirmation")) +pw2.password = true +pw2.rmempty = false + +function pw2.validate(self, value, section) + return pw1:formvalue(section) == value and value +end + +function f.handle(self, state, data) + if state == FORM_VALID then + local stat = luci.sys.user.setpasswd("root", data.pw1) == 0 + + if stat then + f.message = translate("a_s_changepw_changed") + else + f.errmessage = translate("unknownerror") + end + + data.pw1 = nil + data.pw2 = nil + end + return true +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/system.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/system.lua new file mode 100644 index 0000000..6ab7d0d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/system.lua @@ -0,0 +1,55 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: system.lua 3736 2008-11-06 23:10:43Z jow $ +]]-- + +require("luci.sys") +require("luci.sys.zoneinfo") +require("luci.tools.webadmin") + + +m = Map("system", translate("system"), translate("a_s_desc")) + +s = m:section(TypedSection, "system", "") +s.anonymous = true + + + +local system, model, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo() +local uptime = luci.sys.uptime() + +s:option(DummyValue, "_system", translate("system")).value = system +s:option(DummyValue, "_cpu", translate("m_i_processor")).value = model + +local load1, load5, load15 = luci.sys.loadavg() +s:option(DummyValue, "_la", translate("load")).value = + string.format("%.2f, %.2f, %.2f", load1, load5, load15) + +s:option(DummyValue, "_memtotal", translate("m_i_memory")).value = + string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)", + tonumber(memtotal) / 1024, + 100 * memcached / memtotal, + translate("mem_cached") or "", + 100 * membuffers / memtotal, + translate("mem_buffered") or "", + 100 * memfree / memtotal, + translate("mem_free") or "") + +s:option(DummyValue, "_systime", translate("m_i_systemtime")).value = + os.date("%c") + +s:option(DummyValue, "_uptime", translate("m_i_uptime")).value = + luci.tools.webadmin.date_format(tonumber(uptime)) + +s:option(DummyValue, "hostname", translate("hostname")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/wifi.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/wifi.lua new file mode 100644 index 0000000..a182fcb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mini/wifi.lua @@ -0,0 +1,277 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: wifi.lua 4223 2009-02-04 19:20:17Z Cyrus $ +]]-- + +-- Data init -- + +local uci = luci.model.uci.cursor() +if not uci:get("network", "wan") then + uci:section("network", "interface", "wan", {proto="none", ifname=" "}) + uci:save("network") + uci:commit("network") +end + +local wlcursor = luci.model.uci.cursor_state() +local wireless = wlcursor:get_all("wireless") +local wifidata = luci.sys.wifi.getiwconfig() +local wifidevs = {} +local ifaces = {} + +for k, v in pairs(wireless) do + if v[".type"] == "wifi-iface" then + table.insert(ifaces, v) + end +end + +wlcursor:foreach("wireless", "wifi-device", + function(section) + table.insert(wifidevs, section[".name"]) + end) + + +-- Main Map -- + +m = Map("wireless", translate("wifi"), translate("a_w_devices1")) +m:chain("network") + + +-- Status Table -- +s = m:section(Table, ifaces, translate("networks")) + +link = s:option(DummyValue, "_link", translate("link")) +function link.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Link Quality"] or "-" +end + +essid = s:option(DummyValue, "ssid", "ESSID") + +bssid = s:option(DummyValue, "_bsiid", "BSSID") +function bssid.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return (wifidata[ifname] and (wifidata[ifname].Cell + or wifidata[ifname]["Access Point"])) or "-" +end + +channel = s:option(DummyValue, "channel", translate("channel")) +function channel.cfgvalue(self, section) + return wireless[self.map:get(section, "device")].channel +end + +protocol = s:option(DummyValue, "_mode", translate("protocol")) +function protocol.cfgvalue(self, section) + local mode = wireless[self.map:get(section, "device")].mode + return mode and "802." .. mode +end + +mode = s:option(DummyValue, "mode", translate("mode")) +encryption = s:option(DummyValue, "encryption", translate("iwscan_encr")) + +power = s:option(DummyValue, "_power", translate("power")) +function power.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Tx-Power"] or "-" +end + +scan = s:option(Button, "_scan", translate("scan")) +scan.inputstyle = "find" + +function scan.cfgvalue(self, section) + return self.map:get(section, "ifname") or false +end + +-- WLAN-Scan-Table -- + +t2 = m:section(Table, {}, translate("iwscan"), translate("iwscan1")) + +function scan.write(self, section) + m.autoapply = false + t2.render = t2._render + local ifname = self.map:get(section, "ifname") + luci.util.update(t2.data, luci.sys.wifi.iwscan(ifname)) +end + +t2._render = t2.render +t2.render = function() end + +t2:option(DummyValue, "Quality", translate("iwscan_link")) +essid = t2:option(DummyValue, "ESSID", "ESSID") +function essid.cfgvalue(self, section) + return self.map:get(section, "ESSID") +end + +t2:option(DummyValue, "Address", "BSSID") +t2:option(DummyValue, "Mode", translate("mode")) +chan = t2:option(DummyValue, "channel", translate("channel")) +function chan.cfgvalue(self, section) + return self.map:get(section, "Channel") + or self.map:get(section, "Frequency") + or "-" +end + +t2:option(DummyValue, "Encryption key", translate("iwscan_encr")) + +t2:option(DummyValue, "Signal level", translate("iwscan_signal")) + +t2:option(DummyValue, "Noise level", translate("iwscan_noise")) + + + +if #wifidevs < 1 then + return m +end + +-- Config Section -- + +s = m:section(NamedSection, wifidevs[1], "wifi-device", translate("devices")) +s.addremove = false + +local hwtype = m:get(wifidevs[1], "type") + +if hwtype == "atheros" then + mode = s:option(ListValue, "hwmode", translate("mode")) + mode.override_values = true + mode:value("", "auto") + mode:value("11b", "802.11b") + mode:value("11g", "802.11g") + mode:value("11a", "802.11a") + mode:value("11bg", "802.11b+g") + mode.rmempty = true +end + + +ch = s:option(Value, "channel", translate("a_w_channel")) +for i=1, 14 do + ch:value(i, i .. " (2.4 GHz)") +end + + +s = m:section(TypedSection, "wifi-iface", translate("m_n_local")) +s.anonymous = true +s.addremove = false + +s:option(Value, "ssid", translate("a_w_netid")) + +bssid = s:option(Value, "bssid", translate("wifi_bssid")) + +local devs = {} +luci.model.uci.cursor():foreach("wireless", "wifi-device", + function (section) + table.insert(devs, section[".name"]) + end) + +if #devs > 1 then + device = s:option(DummyValue, "device", translate("device")) +else + s.defaults.device = devs[1] +end + +encr = s:option(ListValue, "encryption", translate("encryption")) +encr.override_values = true +encr:value("none", "No Encryption") +encr:value("wep", "WEP") + +if hwtype == "atheros" or hwtype == "mac80211" then + local supplicant = luci.fs.mtime("/usr/sbin/wpa_supplicant") + local hostapd = luci.fs.mtime("/usr/sbin/hostapd") + + if hostapd and supplicant then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") + encr:value("wpa", "WPA-Radius", {mode="ap"}) + encr:value("wpa2i", "WPA2-Radius", {mode="ap"}) + elseif hostapd and not supplicant then + encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="adhoc"}) + encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="adhoc"}) + encr:value("wpa", "WPA-Radius", {mode="ap"}) + encr:value("wpa2i", "WPA2-Radius", {mode="ap"}) + encr.description = translate("wifi_wpareq") + elseif not hostapd and supplicant then + encr:value("psk", "WPA-PSK", {mode="sta"}) + encr:value("psk2", "WPA2-PSK", {mode="sta"}) + encr.description = translate("wifi_wpareq") + else + encr.description = translate("wifi_wpareq") + end +elseif hwtype == "broadcom" then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") +end + +key = s:option(Value, "key", translate("key")) +key:depends("encryption", "wep") +key:depends("encryption", "psk") +key:depends("encryption", "wpa") +key:depends("encryption", "psk2") +key:depends("encryption", "wpa2i") +key.rmempty = true +key.description = translate('wifi_keyreq') + +function key:validate(value, section) + function string.tohex(x) + local hex = '' + for c in x:gmatch('(.)') do hex = hex .. string.format("%02x", c:byte()) end + return hex + end + + function string.hexcheck(x) + return #(x:match('%x*')) == #x and x + end + + if encr:formvalue(section) == 'wep' then + if #value == 5 or #value == 13 then + return value:tohex() + elseif #value == 10 or #value == 26 then + return value:hexcheck() + else + return nil + end + elseif encr:formvalue(section) == 'psk' or encr:formvalue(section) == 'psk2' then + return #value == 64 and value:hexcheck() + else + return value + end +end + +server = s:option(Value, "server", translate("a_w_radiussrv")) +server:depends("encryption", "wpa") +server:depends("encryption", "wpa2i") +server.rmempty = true + +port = s:option(Value, "port", translate("a_w_radiusport")) +port:depends("encryption", "wpa") +port:depends("encryption", "wpa2i") +port.rmempty = true + + +if hwtype == "atheros" or hwtype == "broadcom" then + iso = s:option(Flag, "isolate", translate("a_w_apisolation"), translate("a_w_apisolation1")) + iso.rmempty = true + iso:depends("mode", "ap") + + hide = s:option(Flag, "hidden", translate("a_w_hideessid")) + hide.rmempty = true + hide:depends("mode", "ap") +end + +if hwtype == "mac80211" or hwtype == "atheros" then + bssid:depends({mode="adhoc"}) +end + +if hwtype == "broadcom" then + bssid:depends({mode="wds"}) +end + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mmc_over_gpio.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mmc_over_gpio.lua new file mode 100644 index 0000000..591e7da --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/mmc_over_gpio.lua @@ -0,0 +1,41 @@ +--[[ + +LuCI mmc_over_gpio +(c) 2008 Yanira + +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: mmc_over_gpio.lua 3635 2008-10-27 23:07:46Z jow $ + +]]-- + +m = Map("mmc_over_gpio", translate("mmc_over_gpio"), + translate("mmc_over_gpio_desc")) + +s = m:section(TypedSection, "mmc_over_gpio", translate("settings")) +s.addremove = true +s.anonymous = true + +s:option(Flag, "enabled", translate("enabled", "Enable")) + +s:option(Value, "name", translate("name")) + +pin = s:option(Value, "DI_pin", translate("DI_pin")) +for i = 0,7 do pin:value(i) end + +pin = s:option(Value, "DO_pin", translate("DO_pin")) +for i = 0,7 do pin:value(i) end + +pin = s:option(Value, "CLK_pin", translate("CLK_pin")) +for i = 0,7 do pin:value(i) end + +pin = s:option(Value, "CS_pin", translate("CS_pin")) +for i = 0,7 do pin:value(i) end + +s:option(Value, "mode", translate("mode")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpc.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpc.lua new file mode 100644 index 0000000..50a62fc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpc.lua @@ -0,0 +1,39 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ntpc.lua 3240 2008-09-11 17:25:44Z Cyrus $ +]]-- +m = Map("ntpclient", translate("ntpc"), translate("ntpc_desc")) + +s = m:section(TypedSection, "ntpclient", translate("general")) +s.anonymous = true + +s:option(DummyValue, "_time", translate("ntpc_current")).value = os.date("%c") + +s:option(Value, "interval", translate("ntpc_interval")).rmempty = true +s:option(Value, "count", translate("ntpc_count"), translate("ntpc_count_desc")).rmempty = true + + +s2 = m:section(TypedSection, "ntpdrift", translate("ntpc_drift")) +s2.anonymous = true +s2:option(Value, "freq", translate("ntpc_drift_freq")).rmempty = true + + +s3 = m:section(TypedSection, "ntpserver", translate("ntpc_timeserver")) +s3.anonymous = true +s3.addremove = true +s3.template = "cbi/tblsection" + +s3:option(Value, "hostname", translate("hostname")) +s3:option(Value, "port", translate("port")).rmempty = true + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpcmini.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpcmini.lua new file mode 100644 index 0000000..21241f1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ntpc/ntpcmini.lua @@ -0,0 +1,34 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ntpcmini.lua 3240 2008-09-11 17:25:44Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("ntpclient", translate("ntpc"), translate("ntpc_desc")) + +s = m:section(TypedSection, "ntpclient", translate("general")) +s.anonymous = true + +s:option(DummyValue, "_time", translate("ntpc_current")).value = os.date("%c") + +s:option(Value, "interval", translate("ntpc_interval")).rmempty = true + + +s3 = m:section(TypedSection, "ntpserver", translate("ntpc_timeserver")) +s3.anonymous = true +s3.addremove = true +s3.template = "cbi/tblsection" + +s3:option(Value, "hostname", translate("hostname")) +s3:option(Value, "port", translate("port")).rmempty = true + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrd.lua new file mode 100644 index 0000000..bf4c7b6 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrd.lua @@ -0,0 +1,145 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: olsrd.lua 4204 2009-01-31 03:02:57Z jow $ +]]-- + +require("luci.tools.webadmin") + +m = Map("olsrd", translate("olsrd", "OLSR Daemon")) + +s = m:section(TypedSection, "olsrd", translate("olsrd_general")) +s.dynamic = true +s.anonymous = true + +debug = s:option(ListValue, "DebugLevel") +for i=0, 9 do + debug:value(i) +end +debug.optional = true + +ipv = s:option(ListValue, "IpVersion") +ipv:value("4", "IPv4") +ipv:value("6", "IPv6") + +noint = s:option(Flag, "AllowNoInt") +noint.enabled = "yes" +noint.disabled = "no" +noint.optional = true + +s:option(Value, "Pollrate").optional = true + +tcr = s:option(ListValue, "TcRedundancy") +tcr:value("0", translate("olsrd_olsrd_tcredundancy_0")) +tcr:value("1", translate("olsrd_olsrd_tcredundancy_1")) +tcr:value("2", translate("olsrd_olsrd_tcredundancy_2")) +tcr.optional = true + +s:option(Value, "MprCoverage").optional = true + +lql = s:option(ListValue, "LinkQualityLevel") +lql:value("0", translate("disable")) +lql:value("1", translate("olsrd_olsrd_linkqualitylevel_1")) +lql:value("2", translate("olsrd_olsrd_linkqualitylevel_2")) +lql.optional = true + +s:option(Value, "LinkQualityAging").optional = true + +lqa = s:option(ListValue, "LinkQualityAlgorithm") +lqa.optional = true +lqa:value("etx_fpm", translate("olsrd_etx_fpm")) +lqa:value("etx_float", translate("olsrd_etx_float")) +lqa:value("etx_ff", translate("olsrd_etx_ff")) +lqa.optional = true + +lqfish = s:option(Flag, "LinkQualityFishEye") +lqfish.optional = true + +s:option(Value, "LinkQualityWinSize").optional = true + +s:option(Value, "LinkQualityDijkstraLimit").optional = true + +hyst = s:option(Flag, "UseHysteresis") +hyst.enabled = "yes" +hyst.disabled = "no" +hyst.optional = true + +fib = s:option(ListValue, "FIBMetric") +fib.optional = true +fib:value("flat") +fib:value("correct") +fib:value("approx") +fib.optional = true + +clrscr = s:option(Flag, "ClearScreen") +clrscr.enabled = "yes" +clrscr.disabled = "no" +clrscr.optional = true + +willingness = s:option(ListValue, "Willingness") +for i=0,7 do + willingness:value(i) +end +willingness.optional = true + + + +i = m:section(TypedSection, "Interface", translate("interfaces")) +i.anonymous = true +i.addremove = true +i.dynamic = true + +ign = i:option(Flag, "ignore", "Enable") +ign.enabled = "0" +ign.disabled = "1" + +network = i:option(ListValue, "interface", translate("network")) +luci.tools.webadmin.cbi_add_networks(network) + +i:option(Value, "Ip4Broadcast").optional = true + +ip6t = i:option(ListValue, "Ip6AddrType") +ip6t:value("", translate("cbi_select")) +ip6t:value("auto") +ip6t:value("site-local") +ip6t:value("unique-local") +ip6t:value("global") +ip6t.optional = true + +i:option(Value, "HelloInterval").optional = true +i:option(Value, "HelloValidityTime").optional = true +i:option(Value, "TcInterval").optional = true +i:option(Value, "TcValidityTime").optional = true +i:option(Value, "MidInterval").optional = true +i:option(Value, "MidValidityTime").optional = true +i:option(Value, "HnaInterval").optional = true +i:option(Value, "HnaValidityTime").optional = true + +adc = i:option(Flag, "AutoDetectChanges") +adc.enabled = "yes" +adc.disabled = "no" +adc.optional = true + +--[[ +ipc = m:section(TypedSection, "IpcConnect") +ipc.anonymous = true + +conns = ipc:option(Value, "MaxConnections") +conns.isInteger = true + +nets = ipc:option(Value, "Net") +nets.optional = true + +hosts = ipc:option(Value, "Host") +hosts.optional = true +]] + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdhna.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdhna.lua new file mode 100644 index 0000000..cbf02a4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdhna.lua @@ -0,0 +1,36 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: olsrdhna.lua 3823 2008-11-27 14:26:37Z jow $ +]]-- + +mh = Map("olsrd", translate("olsrd_hna", "OLSR - HNA-Ankündigungen")) + + +hna4 = mh:section(TypedSection, "Hna4") +hna4.addremove = true +hna4.anonymous = true +hna4.template = "cbi/tblsection" + +net4 = hna4:option(Value, "netaddr") +msk4 = hna4:option(Value, "netmask") + + +hna6 = mh:section(TypedSection, "Hna6") +hna6.addremove = true +hna6.anonymous = true +hna6.template = "cbi/tblsection" + +net6 = hna6:option(Value, "netaddr") +msk6 = hna6:option(Value, "prefix") + + +return mh diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdplugins.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdplugins.lua new file mode 100644 index 0000000..5be4662 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/olsr/olsrdplugins.lua @@ -0,0 +1,244 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: olsrdplugins.lua 3976 2009-01-01 14:33:36Z jow $ +]]-- + +require("luci.fs") +require("luci.ip") + + +if arg[1] then + mp = Map("olsrd", translate("olsrd_plugins", "OLSR - Plugins")) + + p = mp:section(TypedSection, "LoadPlugin") + p:depends("library", arg[1]) + p.anonymous = true + + ign = p:option(Flag, "ignore", "Enable") + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + lib = p:option(DummyValue, "library", translate("library")) + lib.default = arg[1] + + local function Range(x,y) + local t = {} + for i = x, y do t[#t+1] = i end + return t + end + + local function Cidr2IpMask(val) + if val then + for i = 1, #val do + local cidr = luci.ip.IPv4(val[i]) or luci.ip.IPv6(val[i]) + if cidr then + val[i] = cidr:network():string() .. " " .. cidr:mask():string() + end + end + return val + end + end + + local function IpMask2Cidr(val) + if val then + for i = 1, #val do + local ip, mask = val[i]:gmatch("([^%s+])%s+([^%s+])")() + local cidr + if ip and mask and ip:match(":") then + cidr = luci.ip.IPv6(ip, mask) + elseif ip and mask then + cidr = luci.ip.IPv4(ip, mask) + end + + if cidr then + val[i] = cidr:string() + end + end + return val + end + end + + + local knownPlParams = { + ["olsrd_bmf.so.1.5.3"] = { + { Value, "BmfInterface", "bmf0" }, + { Value, "BmfInterfaceIp", "10.10.10.234/24" }, + { Flag, "DoLocalBroadcast", "no" }, + { Flag, "CapturePacketsOnOlsrInterfaces", "yes" }, + { ListValue, "BmfMechanism", { "UnicastPromiscuous", "Broadcast" } }, + { Value, "BroadcastRetransmitCount", "2" }, + { Value, "FanOutLimit", "4" }, + { DynamicList, "NonOlsrIf", "eth1" } + }, + + ["olsrd_dyn_gw.so.0.4"] = { + { Value, "Interval", "40" }, + { DynamicList, "Ping", "141.1.1.1" }, + { DynamicList, "HNA", "192.168.80.0/24", IpMask2Cidr, Cidr2IpMask } + }, + + ["olsrd_httpinfo.so.0.1"] = { + { Value, "port", "80" }, + { DynamicList, "Host", "163.24.87.3" }, + { DynamicList, "Net", "0.0.0.0/0", IpMask2Cidr, Cidr2IpMask } + }, + + ["olsrd_nameservice.so.0.3"] = { + { DynamicList, "name", "my-name.mesh" }, + { DynamicList, "hosts", "1.2.3.4 name-for-other-interface.mesh" }, + { Value, "suffix", ".olsr" }, + { Value, "hosts_file", "/path/to/hosts_file" }, + { Value, "add_hosts", "/path/to/file" }, + { Value, "dns_server", "141.1.1.1" }, + { Value, "resolv_file", "/path/to/resolv.conf" }, + { Value, "interval", "120" }, + { Value, "timeout", "240" }, + { Value, "lat", "12.123" }, + { Value, "lon", "12.123" }, + { Value, "latlon_file", "/var/run/latlon.js" }, + { Value, "latlon_infile", "/var/run/gps.txt" }, + { Value, "sighup_pid_file", "/var/run/dnsmasq.pid" }, + { Value, "name_change_script", "/usr/local/bin/announce_new_hosts.sh" }, + { Value, "services_change_script", "/usr/local/bin/announce_new_services.sh" } + }, + + ["olsrd_quagga.so.0.2.2"] = { + { StaticList, "redistribute", { + "system", "kernel", "connect", "static", "rip", "ripng", "ospf", + "ospf6", "isis", "bgp", "hsls" + } }, + { ListValue, "ExportRoutes", { "only", "both" } }, + { Flag, "LocalPref", "true" }, + { Value, "Distance", Range(0,255) } + }, + + ["olsrd_secure.so.0.5"] = { + { Value, "Keyfile", "/etc/private-olsr.key" } + }, + + ["olsrd_txtinfo.so.0.1"] = { + { Value, "accept", "10.247.200.4" } + }, + + ["olsrd_arprefresh.so.0.1"] = {}, + ["olsrd_dot_draw.so.0.3"] = {}, + ["olsrd_dyn_gw_plain.so.0.4"] = {}, + ["olsrd_pgraph.so.1.1"] = {}, + ["olsrd_tas.so.0.1"] = {} + } + + + -- build plugin options with dependencies + if knownPlParams[arg[1]] then + for _, option in ipairs(knownPlParams[arg[1]]) do + local otype, name, default, uci2cbi, cbi2uci = unpack(option) + local values + + if type(default) == "table" then + values = default + default = default[1] + end + + if otype == Flag then + local bool = p:option( Flag, name ) + if default == "yes" or default == "no" then + bool.enabled = "yes" + bool.disabled = "no" + elseif default == "on" or default == "off" then + bool.enabled = "on" + bool.disabled = "off" + elseif default == "1" or default == "0" then + bool.enabled = "1" + bool.disabled = "0" + else + bool.enabled = "true" + bool.disabled = "false" + end + bool.optional = true + bool.default = default + bool:depends({ library = plugin }) + else + local field = p:option( otype, name ) + if values then + for _, value in ipairs(values) do + field:value( value ) + end + end + if type(uci2cbi) == "function" then + function field.cfgvalue(self, section) + return uci2cbi(otype.cfgvalue(self, section)) + end + end + if type(cbi2uci) == "function" then + function field.formvalue(self, section) + return cbi2uci(otype.formvalue(self, section)) + end + end + field.optional = true + field.default = default + --field:depends({ library = arg[1] }) + end + end + end + + return mp + +else + + mpi = Map("olsrd", "OLSR - Plugins") + + local plugins = {} + mpi.uci:foreach("olsrd", "LoadPlugin", + function(section) + if section.library and not plugins[section.library] then + plugins[section.library] = true + end + end + ) + + -- create a loadplugin section for each found plugin + for k, v in pairs(luci.fs.dir("/usr/lib")) do + if v:sub(1, 6) == "olsrd_" then + if not plugins[v] then + mpi.uci:section( + "olsrd", "LoadPlugin", nil, + { library = v, ignore = 1 } + ) + end + end + end + + t = mpi:section( TypedSection, "LoadPlugin", "Plugins" ) + t.anonymous = true + t.template = "cbi/tblsection" + t.override_scheme = true + function t.extedit(self, section) + local lib = self.map:get(section, "library") or "" + return luci.dispatcher.build_url("admin", "services", "olsrd", "plugins") .. "/" .. lib + end + + ign = t:option( Flag, "ignore", "Enabled" ) + ign.enabled = "0" + ign.disabled = "1" + ign.rmempty = false + function ign.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" + end + + t:option( DummyValue, "library", "Library" ) + + return mpi +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/p910nd.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/p910nd.lua new file mode 100644 index 0000000..af55e05 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/p910nd.lua @@ -0,0 +1,33 @@ +--[[ + +LuCI p910nd +(c) 2008 Yanira + +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: p910nd.lua 3467 2008-09-29 19:21:47Z jow $ + +]]-- + +local uci = luci.model.uci.cursor_state() + +m = Map("p910nd", translate("p910nd", "p910nd"), + translatef("p910nd_desc")) + +s = m:section(TypedSection, "p910nd", translate("settings", "settings")) +s.addremove = true +s.anonymous = true + +s:option(Flag, "enabled", translate("enable")) + +s:option(Value, "device", translate("device", "Device")).rmempty = true + +s:option(Value, "port", translate("port"), translate("port_help")).rmempty = true + +s:option(Flag, "bidirectional", translate("bidirectional")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/polipo.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/polipo.lua new file mode 100644 index 0000000..4ccaf79 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/polipo.lua @@ -0,0 +1,67 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Aleksandar Krsteski + +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: polipo.lua 3720 2008-11-05 23:05:09Z jow $ +]]-- +m = Map("polipo") + +-- General section +s = m:section(NamedSection, "general", "polipo") + +-- General settings +s:option(Flag, "enabled", translate("enable")) +s:option(Value, "proxyAddress") +s:option(Value, "proxyPort").optional = true +s:option(DynamicList, "allowedClients") +s:option(Flag, "logSyslog") +s:option(Value, "logFacility"):depends("logSyslog", "1") +v = s:option(Value, "logFile") +v:depends("logSyslog", "") +v.rmempty = true +s:option(Value, "chunkHighMark") + +-- DNS and proxy settings +s:option(Value, "dnsNameServer").optional = true +s:option(Value, "parentProxy").optional = true +s:option(Value, "parentAuthCredentials").optional = true +l = s:option(ListValue, "dnsQueryIPv6") +l.optional = true +l.default = "happily" +l:value("") +l:value("true") +l:value("reluctantly") +l:value("happily") +l:value("false") +l = s:option(ListValue, "dnsUseGethostbyname") +l.optional = true +l.default = "reluctantly" +l:value("") +l:value("true") +l:value("reluctantly") +l:value("happily") +l:value("false") + +-- Dsik cache section +s = m:section(NamedSection, "cache", "polipo") + +-- Dsik cache settings +s:option(Value, "diskCacheRoot").rmempty = true +s:option(Flag, "cacheIsShared") +s:option(Value, "diskCacheTruncateSize").optional = true +s:option(Value, "diskCacheTruncateTime").optional = true +s:option(Value, "diskCacheUnlinkTime").optional = true + +-- Poor man's multiplexing section +s = m:section(NamedSection, "pmm", "polipo") +s:option(Value, "pmmSize").rmempty = true +s:option(Value, "pmmFirstSize").optional = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qos.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qos.lua new file mode 100644 index 0000000..07ad127 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qos.lua @@ -0,0 +1,89 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: qos.lua 4075 2009-01-17 16:20:20Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("qos") + +s = m:section(TypedSection, "interface", translate("interfaces")) +s.addremove = true + +s:option(Flag, "enabled", translate("enable")) + +c = s:option(ListValue, "classgroup") +c:value("Default", "standard") +c.default = "Default" + +s:option(Flag, "overhead") + +s:option(Value, "download", nil, "kb/s") + +s:option(Value, "upload", nil, "kb/s") + +s = m:section(TypedSection, "classify") +s.template = "cbi/tblsection" +s.anonymous = true +s.addremove = true + +t = s:option(ListValue, "target") +t:value("Priority", translate("qos_priority")) +t:value("Express", translate("qos_express")) +t:value("Normal", translate("qos_normal")) +t:value("Bulk", translate("qos_bulk")) +t.default = "Normal" + +srch = s:option(Value, "srchost") +srch.rmempty = true +srch:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(srch) + +dsth = s:option(Value, "dsthost") +dsth.rmempty = true +dsth:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(dsth) + +l7 = s:option(ListValue, "layer7", translate("service")) +l7.rmempty = true +l7:value("", translate("all")) +local pats = luci.fs.dir("/etc/l7-protocols") +if pats then + for i,f in ipairs(pats) do + if f:sub(-4) == ".pat" then + l7:value(f:sub(1, #f-4)) + end + end +end + +p2p = s:option(ListValue, "ipp2p", "P2P") +p2p:value("", "-") +p2p:value("all", translate("all")) +p2p:value("bit", "BIT") +p2p:value("dc", "DC") +p2p:value("edk", "EDK") +p2p:value("gnu", "GNU") +p2p:value("kazaa", "KAZ") +p2p.rmempty = true + +p = s:option(Value, "proto", translate("protocol")) +p:value("", translate("all")) +p:value("tcp", "TCP") +p:value("udp", "UDP") +p:value("icmp", "ICMP") +p.rmempty = true + +ports = s:option(Value, "ports", translate("ports")) +ports.rmempty = true +ports:value("", translate("allf", translate("all"))) + +bytes = s:option(Value, "connbytes", translate("qos_connbytes")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qosmini.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qosmini.lua new file mode 100644 index 0000000..c8dcfe8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/qos/qosmini.lua @@ -0,0 +1,82 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: qosmini.lua 4075 2009-01-17 16:20:20Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("qos") + +s = m:section(NamedSection, "wan", "interface", translate("m_n_inet")) + +s:option(Flag, "enabled", translate("qos")) +s:option(Value, "download", translate("qos_interface_download"), "kb/s") +s:option(Value, "upload", translate("qos_interface_upload"), "kb/s") + +s = m:section(TypedSection, "classify") +s.template = "cbi/tblsection" + +s.anonymous = true +s.addremove = true + +t = s:option(ListValue, "target") +t:value("Priority", translate("qos_priority")) +t:value("Express", translate("qos_express")) +t:value("Normal", translate("qos_normal")) +t:value("Bulk", translate("qos_bulk")) +t.default = "Normal" + +srch = s:option(Value, "srchost") +srch.rmempty = true +srch:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(srch) + +dsth = s:option(Value, "dsthost") +dsth.rmempty = true +dsth:value("", translate("all")) +luci.tools.webadmin.cbi_add_knownips(dsth) + +l7 = s:option(ListValue, "layer7", translate("service")) +l7.rmempty = true +l7:value("", translate("all")) +local pats = luci.fs.dir("/etc/l7-protocols") +if pats then + for i,f in ipairs(pats) do + if f:sub(-4) == ".pat" then + l7:value(f:sub(1, #f-4)) + end + end +end + +p2p = s:option(ListValue, "ipp2p", "P2P") +p2p:value("", "-") +p2p:value("all", translate("all")) +p2p:value("bit", "BIT") +p2p:value("dc", "DC") +p2p:value("edk", "EDK") +p2p:value("gnu", "GNU") +p2p:value("kazaa", "KAZ") +p2p.rmempty = true + +p = s:option(ListValue, "proto", translate("protocol")) +p:value("", translate("all")) +p:value("tcp", "TCP") +p:value("udp", "UDP") +p:value("icmp", "ICMP") +p.rmempty = true + +ports = s:option(Value, "ports", translate("ports")) +ports.rmempty = true +ports:value("", translate("allf", translate("all"))) + +bytes = s:option(Value, "connbytes", translate("qos_connbytes")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/samba.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/samba.lua new file mode 100644 index 0000000..a33c069 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/samba.lua @@ -0,0 +1,56 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: samba.lua 3973 2009-01-01 13:33:45Z Cyrus $ +]]-- + +m = Map("samba") + +s = m:section(TypedSection, "samba", "Samba") +s.anonymous = true + +s:option(Value, "name") +s:option(Value, "description") +s:option(Value, "workgroup") +s:option(Flag, "homes") + + +s = m:section(TypedSection, "sambashare") +s.anonymous = true +s.addremove = true +s.template = "cbi/tblsection" + +s:option(Value, "name", translate("name")) +s:option(Value, "path").titleref = luci.dispatcher.build_url("admin", "system", "fstab") + +s:option(Value, "users").rmempty = true + +ro = s:option(Flag, "read_only") +ro.rmempty = false +ro.enabled = "yes" +ro.disabled = "no" + +go = s:option(Flag, "guest_ok") +go.rmempty = false +go.enabled = "yes" +go.disabled = "no" + +cm = s:option(Value, "create_mask") +cm.rmempty = true +cm.size = 4 + +dm = s:option(Value, "dir_mask") +dm.rmempty = true +dm.size = 4 + + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/siitwizard.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/siitwizard.lua new file mode 100644 index 0000000..048c0f4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/siitwizard.lua @@ -0,0 +1,338 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: siitwizard.lua 3940 2008-12-23 16:49:48Z jow $ + +]]-- + +local uci = require "luci.model.uci".cursor() + +-------------------- View -------------------- +f = SimpleForm("siitwizward", "4over6-Assistent", + "Dieser Assistent unterstüzt bei der Einrichtung von IPv4-over-IPv6 Translation.") + +mode = f:field(ListValue, "mode", "Betriebsmodus") +mode:value("client", "Client") +mode:value("gateway", "Gateway") + +dev = f:field(ListValue, "device", "WLAN-Gerät") +uci:foreach("wireless", "wifi-device", + function(section) + dev:value(section[".name"]) + end) + +lanip = f:field(Value, "ipaddr", "LAN IP Adresse") +lanip.value = "172.23.1.1" + +lanmsk = f:field(Value, "lanmask", "Lokale LAN Netzmaske") +lanmsk.value = "255.255.255.0" + +gv4msk = f:field(Value, "gv4mask", "Globale LAN Netzmaske") +gv4msk.value = "255.255.0.0" + + +-------------------- Control -------------------- +LL_PREFIX = luci.ip.IPv6("fe80::/64") + +-- +-- find link-local address +-- +function find_ll() + for _, r in ipairs(luci.sys.net.routes6()) do + if LL_PREFIX:contains(r.dest) and r.dest:higher(LL_PREFIX) then + return r.dest:sub(LL_PREFIX) + end + end + return luci.ip.IPv6("::") +end + + + +function f.handle(self, state, data) + if state == FORM_VALID then + luci.http.redirect(luci.dispatcher.build_url("admin", "uci", "changes")) + return false + elseif state == FORM_INVALID then + self.errmessage = "Ungültige Eingabe: Bitte die Formularfelder auf Fehler prüfen." + end + return true +end + +function mode.write(self, section, value) + + -- lan interface + local lan_net = luci.ip.IPv4( + lanip:formvalue(section) or "192.168.1.1", + lanmsk:formvalue(section) or "255.255.255.0" + ) + + local gv4_net = luci.ip.IPv4( + lanip:formvalue(section) or "192.168.1.1", + gv4msk:formvalue(section) or "255.255.0.0" + ) + + -- + -- Configure wifi device + -- + local wifi_device = dev:formvalue(section) + local wifi_essid = uci:get("siit", "wifi", "essid") or "6mesh.freifunk.net" + local wifi_bssid = uci:get("siit", "wifi", "bssid") or "02:ca:ff:ee:ba:be" + local wifi_channel = uci:get("siit", "wifi", "channel") or "1" + + -- nuke old device definition + uci:delete_all("wireless", "wifi-iface", + function(s) return s.device == wifi_device end ) + + uci:delete_all("network", "interface", + function(s) return s['.name'] == wifi_device end ) + + -- create wifi device definition + uci:tset("wireless", wifi_device, { + disabled = 0, + channel = wifi_channel, +-- txantenna = 1, +-- rxantenna = 1, +-- diversity = 0 + }) + + uci:section("wireless", "wifi-iface", nil, { + encryption = "none", + mode = "adhoc", + network = wifi_device, + device = wifi_device, + ssid = wifi_essid, + bssid = wifi_bssid, + }) + + + -- + -- Determine defaults + -- + local ula_prefix = uci:get("siit", "ipv6", "ula_prefix") or "fd00::" + local ula_global = uci:get("siit", "ipv6", "ula_global") or "00ca:ffee:babe::" -- = Freifunk + local ula_subnet = uci:get("siit", "ipv6", "ula_subnet") or "0000:0000:0000:4223::" -- = Berlin + local siit_prefix = uci:get("siit", "ipv6", "siit_prefix") or "::ffff:0000:0000" + + -- Find wifi interface + local device = dev:formvalue(section) + + -- + -- Generate ULA + -- + local ula = luci.ip.IPv6("::/64") + + for _, prefix in ipairs({ ula_prefix, ula_global, ula_subnet }) do + ula = ula:add(luci.ip.IPv6(prefix)) + end + + ula = ula:add(find_ll()) + + + -- + -- Gateway mode + -- + -- * wan port is dhcp, lan port is 172.23.1.1/24 + -- * siit0 gets a dummy address: 169.254.42.42 + -- * wl0 gets an ipv6 address, in this case the fdca:ffee:babe::1:1/64 + -- * we do a ::ffff:ffff:0/96 route into siit0, so everything from 6mesh goes into translation. + -- * an HNA6 of ::ffff:ffff:0:0/96 announces the mapped 0.0.0.0/0 ipv4 space. + -- * MTU on WAN, LAN down to 1400, ipv6 headers are slighly larger. + + if value == "gateway" then + + + -- wan mtu + uci:set("network", "wan", "mtu", 1400) + + -- lan settings + uci:tset("network", "lan", { + mtu = 1400, + ipaddr = lan_net:host():string(), + netmask = lan_net:mask():string() + }) + + -- use full siit subnet + siit_route = luci.ip.IPv6(siit_prefix .. "/96") + + -- v4 <-> siit route + uci:delete_all("network", "route", + function(s) return s.interface == "siit0" end) + + uci:section("network", "route", nil, { + interface = "siit0", + target = gv4_net:network():string(), + netmask = gv4_net:mask():string() + }) + + -- + -- Client mode + -- + -- * 172.23.2.1/24 on its lan, fdca:ffee:babe::1:2 on wl0 and the usual dummy address on siit0. + -- * we do a ::ffff:ffff:172.13.2.0/120 to siit0, because in this case, only traffic directed to clients needs to go into translation. + -- * same route as HNA6 announcement to catch the traffic out of the mesh. + -- * Also, MTU on LAN reduced to 1400. + + else + + -- lan settings + uci:tset("network", "lan", { + mtu = 1400, + ipaddr = lan_net:host():string(), + netmask = lan_net:mask():string() + }) + + -- derive siit subnet from lan config + siit_route = luci.ip.IPv6( + siit_prefix .. "/" .. (96 + lan_net:prefix()) + ):add(lan_net[2]) + + -- ipv4 <-> siit route + uci:delete_all("network", "route", + function(s) return s.interface == "siit0" end) + + -- XXX: kind of a catch all, gv4_net would be better + -- but does not cover non-local v4 space + uci:section("network", "route", nil, { + interface = "siit0", + target = "0.0.0.0", + netmask = "0.0.0.0" + }) + end + + -- setup the firewall + uci:delete_all("firewall", "zone", + function(s) return ( + s['.name'] == "siit0" or s.name == "siit0" or + s.network == "siit0" or s['.name'] == wifi_device or + s.name == wifi_device or s.network == wifi_device + ) end) + + uci:delete_all("firewall", "forwarding", + function(s) return ( + s.src == wifi_device and s.dest == "siit0" or + s.dest == wifi_device and s.src == "siit0" or + s.src == "lan" and s.dest == "siit0" or + s.dest == "lan" and s.src == "siit0" + ) end) + + uci:section("firewall", "zone", "siit0", { + name = "siit0", + network = "siit0", + input = "ACCEPT", + output = "ACCEPT", + forward = "ACCEPT" + }) + + uci:section("firewall", "zone", wifi_device, { + name = wifi_device, + network = wifi_device, + input = "ACCEPT", + output = "ACCEPT", + forward = "ACCEPT" + }) + + uci:section("firewall", "forwarding", nil, { + src = wifi_device, + dest = "siit0" + }) + + uci:section("firewall", "forwarding", nil, { + src = "siit0", + dest = wifi_device + }) + + uci:section("firewall", "forwarding", nil, { + src = "lan", + dest = "siit0" + }) + + uci:section("firewall", "forwarding", nil, { + src = "siit0", + dest = "lan" + }) + + -- firewall include + uci:delete_all("firewall", "include", + function(s) return s.path == "/etc/firewall.user" end) + + uci:section("firewall", "include", nil, { + path = "/etc/firewall.user" + }) + + + -- siit0 interface + uci:delete_all("network", "interface", + function(s) return ( s.ifname == "siit0" ) end) + + uci:section("network", "interface", "siit0", { + ifname = "siit0", + proto = "none" + }) + + -- siit0 route + uci:delete_all("network", "route6", + function(s) return siit_route:contains(luci.ip.IPv6(s.target)) end) + + uci:section("network", "route6", nil, { + interface = "siit0", + target = siit_route:string() + }) + + -- create wifi network interface + uci:section("network", "interface", wifi_device, { + proto = "static", + mtu = 1400, + ip6addr = ula:string() + }) + + -- nuke old olsrd interfaces + uci:delete_all("olsrd", "Interface", + function(s) return s.interface == wifi_device end) + + -- configure olsrd interface + uci:foreach("olsrd", "olsrd", + function(s) uci:set("olsrd", s['.name'], "IpVersion", 6) end) + + uci:section("olsrd", "Interface", nil, { + ignore = 0, + interface = wifi_device, + Ip6AddrType = "global" + }) + + -- hna6 + uci:delete_all("olsrd", "Hna6", + function(s) + if s.netaddr and s.prefix then + return siit_route:contains(luci.ip.IPv6(s.netaddr.."/"..s.prefix)) + end + end) + + uci:section("olsrd", "Hna6", nil, { + netaddr = siit_route:host():string(), + prefix = siit_route:prefix() + }) + + -- txtinfo v6 + uci:foreach("olsrd", "LoadPlugin", + function(s) + if s.library == "olsrd_txtinfo.so.0.1" then + uci:set("olsrd", s['.name'], "accept", "::1") + end + end) + + uci:save("wireless") + uci:save("firewall") + uci:save("network") + uci:save("olsrd") +end + +return f diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/splash/splash.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/splash/splash.lua new file mode 100644 index 0000000..29bc6d9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/splash/splash.lua @@ -0,0 +1,47 @@ +-- ToDo: Translate, Add descriptions and help texts +require("luci.model.uci") + +m = Map("luci_splash", "Client-Splash", [[Client-Splash ist das Freifunk Hotspot-Authentifizierungs-System.]]) + +s = m:section(NamedSection, "general", "core", "Allgemein") +s:option(Value, "leasetime", "Freigabezeit", "h") + +s = m:section(TypedSection, "iface", "Schnittstellen") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true + +local uci = luci.model.uci.cursor() + +zone = s:option(ListValue, "zone", "Firewallzone") +uci:foreach("firewall", "zone", + function (section) + zone:value(section.name) + end) + +iface = s:option(ListValue, "network", "Netzwerk") +uci:foreach("network", "interface", + function (section) + if section[".name"] ~= "loopback" then + iface:value(section[".name"]) + end + end) + +uci:foreach("network", "alias", + function (section) + iface:value(section[".name"]) + end) + +s = m:section(TypedSection, "whitelist", "Automatische Freigabe") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true +s:option(Value, "mac", "MAC-Adresse") + +s = m:section(TypedSection, "blacklist", "Automatische Sperrung") +s.template = "cbi/tblsection" +s.addremove = true +s.anonymous = true +s:option(Value, "mac", "MAC-Adresse") + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/tinyproxy.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/tinyproxy.lua new file mode 100644 index 0000000..9a216d7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/tinyproxy.lua @@ -0,0 +1,80 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tinyproxy.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +m = Map("tinyproxy", translate("tinyproxy"), translate("tinyproxy_desc")) + +s = m:section(TypedSection, "tinyproxy", translate("general")) +s.anonymous = true + +s:option(Flag, "enable", translate("enable")) + +s:option(Value, "Port", translate("port")) +s:option(Value, "Listen").optional = true +s:option(Value, "Bind").optional = true +s:option(Value, "Timeout").optional = true + +s:option(Value, "DefaultErrorFile").optional = true +s:option(Value, "StatFile").optional = true + +s:option(Flag, "Syslog").optional = true +f = s:option(Value, "Logfile") +f.optional = true + +l = s:option(ListValue, "LogLevel") +l.optional = true +l:value("Critical") +l:value("Error") +l:value("Warning") +l:value("Notice") +l:value("Connect") +l:value("Info") + +s:option(DynamicList, "XTinyproxy").optional = true + +s:option(DynamicList, "Allow") +s:option(Value, "ViaProxyName") + +s:option(FileUpload, "Filter") +s:option(Flag, "FilterURLs") +s:option(Flag, "FilterExtended") +s:option(Flag, "FilterCaseSensitive") +s:option(Flag, "FilterDefaultDeny") + +s:option(DynamicList, "Anonymous") +s:option(DynamicList, "ConnectPort") + +s:option(Value, "User").optional = true +s:option(Value, "Group").optional = true +s:option(Value, "MaxClients").optional = true +s:option(Value, "MinSpareServers").optional = true +s:option(Value, "MaxSpareServers").optional = true +s:option(Value, "StartServers").optional = true +s:option(Value, "MaxRequestsPerChild").optional = true + + +s = m:section(TypedSection, "upstream") +s.anonymous = true +s.addremove = true + +t = s:option(ListValue, "type") +t:value("proxy", translate("tinyproxy_type_proxy")) +t:value("reject", translate("tinyproxy_type_reject")) + +ta = s:option(Value, "target") +ta.rmempty = true + +v = s:option(Value, "via") +v:depends({type="proxy"}) + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnp.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnp.lua new file mode 100644 index 0000000..1bc6e84 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnp.lua @@ -0,0 +1,38 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upnp.lua 4179 2009-01-28 18:32:47Z jow $ +]]-- +m = Map("upnpd", translate("upnpd"), translate("upnpd_desc")) + +s = m:section(NamedSection, "config", "upnpd", "") +e = s:option(Flag, "enabled", translate("enable")) +e.rmempty = false + +function e.write(self, section, value) + local cmd = (value == "1") and "enable" or "disable" + if value ~= "1" then + os.execute("/etc/init.d/miniupnpd stop") + end + os.execute("/etc/init.d/miniupnpd " .. cmd) +end + +function e.cfgvalue(self, section) + return (os.execute("/etc/init.d/miniupnpd enabled") == 0) and "1" or "0" +end + +s:option(Flag, "secure_mode").rmempty = true +s:option(Flag, "log_output").rmempty = true +s:option(Value, "download", nil, "kByte/s").rmempty = true +s:option(Value, "upload", nil, "kByte/s").rmempty = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnpmini.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnpmini.lua new file mode 100644 index 0000000..2b2a78a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/upnp/upnpmini.lua @@ -0,0 +1,36 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upnpmini.lua 4179 2009-01-28 18:32:47Z jow $ +]]-- +m = Map("upnpd", translate("upnpd"), translate("upnpd_desc")) + +s = m:section(NamedSection, "config", "upnpd", "") +e = s:option(Flag, "enabled", translate("enable")) +e.rmempty = false + +function e.write(self, section, value) + local cmd = (value == "1") and "enable" or "disable" + if value ~= "1" then + os.execute("/etc/init.d/miniupnpd stop") + end + os.execute("/etc/init.d/miniupnpd " .. cmd) +end + +function e.cfgvalue(self, section) + return (os.execute("/etc/init.d/miniupnpd enabled") == 0) and "1" or "0" +end + +s:option(Value, "download", nil, "kByte/s").rmempty = true +s:option(Value, "upload", nil, "kByte/s").rmempty = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ushare.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ushare.lua new file mode 100644 index 0000000..8063aea --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/ushare.lua @@ -0,0 +1,42 @@ +--[[ + +LuCI uShare +(c) 2008 Yanira + +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: ushare.lua 3423 2008-09-24 21:13:42Z jow $ + +]]-- + +m = Map("ushare", translate("ushare"), + translate("ushare_desc")) + +s = m:section(TypedSection, "ushare", translate("settings")) +s.addremove = false +s.anonymous = true + +s:option(Flag, "enabled", translate("enabled", "Enable")) + +s:option(Value, "username", translate("username")) + +s:option(Value, "servername", translate("servername")) + +dif = s:option( Value, "interface", translate("interface")) +for _, nif in ipairs(luci.sys.net.devices()) do + if nif ~= "lo" then dif:value(nif) end +end + +s:option(Value, "content_directories", translate("content_directories")) + +s:option(Flag, "disable_webif", translate("disable_webif")) + +s:option(Flag, "disable_telnet", translate("disable_telnet")) + +s:option(Value, "options", translate("options")) + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/uvc_streamer.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/uvc_streamer.lua new file mode 100644 index 0000000..ead6534 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/cbi/uvc_streamer.lua @@ -0,0 +1,47 @@ +--[[ + +LuCI UVC Streamer +(c) 2008 Yanira + +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: uvc_streamer.lua 3242 2008-09-11 18:54:51Z Cyrus $ + +]]-- + +-- find current lan address and port of first uvc_streamer config section +local uci = luci.model.uci.cursor_state() +local addr = uci:get("network", "lan", "ipaddr") +local port + +uci:foreach( "uvc-streamer", "uvc-streamer", + function(section) port = port or tonumber(section.port) end ) + +addr = addr or "192.168.1.1" +port = port or 8080 + +m = Map("uvc-streamer", translate("uvc_streamer"), + translatef("uvc_streamer_desc", nil, addr, port, addr, port)) + +s = m:section(TypedSection, "uvc-streamer", translate("settings")) +s.addremove = false +s.anonymous = true + +s:option(Flag, "enabled", translate("enabled", "Enable")) + +s:option(Value, "device", translate("device")).rmempty = true + +nm = s:option(Value, "resolution", translate("resolution")) +nm:value("640x480") +nm:value("320x240") +nm:value("160x120") + +s:option(Value, "framespersecond", translate("framespersecond")).rmempty = true + +s:option(Value, "port", translate("port", "Port")).rmempty = true + +return m diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/ipkg.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/ipkg.lua new file mode 100644 index 0000000..c831583 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/ipkg.lua @@ -0,0 +1,150 @@ +--[[ +LuCI - Lua Configuration Interface + +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: ipkg.lua 3837 2008-11-29 21:58:58Z Cyrus $ +]]-- + +local os = require "os" +local io = require "io" +local util = require "luci.util" + +local type = type +local pairs = pairs +local error = error + +local ipkg = "opkg" + +--- LuCI IPKG/OPKG call abstraction library +module "luci.model.ipkg" + + +-- Internal action function +local function _action(cmd, ...) + local pkg = "" + arg.n = nil + for k, v in pairs(arg) do + pkg = pkg .. " '" .. v:gsub("'", "") .. "'" + end + + local c = ipkg.." "..cmd.." "..pkg.." >/dev/null 2>&1" + local r = os.execute(c) + return (r == 0), r +end + +-- Internal parser function +local function _parselist(rawdata) + if type(rawdata) ~= "function" then + error("IPKG: Invalid rawdata given") + end + + local data = {} + local c = {} + local l = nil + + for line in rawdata do + if line:sub(1, 1) ~= " " then + local key, val = line:match("(.-): ?(.*)%s*") + + if key and val then + if key == "Package" then + c = {Package = val} + data[val] = c + elseif key == "Status" then + c.Status = {} + for j in val:gmatch("([^ ]+)") do + c.Status[j] = true + end + else + c[key] = val + end + l = key + end + else + -- Multi-line field + c[l] = c[l] .. "\n" .. line + end + end + + return data +end + +-- Internal lookup function +local function _lookup(act, pkg) + local cmd = ipkg .. " " .. act + if pkg then + cmd = cmd .. " '" .. pkg:gsub("'", "") .. "'" + end + + -- IPKG sometimes kills the whole machine because it sucks + -- Therefore we have to use a sucky approach too and use + -- tmpfiles instead of directly reading the output + local tmpfile = os.tmpname() + os.execute(cmd .. (" >%s 2>/dev/null" % tmpfile)) + + local data = _parselist(io.lines(tmpfile)) + os.remove(tmpfile) + return data +end + + +--- Return information about installed and available packages. +-- @param pkg Limit output to a (set of) packages +-- @return Table containing package information +function info(pkg) + return _lookup("info", pkg) +end + +--- Return the package status of one or more packages. +-- @param pkg Limit output to a (set of) packages +-- @return Table containing package status information +function status(pkg) + return _lookup("status", pkg) +end + +--- Install one or more packages. +-- @param ... List of packages to install +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function install(...) + return _action("install", ...) +end + +--- Determine whether a given package is installed. +-- @param pkg Package +-- @return Boolean +function installed(pkg) + local p = status(pkg)[pkg] + return (p and p.Status and p.Status.installed) +end + +--- Remove one or more packages. +-- @param ... List of packages to install +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function remove(...) + return _action("remove", ...) +end + +--- Update package lists. +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function update() + return _action("update") +end + +--- Upgrades all installed packages. +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function upgrade() + return _action("upgrade") +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/model/uci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/model/uci.lua new file mode 100644 index 0000000..6c6b93b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/model/uci.lua @@ -0,0 +1,333 @@ +--[[ +LuCI - UCI model + +Description: +Generalized UCI model + +FileId: +$Id: uci.lua 4190 2009-01-30 15:36:49Z jow $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +local os = require "os" +local uci = require "uci" +local util = require "luci.util" +local table = require "table" + + +local setmetatable, rawget, rawset = setmetatable, rawget, rawset +local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring +local require, getmetatable, type = require, getmetatable, type + +--- LuCI UCI model library. +-- @cstyle instance +module "luci.model.uci" + +--- Create a new UCI-Cursor. +-- @class function +-- @name cursor +-- @return UCI-Cursor +cursor = uci.cursor + +APIVERSION = uci.APIVERSION + +--- Create a new Cursor initialized to the state directory. +-- @return UCI cursor +function cursor_state() + return cursor(nil, "/var/state") +end + + +local Cursor = getmetatable(cursor()) + +--- Applies UCI configuration changes +-- @param configlist List of UCI configurations +-- @param command Don't apply only return the command +function Cursor.apply(self, configlist, command) + configlist = self:_affected(configlist) + local reloadcmd = "/sbin/luci-reload " .. table.concat(configlist, " ") + + return command and reloadcmd or os.execute(reloadcmd .. " >/dev/null 2>&1") +end + + +--- Delete all sections of a given type that match certain criteria. +-- @param config UCI config +-- @param type UCI section type +-- @param comparator Function that will be called for each section and +-- returns a boolean whether to delete the current section (optional) +function Cursor.delete_all(self, config, stype, comparator) + local del = {} + + if type(comparator) == "table" then + local tbl = comparator + comparator = function(section) + for k, v in pairs(tbl) do + if section[k] ~= v then + return false + end + end + return true + end + end + + local function helper (section) + + if not comparator or comparator(section) then + del[#del+1] = section[".name"] + end + end + + self:foreach(config, stype, helper) + + for i, j in ipairs(del) do + self:delete(config, j) + end +end + +--- Create a new section and initialize it with data. +-- @param config UCI config +-- @param type UCI section type +-- @param name UCI section name (optional) +-- @param values Table of key - value pairs to initialize the section with +-- @return Name of created section +function Cursor.section(self, config, type, name, values) + local stat = true + if name then + stat = self:set(config, name, type) + else + name = self:add(config, type) + stat = name and true + end + + if stat and values then + stat = self:tset(config, name, values) + end + + return stat and name +end + +--- Updated the data of a section using data from a table. +-- @param config UCI config +-- @param section UCI section name (optional) +-- @param values Table of key - value pairs to update the section with +function Cursor.tset(self, config, section, values) + local stat = true + for k, v in pairs(values) do + if k:sub(1, 1) ~= "." then + stat = stat and self:set(config, section, k, v) + end + end + return stat +end + +--- Get a boolean option and return it's value as true or false. +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option +-- @return Boolean +function Cursor.get_bool(self, ...) + local val = self:get(...) + return ( val == "1" or val == "true" or val == "yes" or val == "on" ) +end + +--- Get an option or list and return values as table. +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option +-- @return UCI value +function Cursor.get_list(self, config, section, option) + if config and section and option then + local val = self:get(config, section, option) + return ( type(val) == "table" and val or { val } ) + end + return nil +end + +--- Set given values as list. +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option +-- @param value UCI value +-- @return Boolean whether operation succeeded +function Cursor.set_list(self, config, section, option, value) + if config and section and option then + return self:set( + config, section, option, + ( type(value) == "table" and value or { value } ) + ) + end + return false +end + +-- Return a list of initscripts affected by configuration changes. +function Cursor._affected(self, configlist) + configlist = type(configlist) == "table" and configlist or {configlist} + + local c = cursor() + c:load("ucitrack") + + -- Resolve dependencies + local reloadlist = {} + + local function _resolve_deps(name) + local reload = {name} + local deps = {} + + c:foreach("ucitrack", name, + function(section) + if section.affects then + for i, aff in ipairs(section.affects) do + deps[#deps+1] = aff + end + end + end) + + for i, dep in ipairs(deps) do + for j, add in ipairs(_resolve_deps(dep)) do + reload[#reload+1] = add + end + end + + return reload + end + + -- Collect initscripts + for j, config in ipairs(configlist) do + for i, e in ipairs(_resolve_deps(config)) do + if not util.contains(reloadlist, e) then + reloadlist[#reloadlist+1] = e + end + end + end + + return reloadlist +end + + +--- Add an anonymous section. +-- @class function +-- @name Cursor.add +-- @param config UCI config +-- @param type UCI section type +-- @return Name of created section + +--- Get a table of unsaved changes. +-- @class function +-- @name Cursor.changes +-- @param config UCI config +-- @return Table of changes + +--- Commit unsaved changes. +-- @class function +-- @name Cursor.commit +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.revert + +--- Deletes a section or an option. +-- @class function +-- @name Cursor.delete +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option (optional) +-- @return Boolean whether operation succeeded + +--- Call a function for every section of a certain type. +-- @class function +-- @name Cursor.foreach +-- @param config UCI config +-- @param type UCI section type +-- @param callback Function to be called +-- @return Boolean whether operation succeeded + +--- Get a section type or an option +-- @class function +-- @name Cursor.get +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option (optional) +-- @return UCI value + +--- Get all sections of a config or all values of a section. +-- @class function +-- @name Cursor.get_all +-- @param config UCI config +-- @param section UCI section name (optional) +-- @return Table of UCI sections or table of UCI values + +--- Manually load a config. +-- @class function +-- @name Cursor.load +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.save +-- @see Cursor.unload + +--- Revert unsaved changes. +-- @class function +-- @name Cursor.revert +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.commit + +--- Saves changes made to a config to make them committable. +-- @class function +-- @name Cursor.save +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.load +-- @see Cursor.unload + +--- Set a value or create a named section. +-- @class function +-- @name Cursor.set +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option or UCI section type +-- @param value UCI value or nil if you want to create a section +-- @return Boolean whether operation succeeded + +--- Get the configuration directory. +-- @class function +-- @name Cursor.get_confdir +-- @return Configuration directory + +--- Get the directory for uncomitted changes. +-- @class function +-- @name Cursor.get_savedir +-- @return Save directory + +--- Set the configuration directory. +-- @class function +-- @name Cursor.set_confdir +-- @param directory UCI configuration directory +-- @return Boolean whether operation succeeded + +--- Set the directory for uncommited changes. +-- @class function +-- @name Cursor.set_savedir +-- @param directory UCI changes directory +-- @return Boolean whether operation succeeded + +--- Discard changes made to a config. +-- @class function +-- @name Cursor.unload +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.load +-- @see Cursor.save diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/sauth.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/sauth.lua new file mode 100644 index 0000000..758934e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/sauth.lua @@ -0,0 +1,106 @@ +--[[ + +Session authentication +(c) 2008 Steven Barth + +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: sauth.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +--- LuCI session library. +module("luci.sauth", package.seeall) +require("luci.fs") +require("luci.util") +require("luci.sys") +require("luci.config") + + +luci.config.sauth = luci.config.sauth or {} +sessionpath = luci.config.sauth.sessionpath +sessiontime = tonumber(luci.config.sauth.sessiontime) or 15 * 60 + +--- Manually clean up expired sessions. +function clean() + local now = os.time() + local files = luci.fs.dir(sessionpath) + + if not files then + return nil + end + + for i, file in pairs(files) do + local fname = sessionpath .. "/" .. file + local stat = luci.fs.stat(fname) + if stat and stat.type == "regular" and stat.atime + sessiontime < now then + luci.fs.unlink(fname) + end + end +end + +--- Prepare session storage by creating the session directory. +function prepare() + luci.fs.mkdir(sessionpath) + luci.fs.chmod(sessionpath, "a-rwx,u+rwx") + + if not sane() then + error("Security Exception: Session path is not sane!") + end +end + +--- Read a session and return its content. +-- @param id Session identifier +-- @return Session data +function read(id) + if not id then + return + end + if not id:match("^%w+$") then + error("Session ID is not sane!") + end + clean() + if not sane(sessionpath .. "/" .. id) then + return + end + return luci.fs.readfile(sessionpath .. "/" .. id) +end + + +--- Check whether Session environment is sane. +-- @return Boolean status +function sane(file) + return luci.sys.process.info("uid") + == luci.fs.stat(file or sessionpath, "uid") + and luci.fs.stat(file or sessionpath, "mode") + == (file and "rw-------" or "rwx------") +end + + +--- Write session data to a session file. +-- @param id Session identifier +-- @param data Session data +function write(id, data) + if not sane() then + prepare() + end + if not id:match("^%w+$") then + error("Session ID is not sane!") + end + luci.fs.writefile(sessionpath .. "/" .. id, data) + luci.fs.chmod(sessionpath .. "/" .. id, "a-rwx,u+rw") +end + + +--- Kills a session +-- @param id Session identifier +function kill(id) + if not id:match("^%w+$") then + error("Session ID is not sane!") + end + luci.fs.unlink(sessionpath .. "/" .. id) +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/cgi.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/cgi.lua new file mode 100644 index 0000000..00d9636 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/cgi.lua @@ -0,0 +1,90 @@ +--[[ +LuCI - SGI-Module for CGI + +Description: +Server Gateway Interface for CGI + +FileId: +$Id: cgi.lua 3739 2008-11-08 20:25:49Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.sgi.cgi", package.seeall) +local ltn12 = require("luci.ltn12") +require("luci.http") +require("luci.sys") +require("luci.dispatcher") + +-- Limited source to avoid endless blocking +local function limitsource(handle, limit) + limit = limit or 0 + local BLOCKSIZE = ltn12.BLOCKSIZE + + return function() + if limit < 1 then + handle:close() + return nil + else + local read = (limit > BLOCKSIZE) and BLOCKSIZE or limit + limit = limit - read + + local chunk = handle:read(read) + if not chunk then handle:close() end + return chunk + end + end +end + +function run() + local r = luci.http.Request( + luci.sys.getenv(), + limitsource(io.stdin, tonumber(luci.sys.getenv("CONTENT_LENGTH"))), + ltn12.sink.file(io.stderr) + ) + + local x = coroutine.create(luci.dispatcher.httpdispatch) + local hcache = "" + local active = true + + while coroutine.status(x) ~= "dead" do + local res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + print("Status: 500 Internal Server Error") + print("Content-Type: text/plain\n") + print(id) + break; + end + + if active then + if id == 1 then + io.write("Status: " .. tostring(data1) .. " " .. data2 .. "\r\n") + elseif id == 2 then + hcache = hcache .. data1 .. ": " .. data2 .. "\r\n" + elseif id == 3 then + io.write(hcache) + io.write("\r\n") + elseif id == 4 then + io.write(data1) + elseif id == 5 then + io.flush() + io.close() + active = false + end + end + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/webuci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/webuci.lua new file mode 100644 index 0000000..e0416db --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/webuci.lua @@ -0,0 +1,74 @@ +--[[ +LuCI - SGI-Module for Webuci + +Description: +Server Gateway Interface for Webuci + +FileId: +$Id: webuci.lua 2656 2008-07-23 18:52:12Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.sgi.webuci", package.seeall) +local ltn12 = require("luci.ltn12") +require("luci.http") +require("luci.util") +require("luci.dispatcher") + +function run(env, vars) + local r = luci.http.Request( + env, + ltn12.source.empty(), + ltn12.sink.file(io.stderr) + ) + + r.message.params = vars + + local x = coroutine.create(luci.dispatcher.httpdispatch) + local status = "" + local headers = {} + local active = true + + while coroutine.status(x) ~= "dead" do + local res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + print(env.SERVER_PROTOCOL .. " 500 Internal Server Error") + print("Content-Type: text/plain\n") + print(id) + break; + end + + if active then + if id == 1 then + status = env.SERVER_PROTOCOL .. " " .. tostring(data1) .. " " .. data2 .. "\r\n" + elseif id == 2 then + headers[data1] = data2 + elseif id == 3 then + io.write(status) + for k, v in pairs(headers) do + io.write(k .. ": " .. v .. "\r\n") + end + io.write("\r\n") + elseif id == 4 then + io.write(data1) + elseif id == 5 then + active = false + end + end + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/wsapi.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/wsapi.lua new file mode 100644 index 0000000..1d6e118 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/sgi/wsapi.lua @@ -0,0 +1,79 @@ +--[[ +LuCI - SGI-Module for WSAPI + +Description: +Server Gateway Interface for WSAPI + +FileId: +$Id: wsapi.lua 2656 2008-07-23 18:52:12Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.sgi.wsapi", package.seeall) +local ltn12 = require("luci.ltn12") +require("luci.http") +require("luci.dispatcher") +require("luci.http.protocol") + +function run(wsapi_env) + local r = luci.http.Request( + wsapi_env, + ltn12.source.file(wsapi_env.input), + ltn12.sink.file(wsapi_env.error) + ) + + local res, id, data1, data2 = true, 0, nil, nil + local headers = {} + local status = 200 + + local x = coroutine.create(luci.dispatcher.httpdispatch) + local active = true + + while id < 3 do + res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + status = 500 + headers["Content-Type"] = "text/plain" + local err = {id} + return status, headers, function() local x = table.remove(err) return x end + end + + if id == 1 then + status = data1 + elseif id == 2 then + headers[data1] = data2 + end + end + + local function iter() + local res, id, data = coroutine.resume(x) + if id == 4 and active then + return data + elseif id == 5 then + active = false + return "" + else + return "" + end + if coroutine.status(x) == "dead" then + return nil + end + end + + return status, headers, iter +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/datatree.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/datatree.lua new file mode 100644 index 0000000..3411702 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/datatree.lua @@ -0,0 +1,181 @@ +--[[ + +Luci statistics - rrd data tree builder +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: datatree.lua 3642 2008-10-29 05:08:03Z jow $ + +]]-- + +module("luci.statistics.datatree", package.seeall) + +local util = require("luci.util") +local sys = require("luci.sys") +local fs = require("luci.fs") +local uci = require("luci.model.uci").cursor() +local sections = uci:get_all("luci_statistics") + + +Instance = util.class() + +function Instance.__init__( self, host ) + self._host = host or sections.collectd.Hostname or sys.hostname() + self._libdir = sections.collectd.PluginDir or "/usr/lib/collectd" + self._rrddir = sections.collectd_rrdtool.DataDir or "/tmp/rrd" + + self._libdir = self._libdir:gsub("/$","") + self._rrddir = self._rrddir:gsub("/$","") + self._plugins = { } + + self:_scan() +end + +function Instance._mkpath( self, plugin, pinstance ) + local dir = self._rrddir .. "/" .. self._host + + if type(plugin) == "string" and plugin:len() > 0 then + dir = dir .. "/" .. plugin + + if type(pinstance) == "string" and pinstance:len() > 0 then + dir = dir .. "-" .. pinstance + end + end + + return dir +end + +function Instance._notzero( self, table ) + for k in pairs(table) do + return true + end + + return false +end + +function Instance._scan( self ) + local dirs = fs.dir( self:_mkpath() ) + if not dirs then + return + end + +-- for i, plugin in ipairs( dirs ) do +-- if plugin:match("%w+.so") then +-- self._plugins[ plugin:gsub("%.so$", "") ] = { } +-- end +-- end + + for _, dir in ipairs(dirs) do + if dir ~= "." and dir ~= ".." and + fs.stat(self:_mkpath(dir)).type == "directory" + then + local plugin = dir:gsub("%-.+$", "") + if not self._plugins[plugin] then + self._plugins[plugin] = { } + end + end + end + + for plugin, instances in pairs( self._plugins ) do + + local dirs = fs.dir( self:_mkpath() ) + + if type(dirs) == "table" then + for i, dir in ipairs(dirs) do + if dir:find( plugin .. "%-" ) or dir == plugin then + local instance = "" + + if dir ~= plugin then + instance = dir:gsub( plugin .. "%-", "", 1 ) + end + + instances[instance] = { } + end + end + end + + for instance, data_instances in pairs( instances ) do + + dirs = fs.dir( self:_mkpath( plugin, instance ) ) + + if type(dirs) == "table" then + for i, file in ipairs(dirs) do + if file:find("%.rrd") then + file = file:gsub("%.rrd","") + + local data_type + local data_instance + + if file:find("%-") then + data_type = file:gsub( "%-.+","" ) + data_instance = file:gsub( "[^%-]-%-", "", 1 ) + else + data_type = file + data_instance = "" + end + + if not data_instances[data_type] then + data_instances[data_type] = { data_instance } + else + table.insert( data_instances[data_type], data_instance ) + end + end + end + end + end + end +end + + +function Instance.plugins( self ) + local rv = { } + + for plugin, val in pairs( self._plugins ) do + if self:_notzero( val ) then + table.insert( rv, plugin ) + end + end + + return rv +end + +function Instance.plugin_instances( self, plugin ) + local rv = { } + + for instance, val in pairs( self._plugins[plugin] ) do + table.insert( rv, instance ) + end + + return rv +end + +function Instance.data_types( self, plugin, instance ) + local rv = { } + local p = self._plugins[plugin] + + if type(p) == "table" and type(p[instance]) == "table" then + for type, val in pairs(p[instance]) do + table.insert( rv, type ) + end + end + + return rv +end + +function Instance.data_instances( self, plugin, instance, dtype ) + local rv = { } + local p = self._plugins[plugin] + + if type(p) == "table" and type(p[instance]) == "table" and type(p[instance][dtype]) == "table" then + for i, instance in ipairs(p[instance][dtype]) do + table.insert( rv, instance ) + end + end + + return rv +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/i18n.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/i18n.lua new file mode 100644 index 0000000..b54e30b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/i18n.lua @@ -0,0 +1,115 @@ +--[[ + +Luci statistics - diagram i18n helper +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: i18n.lua 3033 2008-08-31 14:38:28Z jow $ + +]]-- + +module("luci.statistics.i18n", package.seeall) + +require("luci.util") +require("luci.i18n") + + +Instance = luci.util.class() + + +function Instance.__init__( self, graph ) + self.i18n = luci.i18n + self.graph = graph + + self.i18n.loadc("rrdtool") + self.i18n.loadc("statistics") +end + +function Instance._subst( self, str, val ) + str = str:gsub( "%%H", self.graph.opts.host or "" ) + str = str:gsub( "%%pn", val.plugin or "" ) + str = str:gsub( "%%pi", val.pinst or "" ) + str = str:gsub( "%%dt", val.dtype or "" ) + str = str:gsub( "%%di", val.dinst or "" ) + str = str:gsub( "%%ds", val.dsrc or "" ) + + return str +end + +function Instance.title( self, plugin, pinst, dtype, dinst ) + + local title = self.i18n.translate( + string.format( "stat_dg_title_%s_%s_%s", plugin, pinst, dtype ), + self.i18n.translate( + string.format( "stat_dg_title_%s_%s", plugin, pinst ), + self.i18n.translate( + string.format( "stat_dg_title_%s__%s", plugin, dtype ), + self.i18n.translate( + string.format( "stat_dg_title_%s", plugin ), + self.graph:_mkpath( plugin, pinst, dtype ) + ) + ) + ) + ) + + return self:_subst( title, { + plugin = plugin, + pinst = pinst, + dtype = dtype, + dinst = dinst + } ) + +end + +function Instance.label( self, plugin, pinst, dtype, dinst ) + + local label = self.i18n.translate( + string.format( "stat_dg_label_%s_%s_%s", plugin, pinst, dtype ), + self.i18n.translate( + string.format( "stat_dg_label_%s_%s", plugin, pinst ), + self.i18n.translate( + string.format( "stat_dg_label_%s__%s", plugin, dtype ), + self.i18n.translate( + string.format( "stat_dg_label_%s", plugin ), + self.graph:_mkpath( plugin, pinst, dtype ) + ) + ) + ) + ) + + return self:_subst( label, { + plugin = plugin, + pinst = pinst, + dtype = dtype, + dinst = dinst + } ) + +end + +function Instance.ds( self, source ) + + local label = self.i18n.translate( + string.format( "stat_ds_%s_%s_%s", source.type, source.instance, source.ds ), + self.i18n.translate( + string.format( "stat_ds_%s_%s", source.type, source.instance ), + self.i18n.translate( + string.format( "stat_ds_label_%s__%s", source.type, source.ds ), + self.i18n.translate( + string.format( "stat_ds_%s", source.type ), + source.type .. "_" .. source.instance:gsub("[^%w]","_") .. "_" .. source.ds + ) + ) + ) + ) + + return self:_subst( label, { + dtype = source.type, + dinst = source.instance, + dsrc = source.ds + } ) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool.lua new file mode 100644 index 0000000..ca00e42 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool.lua @@ -0,0 +1,607 @@ +--[[ + +Luci statistics - rrdtool interface library / diagram model interpreter +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: rrdtool.lua 3873 2008-12-07 23:44:22Z jow $ + +]]-- + +module("luci.statistics.rrdtool", package.seeall) + +require("luci.statistics.datatree") +require("luci.statistics.rrdtool.colors") +require("luci.statistics.rrdtool.definitions") +require("luci.statistics.i18n") +require("luci.model.uci") +require("luci.util") +require("luci.sys") +require("luci.fs") + + +Graph = luci.util.class() + +function Graph.__init__( self, timespan, opts ) + + opts = opts or { } + + local uci = luci.model.uci.cursor() + local sections = uci:get_all( "luci_statistics" ) + + -- helper classes + self.colors = luci.statistics.rrdtool.colors.Instance() + self.defs = luci.statistics.rrdtool.definitions.Instance() + self.tree = luci.statistics.datatree.Instance() + self.i18n = luci.statistics.i18n.Instance( self ) + + -- options + opts.timespan = timespan or sections.rrdtool.default_timespan or 900 + opts.rrasingle = opts.rrasingle or ( sections.collectd_rrdtool.RRASingle == "1" ) + opts.host = opts.host or sections.collectd.Hostname or luci.sys.hostname() + opts.width = opts.width or sections.rrdtool.image_width or 400 + opts.rrdpath = opts.rrdpath or sections.collectd_rrdtool.DataDir or "/tmp/rrd" + opts.imgpath = opts.imgpath or sections.rrdtool.image_path or "/tmp/rrdimg" + opts.rrdpath = opts.rrdpath:gsub("/$","") + opts.imgpath = opts.imgpath:gsub("/$","") + + -- rrdtool default args + self.args = { + "-a", "PNG", + "-s", "NOW-" .. opts.timespan, + "-w", opts.width + } + + -- store options + self.opts = opts +end + +function Graph._mkpath( self, plugin, plugin_instance, dtype, dtype_instance ) + local t = self.opts.host .. "/" .. plugin + if type(plugin_instance) == "string" and plugin_instance:len() > 0 then + t = t .. "-" .. plugin_instance + end + t = t .. "/" .. dtype + if type(dtype_instance) == "string" and dtype_instance:len() > 0 then + t = t .. "-" .. dtype_instance + end + return t +end + +function Graph.mkrrdpath( self, ... ) + return string.format( "%s/%s.rrd", self.opts.rrdpath, self:_mkpath( ... ) ) +end + +function Graph.mkpngpath( self, ... ) + return string.format( "%s/%s.%i.png", self.opts.imgpath, self:_mkpath( ... ), self.opts.timespan ) +end + +function Graph.strippngpath( self, path ) + return path:sub( self.opts.imgpath:len() + 2 ) +end + +function Graph._forcelol( self, list ) + if type(list[1]) ~= "table" then + return( { list } ) + end + return( list ) +end + +function Graph._rrdtool( self, def, rrd ) + + -- prepare directory + local dir = def[1]:gsub("/[^/]+$","") + luci.fs.mkdir( dir, true ) + + -- construct commandline + local cmdline = "rrdtool graph" + + -- copy default arguments to def stack + for i, opt in ipairs(self.args) do + table.insert( def, 1 + i, opt ) + end + + -- construct commandline from def stack + for i, opt in ipairs(def) do + opt = opt .. "" -- force string + + if rrd then + opt = opt:gsub( "{file}", rrd ) + end + + if opt:match("[^%w]") then + cmdline = cmdline .. " '" .. opt .. "'" + else + cmdline = cmdline .. " " .. opt + end + end + + -- execute rrdtool + local rrdtool = io.popen( cmdline ) + rrdtool:close() +end + +function Graph._generic( self, opts, plugin, plugin_instance, dtype, index ) + + -- generated graph defs + local defs = { } + + -- internal state variables + local _args = { } + local _sources = { } + local _stack_neg = { } + local _stack_pos = { } + local _longest_name = 0 + local _has_totals = false + + -- some convenient aliases + local _ti = table.insert + local _sf = string.format + + -- local helper: append a string.format() formatted string to given table + function _tif( list, fmt, ... ) + table.insert( list, string.format( fmt, ... ) ) + end + + -- local helper: create definitions for min, max, avg and create *_nnl (not null) variable from avg + function __def(source) + + local inst = source.sname + local rrd = source.rrd + local ds = source.ds + + if not ds or ds:len() == 0 then ds = "value" end + + _tif( _args, "DEF:%s_avg=%s:%s:AVERAGE", inst, rrd, ds ) + + if not self.opts.rrasingle then + _tif( _args, "DEF:%s_min=%s:%s:MIN", inst, rrd, ds ) + _tif( _args, "DEF:%s_max=%s:%s:MAX", inst, rrd, ds ) + end + + _tif( _args, "CDEF:%s_nnl=%s_avg,UN,0,%s_avg,IF", inst, inst, inst ) + end + + -- local helper: create cdefs depending on source options like flip and overlay + function __cdef(source) + + local prev + + -- find previous source, choose stack depending on flip state + if source.flip then + prev = _stack_neg[#_stack_neg] + else + prev = _stack_pos[#_stack_pos] + end + + -- is first source in stack or overlay source: source_stk = source_nnl + if not prev or source.overlay then + -- create cdef statement + _tif( _args, "CDEF:%s_stk=%s_nnl", source.sname, source.sname ) + + -- is subsequent source without overlay: source_stk = source_nnl + previous_stk + else + -- create cdef statement + _tif( _args, "CDEF:%s_stk=%s_nnl,%s_stk,+", source.sname, source.sname, prev ) + end + + -- create multiply by minus one cdef if flip is enabled + if source.flip then + + -- create cdef statement: source_stk = source_stk * -1 + _tif( _args, "CDEF:%s_neg=%s_stk,-1,*", source.sname, source.sname ) + + -- push to negative stack if overlay is disabled + if not source.overlay then + _ti( _stack_neg, source.sname ) + end + + -- no flipping, push to positive stack if overlay is disabled + elseif not source.overlay then + + -- push to positive stack + _ti( _stack_pos, source.sname ) + end + + -- calculate total amount of data if requested + if source.total then + _tif( _args, + "CDEF:%s_avg_sample=%s_avg,UN,0,%s_avg,IF,sample_len,*", + source.sname, source.sname, source.sname + ) + + _tif( _args, + "CDEF:%s_avg_sum=PREV,UN,0,PREV,IF,%s_avg_sample,+", + source.sname, source.sname, source.sname + ) + end + end + + -- local helper: create cdefs required for calculating total values + function __cdef_totals() + if _has_totals then + _tif( _args, "CDEF:mytime=%s_avg,TIME,TIME,IF", _sources[1].sname ) + _ti( _args, "CDEF:sample_len_raw=mytime,PREV(mytime),-" ) + _ti( _args, "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF" ) + end + end + + -- local helper: create line and area statements + function __line(source) + + local line_color + local area_color + local legend + local var + + -- find colors: try source, then opts.colors; fall back to random color + if type(source.color) == "string" then + line_color = source.color + area_color = self.colors:from_string( line_color ) + elseif type(opts.colors[source.name:gsub("[^%w]","_")]) == "string" then + line_color = opts.colors[source.name:gsub("[^%w]","_")] + area_color = self.colors:from_string( line_color ) + else + area_color = self.colors:random() + line_color = self.colors:to_string( area_color ) + end + + -- derive area background color from line color + area_color = self.colors:to_string( self.colors:faded( area_color ) ) + + -- choose source_stk or source_neg variable depending on flip state + if source.flip then + var = "neg" + else + var = "stk" + end + + -- create legend + legend = _sf( "%-" .. _longest_name .. "s", source.title ) + + -- create area if not disabled + if not source.noarea then + _tif( _args, "AREA:%s_%s#%s", source.sname, var, area_color ) + end + + -- create line1 statement + _tif( _args, "LINE1:%s_%s#%s:%s", source.sname, var, line_color, legend ) + end + + -- local helper: create gprint statements + function __gprint(source) + + local numfmt = opts.number_format or "%6.1lf" + local totfmt = opts.totals_format or "%5.1lf%s" + + -- don't include MIN if rrasingle is enabled + if not self.opts.rrasingle then + _tif( _args, "GPRINT:%s_min:MIN:\tMin\\: %s", source.sname, numfmt ) + end + + -- always include AVERAGE + _tif( _args, "GPRINT:%s_avg:AVERAGE:\tAvg\\: %s", source.sname, numfmt ) + + -- don't include MAX if rrasingle is enabled + if not self.opts.rrasingle then + _tif( _args, "GPRINT:%s_max:MAX:\tMax\\: %s", source.sname, numfmt ) + end + + -- include total count if requested else include LAST + if source.total then + _tif( _args, "GPRINT:%s_avg_sum:LAST:(ca. %s Total)\\l", source.sname, totfmt ) + else + _tif( _args, "GPRINT:%s_avg:LAST:\tLast\\: %s\\l", source.sname, numfmt ) + end + end + + + -- + -- find all data sources + -- + + -- find data types + local data_types + + if dtype then + data_types = { dtype } + else + data_types = opts.data.types or { } + end + + if not ( dtype or opts.data.types ) then + if opts.data.instances then + for k, v in pairs(opts.data.instances) do + _ti( data_types, k ) + end + elseif opts.data.sources then + for k, v in pairs(opts.data.sources) do + _ti( data_types, k ) + end + end + end + + + -- iterate over data types + for i, dtype in ipairs(data_types) do + + -- find instances + + local data_instances + + if not opts.per_instance then + if type(opts.data.instances) == "table" and type(opts.data.instances[dtype]) == "table" then + data_instances = opts.data.instances[dtype] + else + data_instances = self.tree:data_instances( plugin, plugin_instance, dtype ) + end + end + + if type(data_instances) ~= "table" or #data_instances == 0 then data_instances = { "" } end + + + -- iterate over data instances + for i, dinst in ipairs(data_instances) do + + -- construct combined data type / instance name + local dname = dtype + + if dinst:len() > 0 then + dname = dname .. "_" .. dinst + end + + + -- find sources + local data_sources = { "value" } + + if type(opts.data.sources) == "table" then + if type(opts.data.sources[dname]) == "table" then + data_sources = opts.data.sources[dname] + elseif type(opts.data.sources[dtype]) == "table" then + data_sources = opts.data.sources[dtype] + end + end + + + -- iterate over data sources + for i, dsource in ipairs(data_sources) do + + local dsname = dtype .. "_" .. dinst:gsub("[^%w]","_") .. "_" .. dsource + local altname = dtype .. "__" .. dsource + + -- find datasource options + local dopts = { } + + if type(opts.data.options) == "table" then + if type(opts.data.options[dsname]) == "table" then + dopts = opts.data.options[dsname] + elseif type(opts.data.options[altname]) == "table" then + dopts = opts.data.options[altname] + elseif type(opts.data.options[dname]) == "table" then + dopts = opts.data.options[dname] + elseif type(opts.data.options[dtype]) == "table" then + dopts = opts.data.options[dtype] + end + end + + + -- store values + _ti( _sources, { + rrd = dopts.rrd or self:mkrrdpath( plugin, plugin_instance, dtype, dinst ), + color = dopts.color or self.colors:to_string( self.colors:random() ), + flip = dopts.flip or false, + total = dopts.total or false, + overlay = dopts.overlay or false, + noarea = dopts.noarea or false, + ds = dsource, + type = dtype, + instance = dinst, + index = #_sources + 1, + sname = ( #_sources + 1 ) .. dtype + } ) + + + -- generate datasource title + _sources[#_sources].title = self.i18n:ds( _sources[#_sources] ) + + + -- find longest name ... + if _sources[#_sources].title:len() > _longest_name then + _longest_name = _sources[#_sources].title:len() + end + + + -- has totals? + if _sources[#_sources].total then + _has_totals = true + end + end + end + end + + + -- + -- construct diagrams + -- + + -- if per_instance is enabled then find all instances from the first datasource in diagram + -- if per_instance is disabled then use an empty pseudo instance and use model provided values + local instances = { "" } + + if opts.per_instance then + instances = self.tree:data_instances( plugin, plugin_instance, _sources[1].type ) + end + + + -- iterate over instances + for i, instance in ipairs(instances) do + + -- store title and vlabel + _ti( _args, "-t" ) + _ti( _args, opts.title or self.i18n:title( plugin, plugin_instance, _sources[1].type, instance ) ) + _ti( _args, "-v" ) + _ti( _args, opts.vlabel or self.i18n:label( plugin, plugin_instance, _sources[1].type, instance ) ) + + -- store additional rrd options + if opts.rrdopts then + for i, o in ipairs(opts.rrdopts) do _ti( _args, o ) end + end + + + -- create DEF statements for each instance + for i, source in ipairs(_sources) do + -- fixup properties for per instance mode... + if opts.per_instance then + source.instance = instance + source.rrd = self:mkrrdpath( plugin, plugin_instance, source.type, instance ) + end + + __def( source ) + end + + -- create CDEF required for calculating totals + __cdef_totals() + + -- create CDEF statements for each instance in reversed order + for i, source in ipairs(_sources) do + __cdef( _sources[1 + #_sources - i] ) + end + + -- create LINE1, AREA and GPRINT statements for each instance + for i, source in ipairs(_sources) do + __line( source ) + __gprint( source ) + end + + -- prepend image path to arg stack + _ti( _args, 1, self:mkpngpath( plugin, plugin_instance, index .. instance ) ) + + -- push arg stack to definition list + _ti( defs, _args ) + + -- reset stacks + _args = { } + _stack_pos = { } + _stack_neg = { } + end + + return defs +end + +function Graph.render( self, plugin, plugin_instance ) + + dtype_instances = dtype_instances or { "" } + local pngs = { } + + -- check for a whole graph handler + local plugin_def = "luci.statistics.rrdtool.definitions." .. plugin + local stat, def = luci.util.copcall( require, plugin_def ) + + if stat and def and type(def.rrdargs) == "function" then + + -- temporary image matrix + local _images = { } + + -- get diagram definitions + for i, opts in ipairs( self:_forcelol( def.rrdargs( self, plugin, plugin_instance ) ) ) do + + _images[i] = { } + + -- get diagram definition instances + local diagrams = self:_generic( opts, plugin, plugin_instance, nil, i ) + + -- render all diagrams + for j, def in ipairs( diagrams ) do + + -- remember image + _images[i][j] = def[1] + + -- exec + self:_rrdtool( def ) + end + end + + -- remember images - XXX: fixme (will cause probs with asymmetric data) + for y = 1, #_images[1] do + for x = 1, #_images do + table.insert( pngs, _images[x][y] ) + end + end + else + + -- no graph handler, iterate over data types + for i, dtype in ipairs( self.tree:data_types( plugin, plugin_instance ) ) do + + -- check for data type handler + local dtype_def = plugin_def .. "." .. dtype + local stat, def = luci.util.copcall( require, dtype_def ) + + if stat and def and type(def.rrdargs) == "function" then + + -- temporary image matrix + local _images = { } + + -- get diagram definitions + for i, opts in ipairs( self:_forcelol( def.rrdargs( self, plugin, plugin_instance, dtype ) ) ) do + + _images[i] = { } + + -- get diagram definition instances + local diagrams = self:_generic( opts, plugin, plugin_instance, dtype, i ) + + -- render all diagrams + for j, def in ipairs( diagrams ) do + + -- remember image + _images[i][j] = def[1] + + -- exec + self:_rrdtool( def ) + end + end + + -- remember images - XXX: fixme (will cause probs with asymmetric data) + for y = 1, #_images[1] do + for x = 1, #_images do + table.insert( pngs, _images[x][y] ) + end + end + else + + -- no data type handler, fall back to builtin definition + if type(self.defs.definitions[dtype]) == "table" then + + -- iterate over data type instances + for i, inst in ipairs( self.tree:data_instances( plugin, plugin_instance, dtype ) ) do + + local title = self.i18n:title( plugin, plugin_instance, dtype, inst ) + local label = self.i18n:label( plugin, plugin_instance, dtype, inst ) + local png = self:mkpngpath( plugin, plugin_instance, dtype, inst ) + local rrd = self:mkrrdpath( plugin, plugin_instance, dtype, inst ) + local args = { png, "-t", title, "-v", label } + + for i, o in ipairs(self.defs.definitions[dtype]) do + -- XXX: this is a somewhat ugly hack to exclude min/max RRAs when rrasingle is on + if not ( self.opts.rrasingle and ( o:match("_min") or o:match("_max") ) ) then + table.insert( args, o ) + end + end + + -- remember image + table.insert( pngs, png ) + + -- exec + self:_rrdtool( args, rrd ) + end + end + end + end + end + + return pngs +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/colors.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/colors.lua new file mode 100644 index 0000000..e5fef17 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/colors.lua @@ -0,0 +1,73 @@ +--[[ + +Luci statistics - diagram color helper class +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: colors.lua 2829 2008-08-14 22:51:12Z Cyrus $ + +]]-- + +module("luci.statistics.rrdtool.colors", package.seeall) + +require("luci.util") + + +Instance = luci.util.class() + +function Instance.from_string( self, s ) + return { + tonumber(s:sub(1,2), 16), + tonumber(s:sub(3,4), 16), + tonumber(s:sub(5,6), 16) + } +end + +function Instance.to_string( self, c ) + return string.format( + "%02x%02x%02x", + math.floor(c[1]), + math.floor(c[2]), + math.floor(c[3]) + ) +end + +function Instance.random( self ) + local r = math.random(255) + local g = math.random(255) + local min = 0 + local max = 255 + + if ( r + g ) < 255 then + min = 255 - r - g + else + max = 511 - r - g + end + + local b = min + math.floor( math.random() * ( max - min ) ) + + return { r, g, b } +end + +function Instance.faded( self, fg, opts ) + opts = opts or {} + opts.background = opts.background or { 255, 255, 255 } + opts.alpha = opts.alpha or 0.25 + + if type(opts.background) == "string" then + opts.background = _string_to_color(opts.background) + end + + local bg = opts.background + + return { + ( opts.alpha * fg[1] ) + ( ( 1.0 - opts.alpha ) * bg[1] ), + ( opts.alpha * fg[2] ) + ( ( 1.0 - opts.alpha ) * bg[2] ), + ( opts.alpha * fg[3] ) + ( ( 1.0 - opts.alpha ) * bg[3] ) + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions.lua new file mode 100644 index 0000000..159fa7e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions.lua @@ -0,0 +1,1123 @@ +--[[ + +Luci statistics - data definition database (obsolete) +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: definitions.lua 3540 2008-10-08 15:59:10Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions", package.seeall) + +require("luci.util") +require("luci.fs") + + +Instance = luci.util.class() + +function Instance.__init__( self, ... ) + + -- used color palette + self.palette = { + Canvas = "FFFFFF", + FullRed = "FF0000", + FullGreen = "00E000", + FullBlue = "0000FF", + FullYellow = "F0A000", + FullCyan = "00A0FF", + FullMagenta = "A000FF", + HalfRed = "F7B7B7", + HalfGreen = "B7EFB7", + HalfBlue = "B7B7F7", + HalfYellow = "F3DFB7", + HalfCyan = "B7DFF7", + HalfMagenta = "DFB7F7", + HalfBlueGreen = "89B3C9" + } + + -- plotting arguments for each defined datasource + self.definitions = { + apache_bytes = { + "DEF:min_raw={file}:count:MIN", + "DEF:avg_raw={file}:count:AVERAGE", + "DEF:max_raw={file}:count:MAX", + "CDEF:min=min_raw,8,*", + "CDEF:avg=avg_raw,8,*", + "CDEF:max=max_raw,8,*", + "CDEF:mytime=avg_raw,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*", + "CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+", + "AREA:avg#" .. self.palette.HalfBlue, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bit/s", + "GPRINT:min:MIN:%5.1lf%s Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:max:MAX:%5.1lf%s Max,", + "GPRINT:avg:LAST:%5.1lf%s Last\\l", + "GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)" + }, + + apache_requests = { + "DEF:min={file}:count:MIN", + "DEF:avg={file}:count:AVERAGE", + "DEF:max={file}:count:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Requests/s", + "GPRINT:min:MIN:%6.2lf Min,", + "GPRINT:avg:AVERAGE:%6.2lf Avg,", + "GPRINT:max:MAX:%6.2lf Max,", + "GPRINT:avg:LAST:%6.2lf Last\\l" + }, + + apache_scoreboard = { + "DEF:min={file}:count:MIN", + "DEF:avg={file}:count:AVERAGE", + "DEF:max={file}:count:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Processes", + "GPRINT:min:MIN:%6.2lf Min,", + "GPRINT:avg:AVERAGE:%6.2lf Avg,", + "GPRINT:max:MAX:%6.2lf Max,", + "GPRINT:avg:LAST:%6.2lf Last\\l" + }, + + bitrate = { + "-v", "Bits/s", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bits/s", + "GPRINT:min:MIN:%5.1lf%s Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s Average,", + "GPRINT:max:MAX:%5.1lf%s Max,", + "GPRINT:avg:LAST:%5.1lf%s Last\\l" + }, + + charge = { + "-v", "Ah", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Charge", + "GPRINT:min:MIN:%5.1lf%sAh Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sAh Avg,", + "GPRINT:max:MAX:%5.1lf%sAh Max,", + "GPRINT:avg:LAST:%5.1lf%sAh Last\\l" + }, + + current = { + "-v", "Ampere", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Current", + "GPRINT:min:MIN:%5.1lf%sA Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sA Avg,", + "GPRINT:max:MAX:%5.1lf%sA Max,", + "GPRINT:avg:LAST:%5.1lf%sA Last\\l" + }, + + disk = { + "DEF:rtime_avg={file}:rtime:AVERAGE", + "DEF:rtime_min={file}:rtime:MIN", + "DEF:rtime_max={file}:rtime:MAX", + "DEF:wtime_avg={file}:wtime:AVERAGE", + "DEF:wtime_min={file}:wtime:MIN", + "DEF:wtime_max={file}:wtime:MAX", + "CDEF:rtime_avg_ms=rtime_avg,1000,/", + "CDEF:rtime_min_ms=rtime_min,1000,/", + "CDEF:rtime_max_ms=rtime_max,1000,/", + "CDEF:wtime_avg_ms=wtime_avg,1000,/", + "CDEF:wtime_min_ms=wtime_min,1000,/", + "CDEF:wtime_max_ms=wtime_max,1000,/", + "CDEF:total_avg_ms=rtime_avg_ms,wtime_avg_ms,+", + "CDEF:total_min_ms=rtime_min_ms,wtime_min_ms,+", + "CDEF:total_max_ms=rtime_max_ms,wtime_max_ms,+", + "AREA:total_max_ms#" .. self.palette.HalfRed, + "AREA:total_min_ms#" .. self.palette.Canvas, + "LINE1:wtime_avg_ms#" .. self.palette.FullGreen .. ":Write", + "GPRINT:wtime_min_ms:MIN:%5.1lf%s Min,", + "GPRINT:wtime_avg_ms:AVERAGE:%5.1lf%s Avg,", + "GPRINT:wtime_max_ms:MAX:%5.1lf%s Max,", + "GPRINT:wtime_avg_ms:LAST:%5.1lf%s Last\n", + "LINE1:rtime_avg_ms#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:rtime_min_ms:MIN:%5.1lf%s Min,", + "GPRINT:rtime_avg_ms:AVERAGE:%5.1lf%s Avg,", + "GPRINT:rtime_max_ms:MAX:%5.1lf%s Max,", + "GPRINT:rtime_avg_ms:LAST:%5.1lf%s Last\n", + "LINE1:total_avg_ms#" .. self.palette.FullRed .. ":Total", + "GPRINT:total_min_ms:MIN:%5.1lf%s Min,", + "GPRINT:total_avg_ms:AVERAGE:%5.1lf%s Avg,", + "GPRINT:total_max_ms:MAX:%5.1lf%s Max,", + "GPRINT:total_avg_ms:LAST:%5.1lf%s Last\\l" + }, + + disk_octets = { + "-v", "Bytes/s", + "DEF:out_min={file}:write:MIN", + "DEF:out_avg={file}:write:AVERAGE", + "DEF:out_max={file}:write:MAX", + "DEF:inc_min={file}:read:MIN", + "DEF:inc_avg={file}:read:AVERAGE", + "DEF:inc_max={file}:read:MAX", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "CDEF:mytime=out_avg,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*", + "CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+", + "CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*", + "CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:out_max:MAX:%5.1lf%s Max,", + "GPRINT:out_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:inc_max:MAX:%5.1lf%s Max,", + "GPRINT:inc_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)" + }, + + disk_merged = { + "-v", "Merged Ops/s", + "DEF:out_min={file}:write:MIN", + "DEF:out_avg={file}:write:AVERAGE", + "DEF:out_max={file}:write:MAX", + "DEF:inc_min={file}:read:MIN", + "DEF:inc_avg={file}:read:AVERAGE", + "DEF:inc_max={file}:read:MAX", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:out_max:MAX:%6.2lf Max,", + "GPRINT:out_avg:LAST:%6.2lf Last\\l", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:inc_max:MAX:%6.2lf Max,", + "GPRINT:inc_avg:LAST:%6.2lf Last\\l" + }, + + disk_ops = { + "-v", "Ops/s", + "DEF:out_min={file}:write:MIN", + "DEF:out_avg={file}:write:AVERAGE", + "DEF:out_max={file}:write:MAX", + "DEF:inc_min={file}:read:MIN", + "DEF:inc_avg={file}:read:AVERAGE", + "DEF:inc_max={file}:read:MAX", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:out_max:MAX:%6.2lf Max,", + "GPRINT:out_avg:LAST:%6.2lf Last\\l", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:inc_max:MAX:%6.2lf Max,", + "GPRINT:inc_avg:LAST:%6.2lf Last\\l" + }, + + disk_time = { + "-v", "Seconds/s", + "DEF:out_min_raw={file}:write:MIN", + "DEF:out_avg_raw={file}:write:AVERAGE", + "DEF:out_max_raw={file}:write:MAX", + "DEF:inc_min_raw={file}:read:MIN", + "DEF:inc_avg_raw={file}:read:AVERAGE", + "DEF:inc_max_raw={file}:read:MAX", + "CDEF:out_min=out_min_raw,1000,/", + "CDEF:out_avg=out_avg_raw,1000,/", + "CDEF:out_max=out_max_raw,1000,/", + "CDEF:inc_min=inc_min_raw,1000,/", + "CDEF:inc_avg=inc_avg_raw,1000,/", + "CDEF:inc_max=inc_max_raw,1000,/", + "CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF", + "AREA:out_avg#" .. self.palette.HalfGreen, + "AREA:inc_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_avg:AVERAGE:%5.1lf%ss Avg,", + "GPRINT:out_max:MAX:%5.1lf%ss Max,", + "GPRINT:out_avg:LAST:%5.1lf%ss Last\\l", + "LINE1:inc_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_avg:AVERAGE:%5.1lf%ss Avg,", + "GPRINT:inc_max:MAX:%5.1lf%ss Max,", + "GPRINT:inc_avg:LAST:%5.1lf%ss Last\\l" + }, + + dns_octets = { + "DEF:rsp_min_raw={file}:responses:MIN", + "DEF:rsp_avg_raw={file}:responses:AVERAGE", + "DEF:rsp_max_raw={file}:responses:MAX", + "DEF:qry_min_raw={file}:queries:MIN", + "DEF:qry_avg_raw={file}:queries:AVERAGE", + "DEF:qry_max_raw={file}:queries:MAX", + "CDEF:rsp_min=rsp_min_raw,8,*", + "CDEF:rsp_avg=rsp_avg_raw,8,*", + "CDEF:rsp_max=rsp_max_raw,8,*", + "CDEF:qry_min=qry_min_raw,8,*", + "CDEF:qry_avg=qry_avg_raw,8,*", + "CDEF:qry_max=qry_max_raw,8,*", + "CDEF:overlap=rsp_avg,qry_avg,GT,qry_avg,rsp_avg,IF", + "CDEF:mytime=rsp_avg_raw,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:rsp_avg_sample=rsp_avg_raw,UN,0,rsp_avg_raw,IF,sample_len,*", + "CDEF:rsp_avg_sum=PREV,UN,0,PREV,IF,rsp_avg_sample,+", + "CDEF:qry_avg_sample=qry_avg_raw,UN,0,qry_avg_raw,IF,sample_len,*", + "CDEF:qry_avg_sum=PREV,UN,0,PREV,IF,qry_avg_sample,+", + "AREA:rsp_avg#" .. self.palette.HalfGreen, + "AREA:qry_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:rsp_avg#" .. self.palette.FullGreen .. ":Responses", + "GPRINT:rsp_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:rsp_max:MAX:%5.1lf%s Max,", + "GPRINT:rsp_avg:LAST:%5.1lf%s Last", + "GPRINT:rsp_avg_sum:LAST:(ca. %5.1lf%sB Total)\\l", + "LINE1:qry_avg#" .. self.palette.FullBlue .. ":Queries ", + "GPRINT:qry_min:MIN:%5.1lf %s Min,", + "GPRINT:qry_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:qry_max:MAX:%5.1lf%s Max,", + "GPRINT:qry_avg:LAST:%5.1lf%s Last", + "GPRINT:qry_avg_sum:LAST:(ca. %5.1lf%sB Total)\\l" + }, + + dns_opcode = { + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Queries/s", + "GPRINT:min:MIN:%9.3lf Min,", + "GPRINT:avg:AVERAGE:%9.3lf Average,", + "GPRINT:max:MAX:%9.3lf Max,", + "GPRINT:avg:LAST:%9.3lf Last\\l" + }, + + email_count = { + "-v", "Mails", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":Count ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + email_size = { + "-v", "Bytes", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":Count ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + spam_score = { + "-v", "Score", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Score ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + spam_check = { + "DEF:avg={file}:hits:AVERAGE", + "DEF:min={file}:hits:MIN", + "DEF:max={file}:hits:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":Count ", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + entropy = { + "-v", "Bits", + "DEF:avg={file}:entropy:AVERAGE", + "DEF:min={file}:entropy:MIN", + "DEF:max={file}:entropy:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bits", + "GPRINT:min:MIN:%4.0lfbit Min,", + "GPRINT:avg:AVERAGE:%4.0lfbit Avg,", + "GPRINT:max:MAX:%4.0lfbit Max,", + "GPRINT:avg:LAST:%4.0lfbit Last\\l" + }, + + fanspeed = { + "-v", "RPM", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfMagenta, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullMagenta .. ":RPM", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + frequency = { + "-v", "Hertz", + "DEF:avg={file}:frequency:AVERAGE", + "DEF:min={file}:frequency:MIN", + "DEF:max={file}:frequency:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Frequency [Hz]", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + frequency_offset = { + "DEF:ppm_avg={file}:ppm:AVERAGE", + "DEF:ppm_min={file}:ppm:MIN", + "DEF:ppm_max={file}:ppm:MAX", + "AREA:ppm_max#" .. self.palette.HalfBlue, + "AREA:ppm_min#" .. self.palette.Canvas, + "LINE1:ppm_avg#" .. self.palette.FullBlue .. ":{inst}", + "GPRINT:ppm_min:MIN:%5.2lf Min,", + "GPRINT:ppm_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:ppm_max:MAX:%5.2lf Max,", + "GPRINT:ppm_avg:LAST:%5.2lf Last\\l" + }, + + gauge = { + "-v", "Exec value", + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "AREA:temp_max#" .. self.palette.HalfBlue, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullBlue .. ":Exec value", + "GPRINT:temp_min:MIN:%6.2lf Min,", + "GPRINT:temp_avg:AVERAGE:%6.2lf Avg,", + "GPRINT:temp_max:MAX:%6.2lf Max,", + "GPRINT:temp_avg:LAST:%6.2lf Last\\l" + }, + + hddtemp = { + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "AREA:temp_max#" .. self.palette.HalfRed, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullRed .. ":Temperature", + "GPRINT:temp_min:MIN:%4.1lf Min,", + "GPRINT:temp_avg:AVERAGE:%4.1lf Avg,", + "GPRINT:temp_max:MAX:%4.1lf Max,", + "GPRINT:temp_avg:LAST:%4.1lf Last\\l" + }, + + humidity = { + "-v", "Percent", + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "AREA:temp_max#" .. self.palette.HalfGreen, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullGreen .. ":Temperature", + "GPRINT:temp_min:MIN:%4.1lf%% Min,", + "GPRINT:temp_avg:AVERAGE:%4.1lf%% Avg,", + "GPRINT:temp_max:MAX:%4.1lf%% Max,", + "GPRINT:temp_avg:LAST:%4.1lf%% Last\\l" + }, + + load = { + "-v", "System load", + "DEF:s_avg={file}:shortterm:AVERAGE", + "DEF:s_min={file}:shortterm:MIN", + "DEF:s_max={file}:shortterm:MAX", + "DEF:m_avg={file}:midterm:AVERAGE", + "DEF:m_min={file}:midterm:MIN", + "DEF:m_max={file}:midterm:MAX", + "DEF:l_avg={file}:longterm:AVERAGE", + "DEF:l_min={file}:longterm:MIN", + "DEF:l_max={file}:longterm:MAX", + "AREA:s_max#" .. self.palette.HalfGreen, + "AREA:s_min#" .. self.palette.Canvas, + "LINE1:s_avg#" .. self.palette.FullGreen .. ": 1m average", + "GPRINT:s_min:MIN:%4.2lf Min,", + "GPRINT:s_avg:AVERAGE:%4.2lf Avg,", + "GPRINT:s_max:MAX:%4.2lf Max,", + "GPRINT:s_avg:LAST:%4.2lf Last\n", + "LINE1:m_avg#" .. self.palette.FullBlue .. ": 5m average", + "GPRINT:m_min:MIN:%4.2lf Min,", + "GPRINT:m_avg:AVERAGE:%4.2lf Avg,", + "GPRINT:m_max:MAX:%4.2lf Max,", + "GPRINT:m_avg:LAST:%4.2lf Last\n", + "LINE1:l_avg#" .. self.palette.FullRed .. ":15m average", + "GPRINT:l_min:MIN:%4.2lf Min,", + "GPRINT:l_avg:AVERAGE:%4.2lf Avg,", + "GPRINT:l_max:MAX:%4.2lf Max,", + "GPRINT:l_avg:LAST:%4.2lf Last\\l" + }, + + load_percent = { + "DEF:avg={file}:percent:AVERAGE", + "DEF:min={file}:percent:MIN", + "DEF:max={file}:percent:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Load", + "GPRINT:min:MIN:%5.1lf%s%% Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,", + "GPRINT:max:MAX:%5.1lf%s%% Max,", + "GPRINT:avg:LAST:%5.1lf%s%% Last\\l" + }, + + mails = { + "DEF:rawgood={file}:good:AVERAGE", + "DEF:rawspam={file}:spam:AVERAGE", + "CDEF:good=rawgood,UN,0,rawgood,IF", + "CDEF:spam=rawspam,UN,0,rawspam,IF", + "CDEF:negspam=spam,-1,*", + "AREA:good#" .. self.palette.HalfGreen, + "LINE1:good#" .. self.palette.FullGreen .. ":Good mails", + "GPRINT:good:AVERAGE:%4.1lf Avg,", + "GPRINT:good:MAX:%4.1lf Max,", + "GPRINT:good:LAST:%4.1lf Last\n", + "AREA:negspam#" .. self.palette.HalfRed, + "LINE1:negspam#" .. self.palette.FullRed .. ":Spam mails", + "GPRINT:spam:AVERAGE:%4.1lf Avg,", + "GPRINT:spam:MAX:%4.1lf Max,", + "GPRINT:spam:LAST:%4.1lf Last\\l", + "HRULE:0#000000" + }, + + memory = { + "-b", "1024", "-v", "Bytes", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Memory", + "GPRINT:min:MIN:%5.1lf%sbyte Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sbyte Avg,", + "GPRINT:max:MAX:%5.1lf%sbyte Max,", + "GPRINT:avg:LAST:%5.1lf%sbyte Last\\l" + }, + + old_memory = { + "DEF:used_avg={file}:used:AVERAGE", + "DEF:free_avg={file}:free:AVERAGE", + "DEF:buffers_avg={file}:buffers:AVERAGE", + "DEF:cached_avg={file}:cached:AVERAGE", + "DEF:used_min={file}:used:MIN", + "DEF:free_min={file}:free:MIN", + "DEF:buffers_min={file}:buffers:MIN", + "DEF:cached_min={file}:cached:MIN", + "DEF:used_max={file}:used:MAX", + "DEF:free_max={file}:free:MAX", + "DEF:buffers_max={file}:buffers:MAX", + "DEF:cached_max={file}:cached:MAX", + "CDEF:cached_avg_nn=cached_avg,UN,0,cached_avg,IF", + "CDEF:buffers_avg_nn=buffers_avg,UN,0,buffers_avg,IF", + "CDEF:free_cached_buffers_used=free_avg,cached_avg_nn,+,buffers_avg_nn,+,used_avg,+", + "CDEF:cached_buffers_used=cached_avg,buffers_avg_nn,+,used_avg,+", + "CDEF:buffers_used=buffers_avg,used_avg,+", + "AREA:free_cached_buffers_used#" .. self.palette.HalfGreen, + "AREA:cached_buffers_used#" .. self.palette.HalfBlue, + "AREA:buffers_used#" .. self.palette.HalfYellow, + "AREA:used_avg#" .. self.palette.HalfRed, + "LINE1:free_cached_buffers_used#" .. self.palette.FullGreen .. ":Free ", + "GPRINT:free_min:MIN:%5.1lf%s Min,", + "GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:free_max:MAX:%5.1lf%s Max,", + "GPRINT:free_avg:LAST:%5.1lf%s Last\n", + "LINE1:cached_buffers_used#" .. self.palette.FullBlue .. ":Page cache ", + "GPRINT:cached_min:MIN:%5.1lf%s Min,", + "GPRINT:cached_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:cached_max:MAX:%5.1lf%s Max,", + "GPRINT:cached_avg:LAST:%5.1lf%s Last\n", + "LINE1:buffers_used#" .. self.palette.FullYellow .. ":Buffer cache", + "GPRINT:buffers_min:MIN:%5.1lf%s Min,", + "GPRINT:buffers_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:buffers_max:MAX:%5.1lf%s Max,", + "GPRINT:buffers_avg:LAST:%5.1lf%s Last\n", + "LINE1:used_avg#" .. self.palette.FullRed .. ":Used ", + "GPRINT:used_min:MIN:%5.1lf%s Min,", + "GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:used_max:MAX:%5.1lf%s Max,", + "GPRINT:used_avg:LAST:%5.1lf%s Last\\l" + }, + + mysql_commands = { + "-v", "Issues/s", + "DEF:val_avg={file}:value:AVERAGE", + "DEF:val_min={file}:value:MIN", + "DEF:val_max={file}:value:MAX", + "AREA:val_max#" .. self.palette.HalfBlue, + "AREA:val_min#" .. self.palette.Canvas, + "LINE1:val_avg#" .. self.palette.FullBlue .. ":Issues/s", + "GPRINT:val_min:MIN:%5.2lf Min,", + "GPRINT:val_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:val_max:MAX:%5.2lf Max,", + "GPRINT:val_avg:LAST:%5.2lf Last\\l" + }, + + mysql_handler = { + "-v", "Issues/s", + "DEF:val_avg={file}:value:AVERAGE", + "DEF:val_min={file}:value:MIN", + "DEF:val_max={file}:value:MAX", + "AREA:val_max#" .. self.palette.HalfBlue, + "AREA:val_min#" .. self.palette.Canvas, + "LINE1:val_avg#" .. self.palette.FullBlue .. ":Issues/s", + "GPRINT:val_min:MIN:%5.2lf Min,", + "GPRINT:val_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:val_max:MAX:%5.2lf Max,", + "GPRINT:val_avg:LAST:%5.2lf Last\\l" + }, + + mysql_octets = { + "-v", "Bits/s", + "DEF:out_min={file}:tx:MIN", + "DEF:out_avg={file}:tx:AVERAGE", + "DEF:out_max={file}:tx:MAX", + "DEF:inc_min={file}:rx:MIN", + "DEF:inc_avg={file}:rx:AVERAGE", + "DEF:inc_max={file}:rx:MAX", + "CDEF:mytime=out_avg,TIME,TIME,IF", + "CDEF:sample_len_raw=mytime,PREV(mytime),-", + "CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF", + "CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*", + "CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+", + "CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*", + "CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+", + "CDEF:out_bit_min=out_min,8,*", + "CDEF:out_bit_avg=out_avg,8,*", + "CDEF:out_bit_max=out_max,8,*", + "CDEF:inc_bit_min=inc_min,8,*", + "CDEF:inc_bit_avg=inc_avg,8,*", + "CDEF:inc_bit_max=inc_max,8,*", + "CDEF:overlap=out_bit_avg,inc_bit_avg,GT,inc_bit_avg,out_bit_avg,IF", + "AREA:out_bit_avg#" .. self.palette.HalfGreen, + "AREA:inc_bit_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:out_bit_avg#" .. self.palette.FullGreen .. ":Written", + "GPRINT:out_bit_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:out_bit_max:MAX:%5.1lf%s Max,", + "GPRINT:out_bit_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)", + "LINE1:inc_bit_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:inc_bit_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:inc_bit_max:MAX:%5.1lf%s Max,", + "GPRINT:inc_bit_avg:LAST:%5.1lf%s Last\\l", + "GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)" + }, + + mysql_qcache = { + "-v", "Queries/s", + "DEF:hits_min={file}:hits:MIN", + "DEF:hits_avg={file}:hits:AVERAGE", + "DEF:hits_max={file}:hits:MAX", + "DEF:inserts_min={file}:inserts:MIN", + "DEF:inserts_avg={file}:inserts:AVERAGE", + "DEF:inserts_max={file}:inserts:MAX", + "DEF:not_cached_min={file}:not_cached:MIN", + "DEF:not_cached_avg={file}:not_cached:AVERAGE", + "DEF:not_cached_max={file}:not_cached:MAX", + "DEF:lowmem_prunes_min={file}:lowmem_prunes:MIN", + "DEF:lowmem_prunes_avg={file}:lowmem_prunes:AVERAGE", + "DEF:lowmem_prunes_max={file}:lowmem_prunes:MAX", + "DEF:queries_min={file}:queries_in_cache:MIN", + "DEF:queries_avg={file}:queries_in_cache:AVERAGE", + "DEF:queries_max={file}:queries_in_cache:MAX", + "CDEF:unknown=queries_avg,UNKN,+", + "CDEF:not_cached_agg=hits_avg,inserts_avg,+,not_cached_avg,+", + "CDEF:inserts_agg=hits_avg,inserts_avg,+", + "CDEF:hits_agg=hits_avg", + "AREA:not_cached_agg#" .. self.palette.HalfYellow, + "AREA:inserts_agg#" .. self.palette.HalfBlue, + "AREA:hits_agg#" .. self.palette.HalfGreen, + "LINE1:not_cached_agg#" .. self.palette.FullYellow .. ":Not Cached ", + "GPRINT:not_cached_min:MIN:%5.2lf Min,", + "GPRINT:not_cached_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:not_cached_max:MAX:%5.2lf Max,", + "GPRINT:not_cached_avg:LAST:%5.2lf Last\\l", + "LINE1:inserts_agg#" .. self.palette.FullBlue .. ":Inserts ", + "GPRINT:inserts_min:MIN:%5.2lf Min,", + "GPRINT:inserts_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:inserts_max:MAX:%5.2lf Max,", + "GPRINT:inserts_avg:LAST:%5.2lf Last\\l", + "LINE1:hits_agg#" .. self.palette.FullGreen .. ":Hits ", + "GPRINT:hits_min:MIN:%5.2lf Min,", + "GPRINT:hits_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:hits_max:MAX:%5.2lf Max,", + "GPRINT:hits_avg:LAST:%5.2lf Last\\l", + "LINE1:lowmem_prunes_avg#" .. self.palette.FullRed .. ":Lowmem Prunes ", + "GPRINT:lowmem_prunes_min:MIN:%5.2lf Min,", + "GPRINT:lowmem_prunes_avg:AVERAGE:%5.2lf Avg,", + "GPRINT:lowmem_prunes_max:MAX:%5.2lf Max,", + "GPRINT:lowmem_prunes_avg:LAST:%5.2lf Last\\l", + "LINE1:unknown#" .. self.palette.Canvas .. ":Queries in cache", + "GPRINT:queries_min:MIN:%5.0lf Min,", + "GPRINT:queries_avg:AVERAGE:%5.0lf Avg,", + "GPRINT:queries_max:MAX:%5.0lf Max,", + "GPRINT:queries_avg:LAST:%5.0lf Last\\l" + }, + + mysql_threads = { + "-v", "Threads", + "DEF:running_min={file}:running:MIN", + "DEF:running_avg={file}:running:AVERAGE", + "DEF:running_max={file}:running:MAX", + "DEF:connected_min={file}:connected:MIN", + "DEF:connected_avg={file}:connected:AVERAGE", + "DEF:connected_max={file}:connected:MAX", + "DEF:cached_min={file}:cached:MIN", + "DEF:cached_avg={file}:cached:AVERAGE", + "DEF:cached_max={file}:cached:MAX", + "DEF:created_min={file}:created:MIN", + "DEF:created_avg={file}:created:AVERAGE", + "DEF:created_max={file}:created:MAX", + "CDEF:unknown=created_avg,UNKN,+", + "CDEF:cached_agg=connected_avg,cached_avg,+", + "AREA:cached_agg#" .. self.palette.HalfGreen, + "AREA:connected_avg#" .. self.palette.HalfBlue, + "AREA:running_avg#" .. self.palette.HalfRed, + "LINE1:cached_agg#" .. self.palette.FullGreen .. ":Cached ", + "GPRINT:cached_min:MIN:%5.1lf Min,", + "GPRINT:cached_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:cached_max:MAX:%5.1lf Max,", + "GPRINT:cached_avg:LAST:%5.1lf Last\\l", + "LINE1:connected_avg#" .. self.palette.FullBlue .. ":Connected", + "GPRINT:connected_min:MIN:%5.1lf Min,", + "GPRINT:connected_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:connected_max:MAX:%5.1lf Max,", + "GPRINT:connected_avg:LAST:%5.1lf Last\\l", + "LINE1:running_avg#" .. self.palette.FullRed .. ":Running ", + "GPRINT:running_min:MIN:%5.1lf Min,", + "GPRINT:running_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:running_max:MAX:%5.1lf Max,", + "GPRINT:running_avg:LAST:%5.1lf Last\\l", + "LINE1:unknown#" .. self.palette.Canvas .. ":Created ", + "GPRINT:created_min:MIN:%5.0lf Min,", + "GPRINT:created_avg:AVERAGE:%5.0lf Avg,", + "GPRINT:created_max:MAX:%5.0lf Max,", + "GPRINT:created_avg:LAST:%5.0lf Last\\l" + }, + + nfs_procedure = { + "-v", "Issues/s", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Issues/s", + "GPRINT:min:MIN:%6.2lf Min,", + "GPRINT:avg:AVERAGE:%6.2lf Avg,", + "GPRINT:max:MAX:%6.2lf Max,", + "GPRINT:avg:LAST:%6.2lf Last\\l" + }, + + nfs3_procedures = { + "DEF:null_avg={file}:null:AVERAGE", + "DEF:getattr_avg={file}:getattr:AVERAGE", + "DEF:setattr_avg={file}:setattr:AVERAGE", + "DEF:lookup_avg={file}:lookup:AVERAGE", + "DEF:access_avg={file}:access:AVERAGE", + "DEF:readlink_avg={file}:readlink:AVERAGE", + "DEF:read_avg={file}:read:AVERAGE", + "DEF:write_avg={file}:write:AVERAGE", + "DEF:create_avg={file}:create:AVERAGE", + "DEF:mkdir_avg={file}:mkdir:AVERAGE", + "DEF:symlink_avg={file}:symlink:AVERAGE", + "DEF:mknod_avg={file}:mknod:AVERAGE", + "DEF:remove_avg={file}:remove:AVERAGE", + "DEF:rmdir_avg={file}:rmdir:AVERAGE", + "DEF:rename_avg={file}:rename:AVERAGE", + "DEF:link_avg={file}:link:AVERAGE", + "DEF:readdir_avg={file}:readdir:AVERAGE", + "DEF:readdirplus_avg={file}:readdirplus:AVERAGE", + "DEF:fsstat_avg={file}:fsstat:AVERAGE", + "DEF:fsinfo_avg={file}:fsinfo:AVERAGE", + "DEF:pathconf_avg={file}:pathconf:AVERAGE", + "DEF:commit_avg={file}:commit:AVERAGE", + "DEF:null_max={file}:null:MAX", + "DEF:getattr_max={file}:getattr:MAX", + "DEF:setattr_max={file}:setattr:MAX", + "DEF:lookup_max={file}:lookup:MAX", + "DEF:access_max={file}:access:MAX", + "DEF:readlink_max={file}:readlink:MAX", + "DEF:read_max={file}:read:MAX", + "DEF:write_max={file}:write:MAX", + "DEF:create_max={file}:create:MAX", + "DEF:mkdir_max={file}:mkdir:MAX", + "DEF:symlink_max={file}:symlink:MAX", + "DEF:mknod_max={file}:mknod:MAX", + "DEF:remove_max={file}:remove:MAX", + "DEF:rmdir_max={file}:rmdir:MAX", + "DEF:rename_max={file}:rename:MAX", + "DEF:link_max={file}:link:MAX", + "DEF:readdir_max={file}:readdir:MAX", + "DEF:readdirplus_max={file}:readdirplus:MAX", + "DEF:fsstat_max={file}:fsstat:MAX", + "DEF:fsinfo_max={file}:fsinfo:MAX", + "DEF:pathconf_max={file}:pathconf:MAX", + "DEF:commit_max={file}:commit:MAX", + "CDEF:other_avg=null_avg,readlink_avg,create_avg,mkdir_avg,symlink_avg,mknod_avg,remove_avg,rmdir_avg,rename_avg,link_avg,readdir_avg,readdirplus_avg,fsstat_avg,fsinfo_avg,pathconf_avg,+,+,+,+,+,+,+,+,+,+,+,+,+,+", + "CDEF:other_max=null_max,readlink_max,create_max,mkdir_max,symlink_max,mknod_max,remove_max,rmdir_max,rename_max,link_max,readdir_max,readdirplus_max,fsstat_max,fsinfo_max,pathconf_max,+,+,+,+,+,+,+,+,+,+,+,+,+,+", + "CDEF:stack_read=read_avg", + "CDEF:stack_getattr=stack_read,getattr_avg,+", + "CDEF:stack_access=stack_getattr,access_avg,+", + "CDEF:stack_lookup=stack_access,lookup_avg,+", + "CDEF:stack_write=stack_lookup,write_avg,+", + "CDEF:stack_commit=stack_write,commit_avg,+", + "CDEF:stack_setattr=stack_commit,setattr_avg,+", + "CDEF:stack_other=stack_setattr,other_avg,+", + "AREA:stack_other#" .. self.palette.HalfRed, + "AREA:stack_setattr#" .. self.palette.HalfGreen, + "AREA:stack_commit#" .. self.palette.HalfYellow, + "AREA:stack_write#" .. self.palette.HalfGreen, + "AREA:stack_lookup#" .. self.palette.HalfBlue, + "AREA:stack_access#" .. self.palette.HalfMagenta, + "AREA:stack_getattr#" .. self.palette.HalfCyan, + "AREA:stack_read#" .. self.palette.HalfBlue, + "LINE1:stack_other#" .. self.palette.FullRed .. ":Other ", + "GPRINT:other_max:MAX:%5.1lf Max,", + "GPRINT:other_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:other_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_setattr#" .. self.palette.FullGreen .. ":setattr", + "GPRINT:setattr_max:MAX:%5.1lf Max,", + "GPRINT:setattr_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:setattr_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_commit#" .. self.palette.FullYellow .. ":commit ", + "GPRINT:commit_max:MAX:%5.1lf Max,", + "GPRINT:commit_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:commit_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_write#" .. self.palette.FullGreen .. ":write ", + "GPRINT:write_max:MAX:%5.1lf Max,", + "GPRINT:write_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:write_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_lookup#" .. self.palette.FullBlue .. ":lookup ", + "GPRINT:lookup_max:MAX:%5.1lf Max,", + "GPRINT:lookup_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:lookup_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_access#" .. self.palette.FullMagenta .. ":access ", + "GPRINT:access_max:MAX:%5.1lf Max,", + "GPRINT:access_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:access_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_getattr#" .. self.palette.FullCyan .. ":getattr", + "GPRINT:getattr_max:MAX:%5.1lf Max,", + "GPRINT:getattr_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:getattr_avg:LAST:%5.1lf Last\\l", + "LINE1:stack_read#" .. self.palette.FullBlue .. ":read ", + "GPRINT:read_max:MAX:%5.1lf Max,", + "GPRINT:read_avg:AVERAGE:%5.1lf Avg,", + "GPRINT:read_avg:LAST:%5.1lf Last\\l" + }, + + partition = { + "DEF:rbyte_avg={file}:rbytes:AVERAGE", + "DEF:rbyte_min={file}:rbytes:MIN", + "DEF:rbyte_max={file}:rbytes:MAX", + "DEF:wbyte_avg={file}:wbytes:AVERAGE", + "DEF:wbyte_min={file}:wbytes:MIN", + "DEF:wbyte_max={file}:wbytes:MAX", + "CDEF:overlap=wbyte_avg,rbyte_avg,GT,rbyte_avg,wbyte_avg,IF", + "AREA:wbyte_avg#" .. self.palette.HalfGreen, + "AREA:rbyte_avg#" .. self.palette.HalfBlue, + "AREA:overlap#" .. self.palette.HalfBlueGreen, + "LINE1:wbyte_avg#" .. self.palette.FullGreen .. ":Write", + "GPRINT:wbyte_min:MIN:%5.1lf%s Min,", + "GPRINT:wbyte_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:wbyte_max:MAX:%5.1lf%s Max,", + "GPRINT:wbyte_avg:LAST:%5.1lf%s Last\\l", + "LINE1:rbyte_avg#" .. self.palette.FullBlue .. ":Read ", + "GPRINT:rbyte_min:MIN:%5.1lf%s Min,", + "GPRINT:rbyte_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:rbyte_max:MAX:%5.1lf%s Max,", + "GPRINT:rbyte_avg:LAST:%5.1lf%s Last\\l" + }, + + percent = { + "-v", "Percent", + "DEF:avg={file}:percent:AVERAGE", + "DEF:min={file}:percent:MIN", + "DEF:max={file}:percent:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Percent", + "GPRINT:min:MIN:%5.1lf%% Min,", + "GPRINT:avg:AVERAGE:%5.1lf%% Avg,", + "GPRINT:max:MAX:%5.1lf%% Max,", + "GPRINT:avg:LAST:%5.1lf%% Last\\l" + }, + + power = { + "-v", "Watt", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Watt", + "GPRINT:min:MIN:%5.1lf%sW Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sW Avg,", + "GPRINT:max:MAX:%5.1lf%sW Max,", + "GPRINT:avg:LAST:%5.1lf%sW Last\\l" + }, + + swap = { + "-v", "Bytes", "-b", "1024", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Bytes", + "GPRINT:min:MIN:%6.2lf%sByte Min,", + "GPRINT:avg:AVERAGE:%6.2lf%sByte Avg,", + "GPRINT:max:MAX:%6.2lf%sByte Max,", + "GPRINT:avg:LAST:%6.2lf%sByte Last\\l" + }, + + old_swap = { + "DEF:used_avg={file}:used:AVERAGE", + "DEF:used_min={file}:used:MIN", + "DEF:used_max={file}:used:MAX", + "DEF:free_avg={file}:free:AVERAGE", + "DEF:free_min={file}:free:MIN", + "DEF:free_max={file}:free:MAX", + "DEF:cach_avg={file}:cached:AVERAGE", + "DEF:cach_min={file}:cached:MIN", + "DEF:cach_max={file}:cached:MAX", + "DEF:resv_avg={file}:resv:AVERAGE", + "DEF:resv_min={file}:resv:MIN", + "DEF:resv_max={file}:resv:MAX", + "CDEF:cach_avg_notnull=cach_avg,UN,0,cach_avg,IF", + "CDEF:resv_avg_notnull=resv_avg,UN,0,resv_avg,IF", + "CDEF:used_acc=used_avg", + "CDEF:resv_acc=used_acc,resv_avg_notnull,+", + "CDEF:cach_acc=resv_acc,cach_avg_notnull,+", + "CDEF:free_acc=cach_acc,free_avg,+", + "AREA:free_acc#" .. self.palette.HalfGreen, + "AREA:cach_acc#" .. self.palette.HalfBlue, + "AREA:resv_acc#" .. self.palette.HalfYellow, + "AREA:used_acc#" .. self.palette.HalfRed, + "LINE1:free_acc#" .. self.palette.FullGreen .. ":Free ", + "GPRINT:free_min:MIN:%5.1lf%s Min,", + "GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:free_max:MAX:%5.1lf%s Max,", + "GPRINT:free_avg:LAST:%5.1lf%s Last\n", + "LINE1:cach_acc#" .. self.palette.FullBlue .. ":Cached ", + "GPRINT:cach_min:MIN:%5.1lf%s Min,", + "GPRINT:cach_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:cach_max:MAX:%5.1lf%s Max,", + "GPRINT:cach_avg:LAST:%5.1lf%s Last\\l", + "LINE1:resv_acc#" .. self.palette.FullYellow .. ":Reserved", + "GPRINT:resv_min:MIN:%5.1lf%s Min,", + "GPRINT:resv_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:resv_max:MAX:%5.1lf%s Max,", + "GPRINT:resv_avg:LAST:%5.1lf%s Last\n", + "LINE1:used_acc#" .. self.palette.FullRed .. ":Used ", + "GPRINT:used_min:MIN:%5.1lf%s Min,", + "GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:used_max:MAX:%5.1lf%s Max,", + "GPRINT:used_avg:LAST:%5.1lf%s Last\\l" + }, + + tcp_connections = { + "-v", "Connections", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Connections", + "GPRINT:min:MIN:%4.1lf Min,", + "GPRINT:avg:AVERAGE:%4.1lf Avg,", + "GPRINT:max:MAX:%4.1lf Max,", + "GPRINT:avg:LAST:%4.1lf Last\\l" + }, + + temperature = { + "-v", "Celsius", + "DEF:temp_avg={file}:value:AVERAGE", + "DEF:temp_min={file}:value:MIN", + "DEF:temp_max={file}:value:MAX", + "CDEF:average=temp_avg,0.2,*,PREV,UN,temp_avg,PREV,IF,0.8,*,+", + "AREA:temp_max#" .. self.palette.HalfRed, + "AREA:temp_min#" .. self.palette.Canvas, + "LINE1:temp_avg#" .. self.palette.FullRed .. ":Temperature", + "GPRINT:temp_min:MIN:%4.1lf Min,", + "GPRINT:temp_avg:AVERAGE:%4.1lf Avg,", + "GPRINT:temp_max:MAX:%4.1lf Max,", + "GPRINT:temp_avg:LAST:%4.1lf Last\\l" + }, + + timeleft = { + "-v", "Minutes", + "DEF:avg={file}:timeleft:AVERAGE", + "DEF:min={file}:timeleft:MIN", + "DEF:max={file}:timeleft:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Time left [min]", + "GPRINT:min:MIN:%5.1lf%s Min,", + "GPRINT:avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:max:MAX:%5.1lf%s Max,", + "GPRINT:avg:LAST:%5.1lf%s Last\\l" + }, + + time_offset = { + "DEF:s_avg={file}:seconds:AVERAGE", + "DEF:s_min={file}:seconds:MIN", + "DEF:s_max={file}:seconds:MAX", + "AREA:s_max#" .. self.palette.HalfBlue, + "AREA:s_min#" .. self.palette.Canvas, + "LINE1:s_avg#" .. self.palette.FullBlue .. ":{inst}", + "GPRINT:s_min:MIN:%7.3lf%s Min,", + "GPRINT:s_avg:AVERAGE:%7.3lf%s Avg,", + "GPRINT:s_max:MAX:%7.3lf%s Max,", + "GPRINT:s_avg:LAST:%7.3lf%s Last\\l" + }, + + cpufreq = { + "DEF:cpufreq_avg={file}:value:AVERAGE", + "DEF:cpufreq_min={file}:value:MIN", + "DEF:cpufreq_max={file}:value:MAX", + "AREA:cpufreq_max#" .. self.palette.HalfBlue, + "AREA:cpufreq_min#" .. self.palette.Canvas, + "LINE1:cpufreq_avg#" .. self.palette.FullBlue .. ":Frequency", + "GPRINT:cpufreq_min:MIN:%5.1lf%s Min,", + "GPRINT:cpufreq_avg:AVERAGE:%5.1lf%s Avg,", + "GPRINT:cpufreq_max:MAX:%5.1lf%s Max,", + "GPRINT:cpufreq_avg:LAST:%5.1lf%s Last\\l" + }, + + multimeter = { + "DEF:multimeter_avg={file}:value:AVERAGE", + "DEF:multimeter_min={file}:value:MIN", + "DEF:multimeter_max={file}:value:MAX", + "AREA:multimeter_max#" .. self.palette.HalfBlue, + "AREA:multimeter_min#" .. self.palette.Canvas, + "LINE1:multimeter_avg#" .. self.palette.FullBlue .. ":Multimeter", + "GPRINT:multimeter_min:MIN:%4.1lf Min,", + "GPRINT:multimeter_avg:AVERAGE:%4.1lf Average,", + "GPRINT:multimeter_max:MAX:%4.1lf Max,", + "GPRINT:multimeter_avg:LAST:%4.1lf Last\\l" + }, + + users = { + "-v", "Users", + "DEF:users_avg={file}:users:AVERAGE", + "DEF:users_min={file}:users:MIN", + "DEF:users_max={file}:users:MAX", + "AREA:users_max#" .. self.palette.HalfBlue, + "AREA:users_min#" .. self.palette.Canvas, + "LINE1:users_avg#" .. self.palette.FullBlue .. ":Users", + "GPRINT:users_min:MIN:%4.1lf Min,", + "GPRINT:users_avg:AVERAGE:%4.1lf Average,", + "GPRINT:users_max:MAX:%4.1lf Max,", + "GPRINT:users_avg:LAST:%4.1lf Last\\l" + }, + + voltage = { + "-v", "Voltage", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Voltage", + "GPRINT:min:MIN:%5.1lf%sV Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sV Avg,", + "GPRINT:max:MAX:%5.1lf%sV Max,", + "GPRINT:avg:LAST:%5.1lf%sV Last\\l" + }, + + vs_threads = { + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Threads", + "GPRINT:min:MIN:%5.1lf Min,", + "GPRINT:avg:AVERAGE:%5.1lf Avg.,", + "GPRINT:max:MAX:%5.1lf Max,", + "GPRINT:avg:LAST:%5.1lf Last\\l", + }, + + vs_memory = { + "-b", "1024", "-v", "Bytes", + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":", + "GPRINT:min:MIN:%5.1lf%sbytes Min,", + "GPRINT:avg:AVERAGE:%5.1lf%sbytes Avg.,", + "GPRINT:max:MAX:%5.1lf%sbytes Max,", + "GPRINT:avg:LAST:%5.1lf%sbytes Last\\l", + }, + + vs_processes = { + "DEF:avg={file}:value:AVERAGE", + "DEF:min={file}:value:MIN", + "DEF:max={file}:value:MAX", + "AREA:max#" .. self.palette.HalfBlue, + "AREA:min#" .. self.palette.Canvas, + "LINE1:avg#" .. self.palette.FullBlue .. ":Processes", + "GPRINT:min:MIN:%5.1lf Min,", + "GPRINT:avg:AVERAGE:%5.1lf Avg.,", + "GPRINT:max:MAX:%5.1lf Max,", + "GPRINT:avg:LAST:%5.1lf Last\\l", + }, + } +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/cpu/cpu.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/cpu/cpu.lua new file mode 100644 index 0000000..aca3fb7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/cpu/cpu.lua @@ -0,0 +1,38 @@ +--[[ + +Luci statistics - cpu plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: cpu.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.cpu.cpu",package.seeall) + +function rrdargs( graph, host, plugin, plugin_instance, dtype ) + + return { + data = { + instances = { + cpu = { "idle", "user", "system", "nice" } + }, + + options = { + cpu_idle = { color = "ffffff" }, + cpu_nice = { color = "00e000" }, + cpu_user = { color = "0000ff" }, + cpu_wait = { color = "ffb000" }, + cpu_system = { color = "ff0000" }, + cpu_softirq = { color = "ff00ff" }, + cpu_interrupt = { color = "a000a0" }, + cpu_steal = { color = "000000" } + } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/df/df.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/df/df.lua new file mode 100644 index 0000000..4fd630d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/df/df.lua @@ -0,0 +1,41 @@ +--[[ + +Luci statistics - df plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: df.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.df.df", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + per_instance = true, + number_format = "%5.1lf%s", + + data = { + sources = { + df = { "free", "used" } + }, + + options = { + df__free = { + color = "00ff00" + }, + + df__used = { + color = "ff0000", + flip = true + } + } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/interface.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/interface.lua new file mode 100644 index 0000000..fff8e81 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/interface.lua @@ -0,0 +1,107 @@ +--[[ + +Luci statistics - interface plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: interface.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.interface", package.seeall) + +function rrdargs( graph, host, plugin, plugin_instance ) + + -- + -- traffic diagram + -- + local traffic = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + -- defined sources for data types, if ommitted assume a single DS named "value" (optional) + sources = { + if_octets = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + if_octets__tx = { + total = true, -- report total amount of bytes + color = "00ff00" -- tx is green + }, + + if_octets__rx = { + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- rx is blue + } + } + } + } + + + -- + -- packet diagram + -- + local packets = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + -- data type order + types = { "if_packets", "if_errors" }, + + -- defined sources for data types + sources = { + if_packets = { "tx", "rx" }, + if_errors = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + -- processed packets (tx DS) + if_packets__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of bytes + color = "00ff00" -- processed tx is green + }, + + -- processed packets (rx DS) + if_packets__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- processed rx is blue + }, + + -- packet errors (tx DS) + if_errors__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of packets + color = "ff5500" -- tx errors are orange + }, + + -- packet errors (rx DS) + if_errors__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of packets + color = "ff0000" -- rx errors are red + } + } + } + } + + return { traffic, packets } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_bytes.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_bytes.lua new file mode 100644 index 0000000..c3c2bb9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_bytes.lua @@ -0,0 +1,27 @@ +--[[ + +Luci statistics - iptables plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ipt_bytes.lua 2276 2008-06-03 23:18:37Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.iptables.ipt_bytes", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + options = { + ipt_bytes = { total = true } + } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_packets.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_packets.lua new file mode 100644 index 0000000..698464a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/iptables/ipt_packets.lua @@ -0,0 +1,27 @@ +--[[ + +Luci statistics - iptables plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ipt_packets.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.iptables.ipt_packets", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + options = { + ipt_packets = { total = true } + } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/irq/irq.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/irq/irq.lua new file mode 100644 index 0000000..65ed1e6 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/irq/irq.lua @@ -0,0 +1,25 @@ +--[[ + +Luci statistics - irq plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: irq.lua 2276 2008-06-03 23:18:37Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.irq.irq", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + types = { "irq" } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/load/load.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/load/load.lua new file mode 100644 index 0000000..0c1eb2b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/load/load.lua @@ -0,0 +1,33 @@ +--[[ + +Luci statistics - load plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: load.lua 2329 2008-06-08 21:51:55Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.load.load", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + sources = { + load = { "shortterm", "midterm", "longterm" } + }, + + options = { + load__shortterm = { color = "ff0000" }, + load__midterm = { color = "ff6600" }, + load__longterm = { color = "ffaa00" } + } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/netlink.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/netlink.lua new file mode 100644 index 0000000..a46f7cc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/netlink.lua @@ -0,0 +1,193 @@ +--[[ + +Luci statistics - netlink plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: netlink.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.netlink", package.seeall) + +function rrdargs( graph, plugin, plugin_instance ) + + -- + -- traffic diagram + -- + local traffic = { + + -- diagram data description + data = { + -- defined sources for data types, if ommitted assume a single DS named "value" (optional) + sources = { + if_octets = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + if_octets__tx = { + total = true, -- report total amount of bytes + color = "00ff00" -- tx is green + }, + + if_octets__rx = { + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- rx is blue + } + } + } + } + + + -- + -- packet diagram + -- + local packets = { + + -- diagram data description + data = { + -- data type order + types = { "if_packets", "if_dropped", "if_errors" }, + + -- defined sources for data types + sources = { + if_packets = { "tx", "rx" }, + if_dropped = { "tx", "rx" }, + if_errors = { "tx", "rx" } + }, + + -- special options for single data lines + options = { + -- processed packets (tx DS) + if_packets__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of bytes + color = "00ff00" -- processed tx is green + }, + + -- processed packets (rx DS) + if_packets__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "0000ff" -- processed rx is blue + }, + + -- dropped packets (tx DS) + if_dropped__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of bytes + color = "660055" -- dropped tx is ... dunno ;) + }, + + -- dropped packets (rx DS) + if_dropped__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of bytes + color = "440066" -- dropped rx is violett + }, + + -- packet errors (tx DS) + if_errors__tx = { + overlay = true, -- don't summarize + total = true, -- report total amount of packets + color = "ff5500" -- tx errors are orange + }, + + -- packet errors (rx DS) + if_errors__rx = { + overlay = true, -- don't summarize + flip = true, -- flip rx line + total = true, -- report total amount of packets + color = "ff0000" -- rx errors are red + } + } + } + } + + + -- + -- multicast diagram + -- + local multicast = { + + -- diagram data description + data = { + -- data type order + types = { "if_multicast" }, + + -- special options for single data lines + options = { + -- multicast packets + if_multicast = { + total = true, -- report total amount of packets + color = "0000ff" -- multicast is blue + } + } + } + } + + + -- + -- collision diagram + -- + local collisions = { + + -- diagram data description + data = { + -- data type order + types = { "if_collisions" }, + + -- special options for single data lines + options = { + -- collision rate + if_collisions = { + total = true, -- report total amount of packets + color = "ff0000" -- collsions are red + } + } + } + } + + + -- + -- error diagram + -- + local errors = { + + -- diagram data description + data = { + -- data type order + types = { "if_tx_errors", "if_rx_errors" }, + + -- data type instances + instances = { + if_tx_errors = { "aborted", "carrier", "fifo", "heartbeat", "window" }, + if_rx_errors = { "length", "missed", "over", "crc", "fifo", "frame" } + }, + + -- special options for single data lines + options = { -- XXX: fixme (define colors...) + if_tx_errors = { + total = true + }, + + if_rx_errors = { + flip = true, + total = true + } + } + } + } + + + return { traffic, packets, multicast, collisions, errors } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/ping/ping.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/ping/ping.lua new file mode 100644 index 0000000..a094737 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/ping/ping.lua @@ -0,0 +1,27 @@ +--[[ + +Luci statistics - ping plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: ping.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.ping.ping", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + sources = { + ping = { "ping" } + } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/processes.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/processes.lua new file mode 100644 index 0000000..fc01ca5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/processes.lua @@ -0,0 +1,101 @@ +--[[ + +Luci statistics - processes plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: processes.lua 2276 2008-06-03 23:18:37Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.processes", package.seeall) + +function rrdargs( graph, plugin, plugin_instance ) + + if plugin_instance == "" then + return { + data = { + instances = { + ps_state = { + "sleeping", "running", "paging", "blocked", "stopped", "zombies" + } + }, + + options = { + ps_state_sleeping = { color = "0000ff" }, + ps_state_running = { color = "008000" }, + ps_state_paging = { color = "ffff00" }, + ps_state_blocked = { color = "ff5000" }, + ps_state_stopped = { color = "555555" }, + ps_state_zombies = { color = "ff0000" } + } + } + } + else + return { + + { + data = { + sources = { + ps_cputime = { "syst", "user" } + }, + + options = { + ps_cputime__user = { + color = "0000ff", + overlay = true + }, + + ps_cputime__syst = { + color = "ff0000", + overlay = true + } + } + } + }, + + { + data = { + sources = { + ps_count = { "threads", "processes" } + }, + + options = { + ps_count__threads = { color = "00ff00" }, + ps_count__processes = { color = "0000bb" } + } + } + }, + + { + data = { + sources = { + ps_pagefaults = { "minflt", "majflt" } + }, + + options = { + ps_pagefaults__minflt = { color = "ff0000" }, + ps_pagefaults__majflt = { color = "ff5500" } + } + } + }, + + { + number_format = "%5.1lf%s", + + data = { + types = { "ps_rss" }, + + options = { + ps_rss = { color = "0000ff" } + } + } + } + } + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua new file mode 100644 index 0000000..9d94dd7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/tcpconns/tcp_connections.lua @@ -0,0 +1,31 @@ +--[[ + +Luci statistics - tcpconns plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: tcp_connections.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.tcpconns.tcp_connections", package.seeall) + +function rrdargs( graph, plugin, plugin_instance, dtype ) + + return { + data = { + instances = { + tcp_connections = { + "SYN_SENT", "SYN_RECV", "LISTEN", "ESTABLISHED", + "LAST_ACK", "TIME_WAIT", "CLOSING", "CLOSE_WAIT", + "CLOSED", "FIN_WAIT1", "FIN_WAIT2" + } + } + } + } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/wireless.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/wireless.lua new file mode 100644 index 0000000..867eabd --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/statistics/rrdtool/definitions/wireless.lua @@ -0,0 +1,71 @@ +--[[ + +Luci statistics - wireless plugin diagram definition +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: wireless.lua 2274 2008-06-03 23:15:16Z jow $ + +]]-- + +module("luci.statistics.rrdtool.definitions.wireless", package.seeall) + +function rrdargs( graph, host, plugin, plugin_instance ) + + -- + -- signal/noise diagram + -- + local snr = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + types = { "signal_noise", "signal_power" }, + + -- special options for single data lines + options = { + signal_power = { + overlay = true, -- don't summarize + color = "0000ff" -- power is blue + }, + + signal_noise = { + overlay = true, -- don't summarize + color = "ff0000" -- noise is red + } + } + } + } + + + -- + -- signal quality diagram + -- + local quality = { + + -- draw this diagram for each data instance + per_instance = true, + + -- diagram data description + data = { + types = { "signal_quality" }, + + -- special options for single data lines + options = { + signal_quality = { + noarea = true, -- don't draw area + color = "0000ff" -- quality is blue + } + } + } + } + + return { snr, quality } +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/sys.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/sys.lua new file mode 100644 index 0000000..38a25f9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/sys.lua @@ -0,0 +1,782 @@ +--[[ +LuCI - System library + +Description: +Utilities for interaction with the Linux system + +FileId: +$Id: sys.lua 3867 2008-12-07 19:49:45Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + + +local io = require "io" +local os = require "os" +local posix = require "posix" +local table = require "table" + +local luci = {} +luci.util = require "luci.util" +luci.fs = require "luci.fs" +luci.ip = require "luci.ip" + +local tonumber, ipairs, pairs, pcall = tonumber, ipairs, pairs, pcall + + +--- LuCI Linux and POSIX system utilities. +module "luci.sys" + +--- Execute a given shell command and return the error code +-- @class function +-- @name call +-- @param ... Command to call +-- @return Error code of the command +function call(...) + return os.execute(...) / 256 +end + +--- Execute a given shell command and capture its standard output +-- @class function +-- @name exec +-- @param command Command to call +-- @return String containg the return the output of the command +exec = luci.util.exec + +--- Invoke the luci-flash executable to write an image to the flash memory. +-- @param image Local path or URL to image file +-- @param kpattern Pattern of files to keep over flash process +-- @return Return value of os.execute() +function flash(image, kpattern) + local cmd = "luci-flash " + if kpattern then + cmd = cmd .. "-k '" .. kpattern:gsub("'", "") .. "' " + end + cmd = cmd .. "'" .. image:gsub("'", "") .. "' >/dev/null 2>&1" + + return os.execute(cmd) +end + +--- Retrieve information about currently mounted file systems. +-- @return Table containing mount information +function mounts() + local data = {} + local k = {"fs", "blocks", "used", "available", "percent", "mountpoint"} + local ps = luci.util.execi("df") + + if not ps then + return + else + ps() + end + + for line in ps do + local row = {} + + local j = 1 + for value in line:gmatch("[^%s]+") do + row[k[j]] = value + j = j + 1 + end + + if row[k[1]] then + + -- this is a rather ugly workaround to cope with wrapped lines in + -- the df output: + -- + -- /dev/scsi/host0/bus0/target0/lun0/part3 + -- 114382024 93566472 15005244 86% /mnt/usb + -- + + if not row[k[2]] then + j = 2 + line = ps() + for value in line:gmatch("[^%s]+") do + row[k[j]] = value + j = j + 1 + end + end + + table.insert(data, row) + end + end + + return data +end + +--- Retrieve environment variables. If no variable is given then a table +-- containing the whole environment is returned otherwise this function returns +-- the corresponding string value for the given name or nil if no such variable +-- exists. +-- @class function +-- @name getenv +-- @param var Name of the environment variable to retrieve (optional) +-- @return String containg the value of the specified variable +-- @return Table containing all variables if no variable name is given +getenv = posix.getenv + +--- Determine the current hostname. +-- @return String containing the system hostname +function hostname() + return posix.uname("%n") +end + +--- Returns the contents of a documented referred by an URL. +-- @param url The URL to retrieve +-- @param stream Return a stream instead of a buffer +-- @param target Directly write to target file name +-- @return String containing the contents of given the URL +function httpget(url, stream, target) + if not target then + local source = stream and io.popen or luci.util.exec + return source("wget -qO- '"..url:gsub("'", "").."'") + else + return os.execute("wget -qO '%s' '%s'" % + {target:gsub("'", ""), url:gsub("'", "")}) + end +end + +--- Returns the system load average values. +-- @return String containing the average load value 1 minute ago +-- @return String containing the average load value 5 minutes ago +-- @return String containing the average load value 15 minutes ago +-- @return String containing the active and total number of processes +-- @return String containing the last used pid +function loadavg() + local loadavg = io.lines("/proc/loadavg")() + return loadavg:match("^(.-) (.-) (.-) (.-) (.-)$") +end + +--- Initiate a system reboot. +-- @return Return value of os.execute() +function reboot() + return os.execute("reboot >/dev/null 2>&1") +end + +--- Returns the system type, cpu name and installed physical memory. +-- @return String containing the system or platform identifier +-- @return String containing hardware model information +-- @return String containing the total memory amount in kB +-- @return String containing the memory used for caching in kB +-- @return String containing the memory used for buffering in kB +-- @return String containing the free memory amount in kB +function sysinfo() + local cpuinfo = luci.fs.readfile("/proc/cpuinfo") + local meminfo = luci.fs.readfile("/proc/meminfo") + + local system = cpuinfo:match("system typ.-:%s*([^\n]+)") + local model = "" + local memtotal = tonumber(meminfo:match("MemTotal:%s*(%d+)")) + local memcached = tonumber(meminfo:match("\nCached:%s*(%d+)")) + local memfree = tonumber(meminfo:match("MemFree:%s*(%d+)")) + local membuffers = tonumber(meminfo:match("Buffers:%s*(%d+)")) + + if not system then + system = posix.uname("%m") + model = cpuinfo:match("model name.-:%s*([^\n]+)") + if not model then + model = cpuinfo:match("Processor.-:%s*([^\n]+)") + end + else + model = cpuinfo:match("cpu model.-:%s*([^\n]+)") + end + + return system, model, memtotal, memcached, membuffers, memfree +end + +--- Retrieves the output of the "logread" command. +-- @return String containing the current log buffer +function syslog() + return luci.util.exec("logread") +end + +--- Retrieves the output of the "dmesg" command. +-- @return String containing the current log buffer +function dmesg() + return luci.util.exec("dmesg") +end + +--- Generates a random id with specified length. +-- @param bytes Number of bytes for the unique id +-- @return String containing hex encoded id +function uniqueid(bytes) + local fp = io.open("/dev/urandom") + local chunk = { fp:read(bytes):byte(1, bytes) } + fp:close() + + local hex = "" + + local pattern = "%02X" + for i, byte in ipairs(chunk) do + hex = hex .. pattern:format(byte) + end + + return hex +end + +--- Returns the current system uptime stats. +-- @return String containing total uptime in seconds +-- @return String containing idle time in seconds +function uptime() + local loadavg = io.lines("/proc/uptime")() + return loadavg:match("^(.-) (.-)$") +end + +--- LuCI system utilities / POSIX user group related functions. +-- @class module +-- @name luci.sys.group +group = {} + +--- Returns information about a POSIX user group. +-- @class function +-- @name getgroup +-- @param group Group ID or name of a system user group +-- @return Table with information about the requested group +group.getgroup = posix.getgroup + + +--- LuCI system utilities / network related functions. +-- @class module +-- @name luci.sys.net +net = {} + +--- Returns the current arp-table entries as two-dimensional table. +-- @return Table of table containing the current arp entries. +-- The following fields are defined for arp entry objects: +-- { "IP address", "HW address", "HW type", "Flags", "Mask", "Device" } +function net.arptable() + return _parse_delimited_table(io.lines("/proc/net/arp"), "%s%s+") +end + +--- Returns conntrack information +-- @return Table with the currently tracked IP connections +function net.conntrack() + local connt = {} + if luci.fs.access("/proc/net/nf_conntrack", "r") then + for line in io.lines("/proc/net/nf_conntrack") do + line = line:match "^(.-( [^ =]+=).-)%2" + local entry, flags = _parse_mixed_record(line, " +") + entry.layer3 = flags[1] + entry.layer4 = flags[3] + for i=1, #entry do + entry[i] = nil + end + + connt[#connt+1] = entry + end + elseif luci.fs.access("/proc/net/ip_conntrack", "r") then + for line in io.lines("/proc/net/ip_conntrack") do + line = line:match "^(.-( [^ =]+=).-)%2" + local entry, flags = _parse_mixed_record(line, " +") + entry.layer3 = "ipv4" + entry.layer4 = flags[1] + for i=1, #entry do + entry[i] = nil + end + + connt[#connt+1] = entry + end + else + return nil + end + return connt +end + +--- Determine the current IPv4 default route. If multiple default routes exist, +-- return the one with the lowest metric. +-- @return Table with the properties of the current default route. +-- The following fields are defined: +-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt", +-- "flags", "device" } +function net.defaultroute() + local route = nil + for _, r in pairs(net.routes()) do + if r.dest:prefix() == 0 and (not route or route.metric > r.metric) then + route = r + end + end + return route +end + +--- Determine the current IPv6 default route. If multiple default routes exist, +-- return the one with the lowest metric. +-- @return Table with the properties of the current default route. +-- The following fields are defined: +-- { "source", "dest", "nexthop", "metric", "refcount", "usecount", +-- "flags", "device" } +function net.defaultroute6() + local route = nil + local routes6 = net.routes6() + if routes6 then + for _, r in pairs(routes6) do + if r.dest:prefix() == 0 and + (not route or route.metric > r.metric) + then + route = r + end + end + end + return route +end + +--- Determine the names of available network interfaces. +-- @return Table containing all current interface names +function net.devices() + local devices = {} + for line in io.lines("/proc/net/dev") do + table.insert(devices, line:match(" *(.-):")) + end + return devices +end + + +--- Return information about available network interfaces. +-- @return Table containing all current interface names and their information +function net.deviceinfo() + local devices = {} + for line in io.lines("/proc/net/dev") do + local name, data = line:match("^ *(.-): *(.*)$") + if name and data then + devices[name] = luci.util.split(data, " +", nil, true) + end + end + return devices +end + + +-- Determine the MAC address belonging to the given IP address. +-- @param ip IPv4 address +-- @return String containing the MAC address or nil if it cannot be found +function net.ip4mac(ip) + local mac = nil + + for i, l in ipairs(net.arptable()) do + if l["IP address"] == ip then + mac = l["HW address"] + end + end + + return mac +end + +--- Returns the current kernel routing table entries. +-- @return Table of tables with properties of the corresponding routes. +-- The following fields are defined for route entry tables: +-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt", +-- "flags", "device" } +function net.routes() + local routes = { } + + for line in io.lines("/proc/net/route") do + + local dev, dst_ip, gateway, flags, refcnt, usecnt, metric, + dst_mask, mtu, win, irtt = line:match( + "([^%s]+)\t([A-F0-9]+)\t([A-F0-9]+)\t([A-F0-9]+)\t" .. + "(%d+)\t(%d+)\t(%d+)\t([A-F0-9]+)\t(%d+)\t(%d+)\t(%d+)" + ) + + if dev then + gateway = luci.ip.Hex( gateway, 32, luci.ip.FAMILY_INET4 ) + dst_mask = luci.ip.Hex( dst_mask, 32, luci.ip.FAMILY_INET4 ) + dst_ip = luci.ip.Hex( + dst_ip, dst_mask:prefix(dst_mask), luci.ip.FAMILY_INET4 + ) + + routes[#routes+1] = { + dest = dst_ip, + gateway = gateway, + metric = tonumber(metric), + refcount = tonumber(refcnt), + usecount = tonumber(usecnt), + mtu = tonumber(mtu), + window = tonumber(window), + irtt = tonumber(irtt), + flags = tonumber(flags, 16), + device = dev + } + end + end + + return routes +end + +--- Returns the current ipv6 kernel routing table entries. +-- @return Table of tables with properties of the corresponding routes. +-- The following fields are defined for route entry tables: +-- { "source", "dest", "nexthop", "metric", "refcount", "usecount", +-- "flags", "device" } +function net.routes6() + if luci.fs.access("/proc/net/ipv6_route", "r") then + local routes = { } + + for line in io.lines("/proc/net/ipv6_route") do + + local dst_ip, dst_prefix, src_ip, src_prefix, nexthop, + metric, refcnt, usecnt, flags, dev = line:match( + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) +([^%s]+)" + ) + + src_ip = luci.ip.Hex( + src_ip, tonumber(src_prefix, 16), luci.ip.FAMILY_INET6, false + ) + + dst_ip = luci.ip.Hex( + dst_ip, tonumber(dst_prefix, 16), luci.ip.FAMILY_INET6, false + ) + + nexthop = luci.ip.Hex( nexthop, 128, luci.ip.FAMILY_INET6, false ) + + routes[#routes+1] = { + source = src_ip, + dest = dst_ip, + nexthop = nexthop, + metric = tonumber(metric, 16), + refcount = tonumber(refcnt, 16), + usecount = tonumber(usecnt, 16), + flags = tonumber(flags, 16), + device = dev + } + end + + return routes + end +end + +--- Tests whether the given host responds to ping probes. +-- @param host String containing a hostname or IPv4 address +-- @return Number containing 0 on success and >= 1 on error +function net.pingtest(host) + return os.execute("ping -c1 '"..host:gsub("'", '').."' >/dev/null 2>&1") +end + + +--- LuCI system utilities / process related functions. +-- @class module +-- @name luci.sys.process +process = {} + +--- Get the current process id. +-- @class function +-- @name process.info +-- @return Number containing the current pid +process.info = posix.getpid + +--- Retrieve information about currently running processes. +-- @return Table containing process information +function process.list() + local data = {} + local k + local ps = luci.util.execi("top -bn1") + + if not ps then + return + end + + while true do + local line = ps() + if not line then + return + end + + k = luci.util.split(luci.util.trim(line), "%s+", nil, true) + if k[1] == "PID" then + break + end + end + + for line in ps do + local row = {} + + line = luci.util.trim(line) + for i, value in ipairs(luci.util.split(line, "%s+", #k-1, true)) do + row[k[i]] = value + end + + local pid = tonumber(row[k[1]]) + if pid then + data[pid] = row + end + end + + return data +end + +--- Set the gid of a process identified by given pid. +-- @param pid Number containing the process id +-- @param gid Number containing the Unix group id +-- @return Boolean indicating successful operation +-- @return String containing the error message if failed +-- @return Number containing the error code if failed +function process.setgroup(pid, gid) + return posix.setpid("g", pid, gid) +end + +--- Set the uid of a process identified by given pid. +-- @param pid Number containing the process id +-- @param uid Number containing the Unix user id +-- @return Boolean indicating successful operation +-- @return String containing the error message if failed +-- @return Number containing the error code if failed +function process.setuser(pid, uid) + return posix.setpid("u", pid, uid) +end + +--- Send a signal to a process identified by given pid. +-- @class function +-- @name process.signal +-- @param pid Number containing the process id +-- @param sig Signal to send (default: 15 [SIGTERM]) +-- @return Boolean indicating successful operation +-- @return Number containing the error code if failed +process.signal = posix.kill + + +--- LuCI system utilities / user related functions. +-- @class module +-- @name luci.sys.user +user = {} + +--- Retrieve user informations for given uid. +-- @class function +-- @name getuser +-- @param uid Number containing the Unix user id +-- @return Table containing the following fields: +-- { "uid", "gid", "name", "passwd", "dir", "shell", "gecos" } +user.getuser = posix.getpasswd + +--- Test whether given string matches the password of a given system user. +-- @param username String containing the Unix user name +-- @param password String containing the password to compare +-- @return Boolean indicating wheather the passwords are equal +function user.checkpasswd(username, password) + local account = user.getuser(username) + + if account then + local pwd = account.passwd + local shadowpw + if #pwd == 1 then + if luci.fs.stat("/etc/shadow") then + if not pcall(function() + for l in io.lines("/etc/shadow") do + shadowpw = l:match("^%s:([^:]+)" % username) + if shadowpw then + pwd = shadowpw + break + end + end + end) then + return nil, "Unable to access shadow-file" + end + end + + if pwd == "!" then + return true + end + end + + if pwd and #pwd > 0 and password and #password > 0 then + return (pwd == posix.crypt(password, pwd)) + end + end + + return false +end + +--- Change the password of given user. +-- @param username String containing the Unix user name +-- @param password String containing the password to compare +-- @return Number containing 0 on success and >= 1 on error +function user.setpasswd(username, password) + if password then + password = password:gsub("'", "") + end + + if username then + username = username:gsub("'", "") + end + + local cmd = "(echo '"..password.."';sleep 1;echo '"..password.."')|" + cmd = cmd .. "passwd '"..username.."' >/dev/null 2>&1" + return os.execute(cmd) +end + + +--- LuCI system utilities / wifi related functions. +-- @class module +-- @name luci.sys.wifi +wifi = {} + +--- Get iwconfig output for all wireless devices. +-- @return Table of tables containing the iwconfing output for each wifi device +function wifi.getiwconfig() + local cnt = luci.util.exec("PATH=/sbin:/usr/sbin iwconfig 2>/dev/null") + local iwc = {} + + for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do + local k = l:match("^(.-) ") + l = l:gsub("^(.-) +", "", 1) + if k then + local entry, flags = _parse_mixed_record(l) + if entry then + entry.flags = flags + end + iwc[k] = entry + end + end + + return iwc +end + +--- Get iwlist scan output from all wireless devices. +-- @return Table of tables contaiing all scan results +function wifi.iwscan(iface) + local siface = iface or "" + local cnt = luci.util.exec("iwlist "..siface.." scan 2>/dev/null") + local iws = {} + + for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do + local k = l:match("^(.-) ") + l = l:gsub("^[^\n]+", "", 1) + l = luci.util.trim(l) + if k then + iws[k] = {} + for j, c in pairs(luci.util.split(l, "\n Cell")) do + c = c:gsub("^(.-)- ", "", 1) + c = luci.util.split(c, "\n", 7) + c = table.concat(c, "\n", 1) + local entry, flags = _parse_mixed_record(c) + if entry then + entry.flags = flags + end + table.insert(iws[k], entry) + end + end + end + + return iface and (iws[iface] or {}) or iws +end + + +--- LuCI system utilities / init related functions. +-- @class module +-- @name luci.sys.init +init = {} +init.dir = "/etc/init.d/" + +--- Get the names of all installed init scripts +-- @return Table containing the names of all inistalled init scripts +function init.names() + local names = { } + for _, name in ipairs(luci.fs.glob(init.dir.."*")) do + names[#names+1] = luci.fs.basename(name) + end + return names +end + +--- Test whether the given init script is enabled +-- @param name Name of the init script +-- @return Boolean indicating whether init is enabled +function init.enabled(name) + if luci.fs.access(init.dir..name) then + return ( call(init.dir..name.." enabled") == 0 ) + end + return false +end + +--- Get the index of he given init script +-- @param name Name of the init script +-- @return Numeric index value +function init.index(name) + if luci.fs.access(init.dir..name) then + return call("source "..init.dir..name.."; exit $START") + end +end + +--- Enable the given init script +-- @param name Name of the init script +-- @return Boolean indicating success +function init.enable(name) + if luci.fs.access(init.dir..name) then + return ( call(init.dir..name.." enable") == 1 ) + end +end + +--- Disable the given init script +-- @param name Name of the init script +-- @return Boolean indicating success +function init.disable(name) + if luci.fs.access(init.dir..name) then + return ( call(init.dir..name.." disable") == 0 ) + end +end + + +-- Internal functions + +function _parse_delimited_table(iter, delimiter) + delimiter = delimiter or "%s+" + + local data = {} + local trim = luci.util.trim + local split = luci.util.split + + local keys = split(trim(iter()), delimiter, nil, true) + for i, j in pairs(keys) do + keys[i] = trim(keys[i]) + end + + for line in iter do + local row = {} + line = trim(line) + if #line > 0 then + for i, j in pairs(split(line, delimiter, nil, true)) do + if keys[i] then + row[keys[i]] = j + end + end + end + table.insert(data, row) + end + + return data +end + +function _parse_mixed_record(cnt, delimiter) + delimiter = delimiter or " " + local data = {} + local flags = {} + + for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n")) do + for j, f in pairs(luci.util.split(luci.util.trim(l), delimiter, nil, true)) do + local k, x, v = f:match('([^%s][^:=]*) *([:=]*) *"*([^\n"]*)"*') + + if k then + if x == "" then + table.insert(flags, k) + else + data[k] = v + end + end + end + end + + return data, flags +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/sys/iptparser.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/sys/iptparser.lua new file mode 100644 index 0000000..524dfd9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/sys/iptparser.lua @@ -0,0 +1,244 @@ +--[[ +LuCI - Iptables parser and query library + +Copyright 2008 Jo-Philipp Wich + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +$Id: iptparser.lua 2733 2008-08-06 21:40:48Z Cyrus $ + +]]-- + +module("luci.sys.iptparser", package.seeall) +require("luci.util") + + +IptParser = luci.util.class() + +--[[ +IptParser.__init__( ... ) + +The class constructor, initializes the internal lookup table. +]]-- + +function IptParser.__init__( self, ... ) + self._rules = { } + self._chain = nil + self:_parse_rules() +end + + +--[[ +IptParser.find( args ) + +Find all firewall rules that match the given criteria. Expects a table with search criteria as only argument. +If args is nil or an empty table then all rules will be returned. + +The following keys in the args table are recognized: + + - table Match rules that are located within the given table + - chain Match rules that are located within the given chain + - target Match rules with the given target + - protocol Match rules that match the given protocol, rules with protocol "all" are always matched + - source Match rules with the given source, rules with source "0.0.0.0/0" are always matched + - destination Match rules with the given destination, rules with destination "0.0.0.0/0" are always matched + - inputif Match rules with the given input interface, rules with input interface "*" (=all) are always matched + - outputif Match rules with the given output interface, rules with output interface "*" (=all) are always matched + - flags Match rules that match the given flags, current supported values are "-f" (--fragment) and "!f" (! --fragment) + - options Match rules containing all given options + +The return value is a list of tables representing the matched rules. +Each rule table contains the following fields: + + - index The index number of the rule + - table The table where the rule is located, can be one of "filter", "nat" or "mangle" + - chain The chain where the rule is located, e.g. "INPUT" or "postrouting_wan" + - target The rule target, e.g. "REJECT" or "DROP" + - protocol The matching protocols, e.g. "all" or "tcp" + - flags Special rule options ("--", "-f" or "!f") + - inputif Input interface of the rule, e.g. "eth0.0" or "*" for all interfaces + - outputif Output interface of the rule, e.g. "eth0.0" or "*" for all interfaces + - source The source ip range, e.g. "0.0.0.0/0" + - destination The destination ip range, e.g. "0.0.0.0/0" + - options A list of specific options of the rule, e.g. { "reject-with", "tcp-reset" } + - packets The number of packets matched by the rule + - bytes The number of total bytes matched by the rule + +Example: + +ip = luci.sys.iptparser.IptParser() +result = ip.find( { + target="REJECT", + protocol="tcp", + options={ "reject-with", "tcp-reset" } +} ) + +This will match all rules with target "-j REJECT", protocol "-p tcp" (or "-p all") and the option "--reject-with tcp-reset". + +]]-- + +function IptParser.find( self, args ) + + local args = args or { } + local rv = { } + + for i, rule in ipairs(self._rules) do + local match = true + + -- match table + if not ( not args.table or args.table == rule.table ) then + match = false + end + + -- match chain + if not ( match == true and ( not args.chain or args.chain == rule.chain ) ) then + match = false + end + + -- match target + if not ( match == true and ( not args.target or args.target == rule.target ) ) then + match = false + end + + -- match protocol + if not ( match == true and ( not args.protocol or rule.protocol == "all" or args.protocol == rule.protocol ) ) then + match = false + end + + -- match source (XXX: implement ipcalc stuff so that 192.168.1.0/24 matches 0.0.0.0/0 etc.) + if not ( match == true and ( not args.source or rule.source == "0.0.0.0/0" or rule.source == args.source ) ) then + match = false + end + + -- match destination (XXX: implement ipcalc stuff so that 192.168.1.0/24 matches 0.0.0.0/0 etc.) + if not ( match == true and ( not args.destination or rule.destination == "0.0.0.0/0" or rule.destination == args.destination ) ) then + match = false + end + + -- match input interface + if not ( match == true and ( not args.inputif or rule.inputif == "*" or args.inputif == rule.inputif ) ) then + match = false + end + + -- match output interface + if not ( match == true and ( not args.outputif or rule.outputif == "*" or args.outputif == rule.outputif ) ) then + match = false + end + + -- match flags (the "opt" column) + if not ( match == true and ( not args.flags or rule.flags == args.flags ) ) then + match = false + end + + -- match specific options + if not ( match == true and ( not args.options or self:_match_options( rule.options, args.options ) ) ) then + match = false + end + + + -- insert match + if match == true then + table.insert( rv, rule ) + end + end + + return rv +end + + +--[[ +IptParser.resync() + +Rebuild the internal lookup table, for example when rules have changed through external commands. +]]-- + +function IptParser.resync( self ) + self._rules = { } + self._chain = nil + self:_parse_rules() +end + + +--[[ +IptParser._parse_rules() + +[internal] Parse iptables output from all tables. +]]-- + +function IptParser._parse_rules( self ) + + for i, tbl in ipairs({ "filter", "nat", "mangle" }) do + + for i, rule in ipairs(luci.util.execl("iptables -t " .. tbl .. " --line-numbers -nxvL")) do + + if rule:find( "Chain " ) == 1 then + + self._chain = rule:gsub("Chain ([^%s]*) .*", "%1") + + else + if rule:find("%d") == 1 then + + local rule_parts = luci.util.split( rule, "%s+", nil, true ) + local rule_details = { } + + rule_details["table"] = tbl + rule_details["chain"] = self._chain + rule_details["index"] = tonumber(rule_parts[1]) + rule_details["packets"] = tonumber(rule_parts[2]) + rule_details["bytes"] = tonumber(rule_parts[3]) + rule_details["target"] = rule_parts[4] + rule_details["protocol"] = rule_parts[5] + rule_details["flags"] = rule_parts[6] + rule_details["inputif"] = rule_parts[7] + rule_details["outputif"] = rule_parts[8] + rule_details["source"] = rule_parts[9] + rule_details["destination"] = rule_parts[10] + rule_details["options"] = { } + + for i = 11, #rule_parts - 1 do + rule_details["options"][i-10] = rule_parts[i] + end + + table.insert( self._rules, rule_details ) + end + end + end + end + + self._chain = nil +end + + +--[[ +IptParser._match_options( optlist1, optlist2 ) + +[internal] Return true if optlist1 contains all elements of optlist2. Return false in all other cases. +]]-- + +function IptParser._match_options( self, o1, o2 ) + + -- construct a hashtable of first options list to speed up lookups + local oh = { } + for i, opt in ipairs( o1 ) do oh[opt] = true end + + -- iterate over second options list + -- each string in o2 must be also present in o1 + -- if o2 contains a string which is not found in o1 then return false + for i, opt in ipairs( o2 ) do + if not oh[opt] then + return false + end + end + + return true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/sys/zoneinfo.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/sys/zoneinfo.lua new file mode 100644 index 0000000..d6de704 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/sys/zoneinfo.lua @@ -0,0 +1,572 @@ +--[[ +LuCI - Autogenerated Zoneinfo Module + +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 + +]]-- + +module "luci.sys.zoneinfo" + +TZ = { + { 'Africa/Abidjan', 'GMT0' }, + { 'Africa/Accra', 'GMT0' }, + { 'Africa/Addis Ababa', 'EAT-3' }, + { 'Africa/Algiers', 'CET-1' }, + { 'Africa/Asmara', 'EAT-3' }, + { 'Africa/Bamako', 'GMT0' }, + { 'Africa/Bangui', 'WAT-1' }, + { 'Africa/Banjul', 'GMT0' }, + { 'Africa/Bissau', 'GMT0' }, + { 'Africa/Blantyre', 'CAT-2' }, + { 'Africa/Brazzaville', 'WAT-1' }, + { 'Africa/Bujumbura', 'CAT-2' }, + { 'Africa/Casablanca', 'WET0' }, + { 'Africa/Ceuta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Africa/Conakry', 'GMT0' }, + { 'Africa/Dakar', 'GMT0' }, + { 'Africa/Dar es Salaam', 'EAT-3' }, + { 'Africa/Djibouti', 'EAT-3' }, + { 'Africa/Douala', 'WAT-1' }, + { 'Africa/El Aaiun', 'WET0' }, + { 'Africa/Freetown', 'GMT0' }, + { 'Africa/Gaborone', 'CAT-2' }, + { 'Africa/Harare', 'CAT-2' }, + { 'Africa/Johannesburg', 'SAST-2' }, + { 'Africa/Kampala', 'EAT-3' }, + { 'Africa/Khartoum', 'EAT-3' }, + { 'Africa/Kigali', 'CAT-2' }, + { 'Africa/Kinshasa', 'WAT-1' }, + { 'Africa/Lagos', 'WAT-1' }, + { 'Africa/Libreville', 'WAT-1' }, + { 'Africa/Lome', 'GMT0' }, + { 'Africa/Luanda', 'WAT-1' }, + { 'Africa/Lubumbashi', 'CAT-2' }, + { 'Africa/Lusaka', 'CAT-2' }, + { 'Africa/Malabo', 'WAT-1' }, + { 'Africa/Maputo', 'CAT-2' }, + { 'Africa/Maseru', 'SAST-2' }, + { 'Africa/Mbabane', 'SAST-2' }, + { 'Africa/Mogadishu', 'EAT-3' }, + { 'Africa/Monrovia', 'GMT0' }, + { 'Africa/Nairobi', 'EAT-3' }, + { 'Africa/Ndjamena', 'WAT-1' }, + { 'Africa/Niamey', 'WAT-1' }, + { 'Africa/Nouakchott', 'GMT0' }, + { 'Africa/Ouagadougou', 'GMT0' }, + { 'Africa/Porto-Novo', 'WAT-1' }, + { 'Africa/Sao Tome', 'GMT0' }, + { 'Africa/Tripoli', 'EET-2' }, + { 'Africa/Tunis', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Africa/Windhoek', 'WAT-1WAST,M9.1.0,M4.1.0' }, + { 'America/Adak', 'HAST10HADT,M3.2.0,M11.1.0' }, + { 'America/Anchorage', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Anguilla', 'AST4' }, + { 'America/Antigua', 'AST4' }, + { 'America/Araguaina', 'BRT3' }, + { 'America/Argentina/Buenos Aires', 'ART3ARST,M10.3.0/0,M3.3.0/0' }, + { 'America/Argentina/Catamarca', 'ART3' }, + { 'America/Argentina/Cordoba', 'ART3ARST,M10.3.0/0,M3.3.0/0' }, + { 'America/Argentina/Jujuy', 'ART3' }, + { 'America/Argentina/La Rioja', 'ART3' }, + { 'America/Argentina/Mendoza', 'ART3' }, + { 'America/Argentina/Rio Gallegos', 'ART3' }, + { 'America/Argentina/Salta', 'ART3' }, + { 'America/Argentina/San Juan', 'ART3' }, + { 'America/Argentina/San Luis', 'ART3' }, + { 'America/Argentina/Tucuman', 'ART3ARST,M10.3.0/0,M3.3.0/0' }, + { 'America/Argentina/Ushuaia', 'ART3' }, + { 'America/Aruba', 'AST4' }, + { 'America/Asuncion', 'PYT4PYST,M10.3.0/0,M3.2.0/0' }, + { 'America/Atikokan', 'EST5' }, + { 'America/Bahia', 'BRT3' }, + { 'America/Barbados', 'AST4' }, + { 'America/Belem', 'BRT3' }, + { 'America/Belize', 'CST6' }, + { 'America/Blanc-Sablon', 'AST4' }, + { 'America/Boa Vista', 'AMT4' }, + { 'America/Bogota', 'COT5' }, + { 'America/Boise', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Cambridge Bay', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Campo Grande', 'AMT4AMST,M10.3.0/0,M2.3.0/0' }, + { 'America/Cancun', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Caracas', 'VET4:30' }, + { 'America/Cayenne', 'GFT3' }, + { 'America/Cayman', 'EST5' }, + { 'America/Chicago', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Chihuahua', 'MST7MDT,M4.1.0,M10.5.0' }, + { 'America/Costa Rica', 'CST6' }, + { 'America/Cuiaba', 'AMT4AMST,M10.3.0/0,M2.3.0/0' }, + { 'America/Curacao', 'AST4' }, + { 'America/Danmarkshavn', 'GMT0' }, + { 'America/Dawson', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Dawson Creek', 'MST7' }, + { 'America/Denver', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Detroit', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Dominica', 'AST4' }, + { 'America/Edmonton', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Eirunepe', 'AMT4' }, + { 'America/El Salvador', 'CST6' }, + { 'America/Fortaleza', 'BRT3' }, + { 'America/Glace Bay', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Goose Bay', 'AST4ADT,M3.2.0/0:01,M11.1.0/0:01' }, + { 'America/Grand Turk', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Grenada', 'AST4' }, + { 'America/Guadeloupe', 'AST4' }, + { 'America/Guatemala', 'CST6' }, + { 'America/Guayaquil', 'ECT5' }, + { 'America/Guyana', 'GYT4' }, + { 'America/Halifax', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Havana', 'CST5CDT,M3.3.0/0,M10.5.0/1' }, + { 'America/Hermosillo', 'MST7' }, + { 'America/Indiana/Indianapolis', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Knox', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Marengo', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Petersburg', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Tell City', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Vevay', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Vincennes', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Winamac', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Inuvik', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Iqaluit', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Jamaica', 'EST5' }, + { 'America/Juneau', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Kentucky/Louisville', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Kentucky/Monticello', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/La Paz', 'BOT4' }, + { 'America/Lima', 'PET5' }, + { 'America/Los Angeles', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Maceio', 'BRT3' }, + { 'America/Managua', 'CST6' }, + { 'America/Manaus', 'AMT4' }, + { 'America/Marigot', 'AST4' }, + { 'America/Martinique', 'AST4' }, + { 'America/Mazatlan', 'MST7MDT,M4.1.0,M10.5.0' }, + { 'America/Menominee', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Merida', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Mexico City', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Miquelon', 'PMST3PMDT,M3.2.0,M11.1.0' }, + { 'America/Moncton', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Monterrey', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Montevideo', 'UYT3UYST,M10.1.0,M3.2.0' }, + { 'America/Montreal', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Montserrat', 'AST4' }, + { 'America/Nassau', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/New York', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Nipigon', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Nome', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Noronha', 'FNT2' }, + { 'America/North Dakota/Center', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/North Dakota/New Salem', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Panama', 'EST5' }, + { 'America/Pangnirtung', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Paramaribo', 'SRT3' }, + { 'America/Phoenix', 'MST7' }, + { 'America/Port of Spain', 'AST4' }, + { 'America/Port-au-Prince', 'EST5' }, + { 'America/Porto Velho', 'AMT4' }, + { 'America/Puerto Rico', 'AST4' }, + { 'America/Rainy River', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Rankin Inlet', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Recife', 'BRT3' }, + { 'America/Regina', 'CST6' }, + { 'America/Resolute', 'EST5' }, + { 'America/Rio Branco', 'AMT4' }, + { 'America/Santarem', 'BRT3' }, + { 'America/Santo Domingo', 'AST4' }, + { 'America/Sao Paulo', 'BRT3BRST,M10.3.0/0,M2.3.0/0' }, + { 'America/Scoresbysund', 'EGT1EGST,M3.5.0/0,M10.5.0/1' }, + { 'America/Shiprock', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/St Barthelemy', 'AST4' }, + { 'America/St Johns', 'NST3:30NDT,M3.2.0/0:01,M11.1.0/0:01' }, + { 'America/St Kitts', 'AST4' }, + { 'America/St Lucia', 'AST4' }, + { 'America/St Thomas', 'AST4' }, + { 'America/St Vincent', 'AST4' }, + { 'America/Swift Current', 'CST6' }, + { 'America/Tegucigalpa', 'CST6' }, + { 'America/Thule', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Thunder Bay', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Tijuana', 'PST8PDT,M4.1.0,M10.5.0' }, + { 'America/Toronto', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Tortola', 'AST4' }, + { 'America/Vancouver', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Whitehorse', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'Antarctica/Casey', 'WST-8' }, + { 'Antarctica/Davis', 'DAVT-7' }, + { 'Antarctica/DumontDUrville', 'DDUT-10' }, + { 'Antarctica/Mawson', 'MAWT-6' }, + { 'Antarctica/McMurdo', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Antarctica/Rothera', 'ROTT3' }, + { 'Antarctica/South Pole', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Antarctica/Syowa', 'SYOT-3' }, + { 'Antarctica/Vostok', 'VOST-6' }, + { 'Arctic/Longyearbyen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Asia/Aden', 'AST-3' }, + { 'Asia/Almaty', 'ALMT-6' }, + { 'Asia/Amman', 'EET-2EEST,M3.5.4/0,M10.5.5/1' }, + { 'Asia/Anadyr', 'ANAT-12ANAST,M3.5.0,M10.5.0/3' }, + { 'Asia/Aqtau', 'AQTT-5' }, + { 'Asia/Aqtobe', 'AQTT-5' }, + { 'Asia/Ashgabat', 'TMT-5' }, + { 'Asia/Baghdad', 'AST-3' }, + { 'Asia/Bahrain', 'AST-3' }, + { 'Asia/Baku', 'AZT-4AZST,M3.5.0/4,M10.5.0/5' }, + { 'Asia/Bangkok', 'ICT-7' }, + { 'Asia/Beirut', 'EET-2EEST,M3.5.0/0,M10.5.0/0' }, + { 'Asia/Bishkek', 'KGT-6' }, + { 'Asia/Brunei', 'BNT-8' }, + { 'Asia/Choibalsan', 'CHOT-8' }, + { 'Asia/Chongqing', 'CST-8' }, + { 'Asia/Colombo', 'IST-5:30' }, + { 'Asia/Damascus', 'EET-2EEST,M4.1.5/0,J305/0' }, + { 'Asia/Dhaka', 'BDT-6' }, + { 'Asia/Dili', 'TLT-9' }, + { 'Asia/Dubai', 'GST-4' }, + { 'Asia/Dushanbe', 'TJT-5' }, + { 'Asia/Gaza', 'EET-2EEST,J91/0,M8.5.4' }, + { 'Asia/Harbin', 'CST-8' }, + { 'Asia/Ho Chi Minh', 'ICT-7' }, + { 'Asia/Hong Kong', 'HKT-8' }, + { 'Asia/Hovd', 'HOVT-7' }, + { 'Asia/Irkutsk', 'IRKT-8IRKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Jakarta', 'WIT-7' }, + { 'Asia/Jayapura', 'EIT-9' }, + { 'Asia/Kabul', 'AFT-4:30' }, + { 'Asia/Kamchatka', 'PETT-12PETST,M3.5.0,M10.5.0/3' }, + { 'Asia/Karachi', 'PKT-5' }, + { 'Asia/Kashgar', 'CST-8' }, + { 'Asia/Katmandu', 'NPT-5:45' }, + { 'Asia/Kolkata', 'IST-5:30' }, + { 'Asia/Krasnoyarsk', 'KRAT-7KRAST,M3.5.0,M10.5.0/3' }, + { 'Asia/Kuala Lumpur', 'MYT-8' }, + { 'Asia/Kuching', 'MYT-8' }, + { 'Asia/Kuwait', 'AST-3' }, + { 'Asia/Macau', 'CST-8' }, + { 'Asia/Magadan', 'MAGT-11MAGST,M3.5.0,M10.5.0/3' }, + { 'Asia/Makassar', 'CIT-8' }, + { 'Asia/Manila', 'PHT-8' }, + { 'Asia/Muscat', 'GST-4' }, + { 'Asia/Nicosia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Asia/Novosibirsk', 'NOVT-6NOVST,M3.5.0,M10.5.0/3' }, + { 'Asia/Omsk', 'OMST-6OMSST,M3.5.0,M10.5.0/3' }, + { 'Asia/Oral', 'ORAT-5' }, + { 'Asia/Phnom Penh', 'ICT-7' }, + { 'Asia/Pontianak', 'WIT-7' }, + { 'Asia/Pyongyang', 'KST-9' }, + { 'Asia/Qatar', 'AST-3' }, + { 'Asia/Qyzylorda', 'QYZT-6' }, + { 'Asia/Rangoon', 'MMT-6:30' }, + { 'Asia/Riyadh', 'AST-3' }, + { 'Asia/Sakhalin', 'SAKT-10SAKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Samarkand', 'UZT-5' }, + { 'Asia/Seoul', 'KST-9' }, + { 'Asia/Shanghai', 'CST-8' }, + { 'Asia/Singapore', 'SGT-8' }, + { 'Asia/Taipei', 'CST-8' }, + { 'Asia/Tashkent', 'UZT-5' }, + { 'Asia/Tbilisi', 'GET-4' }, + { 'Asia/Thimphu', 'BTT-6' }, + { 'Asia/Tokyo', 'JST-9' }, + { 'Asia/Ulaanbaatar', 'ULAT-8' }, + { 'Asia/Urumqi', 'CST-8' }, + { 'Asia/Vientiane', 'ICT-7' }, + { 'Asia/Vladivostok', 'VLAT-10VLAST,M3.5.0,M10.5.0/3' }, + { 'Asia/Yakutsk', 'YAKT-9YAKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Yekaterinburg', 'YEKT-5YEKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Yerevan', 'AMT-4AMST,M3.5.0,M10.5.0/3' }, + { 'Atlantic/Azores', 'AZOT1AZOST,M3.5.0/0,M10.5.0/1' }, + { 'Atlantic/Bermuda', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'Atlantic/Canary', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Cape Verde', 'CVT1' }, + { 'Atlantic/Faroe', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Madeira', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Reykjavik', 'GMT0' }, + { 'Atlantic/South Georgia', 'GST2' }, + { 'Atlantic/St Helena', 'GMT0' }, + { 'Atlantic/Stanley', 'FKT4FKST,M9.1.0,M4.3.0' }, + { 'Australia/Adelaide', 'CST-9:30CST,M10.1.0,M4.1.0/3' }, + { 'Australia/Brisbane', 'EST-10' }, + { 'Australia/Broken Hill', 'CST-9:30CST,M10.1.0,M4.1.0/3' }, + { 'Australia/Currie', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Australia/Darwin', 'CST-9:30' }, + { 'Australia/Eucla', 'CWST-8:45' }, + { 'Australia/Hobart', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Australia/Lindeman', 'EST-10' }, + { 'Australia/Lord Howe', 'LHST-10:30LHST-11,M10.1.0,M4.1.0' }, + { 'Australia/Melbourne', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Australia/Perth', 'WST-8' }, + { 'Australia/Sydney', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Andorra', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Athens', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Belgrade', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Berlin', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Bratislava', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Brussels', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Bucharest', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Budapest', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Chisinau', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Copenhagen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Dublin', 'GMT0IST,M3.5.0/1,M10.5.0' }, + { 'Europe/Gibraltar', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Guernsey', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Helsinki', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Isle of Man', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Istanbul', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Jersey', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Kaliningrad', 'EET-2EEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Kiev', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Lisbon', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Europe/Ljubljana', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/London', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Luxembourg', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Madrid', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Malta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Mariehamn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Minsk', 'EET-2EEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Monaco', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Moscow', 'MSK-3MSD,M3.5.0,M10.5.0/3' }, + { 'Europe/Oslo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Paris', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Podgorica', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Prague', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Riga', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Rome', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Samara', 'SAMT-4SAMST,M3.5.0,M10.5.0/3' }, + { 'Europe/San Marino', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Sarajevo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Simferopol', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Skopje', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Sofia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Stockholm', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Tallinn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Tirane', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Uzhgorod', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Vaduz', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vatican', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vienna', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vilnius', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Volgograd', 'VOLT-3VOLST,M3.5.0,M10.5.0/3' }, + { 'Europe/Warsaw', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zagreb', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zaporozhye', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Zurich', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Indian/Antananarivo', 'EAT-3' }, + { 'Indian/Chagos', 'IOT-6' }, + { 'Indian/Christmas', 'CXT-7' }, + { 'Indian/Cocos', 'CCT-6:30' }, + { 'Indian/Comoro', 'EAT-3' }, + { 'Indian/Kerguelen', 'TFT-5' }, + { 'Indian/Mahe', 'SCT-4' }, + { 'Indian/Maldives', 'MVT-5' }, + { 'Indian/Mauritius', 'MUT-4MUST,M10.5.0,M3.5.0/3' }, + { 'Indian/Mayotte', 'EAT-3' }, + { 'Indian/Reunion', 'RET-4' }, + { 'Pacific/Apia', 'WST11' }, + { 'Pacific/Auckland', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Pacific/Chatham', 'CHAST-12:45CHADT,M9.5.0/2:45,M4.1.0/3:45' }, + { 'Pacific/Efate', 'VUT-11' }, + { 'Pacific/Enderbury', 'PHOT-13' }, + { 'Pacific/Fakaofo', 'TKT10' }, + { 'Pacific/Fiji', 'FJT-12' }, + { 'Pacific/Funafuti', 'TVT-12' }, + { 'Pacific/Galapagos', 'GALT6' }, + { 'Pacific/Gambier', 'GAMT9' }, + { 'Pacific/Guadalcanal', 'SBT-11' }, + { 'Pacific/Guam', 'ChST-10' }, + { 'Pacific/Honolulu', 'HST10' }, + { 'Pacific/Johnston', 'HST10' }, + { 'Pacific/Kiritimati', 'LINT-14' }, + { 'Pacific/Kosrae', 'KOST-11' }, + { 'Pacific/Kwajalein', 'MHT-12' }, + { 'Pacific/Majuro', 'MHT-12' }, + { 'Pacific/Marquesas', 'MART9:30' }, + { 'Pacific/Midway', 'SST11' }, + { 'Pacific/Nauru', 'NRT-12' }, + { 'Pacific/Niue', 'NUT11' }, + { 'Pacific/Norfolk', 'NFT-11:30' }, + { 'Pacific/Noumea', 'NCT-11' }, + { 'Pacific/Pago Pago', 'SST11' }, + { 'Pacific/Palau', 'PWT-9' }, + { 'Pacific/Pitcairn', 'PST8' }, + { 'Pacific/Ponape', 'PONT-11' }, + { 'Pacific/Port Moresby', 'PGT-10' }, + { 'Pacific/Rarotonga', 'CKT10' }, + { 'Pacific/Saipan', 'ChST-10' }, + { 'Pacific/Tahiti', 'TAHT10' }, + { 'Pacific/Tarawa', 'GILT-12' }, + { 'Pacific/Tongatapu', 'TOT-13' }, + { 'Pacific/Truk', 'TRUT-10' }, + { 'Pacific/Wake', 'WAKT-12' }, + { 'Pacific/Wallis', 'WFT-12' }, +} + +OFFSET = { + gmt = 0, -- GMT + eat = 10800, -- EAT + cet = 3600, -- CET + wat = 3600, -- WAT + cat = 7200, -- CAT + wet = 0, -- WET + sast = 7200, -- SAST + eet = 7200, -- EET + hast = -36000, -- HAST + hadt = -32400, -- HADT + akst = -32400, -- AKST + akdt = -28800, -- AKDT + ast = -14400, -- AST + brt = -10800, -- BRT + art = -10800, -- ART + arst = -7200, -- ARST + pyt = -14400, -- PYT + pyst = -10800, -- PYST + est = -18000, -- EST + cst = -21600, -- CST + amt = -14400, -- AMT + cot = -18000, -- COT + mst = -25200, -- MST + mdt = -21600, -- MDT + vet = -16200, -- VET + gft = -10800, -- GFT + pst = -28800, -- PST + pdt = -25200, -- PDT + ect = -18000, -- ECT + gyt = -14400, -- GYT + bot = -14400, -- BOT + pet = -18000, -- PET + pmst = -10800, -- PMST + pmdt = -7200, -- PMDT + uyt = -10800, -- UYT + uyst = -7200, -- UYST + fnt = -7200, -- FNT + srt = -10800, -- SRT + egt = -3600, -- EGT + egst = 0, -- EGST + nst = -12600, -- NST + ndt = -9000, -- NDT + wst = 28800, -- WST + davt = 25200, -- DAVT + ddut = 36000, -- DDUT + mawt = 21600, -- MAWT + nzst = 43200, -- NZST + nzdt = 46800, -- NZDT + rott = -10800, -- ROTT + syot = 10800, -- SYOT + vost = 21600, -- VOST + almt = 21600, -- ALMT + anat = 43200, -- ANAT + anast = 46800, -- ANAST + aqtt = 18000, -- AQTT + tmt = 18000, -- TMT + azt = 14400, -- AZT + azst = 18000, -- AZST + ict = 25200, -- ICT + kgt = 21600, -- KGT + bnt = 28800, -- BNT + chot = 28800, -- CHOT + ist = 19800, -- IST + bdt = 21600, -- BDT + tlt = 32400, -- TLT + gst = 14400, -- GST + tjt = 18000, -- TJT + hkt = 28800, -- HKT + hovt = 25200, -- HOVT + irkt = 28800, -- IRKT + irkst = 32400, -- IRKST + wit = 25200, -- WIT + eit = 32400, -- EIT + aft = 16200, -- AFT + pett = 43200, -- PETT + petst = 46800, -- PETST + pkt = 18000, -- PKT + npt = 20700, -- NPT + krat = 25200, -- KRAT + krast = 28800, -- KRAST + myt = 28800, -- MYT + magt = 39600, -- MAGT + magst = 43200, -- MAGST + cit = 28800, -- CIT + pht = 28800, -- PHT + novt = 21600, -- NOVT + novst = 25200, -- NOVST + omst = 21600, -- OMST + omsst = 25200, -- OMSST + orat = 18000, -- ORAT + kst = 32400, -- KST + qyzt = 21600, -- QYZT + mmt = 23400, -- MMT + sakt = 36000, -- SAKT + sakst = 39600, -- SAKST + uzt = 18000, -- UZT + sgt = 28800, -- SGT + get = 14400, -- GET + btt = 21600, -- BTT + jst = 32400, -- JST + ulat = 28800, -- ULAT + vlat = 36000, -- VLAT + vlast = 39600, -- VLAST + yakt = 32400, -- YAKT + yakst = 36000, -- YAKST + yekt = 18000, -- YEKT + yekst = 21600, -- YEKST + azot = -3600, -- AZOT + azost = 0, -- AZOST + cvt = -3600, -- CVT + fkt = -14400, -- FKT + fkst = -10800, -- FKST + cwst = 31500, -- CWST + lhst = 37800, -- LHST + lhst = 39600, -- LHST + msk = 10800, -- MSK + msd = 14400, -- MSD + samt = 14400, -- SAMT + samst = 18000, -- SAMST + volt = 10800, -- VOLT + volst = 14400, -- VOLST + iot = 21600, -- IOT + cxt = 25200, -- CXT + cct = 23400, -- CCT + tft = 18000, -- TFT + sct = 14400, -- SCT + mvt = 18000, -- MVT + mut = 14400, -- MUT + must = 18000, -- MUST + ret = 14400, -- RET + chast = 45900, -- CHAST + chadt = 49500, -- CHADT + vut = 39600, -- VUT + phot = 46800, -- PHOT + tkt = -36000, -- TKT + fjt = 43200, -- FJT + tvt = 43200, -- TVT + galt = -21600, -- GALT + gamt = -32400, -- GAMT + sbt = 39600, -- SBT + hst = -36000, -- HST + lint = 50400, -- LINT + kost = 39600, -- KOST + mht = 43200, -- MHT + mart = -34200, -- MART + sst = -39600, -- SST + nrt = 43200, -- NRT + nut = -39600, -- NUT + nft = 41400, -- NFT + nct = 39600, -- NCT + pwt = 32400, -- PWT + pont = 39600, -- PONT + pgt = 36000, -- PGT + ckt = -36000, -- CKT + taht = -36000, -- TAHT + gilt = 43200, -- GILT + tot = 46800, -- TOT + trut = 36000, -- TRUT + wakt = 43200, -- WAKT + wft = 43200, -- WFT +} diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/template.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/template.lua new file mode 100644 index 0000000..df30060 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/template.lua @@ -0,0 +1,239 @@ +--[[ +LuCI - Template Parser + +Description: +A template parser supporting includes, translations, Lua code blocks +and more. It can be used either as a compiler or as an interpreter. + +FileId: $Id: template.lua 3246 2008-09-12 07:48:36Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local fs = require"luci.fs" +local sys = require "luci.sys" +local util = require "luci.util" +local table = require "table" +local string = require "string" +local config = require "luci.config" +local coroutine = require "coroutine" + +local tostring, pairs, loadstring = tostring, pairs, loadstring +local setmetatable, loadfile = setmetatable, loadfile +local getfenv, setfenv, rawget = getfenv, setfenv, rawget +local assert, type, error = assert, type, error + +--- LuCI template library. +module "luci.template" + +config.template = config.template or {} + +viewdir = config.template.viewdir or util.libpath() .. "/view" +compiledir = config.template.compiledir or util.libpath() .. "/view" + + +-- Compile modes: +-- memory: Always compile, do not save compiled files, ignore precompiled +-- file: Compile on demand, save compiled files, update precompiled +compiler_mode = config.template.compiler_mode or "memory" + + +-- Define the namespace for template modules +context = util.threadlocal() + +--- Manually compile a given template into an executable Lua function +-- @param template LuCI template +-- @return Lua template function +function compile(template) + local expr = {} + + -- Search all <% %> expressions + local function expr_add(ws1, skip1, command, skip2, ws2) + expr[#expr+1] = command + return ( #skip1 > 0 and "" or ws1 ) .. + "<%" .. tostring(#expr) .. "%>" .. + ( #skip2 > 0 and "" or ws2 ) + end + + -- Save all expressiosn to table "expr" + template = template:gsub("(%s*)<%%(%-?)(.-)(%-?)%%>(%s*)", expr_add) + + local function sanitize(s) + s = "%q" % s + return s:sub(2, #s-1) + end + + -- Escape and sanitize all the template (all non-expressions) + template = sanitize(template) + + -- Template module header/footer declaration + local header = 'write("' + local footer = '")' + + template = header .. template .. footer + + -- Replacements + local r_include = '")\ninclude("%s")\nwrite("' + local r_i18n = '"..translate("%1","%2").."' + local r_i18n2 = '"..translate("%1", "").."' + local r_pexec = '"..(%s or "").."' + local r_exec = '")\n%s\nwrite("' + + -- Parse the expressions + for k,v in pairs(expr) do + local p = v:sub(1, 1) + v = v:gsub("%%", "%%%%") + local re = nil + if p == "+" then + re = r_include:format(sanitize(string.sub(v, 2))) + elseif p == ":" then + if v:find(" ") then + re = sanitize(v):gsub(":(.-) (.*)", r_i18n) + else + re = sanitize(v):gsub(":(.+)", r_i18n2) + end + elseif p == "=" then + re = r_pexec:format(v:sub(2)) + elseif p == "#" then + re = "" + else + re = r_exec:format(v) + end + template = template:gsub("<%%"..tostring(k).."%%>", re) + end + + return loadstring(template) +end + +--- Render a certain template. +-- @param name Template name +-- @param scope Scope to assign to template (optional) +function render(name, scope) + return Template(name):render(scope or getfenv(2)) +end + + +-- Template class +Template = util.class() + +-- Shared template cache to store templates in to avoid unnecessary reloading +Template.cache = setmetatable({}, {__mode = "v"}) + + +-- Constructor - Reads and compiles the template on-demand +function Template.__init__(self, name) + local function _encode_filename(str) + + local function __chrenc( chr ) + return "%%%02x" % string.byte( chr ) + end + + if type(str) == "string" then + str = str:gsub( + "([^a-zA-Z0-9$_%-%.%+!*'(),])", + __chrenc + ) + end + + return str + end + + self.template = self.cache[name] + self.name = name + + -- Create a new namespace for this template + self.viewns = context.viewns + + -- If we have a cached template, skip compiling and loading + if self.template then + return + end + + -- Enforce cache security + local cdir = compiledir .. "/" .. sys.process.info("uid") + + -- Compile and build + local sourcefile = viewdir .. "/" .. name + local compiledfile = cdir .. "/" .. _encode_filename(name) .. ".lua" + local err + + if compiler_mode == "file" then + local tplmt = fs.mtime(sourcefile) or fs.mtime(sourcefile .. ".htm") + local commt = fs.mtime(compiledfile) + + if not fs.mtime(cdir) then + fs.mkdir(cdir, true) + fs.chmod(fs.dirname(cdir), "a+rxw") + end + + assert(tplmt or commt, "No such template: " .. name) + + -- Build if there is no compiled file or if compiled file is outdated + if not commt or (commt and tplmt and commt < tplmt) then + local source + source, err = fs.readfile(sourcefile) or fs.readfile(sourcefile .. ".htm") + + if source then + local compiled, err = compile(source) + + fs.writefile(compiledfile, util.get_bytecode(compiled)) + fs.chmod(compiledfile, "a-rwx,u+rw") + self.template = compiled + end + else + assert( + sys.process.info("uid") == fs.stat(compiledfile, "uid") + and fs.stat(compiledfile, "mode") == "rw-------", + "Fatal: Cachefile is not sane!" + ) + self.template, err = loadfile(compiledfile) + end + + elseif compiler_mode == "memory" then + local source + source, err = fs.readfile(sourcefile) or fs.readfile(sourcefile .. ".htm") + if source then + self.template, err = compile(source) + end + + end + + -- If we have no valid template throw error, otherwise cache the template + if not self.template then + error(err) + else + self.cache[name] = self.template + end +end + + +-- Renders a template +function Template.render(self, scope) + scope = scope or getfenv(2) + + -- Put our predefined objects in the scope of the template + setfenv(self.template, setmetatable({}, {__index = + function(tbl, key) + return rawget(tbl, key) or self.viewns[key] or scope[key] + end})) + + -- Now finally render the thing + local stat, err = util.copcall(self.template) + if not stat then + error("Error in template %s: %s" % {self.name, err}) + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/tools/ffwizard.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/tools/ffwizard.lua new file mode 100644 index 0000000..3f5e17a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/tools/ffwizard.lua @@ -0,0 +1,149 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ffwizard.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +local uci = require "luci.model.uci" +local util = require "luci.util" +local table = require "table" + +local type = type + +module "luci.tools.ffwizard" + +-- Deletes all references of a wifi device +function wifi_delete_ifaces(device) + local cursor = uci.cursor() + cursor:delete_all("wireless", "wifi-iface", {device=device}) + cursor:save("wireless") +end + +-- Deletes a network interface and all occurences of it in firewall zones and dhcp +function network_remove_interface(iface) + local cursor = uci.cursor() + + if not cursor:delete("network", iface) then + return false + end + + local aliases = {iface} + cursor:foreach("network", "alias", + function(section) + if section.interface == iface then + table.insert(aliases, section[".name"]) + end + end) + + -- Delete Aliases and Routes + cursor:delete_all("network", "route", {interface=iface}) + cursor:delete_all("network", "alias", {interface=iface}) + + -- Delete DHCP sections + cursor:delete_all("dhcp", "dhcp", + function(section) + return util.contains(aliases, section.interface) + end) + + -- Remove OLSR sections + cursor:delete_all("olsrd", "Interface", {Interface=iface}) + + -- Remove Splash sections + cursor:delete_all("luci-splash", "iface", {network=iface}) + + cursor:save("network") + cursor:save("olsr") + cursor:save("dhcp") + cursor:save("luci-splash") +end + +-- Creates a firewall zone +function firewall_create_zone(zone, input, output, forward, masq) + local cursor = uci.cursor() + if not firewall_find_zone(zone) then + local stat = cursor:section("firewall", "zone", nil, { + input = input, + output = output, + forward = forward, + masq = masq and "1", + name = zone + }) + cursor:save("firewall") + return stat + end +end + +-- Adds interface to zone, creates zone on-demand +function firewall_zone_add_interface(name, interface) + local cursor = uci.cursor() + local zone = firewall_find_zone(name) + local net = cursor:get("firewall", zone, "network") + local old = net or (cursor:get("network", name) and name) + cursor:set("firewall", zone, "network", (old and old .. " " or "") .. interface) + cursor:save("firewall") +end + +-- Removes interface from zone +function firewall_zone_remove_interface(name, interface) + local cursor = uci.cursor() + local zone = firewall_find_zone(name) + if zone then + local net = cursor:get("firewall", zone, "network") + local new = remove_list_entry(net, interface) + if new then + if #new > 0 then + cursor:set("firewall", zone, "network", new) + else + cursor:delete("firewall", zone, "network") + end + cursor:save("firewall") + end + end +end + + +-- Finds the firewall zone with given name +function firewall_find_zone(name) + local find + + uci.cursor():foreach("firewall", "zone", + function (section) + if section.name == name then + find = section[".name"] + end + end) + + return find +end + + + +-- Helpers -- + +-- Removes a listentry, handles real and pseduo lists transparently +function remove_list_entry(value, entry) + if type(value) == "nil" then + return nil + end + + local result = type(value) == "table" and value or util.split(value, " ") + local key = util.contains(result, entry) + + while key do + table.remove(result, key) + key = util.contains(result, entry) + end + + result = type(value) == "table" and result or table.concat(result, " ") + return result ~= value and result +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/tools/webadmin.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/tools/webadmin.lua new file mode 100644 index 0000000..ae90c50 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/tools/webadmin.lua @@ -0,0 +1,173 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: webadmin.lua 4169 2009-01-27 17:15:58Z jow $ +]]-- + +module("luci.tools.webadmin", package.seeall) +local uci = require("luci.model.uci") +require("luci.sys") +require("luci.ip") + +function byte_format(byte) + local suff = {"B", "KB", "MB", "GB", "TB"} + for i=1, 5 do + if byte > 1024 and i < 5 then + byte = byte / 1024 + else + return string.format("%.2f %s", byte, suff[i]) + end + end +end + +function date_format(secs) + local suff = {"min", "h", "d"} + local mins = 0 + local hour = 0 + local days = 0 + + secs = math.floor(secs) + if secs > 60 then + mins = math.floor(secs / 60) + secs = secs % 60 + end + + if mins > 60 then + hour = math.floor(mins / 60) + mins = mins % 60 + end + + if hour > 24 then + days = math.floor(hour / 24) + hour = hour % 24 + end + + if days > 0 then + return string.format("%.0fd %02.0fh %02.0fmin %02.0fs", days, hour, mins, secs) + else + return string.format("%02.0fh %02.0fmin %02.0fs", hour, mins, secs) + end +end + +function network_get_addresses(net) + local state = uci.cursor_state() + state:load("network") + local addr = {} + local ipv4 = state:get("network", net, "ipaddr") + local mav4 = state:get("network", net, "netmask") + local ipv6 = state:get("network", net, "ip6addr") + + if ipv4 and #ipv4 > 0 then + if mav4 and #mav4 == 0 then mav4 = nil end + + ipv4 = luci.ip.IPv4(ipv4, mav4) + + if ipv4 then + table.insert(addr, ipv4:string()) + end + end + + if ipv6 then + table.insert(addr, ipv6) + end + + state:foreach("network", "alias", + function (section) + if section.interface == net then + if section.ipaddr and section.netmask then + local ipv4 = luci.ip.IPv4(section.ipaddr, section.netmask) + + if ipv4 then + table.insert(addr, ipv4:string()) + end + end + + if section.ip6addr then + table.insert(addr, section.ip6addr) + end + end + end + ) + + return addr +end + +function cbi_add_networks(field) + uci.cursor():foreach("network", "interface", + function (section) + if section[".name"] ~= "loopback" then + field:value(section[".name"]) + end + end + ) + field.titleref = luci.dispatcher.build_url("admin", "network", "network") +end + +function cbi_add_knownips(field) + for i, dataset in ipairs(luci.sys.net.arptable()) do + field:value(dataset["IP address"]) + end +end + +function network_get_zones(net) + local state = uci.cursor_state() + if not state:load("firewall") then + return nil + end + + local zones = {} + + state:foreach("firewall", "zone", + function (section) + local znet = section.network or section.name + if luci.util.contains(luci.util.split(znet, " "), net) then + table.insert(zones, section.name) + end + end + ) + + return zones +end + +function firewall_find_zone(name) + local find + + luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + if section.name == name then + find = section[".name"] + end + end + ) + + return find +end + +function iface_get_network(iface) + local state = uci.cursor_state() + state:load("network") + local net + + state:foreach("network", "interface", + function (section) + local ifname = state:get( + "network", section[".name"], "ifname" + ) + + if iface == ifname then + net = section[".name"] + end + end + ) + + return net +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/file.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/file.lua new file mode 100644 index 0000000..e1f707c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/file.lua @@ -0,0 +1,252 @@ +--[[ + +HTTP server implementation for LuCI - file handler +(c) 2008 Steven Barth +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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$ + +]]-- + +local ipairs, type, tonumber = ipairs, type, tonumber +local io = require "io" +local os = require "os" +local fs = require "luci.fs" +local util = require "luci.util" +local ltn12 = require "luci.ltn12" +local mod = require "luci.ttpd.module" +local srv = require "luci.ttpd.server" +local string = require "string" + +local prot = require "luci.http.protocol" +local date = require "luci.http.protocol.date" +local mime = require "luci.http.protocol.mime" +local cond = require "luci.http.protocol.conditionals" + +module "luci.ttpd.handler.file" + +Simple = util.class(mod.Handler) +Response = mod.Response + +function Simple.__init__(self, docroot, dirlist) + mod.Handler.__init__(self) + self.docroot = docroot + self.dirlist = dirlist and true or false +end + +function Simple.parse_range(self, request, size) + if not request.headers.Range then + return true + end + + local from, to = request.headers.Range:match("bytes=([0-9]*)-([0-9]*)") + if not (from or to) then + return true + end + + from, to = tonumber(from), tonumber(to) + if not (from or to) then + return true + elseif not from then + from, to = size - to, size - 1 + elseif not to then + to = size - 1 + end + + -- Not satisfiable + if from >= size then + return false + end + + -- Normalize + if to >= size then + to = size - 1 + end + + local range = "bytes " .. from .. "-" .. to .. "/" .. size + return from, (1 + to - from), range +end + +function Simple.getfile(self, uri) + local file = self.docroot .. uri:gsub("%.%./+", "") + local stat = fs.stat(file) + + return file, stat +end + +function Simple.handle_get(self, request, sourcein, sinkerr) + local file, stat = self:getfile( prot.urldecode( request.env.PATH_INFO, true ) ) + + if stat then + if stat.type == "regular" then + + -- Generate Entity Tag + local etag = cond.mk_etag( stat ) + + -- Check conditionals + local ok, code, hdrs + + ok, code, hdrs = cond.if_modified_since( request, stat ) + if ok then + ok, code, hdrs = cond.if_match( request, stat ) + if ok then + ok, code, hdrs = cond.if_unmodified_since( request, stat ) + if ok then + ok, code, hdrs = cond.if_none_match( request, stat ) + if ok then + local f, err = io.open(file) + + if f then + local code = 200 + local o, s, r = self:parse_range(request, stat.size) + + if not o then + return self:failure(416, "Invalid Range") + end + + local headers = { + ["Last-Modified"] = date.to_http( stat.mtime ), + ["Content-Type"] = mime.to_mime( file ), + ["ETag"] = etag, + ["Accept-Ranges"] = "bytes", + } + + if o == true then + o = 0 + s = stat.size + else + code = 206 + headers["Content-Range"] = r + end + + headers["Content-Length"] = s + + -- Send Response + return Response(code, headers), + srv.IOResource(f, o, s) + else + return self:failure( 403, err:gsub("^.+: ", "") ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + + elseif stat.type == "directory" then + + local ruri = request.request_uri:gsub("/$","") + local duri = prot.urldecode( ruri, true ) + local root = self.docroot:gsub("/$","") + + -- check for index files + local index_candidates = { + "index.html", "index.htm", "default.html", "default.htm", + "index.txt", "default.txt" + } + + -- try to find an index file and redirect to it + for i, candidate in ipairs( index_candidates ) do + local istat = fs.stat( + root .. "/" .. duri .. "/" .. candidate + ) + + if istat ~= nil and istat.type == "regular" then + return Response( 302, { + ["Location"] = ruri .. "/" .. candidate + } ) + end + end + + + local html = string.format( + '\n' .. + '\n' .. + '\n' .. + '\n' .. + 'Index of %s/\n' .. + '

Index of %s/


    ', + duri, duri + ) + + local entries = fs.dir( file ) + + if type(entries) == "table" then + for i, e in util.spairs( + entries, function(a,b) + if entries[a] == '..' then + return true + elseif entries[b] == '..' then + return false + else + return ( entries[a] < entries[b] ) + end + end + ) do + if e ~= '.' and ( e == '..' or e:sub(1,1) ~= '.' ) then + local estat = fs.stat( file .. "/" .. e ) + + if estat.type == "directory" then + html = html .. string.format( + '
  • %s/ ' .. + '(directory)
    ' .. + 'Changed: %s

  • ', + ruri, prot.urlencode( e ), e, + date.to_http( estat.mtime ) + ) + else + html = html .. string.format( + '
  • %s ' .. + '(%s)
    ' .. + 'Size: %i Bytes | ' .. + 'Changed: %s

  • ', + ruri, prot.urlencode( e ), e, + mime.to_mime( e ), + estat.size, date.to_http( estat.mtime ) + ) + end + end + end + + html = html .. '

' + + return Response( + 200, { + ["Date"] = date.to_http( os.time() ); + ["Content-Type"] = "text/html; charset=ISO-8859-15"; + } + ), ltn12.source.string(html) + else + return self:failure(403, "Permission denied") + end + else + return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file) + end + else + return self:failure(404, "No such file: " .. file) + end +end + +function Simple.handle_head(self, ...) + return (self:handle_get(...)) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/luci.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/luci.lua new file mode 100644 index 0000000..eb60625 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/handler/luci.lua @@ -0,0 +1,92 @@ +--[[ + +HTTP server implementation for LuCI - luci handler +(c) 2008 Steven Barth + +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$ + +]]-- +local dsp = require "luci.dispatcher" +local util = require "luci.util" +local http = require "luci.http" +local ltn12 = require "luci.ltn12" +local mod = require "luci.ttpd.module" +local table = require "table" +local coroutine = require "coroutine" + +module "luci.ttpd.handler.luci" + +Luci = util.class(mod.Handler) +Response = mod.Response + +function Luci.__init__(self, limit) + mod.Handler.__init__(self) +end + +function Luci.handle_head(self, ...) + return (self:handle_get(...)) +end + +function Luci.handle_post(self, ...) + return self:handle_get(...) +end + +function Luci.handle_get(self, request, sourcein, sinkerr) + local r = http.Request( + request.env, + sourcein, + sinkerr + ) + + local res, id, data1, data2 = true, 0, nil, nil + local headers = {} + local status = 200 + local active = true + + local x = coroutine.create(dsp.httpdispatch) + while not id or id < 3 do + res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + status = 500 + headers["Content-Type"] = "text/plain" + local err = {id} + return Response( status, headers ), function() return table.remove(err) end + end + + if id == 1 then + status = data1 + elseif id == 2 then + headers[data1] = data2 + end + end + + local function iter() + local res, id, data = coroutine.resume(x) + if not res then + return nil, id + elseif not id or not active then + return true + elseif id == 5 then + active = false + + while (coroutine.resume(x)) do + end + + return nil + elseif id == 4 then + return data + end + if coroutine.status(x) == "dead" then + return nil + end + end + + return Response(status, headers), iter +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/module.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/module.lua new file mode 100644 index 0000000..1a7c574 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/module.lua @@ -0,0 +1,121 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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$ +]]-- + +local pcall, ipairs, tonumber, type, next = pcall, ipairs, tonumber, type, next +local util = require "luci.util" +local http = require "luci.http.protocol" +local ltn12 = require "luci.ltn12" +local table = require "table" + +module "luci.ttpd.module" + + +-- Server handler implementation +Handler = util.class() + +-- Constructor +function Handler.__init__(self) + self.handler = {} + self.filters = {} + self.modifiers = {} +end + +-- Add a filter +function Handler.setfilter(self, filter, key) + self.filters[(key) or (#self.filters+1)] = filter +end + +-- Add a modifier +function Handler.setmodifier(self, modifier, key) + self.modifiers[(pos) or (#self.modifiers+1)] = modifier +end + +-- Creates a failure reply +function Handler.failure(self, code, message) + local response = Response(code, { ["Content-Type"] = "text/plain" }) + local sourceout = ltn12.source.string(message) + + return response, sourceout +end + +-- Processes a request +function Handler.process(self, request, sourcein, sinkerr) + local stat, response, sourceout + + -- Detect request Method + local hname = "handle_" .. request.request_method + if self[hname] then + local t = { + processor = self[hname], + handler = self, + request = request, + sourcein = sourcein, + sinkerr = sinkerr + } + + if next(self.modifiers) then + for _, mod in util.kspairs(self.modifiers) do + mod(t) + end + end + + -- Run the handler + stat, response, sourceout = pcall( + t.processor, t.handler, t.request, t.sourcein, t.sinkerr + ) + + -- Check for any errors + if not stat then + response, sourceout = self:failure(500, response) + elseif next(self.filters) then + local t = { + response = response, + sourceout = sourceout, + sinkerr = t.sinkerr + } + + for _, filter in util.kspairs(self.filters) do + filter(t) + end + + response = t.response + sourceout = t.sourceout + end + else + response, sourceout = self:failure(405, http.protocol.statusmsg[405]) + end + + -- Check data + if not util.instanceof(response, Response) then + response, sourceout = self:failure(500, "Core error: Invalid module response!") + end + + return response, sourceout +end + +-- Handler Response +Response = util.class() + +function Response.__init__(self, status, headers) + self.status = tonumber(status) or 200 + self.headers = (type(headers) == "table") and headers or {} +end + +function Response.addheader(self, key, value) + self.headers[key] = value +end + +function Response.setstatus(self, status) + self.status = status +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/server.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/server.lua new file mode 100644 index 0000000..a2c7ffc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/ttpd/server.lua @@ -0,0 +1,444 @@ +--[[ +LuCIttpd +(c) 2008 Steven Barth +(c) 2008 Jo-Philipp Wich + +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$ +]]-- + +local ipairs, pairs = ipairs, pairs +local tostring, tonumber = tostring, tonumber +local pcall, assert = pcall, assert + +local os = require "os" +local io = require "io" +local uci = require "luci.model.uci" +local util = require "luci.util" +local ltn12 = require "luci.ltn12" +local proto = require "luci.http.protocol" +local string = require "string" +local date = require "luci.http.protocol.date" + +module "luci.ttpd.server" + +BUFSIZE = 4096 +VERSION = 0.91 + + +-- File Resource +IOResource = util.class() + +function IOResource.__init__(self, fd, offset, len) + self.fd, self.offset, self.len = fd, offset, len +end + + +VHost = util.class() + +function VHost.__init__(self, handler) + self.handler = handler + self.dhandler = {} +end + +function VHost.process(self, request, sourcein, sinkerr, ...) + local handler = self.handler + + local uri = request.env.REQUEST_URI:match("^([^?]*)") + + -- SCRIPT_NAME + request.env.SCRIPT_NAME = "" + + -- Call URI part + request.env.PATH_INFO = uri + + for k, dhandler in pairs(self.dhandler) do + if k == uri or k.."/" == uri:sub(1, #k+1) then + handler = dhandler + request.env.SCRIPT_NAME = k + request.env.PATH_INFO = uri:sub(#k+1) + break; + end + end + + if handler then + return handler:process(request, sourcein, sinkerr, ...) + end +end + +function VHost.get_default_handler(self) + return self.handler +end + +function VHost.set_default_handler(self, handler) + self.handler = handler +end + +function VHost.get_handlers(self) + return self.dhandler +end + +function VHost.set_handler(self, match, handler) + self.dhandler[match] = handler +end + + + +Server = util.class() + +function Server.__init__(self, host) + self.uci = uci.cursor() + self.host = host + self.vhosts = {} + + self.rbuf = "" + self.wbuf = "" +end + +function Server.get_default_vhost(self) + return self.host +end + +function Server.set_default_vhost(self, vhost) + self.host = vhost +end + +function Server.get_vhosts(self) + return self.vhosts +end + +function Server.set_vhost(self, name, vhost) + self.vhosts[name] = vhost +end + +function Server.flush(self) + if #self.wbuf > 0 then + self._write(self.wbuf) + self.wbuf = "" + end +end + +function Server.read(self, len) + while #self.rbuf < len do + self.rbuf = self.rbuf .. self._read(len - #self.rbuf) + end + + local chunk = self.rbuf:sub(1, len) + self.rbuf = self.rbuf:sub(len + 1) + return chunk +end + +function Server.limitsource(self, limit) + limit = limit or 0 + + return function() + if limit < 1 then + return nil + else + local read = (limit > BUFSIZE) and BUFSIZE or limit + limit = limit - read + return self:read(read) + end + end +end + +-- Adapted from Luaposix +function Server.receiveheaders(self) + local line, name, value, err + local headers = {} + -- get first line + line, err = self:readline() + if err then return nil, err end + -- headers go until a blank line is found + while line do + -- get field-name and value + _, _, name, value = line:find("^(.-):%s*(.*)") + if not (name and value) then return nil, "malformed reponse headers" end + name = name:lower() + -- get next line (value might be folded) + line, err = self:readline() + if err then return nil, err end + -- unfold any folded values + while line:find("^%s") do + value = value .. line + line = self:readline() + if err then return nil, err end + end + -- save pair in table + if headers[name] then headers[name] = headers[name] .. ", " .. value + else headers[name] = value end + end + return headers +end + +function Server.readchunk(self) + -- get chunk size, skip extention + local line, err = self:readline() + if err then return nil, err end + local size = tonumber(line:gsub(";.*", ""), 16) + if not size then return nil, "invalid chunk size" end + -- was it the last chunk? + if size > 0 then + -- if not, get chunk and skip terminating CRLF + local chunk, err, part = self:read(size) + if chunk then self:readline() end + return chunk, err + else + -- if it was, read trailers into headers table + headers, err = self:receiveheaders() + if not headers then return nil, err end + end +end + +function Server.readline(self) + if #self.rbuf < 1 then + self.rbuf = self._read(BUFSIZE) + end + + while true do + local le = self.rbuf:find("\r\n", nil, true) + if le then + if le == 1 then -- EoH + self.rbuf = self.rbuf:sub(le + 2) + return nil + else -- Header + local line = self.rbuf:sub(1, le - 1) + self.rbuf = self.rbuf:sub(le + 2) + return line + end + else + if #self.rbuf >= BUFSIZE then + return nil, "Invalid Request" + end + self.rbuf = self.rbuf .. self._read(BUFSIZE-#self.rbuf) + end + end +end + +function Server.sink(self) + return function(chunk, err) + if err then + return nil, err + elseif chunk then + local stat, err = pcall(self.write, self, chunk) + if stat then + return stat + else + return nil, err + end + else + return true + end + end +end + +function Server.chunksink(self) + return function(chunk, err) + local stat, err = pcall(self.writechunk, self, chunk) + if stat then + return stat + else + return nil, err + end + end +end + +function Server.writechunk(self, chunk, err) + self:flush() + if not chunk then return self._write("0\r\n\r\n") end + local size = string.format("%X\r\n", #chunk) + return self._write(size .. chunk .. "\r\n") +end + +function Server.write(self, chunk) + while #chunk > 0 do + local missing = BUFSIZE - #self.wbuf + self.wbuf = self.wbuf .. chunk:sub(1, missing) + chunk = chunk:sub(missing + 1) + if #self.wbuf == BUFSIZE then + assert(self._write(self.wbuf)) + self.wbuf = "" + end + end +end + +function Server.close(self) + self:flush() + self._close() +end + +function Server.sendfile(self, fd, offset, len) + self:flush() + self._sendfile(fd, offset, len) +end + + +function Server.error(self, code, msg) + hcode = tostring(code) + + self:write( "HTTP/1.0 " .. hcode .. " " .. + proto.statusmsg[code] .. "\r\n" ) + self:write( "Connection: close\r\n" ) + self:write( "Content-Type: text/plain\r\n\r\n" ) + + if msg then + self:write( "HTTP-Error " .. code .. ": " .. msg .. "\r\n" ) + end +end + + +function Server.process(self, functions) + util.update(self, functions) + + local sourcein = ltn12.source.empty() + local sourcehdr = function() return self:readline() or "" end + local sinkerr = ltn12.sink.file( io.stderr ) + local sinkout = self:sink() + + local close = false + local stat, message, err + + repeat + -- parse headers + stat, message, err = pcall(proto.parse_message_header, sourcehdr) + + -- remote socket closed + if not stat and message == 0 then + break + end + + -- remote timeout + if not stat and message == 11 then + --self:error(408) + break + end + + -- any other error + if not stat or not message then + self:error(400, err) + break + end + + -- keep-alive + if message.http_version == 1.1 then + close = (message.env.HTTP_CONNECTION == "close") + else + close = not message.env.HTTP_CONNECTION or message.env.HTTP_CONNECTION == "close" + end + -- Uncomment this to disable keep-alive + close = not (self.uci:get("lucittpd", "lucittpd", "keepalive") == "1") + + if message.request_method == "get" or message.request_method == "head" then + -- Be happy + + elseif message.request_method == "post" then + -- If we have a HTTP/1.1 client and an Expect: 100-continue header then + -- respond with HTTP 100 Continue message + if message.http_version == 1.1 and message.headers['Expect'] and + message.headers['Expect'] == '100-continue' + then + self:write("HTTP/1.1 100 Continue\r\n\r\n") + end + + if message.headers['Transfer-Encoding'] and + message.headers['Transfer-Encoding'] ~= "identity" then + sourcein = function() return self:readchunk() end + elseif message.env.CONTENT_LENGTH then + sourcein = self:limitsource( + tonumber(message.env.CONTENT_LENGTH) + ) + else + self:error( 411, proto.statusmsg[411] ) + break + end + else + self:error( 405, proto.statusmsg[405] ) + break + + end + + + local host = self.vhosts[message.env.HTTP_HOST] or self.host + if not host then + self:error( 500, "Unable to find matching host" ) + break; + end + + local response, sourceout = host:process( + message, sourcein, sinkerr, + client, io.stderr + ) + if not response then + self:error( 500, "Error processing handler" ) + end + + -- Post process response + if sourceout then + if util.instanceof(sourceout, IOResource) then + if not response.headers["Content-Length"] then + response.headers["Content-Length"] = sourceout.len + end + end + if not response.headers["Content-Length"] then + if message.http_version == 1.1 then + response.headers["Transfer-Encoding"] = "chunked" + sinkout = self:chunksink() + else + close = true + end + end + elseif message.request_method ~= "head" then + response.headers["Content-Length"] = 0 + end + + if close then + response.headers["Connection"] = "close" + end + + response.headers["Date"] = date.to_http(os.time()) + + local header = + message.env.SERVER_PROTOCOL .. " " .. + tostring(response.status) .. " " .. + proto.statusmsg[response.status] .. "\r\n" + + header = header .. "Server: LuCIttpd/" .. tostring(VERSION) .. "\r\n" + + + for k,v in pairs(response.headers) do + header = header .. k .. ": " .. v .. "\r\n" + end + + -- Output + local stat, err = pcall(function() + self:write(header .. "\r\n") + + if sourceout then + if util.instanceof(sourceout, IOResource) then + self:sendfile(sourceout.fd, sourceout.offset, sourceout.len) + else + ltn12.pump.all(sourceout, sinkout) + end + end + + self:flush() + end) + + -- Write errors + if not stat then + if err == 107 then + -- Remote end closed the socket, so do we + elseif err then + io.stderr:write("Error sending data: " .. err .. "\n") + end + break + end + until close + + self:close() +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/util.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/util.lua new file mode 100644 index 0000000..5815942 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/util.lua @@ -0,0 +1,787 @@ +--[[ +LuCI - Utility library + +Description: +Several common useful Lua functions + +FileId: +$Id: util.lua 4119 2009-01-25 13:14:29Z jow $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local io = require "io" +local math = require "math" +local table = require "table" +local debug = require "debug" +local ldebug = require "luci.debug" +local string = require "string" +local coroutine = require "coroutine" + +local getmetatable, setmetatable = getmetatable, setmetatable +local rawget, rawset, unpack = rawget, rawset, unpack +local tostring, type, assert = tostring, type, assert +local ipairs, pairs, loadstring = ipairs, pairs, loadstring +local require, pcall, xpcall = require, pcall, xpcall + +--- LuCI utility functions. +module "luci.util" + +-- +-- Pythonic string formatting extension +-- +getmetatable("").__mod = function(a, b) + if not b then + return a + elseif type(b) == "table" then + return a:format(unpack(b)) + else + return a:format(b) + end +end + + +-- +-- Class helper routines +-- + +-- Instantiates a class +local function _instantiate(class, ...) + local inst = setmetatable({}, {__index = class}) + + if inst.__init__ then + inst:__init__(...) + end + + return inst +end + +--- Create a Class object (Python-style object model). +-- The class object can be instantiated by calling itself. +-- Any class functions or shared parameters can be attached to this object. +-- Attaching a table to the class object makes this table shared between +-- all instances of this class. For object parameters use the __init__ function. +-- Classes can inherit member functions and values from a base class. +-- Class can be instantiated by calling them. All parameters will be passed +-- to the __init__ function of this class - if such a function exists. +-- The __init__ function must be used to set any object parameters that are not shared +-- with other objects of this class. Any return values will be ignored. +-- @param base The base class to inherit from (optional) +-- @return A class object +-- @see instanceof +-- @see clone +function class(base) + return setmetatable({}, { + __call = _instantiate, + __index = base + }) +end + +--- Test whether the given object is an instance of the given class. +-- @param object Object instance +-- @param class Class object to test against +-- @return Boolean indicating whether the object is an instance +-- @see class +-- @see clone +function instanceof(object, class) + local meta = getmetatable(object) + while meta and meta.__index do + if meta.__index == class then + return true + end + meta = getmetatable(meta.__index) + end + return false +end + + +-- +-- Scope manipulation routines +-- + +--- Create a new or get an already existing thread local store associated with +-- the current active coroutine. A thread local store is private a table object +-- whose values can't be accessed from outside of the running coroutine. +-- @return Table value representing the corresponding thread local store +function threadlocal() + local tbl = {} + + local function get(self, key) + local c = coroutine.running() + local thread = coxpt[c] or c or 0 + if not rawget(self, thread) then + return nil + end + return rawget(self, thread)[key] + end + + local function set(self, key, value) + local c = coroutine.running() + local thread = coxpt[c] or c or 0 + if not rawget(self, thread) then + rawset(self, thread, {}) + end + rawget(self, thread)[key] = value + end + + setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"}) + + return tbl +end + + +-- +-- Debugging routines +-- + +--- Write given object to stderr. +-- @param obj Value to write to stderr +-- @return Boolean indicating whether the write operation was successful +function perror(obj) + return io.stderr:write(tostring(obj) .. "\n") +end + +--- Recursively dumps a table to stdout, useful for testing and debugging. +-- @param t Table value to dump +-- @param maxdepth Maximum depth +-- @return Always nil +function dumptable(t, maxdepth, i, seen) + i = i or 0 + seen = seen or setmetatable({}, {__mode="k"}) + + for k,v in pairs(t) do + perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v)) + if type(v) == "table" and (not maxdepth or i < maxdepth) then + if not seen[v] then + seen[v] = true + dumptable(v, maxdepth, i+1, seen) + else + perror(string.rep("\t", i) .. "*** RECURSION ***") + end + end + end +end + + +-- +-- String and data manipulation routines +-- + +--- Escapes all occurrences of the given character in given string. +-- @param s String value containing unescaped characters +-- @param c String value with character to escape (optional, defaults to "\") +-- @return String value with each occurrence of character escaped with "\" +function escape(s, c) + c = c or "\\" + return s:gsub(c, "\\" .. c) +end + +--- Create valid XML PCDATA from given string. +-- @param value String value containing the data to escape +-- @return String value containing the escaped data +local function _pcdata_repl(c) + local i = string.byte(c) + + if ( i >= 0x00 and i <= 0x08 ) or ( i >= 0x0B and i <= 0x0C ) or + ( i >= 0x0E and i <= 0x1F ) or ( i == 0x7F ) + then + return "" + + elseif ( i == 0x26 ) or ( i == 0x27 ) or ( i == 0x22 ) or + ( i == 0x3C ) or ( i == 0x3E ) + then + return string.format("&#%i;", i) + end + + return c +end + +function pcdata(value) + return value and tostring(value):gsub("[&\"'<>%c]", _pcdata_repl) +end + +--- Strip HTML tags from given string. +-- @param value String containing the HTML text +-- @return String with HTML tags stripped of +function striptags(s) + return pcdata(s:gsub("]*>", " "):gsub("%s+", " ")) +end + +--- Splits given string on a defined separator sequence and return a table +-- containing the resulting substrings. The optional max parameter specifies +-- the number of bytes to process, regardless of the actual length of the given +-- string. The optional last parameter, regex, specifies whether the separator +-- sequence is interpreted as regular expression. +-- @param str String value containing the data to split up +-- @param pat String with separator pattern (optional, defaults to "\n") +-- @param max Maximum times to split (optional) +-- @param regex Boolean indicating whether to interpret the separator +-- pattern as regular expression (optional, default is false) +-- @return Table containing the resulting substrings +function split(str, pat, max, regex) + pat = pat or "\n" + max = max or #str + + local t = {} + local c = 1 + + if #str == 0 then + return {""} + end + + if #pat == 0 then + return nil + end + + if max == 0 then + return str + end + + repeat + local s, e = str:find(pat, c, not regex) + max = max - 1 + if s and max < 0 then + t[#t+1] = str:sub(c) + else + t[#t+1] = str:sub(c, s and s - 1) + end + c = e and e + 1 or #str + 1 + until not s or max < 0 + + return t +end + +--- Remove leading and trailing whitespace from given string value. +-- @param str String value containing whitespace padded data +-- @return String value with leading and trailing space removed +function trim(str) + return (str:gsub("^%s*(.-)%s*$", "%1")) +end + +--- Count the occurences of given substring in given string. +-- @param str String to search in +-- @param pattern String containing pattern to find +-- @return Number of found occurences +function cmatch(str, pat) + local count = 0 + for _ in str:gmatch(pat) do count = count + 1 end + return count +end + +--- Parse certain units from the given string and return the canonical integer +-- value or 0 if the unit is unknown. Upper- or lower case is irrelevant. +-- Recognized units are: +-- o "y" - one year (60*60*24*366) +-- o "m" - one month (60*60*24*31) +-- o "w" - one week (60*60*24*7) +-- o "d" - one day (60*60*24) +-- o "h" - one hour (60*60) +-- o "min" - one minute (60) +-- o "kb" - one kilobyte (1024) +-- o "mb" - one megabyte (1024*1024) +-- o "gb" - one gigabyte (1024*1024*1024) +-- o "kib" - one si kilobyte (1000) +-- o "mib" - one si megabyte (1000*1000) +-- o "gib" - one si gigabyte (1000*1000*1000) +-- @param ustr String containing a numerical value with trailing unit +-- @return Number containing the canonical value +function parse_units(ustr) + + local val = 0 + + -- unit map + local map = { + -- date stuff + y = 60 * 60 * 24 * 366, + m = 60 * 60 * 24 * 31, + w = 60 * 60 * 24 * 7, + d = 60 * 60 * 24, + h = 60 * 60, + min = 60, + + -- storage sizes + kb = 1024, + mb = 1024 * 1024, + gb = 1024 * 1024 * 1024, + + -- storage sizes (si) + kib = 1000, + mib = 1000 * 1000, + gib = 1000 * 1000 * 1000 + } + + -- parse input string + for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do + + local num = spec:gsub("[^0-9%.]+$","") + local spn = spec:gsub("^[0-9%.]+", "") + + if map[spn] or map[spn:sub(1,1)] then + val = val + num * ( map[spn] or map[spn:sub(1,1)] ) + else + val = val + num + end + end + + + return val +end + +-- also register functions above in the central string class for convenience +string.escape = escape +string.pcdata = pcdata +string.striptags = striptags +string.split = split +string.trim = trim +string.cmatch = cmatch +string.parse_units = parse_units + + +--- Appends numerically indexed tables or single objects to a given table. +-- @param src Target table +-- @param ... Objects to insert +-- @return Target table +function append(src, ...) + for i, a in ipairs({...}) do + if type(a) == "table" then + for j, v in ipairs(a) do + src[#src+1] = v + end + else + src[#src+1] = a + end + end + return src +end + +--- Combines two or more numerically indexed tables and single objects into one table. +-- @param tbl1 Table value to combine +-- @param tbl2 Table value to combine +-- @param ... More tables to combine +-- @return Table value containing all values of given tables +function combine(...) + return append({}, ...) +end + +--- Checks whether the given table contains the given value. +-- @param table Table value +-- @param value Value to search within the given table +-- @return Boolean indicating whether the given value occurs within table +function contains(table, value) + for k, v in pairs(table) do + if value == v then + return k + end + end + return false +end + +--- Update values in given table with the values from the second given table. +-- Both table are - in fact - merged together. +-- @param t Table which should be updated +-- @param updates Table containing the values to update +-- @return Always nil +function update(t, updates) + for k, v in pairs(updates) do + t[k] = v + end +end + +--- Retrieve all keys of given associative table. +-- @param t Table to extract keys from +-- @return Sorted table containing the keys +function keys(t) + local keys = { } + if t then + for k, _ in kspairs(t) do + keys[#keys+1] = k + end + end + return keys +end + +--- Clones the given object and return it's copy. +-- @param object Table value to clone +-- @param deep Boolean indicating whether to do recursive cloning +-- @return Cloned table value +function clone(object, deep) + local copy = {} + + for k, v in pairs(object) do + if deep and type(v) == "table" then + v = clone(v, deep) + end + copy[k] = v + end + + return setmetatable(copy, getmetatable(object)) +end + + +--- Create a dynamic table which automatically creates subtables. +-- @return Dynamic Table +function dtable() + return setmetatable({}, { __index = + function(tbl, key) + return rawget(tbl, key) + or rawget(rawset(tbl, key, dtable()), key) + end + }) +end + + +-- Serialize the contents of a table value. +function _serialize_table(t, seen) + assert(not seen[t], "Recursion detected.") + seen[t] = true + + local data = "" + local idata = "" + local ilen = 0 + + for k, v in pairs(t) do + if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then + k = serialize_data(k, seen) + v = serialize_data(v, seen) + data = data .. ( #data > 0 and ", " or "" ) .. + '[' .. k .. '] = ' .. v + elseif k > ilen then + ilen = k + end + end + + for i = 1, ilen do + local v = serialize_data(t[i], seen) + idata = idata .. ( #idata > 0 and ", " or "" ) .. v + end + + return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data +end + +--- Recursively serialize given data to lua code, suitable for restoring +-- with loadstring(). +-- @param val Value containing the data to serialize +-- @return String value containing the serialized code +-- @see restore_data +-- @see get_bytecode +function serialize_data(val, seen) + seen = seen or setmetatable({}, {__mode="k"}) + + if val == nil then + return "nil" + elseif type(val) == "number" then + return val + elseif type(val) == "string" then + return "%q" % val + elseif type(val) == "boolean" then + return val and "true" or "false" + elseif type(val) == "function" then + return "loadstring(%q)" % get_bytecode(val) + elseif type(val) == "table" then + return "{ " .. _serialize_table(val, seen) .. " }" + else + return '"[unhandled data type:' .. type(val) .. ']"' + end +end + +--- Restore data previously serialized with serialize_data(). +-- @param str String containing the data to restore +-- @return Value containing the restored data structure +-- @see serialize_data +-- @see get_bytecode +function restore_data(str) + return loadstring("return " .. str)() +end + + +-- +-- Byte code manipulation routines +-- + +--- Return the current runtime bytecode of the given data. The byte code +-- will be stripped before it is returned. +-- @param val Value to return as bytecode +-- @return String value containing the bytecode of the given data +function get_bytecode(val) + local code + + if type(val) == "function" then + code = string.dump(val) + else + code = string.dump( loadstring( "return " .. serialize_data(val) ) ) + end + + return code and strip_bytecode(code) +end + +--- Strips unnescessary lua bytecode from given string. Information like line +-- numbers and debugging numbers will be discarded. Original version by +-- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) +-- @param code String value containing the original lua byte code +-- @return String value containing the stripped lua byte code +function strip_bytecode(code) + local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12) + local subint + if endian == 1 then + subint = function(code, i, l) + local val = 0 + for n = l, 1, -1 do + val = val * 256 + code:byte(i + n - 1) + end + return val, i + l + end + else + subint = function(code, i, l) + local val = 0 + for n = 1, l, 1 do + val = val * 256 + code:byte(i + n - 1) + end + return val, i + l + end + end + + local strip_function + strip_function = function(code) + local count, offset = subint(code, 1, size) + local stripped, dirty = string.rep("\0", size), offset + count + offset = offset + count + int * 2 + 4 + offset = offset + int + subint(code, offset, int) * ins + count, offset = subint(code, offset, int) + for n = 1, count do + local t + t, offset = subint(code, offset, 1) + if t == 1 then + offset = offset + 1 + elseif t == 4 then + offset = offset + size + subint(code, offset, size) + elseif t == 3 then + offset = offset + num + elseif t == 254 or t == 9 then + offset = offset + lnum + end + end + count, offset = subint(code, offset, int) + stripped = stripped .. code:sub(dirty, offset - 1) + for n = 1, count do + local proto, off = strip_function(code:sub(offset, -1)) + stripped, offset = stripped .. proto, offset + off - 1 + end + offset = offset + subint(code, offset, int) * int + int + count, offset = subint(code, offset, int) + for n = 1, count do + offset = offset + subint(code, offset, size) + size + int * 2 + end + count, offset = subint(code, offset, int) + for n = 1, count do + offset = offset + subint(code, offset, size) + size + end + stripped = stripped .. string.rep("\0", int * 3) + return stripped, offset + end + + return code:sub(1,12) .. strip_function(code:sub(13,-1)) +end + + +-- +-- Sorting iterator functions +-- + +function _sortiter( t, f ) + local keys = { } + + for k, v in pairs(t) do + keys[#keys+1] = k + end + + local _pos = 0 + + table.sort( keys, f ) + + return function() + _pos = _pos + 1 + if _pos <= #keys then + return keys[_pos], t[keys[_pos]] + end + end +end + +--- Return a key, value iterator which returns the values sorted according to +-- the provided callback function. +-- @param t The table to iterate +-- @param f A callback function to decide the order of elements +-- @return Function value containing the corresponding iterator +function spairs(t,f) + return _sortiter( t, f ) +end + +--- Return a key, value iterator for the given table. +-- The table pairs are sorted by key. +-- @param t The table to iterate +-- @return Function value containing the corresponding iterator +function kspairs(t) + return _sortiter( t ) +end + +--- Return a key, value iterator for the given table. +-- The table pairs are sorted by value. +-- @param t The table to iterate +-- @return Function value containing the corresponding iterator +function vspairs(t) + return _sortiter( t, function (a,b) return t[a] < t[b] end ) +end + + +-- +-- System utility functions +-- + +--- Test whether the current system is operating in big endian mode. +-- @return Boolean value indicating whether system is big endian +function bigendian() + return string.byte(string.dump(function() end), 7) == 0 +end + +--- Execute given commandline and gather stdout. +-- @param command String containing command to execute +-- @return String containing the command's stdout +function exec(command) + local pp = io.popen(command) + local data = pp:read("*a") + pp:close() + + return data +end + +--- Return a line-buffered iterator over the output of given command. +-- @param command String containing the command to execute +-- @return Iterator +function execi(command) + local pp = io.popen(command) + + return pp and function() + local line = pp:read() + + if not line then + pp:close() + end + + return line + end +end + +-- Deprecated +function execl(command) + local pp = io.popen(command) + local line = "" + local data = {} + + while true do + line = pp:read() + if (line == nil) then break end + data[#data+1] = line + end + pp:close() + + return data +end + +--- Returns the absolute path to LuCI base directory. +-- @return String containing the directory path +function libpath() + return require "luci.fs".dirname(ldebug.__file__) +end + + +-- +-- Coroutine safe xpcall and pcall versions modified for Luci +-- original version: +-- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org) +-- +-- Copyright © 2005 Kepler Project. +-- Permission is hereby granted, free of charge, to any person obtaining a +-- copy of this software and associated documentation files (the "Software"), +-- to deal in the Software without restriction, including without limitation +-- the rights to use, copy, modify, merge, publish, distribute, sublicense, +-- and/or sell copies of the Software, and to permit persons to whom the +-- Software is furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be +-- included in all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +-- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +-- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +local performResume, handleReturnValue +local oldpcall, oldxpcall = pcall, xpcall +coxpt = {} +setmetatable(coxpt, {__mode = "kv"}) + +-- Identity function for copcall +local function copcall_id(trace, ...) + return ... +end + +--- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function +-- @param f Lua function to be called protected +-- @param err Custom error handler +-- @param ... Parameters passed to the function +-- @return A boolean whether the function call succeeded and the return +-- values of either the function or the error handler +function coxpcall(f, err, ...) + local res, co = oldpcall(coroutine.create, f) + if not res then + local params = {...} + local newf = function() return f(unpack(params)) end + co = coroutine.create(newf) + end + local c = coroutine.running() + coxpt[co] = coxpt[c] or c or 0 + + return performResume(err, co, ...) +end + +--- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function +-- @param f Lua function to be called protected +-- @param ... Parameters passed to the function +-- @return A boolean whether the function call succeeded and the returns +-- values of the function or the error object +function copcall(f, ...) + return coxpcall(f, copcall_id, ...) +end + +-- Handle return value of protected call +function handleReturnValue(err, co, status, ...) + if not status then + return false, err(debug.traceback(co, (...)), ...) + end + if coroutine.status(co) == 'suspended' then + return performResume(err, co, coroutine.yield(...)) + else + return true, ... + end +end + +-- Resume execution of protected function call +function performResume(err, co, ...) + return handleReturnValue(err, co, coroutine.resume(co, ...)) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvl.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl.lua new file mode 100644 index 0000000..1eed5e0 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl.lua @@ -0,0 +1,1209 @@ +--[[ + +UCI Validation Layer - Main Library +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: uvl.lua 4087 2009-01-18 00:02:52Z jow $ + +]]-- + + +--- UVL - UCI Validation Layer +-- @class module +-- @cstyle instance + +local fs = require "luci.fs" +local uci = require "luci.model.uci" +local util = require "luci.util" +local table = require "table" +local string = require "string" + +local require, pcall, ipairs, pairs = require, pcall, ipairs, pairs +local type, error, tonumber, tostring = type, error, tonumber, tostring +local unpack, loadfile = unpack, loadfile + +module "luci.uvl" + +local ERR = require "luci.uvl.errors" +local datatypes = require "luci.uvl.datatypes" +local validation = require "luci.uvl.validation" +local dependencies = require "luci.uvl.dependencies" + +local TYPE_SCHEME = 0x00 +local TYPE_CONFIG = 0x01 +local TYPE_SECTION = 0x02 +local TYPE_OPTION = 0x03 +local TYPE_ENUM = 0x04 + +--- Boolean; default true; +-- treat sections found in config but not in scheme as error +STRICT_UNKNOWN_SECTIONS = true + +--- Boolean; default true; +-- treat options found in config but not in scheme as error +STRICT_UNKNOWN_OPTIONS = true + +--- Boolean; default true; +-- treat failed external validators as error +STRICT_EXTERNAL_VALIDATORS = true + +--- Boolean; default true; +-- treat list values stored as options like errors +STRICT_LIST_TYPE = true + + +local default_schemedir = "/lib/uci/schema" +local default_savedir = "/tmp/.uvl" + + +--- Object constructor +-- @class function +-- @name UVL +-- @param schemedir Path to the scheme directory (optional) +-- @param configdir Override config directory (optional) +-- @return Instance object +UVL = util.class() + +function UVL.__init__( self, schemedir, configdir ) + self.schemedir = schemedir or default_schemedir + self.configdir = configdir + self.packages = { } + self.beenthere = { } + self.depseen = { } + self.uci = uci + self.err = ERR + self.dep = dependencies + self.datatypes = datatypes +end + + +--- Parse given scheme and return the scheme tree. +-- @param scheme Name of the scheme to parse +-- @return Table containing the parsed scheme or nil on error +-- @return String containing the reason for errors (if any) +function UVL.get_scheme( self, scheme ) + if not self.packages[scheme] then + local ok, err = self:read_scheme( scheme ) + if not ok then + return nil, err + end + end + return self.packages[scheme], nil +end + +--- Validate given configuration, section or option. +-- @param config Name of the configuration to validate +-- @param section Name of the section to validate (optional) +-- @param option Name of the option to validate (optional) +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate( self, config, section, option ) + if config and section and option then + return self:validate_option( config, section, option ) + elseif config and section then + return self:validate_section( config, section ) + elseif config then + return self:validate_config( config ) + end +end + +--- Validate given configuration. +-- @param cfg Name of the configuration to validate +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate_config( self, cfg, uci ) + + if not self.packages[cfg] then + local ok, err = self:read_scheme(cfg) + if not ok then + return false, err + end + end + + local co = config( self, uci or cfg, uci and cfg ) + local sc = { } + + self.beenthere = { } + self.depseen = { } + + if not co:config() then + return false, co:errors() + end + + local function _uci_foreach( type, func ) + for k, v in pairs(co:config()) do + if v['.type'] == type then + sc[type] = sc[type] + 1 + local ok, err = func( k, v ) + if not ok then co:error(err) end + end + end + end + + for k, v in pairs( self.packages[cfg].sections ) do + sc[k] = 0 + _uci_foreach( k, + function(s) + return self:_validate_section( co:section(s) ) + end + ) + end + + if STRICT_UNKNOWN_SECTIONS then + for k, v in pairs(co:config()) do + local so = co:section(k) + if not self.beenthere[so:cid()] then + co:error(ERR.SECT_UNKNOWN(so)) + end + end + end + + for _, k in ipairs(util.keys(sc)) do + local so = co:section(k) + if so:scheme('required') and sc[k] == 0 then + co:error(ERR.SECT_REQUIRED(so)) + elseif so:scheme('unique') and sc[k] > 1 then + co:error(ERR.SECT_UNIQUE(so)) + end + end + + return co:ok(), co:errors() +end + +--- Validate given config section. +-- @param config Name of the configuration to validate +-- @param section Name of the section to validate +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate_section( self, cfg, section, uci ) + + if not self.packages[cfg] then + local ok, err = self:read_scheme( cfg ) + if not ok then + return false, err + end + end + + local co = config( self, uci or cfg, uci and cfg ) + local so = co:section( section ) + + self.beenthere = { } + self.depseen = { } + + if not co:config() then + return false, co:errors() + end + + if so:config() then + return self:_validate_section( so ) + else + return false, ERR.SECT_NOTFOUND(so) + end +end + +--- Validate given config option. +-- @param config Name of the configuration to validate +-- @param section Name of the section to validate +-- @param option Name of the option to validate +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate_option( self, cfg, section, option, uci ) + + if not self.packages[cfg] then + local ok, err = self:read_scheme( cfg ) + if not ok then + return false, err + end + end + + local co = config( self, uci or cfg, uci and cfg ) + local so = co:section( section ) + local oo = so:option( option ) + + if not co:config() then + return false, co:errors() + end + + if so:config() and oo:config() then + return self:_validate_option( oo ) + else + return false, ERR.OPT_NOTFOUND(oo) + end +end + + +function UVL._validate_section( self, section ) + + self.beenthere[section:cid()] = true + + if section:config() then + if section:scheme('named') == true and + section:config('.anonymous') == true + then + return false, ERR.SECT_NAMED(section) + end + + for _, v in ipairs(section:variables()) do + local ok, err = self:_validate_option( v ) + if not ok and ( + v:scheme('required') or v:scheme('type') == "enum" or ( + not err:is(ERR.ERR_DEP_NOTEQUAL) and + not err:is(ERR.ERR_DEP_NOVALUE) + ) + ) then + section:error(err) + end + end + + local ok, err = dependencies.check( self, section ) + if not ok then + section:error(err) + end + else + return false, ERR.SECT_NOTFOUND(section) + end + + if STRICT_UNKNOWN_OPTIONS and not section:scheme('dynamic') then + for k, v in pairs(section:config()) do + local oo = section:option(k) + if k:sub(1,1) ~= "." and not self.beenthere[oo:cid()] then + section:error(ERR.OPT_UNKNOWN(oo)) + end + end + end + + return section:ok(), section:errors() +end + +function UVL._validate_option( self, option, nodeps ) + + self.beenthere[option:cid()] = true + + if not option:scheme() and not option:parent():scheme('dynamic') then + if STRICT_UNKNOWN_OPTIONS then + return false, option:error(ERR.OPT_UNKNOWN(option)) + else + return true + end + + elseif option:scheme() then + if not nodeps then + local ok, err = dependencies.check( self, option ) + if not ok then + if not err:is_all( + ERR.ERR_OPT_REQUIRED, + ERR.ERR_DEP_NOTEQUAL, + ERR.ERR_DEP_NOVALUE + ) then + option:error(err) + return false, option:errors() + else + return true + end + end + end + + if option:scheme('required') and not option:value() then + return false, option:error(ERR.OPT_REQUIRED(option)) + + elseif option:value() then + local val = option:value() + + if option:scheme('type') == "reference" or + option:scheme('type') == "enum" + then + local scheme_values = option:scheme('values') or { } + local config_values = ( type(val) == "table" and val or { val } ) + for _, v in ipairs(config_values) do + if not scheme_values[v] then + return false, option:error( ERR.OPT_BADVALUE( + option, { v, util.serialize_data( + util.keys(scheme_values) + ) } + ) ) + end + end + elseif option:scheme('type') == "list" then + if type(val) ~= "table" and STRICT_LIST_TYPE then + return false, option:error(ERR.OPT_NOTLIST(option)) + end + end + + if option:scheme('datatype') then + local dt = option:scheme('datatype') + + if self.datatypes[dt] then + val = ( type(val) == "table" and val or { val } ) + for i, v in ipairs(val) do + if not self.datatypes[dt]( v ) then + return false, option:error( + ERR.OPT_INVVALUE(option, { v, dt }) + ) + end + end + else + return false, option:error(ERR.OPT_DATATYPE(option, dt)) + end + end + + val = ( type(val) == "table" and val or { val } ) + for _, v in ipairs(val) do + if option:scheme('minlength') then + if #v < option:scheme('minlength') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + if option:scheme('maxlength') then + if #v > option:scheme('maxlength') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + local w = tonumber(v) + + if option:scheme('minimum') then + if not w or w < option:scheme('minimum') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + if option:scheme('maximum') then + if not w or w > option:scheme('maximum') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + end + end + + local ok, err = validation.check( self, option ) + if not ok and STRICT_EXTERNAL_VALIDATORS then + return false, option:error(err) + end + end + + return option:ok(), option:errors() +end + +--- Find all parts of given scheme and construct validation tree. +-- This is normally done on demand, so you don't have to call this function +-- by yourself. +-- @param shm Name of the scheme to parse +-- @param alias Create an alias for the loaded scheme +function UVL.read_scheme( self, shm, alias ) + + local so = scheme( self, shm ) + local bc = "%s/bytecode/%s.lua" %{ self.schemedir, shm } + + if not fs.access(bc) then + local files = fs.glob(self.schemedir .. '/*/' .. shm) + + if files then + local ok, err + for i, file in ipairs( files ) do + if not fs.access(file) then + return false, so:error(ERR.SME_READ(so,file)) + end + + local uci = uci.cursor( fs.dirname(file), default_savedir ) + + local sname = fs.basename(file) + local sd, err = uci:load( sname ) + + if not sd then + return false, ERR.UCILOAD(so, err) + end + + ok, err = pcall(function() + uci:foreach(sname, "package", function(s) + self:_parse_package(so, s[".name"], s) + end) + uci:foreach(sname, "section", function(s) + self:_parse_section(so, s[".name"], s) + end) + uci:foreach(sname, "variable", function(s) + self:_parse_var(so, s[".name"], s) + end) + uci:foreach(sname, "enum", function(s) + self:_parse_enum(so, s[".name"], s) + end) + + end) + end + + if ok and alias then self.packages[alias] = self.packages[shm] end + return ok and self, err + else + return false, so:error(ERR.SME_FIND(so, self.schemedir)) + end + else + local sc = loadfile(bc) + if sc then + self.packages[shm] = sc() + return true + else + return false, so:error(ERR.SME_READ(so,bc)) + end + end +end + +-- helper function to check for required fields +local function _req( t, n, c, r ) + for i, v in ipairs(r) do + if not c[v] then + local p, o = scheme:sid(), nil + + if t == TYPE_SECTION then + o = section( scheme, nil, p, n ) + elseif t == TYPE_OPTION then + o = option( scheme, nil, p, '(nil)', n ) + elseif t == TYPE_ENUM then + o = enum( scheme, nil, p, '(nil)', '(nil)', n ) + end + + return false, ERR.SME_REQFLD(o,v) + end + end + return true +end + +-- helper function to validate references +local function _ref( c, t ) + local r, k, n = {} + if c == TYPE_SECTION then + k = "package" + n = 1 + elseif c == TYPE_OPTION then + k = "section" + n = 2 + elseif c == TYPE_ENUM then + k = "variable" + n = 3 + end + + for o in t[k]:gmatch("[^.]+") do + r[#r+1] = o + end + r[1] = ( #r[1] > 0 and r[1] or scheme:sid() ) + + if #r ~= n then + return false, ERR.SME_BADREF(scheme, k) + end + + return r +end + +-- helper function to read bools +local function _bool( v ) + return ( v == "true" or v == "yes" or v == "on" or v == "1" ) +end + +-- Step 0: get package meta information +function UVL._parse_package(self, scheme, k, v) + local sid = scheme:sid() + local pkg = self.packages[sid] or { + ["name"] = sid; + ["sections"] = { }; + ["variables"] = { }; + } + + pkg.title = v.title + pkg.description = v.description + + self.packages[sid] = pkg +end + +-- Step 1: get all sections +function UVL._parse_section(self, scheme, k, v) + local ok, err = _req( TYPE_SECTION, k, v, { "name", "package" } ) + if err then error(scheme:error(err)) end + + local r, err = _ref( TYPE_SECTION, v ) + if err then error(scheme:error(err)) end + + local p = self.packages[r[1]] or { + ["name"] = r[1]; + ["sections"] = { }; + ["variables"] = { }; + } + p.sections[v.name] = p.sections[v.name] or { } + p.variables[v.name] = p.variables[v.name] or { } + self.packages[r[1]] = p + + local s = p.sections[v.name] + local so = scheme:section(v.name) + + for k, v2 in pairs(v) do + if k ~= "name" and k ~= "package" and k:sub(1,1) ~= "." then + if k == "depends" then + s.depends = self:_read_dependency( v2, s.depends ) + if not s.depends then + return false, scheme:error( + ERR.SME_BADDEP(so, util.serialize_data(s.depends)) + ) + end + elseif k == "dynamic" or k == "unique" or + k == "required" or k == "named" + then + s[k] = _bool(v2) + else + s[k] = v2 + end + end + end + + s.dynamic = s.dynamic or false + s.unique = s.unique or false + s.required = s.required or false + s.named = s.named or false +end + +-- Step 2: get all variables +function UVL._parse_var(self, scheme, k, v) + local ok, err = _req( TYPE_OPTION, k, v, { "name", "section" } ) + if err then error(scheme:error(err)) end + + local r, err = _ref( TYPE_OPTION, v ) + if err then error(scheme:error(err)) end + + local p = self.packages[r[1]] + if not p then + error(scheme:error( + ERR.SME_VBADPACK({scheme:sid(), '', v.name}, r[1]) + )) + end + + local s = p.variables[r[2]] + if not s then + error(scheme:error( + ERR.SME_VBADSECT({scheme:sid(), '', v.name}, r[2]) + )) + end + + s[v.name] = s[v.name] or { } + + local t = s[v.name] + local so = scheme:section(r[2]) + local to = so:option(v.name) + + for k, v2 in pairs(v) do + if k ~= "name" and k ~= "section" and k:sub(1,1) ~= "." then + if k == "depends" then + t.depends = self:_read_dependency( v2, t.depends ) + if not t.depends then + error(scheme:error(so:error( + ERR.SME_BADDEP(to, util.serialize_data(v2)) + ))) + end + elseif k == "validator" then + t.validators = self:_read_validator( v2, t.validators ) + if not t.validators then + error(scheme:error(so:error( + ERR.SME_BADVAL(to, util.serialize_data(v2)) + ))) + end + elseif k == "valueof" then + local values, err = self:_read_reference( v2 ) + if err then + error(scheme:error(so:error( + ERR.REFERENCE(to, util.serialize_data(v2)):child(err) + ))) + end + t.type = "reference" + t.values = values + t.valueof = type(v2) == "table" and v2 or {v2} + elseif k == "required" then + t[k] = _bool(v2) + elseif k == "minlength" or k == "maxlength" or + k == "minimum" or k == "maximum" + then + t[k] = tonumber(v2) + else + t[k] = t[k] or v2 + end + end + end + + t.type = t.type or "variable" + t.datatype = t.datatype or "string" + t.required = t.required or false +end + +-- Step 3: get all enums +function UVL._parse_enum(self, scheme, k, v) + local ok, err = _req( TYPE_ENUM, k, v, { "value", "variable" } ) + if err then error(scheme:error(err)) end + + local r, err = _ref( TYPE_ENUM, v ) + if err then error(scheme:error(err)) end + + local p = self.packages[r[1]] + if not p then + error(scheme:error( + ERR.SME_EBADPACK({scheme:sid(), '', '', v.value}, r[1]) + )) + end + + local s = p.variables[r[2]] + if not s then + error(scheme:error( + ERR.SME_EBADSECT({scheme:sid(), '', '', v.value}, r[2]) + )) + end + + local t = s[r[3]] + if not t then + error(scheme:error( + ERR.SME_EBADOPT({scheme:sid(), '', '', v.value}, r[3]) + )) + end + + + local so = scheme:section(r[2]) + local oo = so:option(r[3]) + local eo = oo:enum(v.value) + + if t.type ~= "enum" and t.type ~= "reference" then + error(scheme:error(ERR.SME_EBADTYPE(eo))) + end + + if not t.values then + t.values = { [v.value] = v.title or v.value } + t.valuelist = { {value = v.value, title = v.title} } + else + t.values[v.value] = v.title or v.value + t.valuelist[#t.valuelist + 1] = {value = v.value, title = v.title} + end + + if not t.enum_depends then + t.enum_depends = { } + end + + if v.default then + if t.default then + error(scheme:error(ERR.SME_EBADDEF(eo))) + end + t.default = v.value + end + + if v.depends then + t.enum_depends[v.value] = self:_read_dependency( + v.depends, t.enum_depends[v.value] + ) + + if not t.enum_depends[v.value] then + error(scheme:error(so:error(oo:error( + ERR.SME_BADDEP(eo, util.serialize_data(v.depends)) + )))) + end + end +end + +-- Read a dependency specification +function UVL._read_dependency( self, values, deps ) + local expr = "%$?[%w_]+" + if values then + values = ( type(values) == "table" and values or { values } ) + for _, value in ipairs(values) do + local condition = { } + for val in value:gmatch("[^,]+") do + local k, e, v = val:match("%s*([%w$_.]+)%s*(=?)%s*(.*)") + + if k and ( + k:match("^"..expr.."%."..expr.."%."..expr.."$") or + k:match("^"..expr.."%."..expr.."$") or + k:match("^"..expr.."$") + ) then + condition[k] = (e == '=') and v or true + else + return nil + end + end + + if not deps then + deps = { condition } + else + deps[#deps+1] = condition + end + end + end + + return deps +end + +-- Read a validator specification +function UVL._read_validator( self, values, validators ) + if values then + values = ( type(values) == "table" and values or { values } ) + for _, value in ipairs(values) do + local validator + + if value:match("^exec:") then + validator = value:gsub("^exec:","") + elseif value:match("^lua:") then + validator = self:_resolve_function( (value:gsub("^lua:","") ) ) + elseif value:match("^regexp:") then + local pattern = value:gsub("^regexp:","") + validator = function( type, dtype, pack, sect, optn, ... ) + local values = { ... } + for _, v in ipairs(values) do + local ok, match = + pcall( string.match, v, pattern ) + + if not ok then + return false, match + elseif not match then + return false, + 'Value "%s" does not match pattern "%s"' % { + v, pattern + } + end + end + return true + end + end + + if validator then + if not validators then + validators = { validator } + else + validators[#validators+1] = validator + end + else + return nil + end + end + + return validators + end +end + +-- Read a reference specification (XXX: We should validate external configs too...) +function UVL._read_reference( self, values ) + local val = { } + values = ( type(values) == "table" and values or { values } ) + + for _, value in ipairs(values) do + local ref = util.split(value, ".") + + if #ref == 2 or #ref == 3 then + local co = config( self, ref[1] ) + if not co:config() then return false, co:errors() end + + for k, v in pairs(co:config()) do + if v['.type'] == ref[2] then + if #ref == 2 then + if v['.anonymous'] == true then + return false, ERR.SME_INVREF('', value) + end + val[k] = k -- XXX: title/description would be nice + elseif v[ref[3]] then + val[v[ref[3]]] = v[ref[3]] -- XXX: dito + end + end + end + else + return false, ERR.SME_BADREF('', value) + end + end + + return val, nil +end + +-- Resolve given path +function UVL._resolve_function( self, value ) + local path = util.split(value, ".") + + for i=1, #path-1 do + local stat, mod = pcall( + require, table.concat(path, ".", 1, i) + ) + + if stat and mod then + for j=i+1, #path-1 do + if not type(mod) == "table" then + break + end + mod = mod[path[j]] + if not mod then + break + end + end + mod = type(mod) == "table" and mod[path[#path]] or nil + if type(mod) == "function" then + return mod + end + end + end +end + + +--- Object representation of an uvl item - base class. +uvlitem = util.class() + +function uvlitem.cid(self) + if #self.cref == 1 then + return self.cref[1] + else + local r = { unpack(self.cref) } + local c = self.c + if c and c[r[2]] and c[r[2]]['.anonymous'] and c[r[2]]['.index'] then + r[2] = '@' .. c[r[2]]['.type'] .. + '[' .. tostring(c[r[2]]['.index']) .. ']' + end + return table.concat( r, '.' ) + end +end + +function uvlitem.sid(self) + return table.concat( self.sref, '.' ) +end + +function uvlitem.scheme(self, opt) + local s = self.s and self.s.packages + s = s and s[self.sref[1]] + if #self.sref == 4 or #self.sref == 3 then + s = s and s.variables + s = s and s[self.sref[2]] + s = s and s[self.sref[3]] + elseif #self.sref == 2 then + s = s and s.sections + s = s and s[self.sref[2]] + end + + if s and opt then + return s[opt] + elseif s then + return s + end +end + +function uvlitem.config(self, opt) + local c = self.c + + if #self.cref >= 2 and #self.cref <= 4 then + c = c and self.c[self.cref[2]] or nil + if #self.cref >= 3 then + c = c and c[self.cref[3]] or nil + end + end + + if c and opt then + return c[opt] + elseif c then + return c + end +end + +function uvlitem.title(self) + return self:scheme() and self:scheme('title') or + self.cref[3] or self.cref[2] or self.cref[1] +end + +function uvlitem.type(self) + if self.t == TYPE_CONFIG then + return 'config' + elseif self.t == TYPE_SECTION then + return 'section' + elseif self.t == TYPE_OPTION then + return 'option' + elseif self.t == TYPE_ENUM then + return 'enum' + end +end + +function uvlitem.error(self, ...) + if not self.e then + local errconst = { ERR.CONFIG, ERR.SECTION, ERR.OPTION, ERR.OPTION } + self.e = errconst[#self.cref]( self ) + end + + return self.e:child( ... ) +end + +function uvlitem.errors(self) + return self.e +end + +function uvlitem.ok(self) + return not self:errors() +end + +function uvlitem.parent(self) + if self.p then + return self.p + elseif #self.cref == 3 or #self.cref == 4 then + return section( self.s, self.c, self.cref[1], self.cref[2] ) + elseif #self.cref == 2 then + return config( self.s, self.c, self.cref[1] ) + else + return nil + end +end + +function uvlitem._loadconf(self, co, c, configdir) + co = co or self._configcache + if not co then + local err + co, err = uci.cursor(configdir):get_all(c) + + if err then + self:error(ERR.UCILOAD(self, err)) + end + + self._configcache = co + end + return co +end + + +--- Object representation of a scheme. +-- @class scheme +-- @cstyle instance +-- @name luci.uvl.scheme + +--- Scheme instance constructor. +-- @class function +-- @name scheme +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @return Config instance +scheme = util.class(uvlitem) + +function scheme.__init__(self, scheme, co, c) + if not c then + c, co = co, nil + end + + self.cref = { c } + self.sref = { c } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_SCHEME +end + +--- Add an error to scheme. +-- @return Scheme error context +function scheme.error(self, ...) + if not self.e then self.e = ERR.SCHEME( self ) end + return self.e:child( ... ) +end + +--- Get an associated config object. +-- @return Config instance +function scheme.config(self) + local co = config( self.s, self.cref[1] ) + co.p = self + + return co +end + +--- Get all section objects associated with this scheme. +-- @return Table containing all associated luci.uvl.section instances +function scheme.sections(self) + local v = { } + if self.s.packages[self.sref[1]].sections then + for o, _ in pairs( self.s.packages[self.sref[1]].sections ) do + v[#v+1] = option( + self.s, self.c, self.cref[1], self.cref[2], o + ) + end + end + return v +end + +--- Get an associated section object. +-- @param s Section to select +-- @return Section instance +function scheme.section(self, s) + local so = section( self.s, self.c, self.cref[1], s ) + so.p = self + + return so +end + + +--- Object representation of a config. +-- @class config +-- @cstyle instance +-- @name luci.uvl.config + +--- Config instance constructor. +-- @class function +-- @name config +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @return Config instance +config = util.class(uvlitem) + +function config.__init__(self, scheme, co, c) + if not c then + c, co = co, nil + end + self.cref = { c } + self.sref = { c } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_CONFIG +end + +--- Get all section objects associated with this config. +-- @return Table containing all associated luci.uvl.section instances +function config.sections(self) + local v = { } + if self.s.packages[self.sref[1]].sections then + for o, _ in pairs( self.s.packages[self.sref[1]].sections ) do + v[#v+1] = option( + self.s, self.c, self.cref[1], self.cref[2], o + ) + end + end + return v +end + +--- Get an associated section object. +-- @param s Section to select +-- @return Section instance +function config.section(self, s) + local so = section( self.s, self.c, self.cref[1], s ) + so.p = self + + return so +end + + +--- Object representation of a scheme/config section. +-- @class module +-- @cstyle instance +-- @name luci.uvl.section + +--- Section instance constructor. +-- @class function +-- @name section +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @param s Section name +-- @return Section instance +section = util.class(uvlitem) + +function section.__init__(self, scheme, co, c, s) + self.cref = { c, s } + self.sref = { c, co and co[s] and co[s]['.type'] or s } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_SECTION +end + +--- Get all option objects associated with this section. +-- @return Table containing all associated luci.uvl.option instances +function section.variables(self) + local v = { } + if self.s.packages[self.sref[1]].variables[self.sref[2]] then + for o, _ in pairs( + self.s.packages[self.sref[1]].variables[self.sref[2]] + ) do + v[#v+1] = option( + self.s, self.c, self.cref[1], self.cref[2], o + ) + end + end + return v +end + +--- Get an associated option object. +-- @param o Option to select +-- @return Option instance +function section.option(self, o) + local oo = option( self.s, self.c, self.cref[1], self.cref[2], o ) + oo.p = self + + return oo +end + + +--- Object representation of a scheme/config option. +-- @class module +-- @cstyle instance +-- @name luci.uvl.option + +--- Section instance constructor. +-- @class function +-- @name option +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @param s Section name +-- @param o Option name +-- @return Option instance +option = util.class(uvlitem) + +function option.__init__(self, scheme, co, c, s, o) + self.cref = { c, s, o } + self.sref = { c, co and co[s] and co[s]['.type'] or s, o } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_OPTION +end + +--- Get the value of this option. +-- @return The associated configuration value +function option.value(self) + local v = self:config() or self:scheme('default') + if v and self:scheme('multival') then + v = util.split( v, "%s+", nil, true ) + end + return v +end + +--- Get the associated section information in scheme. +-- @return Table containing the scheme properties +function option.section(self) + return self.s.packages[self.sref[1]].sections[self.sref[2]] +end + +--- Construct an enum object instance from given or default value. +-- @param v Value to select +-- @return Enum instance for selected value +function option.enum(self, val) + return enum( + self.s, self.c, + self.cref[1], self.cref[2], self.cref[3], + val or self:value() + ) +end + + +--- Object representation of a enum value. +-- @class module +-- @cstyle instance +-- @name luci.uvl.enum + +--- Section instance constructor. +-- @class function +-- @name enum +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @param s Section name +-- @param o Enum name +-- @param v Enum value +-- @return Enum value instance +enum = util.class(option) + +function enum.__init__(self, scheme, co, c, s, o, v) + self.cref = { c, s, o, v } + self.sref = { c, co and co[s] and co[s]['.type'] or s, o, v } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_ENUM +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/datatypes.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/datatypes.lua new file mode 100644 index 0000000..b6aeb2e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/datatypes.lua @@ -0,0 +1,187 @@ +--[[ + +UCI Validation Layer - Datatype Tests +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: datatypes.lua 3569 2008-10-12 22:38:30Z jow $ + +]]-- + +local fs = require "luci.fs" +local ip = require "luci.ip" +local math = require "math" +local util = require "luci.util" + +local tonumber = tonumber + +module "luci.uvl.datatypes" + + +function boolean( val ) + if val == "1" or val == "yes" or val == "on" or val == "true" then + return true + elseif val == "0" or val == "no" or val == "off" or val == "false" then + return true + elseif val == "" or val == nil then + return true + end + + return false +end + +function uint( val ) + local n = tonumber(val) + if n ~= nil and math.floor(n) == n and n >= 0 then + return true + end + + return false +end + +function integer( val ) + local n = tonumber(val) + if n ~= nil and math.floor(n) == n then + return true + end + + return false +end + +function float( val ) + return ( tonumber(val) ~= nil ) +end + +function ipaddr( val ) + return ip4addr(val) or ip6addr(val) +end + +function ip4addr( val ) + if val then + return ip.IPv4(val) and true or false + end + + return false +end + +function ip4prefix( val ) + val = tonumber(val) + return ( val and val >= 0 and val <= 32 ) +end + +function ip6addr( val ) + if val then + return ip.IPv6(val) and true or false + end + + return false +end + +function ip6prefix( val ) + val = tonumber(val) + return ( val and val >= 0 and val <= 128 ) +end + +function port( val ) + val = tonumber(val) + return ( val and val >= 1 and val <= 65535 ) +end + +function portrange( val ) + local p1, p2 = val:match("^(%d+)%-(%d+)$") + if p1 and p2 and port(p1) and port(p2) then + return true + else + return port(val) + end +end + +function macaddr( val ) + if val and val:match( + "^[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+:" .. + "[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+$" + ) then + local parts = util.split( val, ":" ) + + for i = 1,6 do + parts[i] = tonumber( parts[i], 16 ) + if parts[i] < 0 or parts[i] > 255 then + return false + end + end + + return true + end + + return false +end + +function hostname( val ) + if val and val:match("[a-zA-Z0-9_][a-zA-Z0-9_%-%.]*") then + return true -- XXX: ToDo: need better solution + end + + return false +end + +function host( val ) + return hostname(val) or ipaddr(val) +end + +function string( val ) + return true -- Everything qualifies as valid string +end + +function directory( val, seen ) + local s = fs.stat( val ) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "directory" then + return true + elseif s.type == "link" then + return directory( fs.readlink(val), seen ) + end + end + + return false +end + +function file( val, seen ) + local s = fs.stat( val ) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "regular" then + return true + elseif s.type == "link" then + return file( fs.readlink(val), seen ) + end + end + + return false +end + +function device( val, seen ) + local s = fs.stat( val ) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "character device" or s.type == "block device" then + return true + elseif s.type == "link" then + return device( fs.readlink(val), seen ) + end + end + + return false +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/dependencies.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/dependencies.lua new file mode 100644 index 0000000..567b972 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/dependencies.lua @@ -0,0 +1,196 @@ +--[[ + +UCI Validation Layer - Dependency helper +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: dependencies.lua 3260 2008-09-13 09:09:38Z Cyrus $ + +]]-- + +local uvl = require "luci.uvl" +local ERR = require "luci.uvl.errors" +local util = require "luci.util" +local table = require "table" + +local type, unpack = type, unpack +local ipairs, pairs = ipairs, pairs + +module "luci.uvl.dependencies" + + + +function _parse_reference( r, c, s, o ) + local ref = { } + local vars = { + config = c, + section = s, + option = o + } + + for v in r:gmatch("[^.]+") do + ref[#ref+1] = (v:gsub( "%$(.+)", vars )) + end + + if #ref < 2 then + table.insert(ref, 1, s or '$section') + end + if #ref < 3 then + table.insert(ref, 1, c or '$config') + end + + return ref +end + +function _serialize_dependency( dep, v ) + local str + + for k, v in util.spairs( dep, + function(a,b) + a = ( type(dep[a]) ~= "boolean" and "_" or "" ) .. a + b = ( type(dep[b]) ~= "boolean" and "_" or "" ) .. b + return a < b + end + ) do + str = ( str and str .. " and " or "" ) .. k .. + ( type(v) ~= "boolean" and "=" .. v or "" ) + end + + return str +end + +function check( self, object, nodeps ) + + local derr = ERR.DEPENDENCY(object) + + if not self.depseen[object:cid()] then + self.depseen[object:cid()] = true + else + return false, derr:child(ERR.DEP_RECURSIVE(object)) + end + + if object:scheme('depends') then + local ok = true + local valid = false + + for _, dep in ipairs(object:scheme('depends')) do + local subcondition = true + for k, v in pairs(dep) do + -- XXX: better error + local ref = _parse_reference( k, unpack(object.cref) ) + + if not ref then + return false, derr:child(ERR.SME_BADDEP(object,k)) + end + + local option = uvl.option( self, object.c, unpack(ref) ) + + valid, err = self:_validate_option( option, true ) + if valid then + if not ( + ( type(v) == "boolean" and option:value() ) or + ( ref[3] and option:value() ) == v + ) then + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + derr:child( + type(v) == "boolean" + and ERR.DEP_NOVALUE(option, depstr) + or ERR.DEP_NOTEQUAL(option, {depstr, v}) + ) + + break + end + else + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + derr:child(ERR.DEP_NOTVALID(option, depstr):child(err)) + + break + end + end + + if subcondition then + ok = true + break + else + ok = false + end + end + + if not ok then + return false, derr + end + else + return true + end + + if object:scheme("type") == "enum" and + object:scheme("enum_depends")[object:value()] + then + local ok = true + local valid = false + local enum = object:enum() + local eerr = ERR.DEP_BADENUM(enum) + + for _, dep in ipairs(enum:scheme('enum_depends')[object:value()]) do + local subcondition = true + for k, v in pairs(dep) do + -- XXX: better error + local ref = _parse_reference( k, unpack(object.cref) ) + + if not ref then + return false, derr:child(eerr:child(ERR.SME_BADDEP(enum,k))) + end + + local option = luci.uvl.option( self, object.c, unpack(ref) ) + + valid, err = self:_validate_option( option, true ) + if valid then + if not ( + ( type(v) == "boolean" and object.config[ref[2]][ref[3]] ) or + ( ref[3] and object:config() ) == v + ) then + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + eerr:child( + type(v) == "boolean" + and ERR.DEP_NOVALUE(option, depstr) + or ERR.DEP_NOTEQUAL(option, {depstr, v}) + ) + + break + end + else + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + eerr:child(ERR.DEP_NOTVALID(option, depstr):child(err)) + + break + end + end + + if subcondition then + return true + else + ok = false + end + end + + if not ok then + return false, derr:child(eerr) + end + end + + return true +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/errors.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/errors.lua new file mode 100644 index 0000000..e2a9f2c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/errors.lua @@ -0,0 +1,204 @@ +--[[ + +UCI Validation Layer - Error handling +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: errors.lua 3711 2008-11-04 23:50:14Z jow $ + +]]-- + +local uci = require "luci.model.uci" +local uvl = require "luci.uvl" +local util = require "luci.util" +local string = require "string" + +local ipairs, error, type = ipairs, error, type +local tonumber, unpack = tonumber, unpack + + +local luci = luci + +module "luci.uvl.errors" + +ERRCODES = { + { 'UCILOAD', 'Unable to load config "%p": %1' }, + + { 'SCHEME', 'Error in scheme "%p":\n%c' }, + { 'CONFIG', 'Error in config "%p":\n%c' }, + { 'SECTION', 'Error in section "%i" (%I):\n%c' }, + { 'OPTION', 'Error in option "%i" (%I):\n%c' }, + { 'REFERENCE', 'Option "%i" has invalid reference specification %1:\n%c' }, + { 'DEPENDENCY', 'In dependency check for %t "%i":\n%c' }, + + { 'SME_FIND', 'Can not find scheme "%p" in "%1"' }, + { 'SME_READ', 'Can not access file "%1"' }, + { 'SME_REQFLD', 'Missing required scheme field "%1" in "%i"' }, + { 'SME_INVREF', 'Illegal reference "%1" to an anonymous section' }, + { 'SME_BADREF', 'Malformed reference in "%1"' }, + { 'SME_BADDEP', 'Malformed dependency specification "%1" in "%i"' }, + { 'SME_BADVAL', 'Malformed validator specification "%1" in "%i"' }, + { 'SME_ERRVAL', 'External validator "%1" failed: %2' }, + { 'SME_VBADPACK', 'Variable "%o" in scheme "%p" references unknown package "%1"' }, + { 'SME_VBADSECT', 'Variable "%o" in scheme "%p" references unknown section "%1"' }, + { 'SME_EBADPACK', 'Enum "%v" in scheme "%p" references unknown package "%1"' }, + { 'SME_EBADSECT', 'Enum "%v" in scheme "%p" references unknown section "%1"' }, + { 'SME_EBADOPT', 'Enum "%v" in scheme "%p" references unknown option "%1"' }, + { 'SME_EBADTYPE', 'Enum "%v" in scheme "%p" references non-enum option "%I"' }, + { 'SME_EBADDEF', 'Enum "%v" in scheme "%p" redeclares the default value of "%I"' }, + + { 'SECT_UNKNOWN', 'Section "%i" (%I) not found in scheme' }, + { 'SECT_REQUIRED', 'Required section "%p.%S" not found in config' }, + { 'SECT_UNIQUE', 'Unique section "%p.%S" occurs multiple times in config' }, + { 'SECT_NAMED', 'The section of type "%p.%S" is stored anonymously in config but must be named' }, + { 'SECT_NOTFOUND', 'Section "%p.%s" not found in config' }, + + { 'OPT_UNKNOWN', 'Option "%i" (%I) not found in scheme' }, + { 'OPT_REQUIRED', 'Required option "%i" has no value' }, + { 'OPT_BADVALUE', 'Value "%1" of option "%i" is not defined in enum %2' }, + { 'OPT_INVVALUE', 'Value "%1" of option "%i" does not validate as datatype "%2"' }, + { 'OPT_NOTLIST', 'Option "%i" is defined as list but stored as plain value' }, + { 'OPT_DATATYPE', 'Option "%i" has unknown datatype "%1"' }, + { 'OPT_NOTFOUND', 'Option "%p.%s.%o" not found in config' }, + { 'OPT_RANGE', 'Option "%p.%s.%o" is not within the specified range' }, + + { 'DEP_NOTEQUAL', 'Dependency (%1) failed:\nOption "%i" is not eqal "%2"' }, + { 'DEP_NOVALUE', 'Dependency (%1) failed:\nOption "%i" has no value' }, + { 'DEP_NOTVALID', 'Dependency (%1) failed:\n%c' }, + { 'DEP_RECURSIVE', 'Recursive dependency for option "%i" detected' }, + { 'DEP_BADENUM', 'In dependency check for enum value "%i":\n%c' } +} + +-- build error constants and instance constructors +for i, v in ipairs(ERRCODES) do + _M[v[1]] = function(...) + return error(i, ...) + end + + _M['ERR_'..v[1]] = i +end + + +function i18n(key, def) + if luci.i18n then + return luci.i18n.translate(key,def) + else + return def + end +end + + +error = util.class() + +function error.__init__(self, code, pso, args) + + self.code = code + self.args = ( type(args) == "table" and args or { args } ) + + if util.instanceof( pso, uvl.uvlitem ) then + self.stype = pso.sref[2] + self.package, self.section, self.option, self.value = unpack(pso.cref) + self.object = pso + self.value = self.value or ( pso.value and pso:value() ) + else + pso = ( type(pso) == "table" and pso or { pso } ) + + if pso[2] then + local uci = uci.cursor() + self.stype = uci:get(pso[1], pso[2]) or pso[2] + end + + self.package, self.section, self.option, self.value = unpack(pso) + end +end + +function error.child(self, err) + if not self.childs then + self.childs = { err } + else + self.childs[#self.childs+1] = err + end + return self +end + +function error.string(self,pad) + pad = pad or " " + + local str = i18n( + 'uvl_err_%s' % string.lower(ERRCODES[self.code][1]), + ERRCODES[self.code][2] + ) + :gsub("\n", "\n"..pad) + :gsub("%%i", self:cid()) + :gsub("%%I", self:sid()) + :gsub("%%p", self.package or '(nil)') + :gsub("%%s", self.section or '(nil)') + :gsub("%%S", self.stype or '(nil)') + :gsub("%%o", self.option or '(nil)') + :gsub("%%v", self.value or '(nil)') + :gsub("%%t", self.object and self.object:type() or '(nil)' ) + :gsub("%%T", self.object and self.object:title() or '(nil)' ) + :gsub("%%([1-9])", function(n) return self.args[tonumber(n)] or '(nil)' end) + :gsub("%%c", + function() + local s = "" + for _, err in ipairs(self.childs or {}) do + s = s .. err:string(pad.." ") .. "\n" .. pad + end + return s + end + ) + + return (str:gsub("%s+$","")) +end + +function error.cid(self) + return self.object and self.object:cid() or self.package .. + ( self.section and '.' .. self.section or '' ) .. + ( self.option and '.' .. self.option or '' ) .. + ( self.value and '.' .. self.value or '' ) +end + +function error.sid(self) + return self.object and self.object:sid() or self.package .. + ( self.stype and '.' .. self.stype or '' ) .. + ( self.option and '.' .. self.option or '' ) .. + ( self.value and '.' .. self.value or '' ) +end + +function error.is(self, code) + if self.code == code then + return true + elseif self.childs then + for _, c in ipairs(self.childs) do + if c:is(code) then + return true + end + end + end + return false +end + +function error.is_all(self, ...) + local codes = { ... } + + if util.contains(codes, self.code) then + return true + else + local equal = false + for _, c in ipairs(self.childs) do + if c.childs then + equal = c:is_all(...) + else + equal = util.contains(codes, c.code) + end + end + return equal + end +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/validation.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/validation.lua new file mode 100644 index 0000000..24f2f0c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvl/validation.lua @@ -0,0 +1,72 @@ +--[[ + +UCI Validation Layer - Validation helper +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: validation.lua 3260 2008-09-13 09:09:38Z Cyrus $ + +]]-- + +local os = require "os" +local fs = require "luci.fs" +local sys = require "luci.sys" +local ERR = require "luci.uvl.errors" + +local ipairs, unpack, type, tostring = ipairs, unpack, type, tostring + +module "luci.uvl.validation" + +function _exec( bin, args ) + local cmd, output = "", nil + + for _, v in ipairs({ bin, unpack(args) }) do + cmd = cmd .. ("%q " % v):gsub("([%$`])","\\%1") + end + + local tmpfile = "/tmp/uvl" .. sys.uniqueid(8) + local retval = os.execute( cmd .. " 1>" .. tmpfile .. " 2>" .. tmpfile ) + + if fs.access(tmpfile) then + output = fs.readfile(tmpfile) + fs.unlink(tmpfile) + end + + return retval, output +end + +function check( self, object ) + if object:scheme('validators') then + for _, val in ipairs(object:scheme('validators')) do + local ok, err = false, nil + + local values = object:value() + values = type(values) == "table" and values or { values } + + local args = { + object:scheme('type'), object:scheme('datatype'), + object.cref[1], object.cref[2], object.cref[3] or '', + unpack(values) + } + + if type(val) == "function" then + ok, err = val(unpack(args)) + else + ok, err = _exec( val, args ) + ok = ( ok == 0 ) + end + + if not ok then + return false, ERR.SME_ERRVAL(object, {tostring(val), err}) + end + end + end + + return true, nil +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/footer.xml b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/footer.xml new file mode 100644 index 0000000..4b97469 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/footer.xml @@ -0,0 +1,11 @@ + +
+
+generated on <%=require "os".date("%c")%> with LuCI UVLDoc - written by Steven Barth and Jo-Philipp Wich +
+ +
+
 
+ + + \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/header.xml b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/header.xml new file mode 100644 index 0000000..f4a89b5 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/header.xml @@ -0,0 +1,15 @@ + + + + + + + <% if title then %><%=title%> - <% end %>LuCI UVLDoc + + + + + +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/index.xml b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/index.xml new file mode 100644 index 0000000..a905004 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/index.xml @@ -0,0 +1,12 @@ +<%+header.xml%> +

UCI Documentation

+

Schemes

+ +<% for k, v in luci.util.kspairs(self.schemes) do %> + + + + +<% end %> +
<%=k%><%=self.schemes[k].title%>
+<%+footer.xml%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/menu.xml b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/menu.xml new file mode 100644 index 0000000..c0ad3da --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/menu.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/scheme.xml b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/scheme.xml new file mode 100644 index 0000000..f4fe22e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/scheme.xml @@ -0,0 +1,16 @@ +<%- title = scheme -%> +<%+header.xml%> +

<%=scheme-%> +<%-if package.title then%> - <%=package.title%><%end%>

+
<%=package.description%>
+ +

Sections:

+ +<% for k, v in luci.util.kspairs(package.sections) do %> + + + + +<% end %> +
<%=k%><%=v.title%>
+<%+footer.xml%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/section.xml b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/section.xml new file mode 100644 index 0000000..691fde4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/section.xml @@ -0,0 +1,198 @@ +<%- title = scheme .. "." .. type -%> +<%+header.xml%> +<% +local table = require "table" + +types = { + list = "List", + variable = "Variable", + lazylist = "Mixed", + enum = "Enumerator", + reference = "Reference" +} + +datatypes = { + boolean = "Boolean", + string = "String", + uint = "Unsigned Integer", + integer = "Integer", + float = "Real Number", + ipaddr = "IP-Address", + ip4addr = "IPv4-Address", + ip6addr = "IPv6-Address", + ip4prefix = "IPv4-Prefix", + ip6prefix = "IPv6-Prefix", + hostname = "Hostname", + host = "Host (Hostname or IP-Address)", + directory = "Filesystem path (to directory)", + file = "Filesystem path (to file)", + macaddr = "MAC-Address", + port = "Port", + portrange = "Single Port or Portrange (First-Last)" +} + +function _parse_ref( r ) + local k, v, h = r:match("([^.]+)%.([^.]+)%.([^.]+)") + if not k then + k, v = r:match("([^.]+)%.([^.]+)") + end + if k then + if h then + return self:_variable_target(k, v, h), true + else + return self:_section_filename(k, v) + end + end +end + +function _parse_dep( r, c, s, o ) + local ref = { } + local vars = { + config = c, + section = s, + option = o + } + + for v in r:gmatch("[^.]+") do + ref[#ref+1] = (v:gsub( "%$(.+)", vars )) + end + + if #ref < 2 then + table.insert(ref, 1, s or '$section') + end + if #ref < 3 then + table.insert(ref, 1, c or '$config') + end + + return self:_variable_target(unpack(ref)) +end + +%> + +

<%=scheme-%> +<%-if package.title then%> - <%=package.title%><%end%>

+

<%=type-%> +<%-if section.title then%> - <%=section.title%><%end%>

+
<%=section.description%>
+ +

Attributes:

+
    +<%- +if section.required then %> +
  • required: A section of this type is required.
  • +<% end +if section.unique then %> +
  • unique: There can be only one section of this type.
  • +<%- else -%> +
  • multiple: There can be more than one section of this type.
  • +<% end +if section.dynamic then %> +
  • dynamic: Sections of this type may contain user-defined options.
  • +<% end +if section.named then %> +
  • named: Sections of this type require a name.
  • +<% end -%> +
+ +<% if section.depends then %> +

Requirements (one of):

+
    + <% for i, d in ipairs(section.depends) do + local nf = false%> +
  • + <% for k2, v in luci.util.kspairs(d) do + local t = _parse_dep(k2, scheme, type) + %> + <% if nf then %>and<% end %> + <%if t then%><%end%><%=k2%><%if t then%><%end%><%if v~=true then%>=<%=v%><%end%> + <% nf = true + end %> +
  • + <% end %> +
+<% end %> + +

Variable Overview:

+ +<% for k, v in luci.util.kspairs(package.variables[type]) do +if v.required then%> + + + + +<% end end +for k, v in luci.util.kspairs(package.variables[type]) do +if not v.required then%> + + + + +<% end end %> +
<%=k%><%=v.title%>
<%=k%><%=v.title%>
+ +

Options:

+<%- +for i=0, 1 do +for k, v in luci.util.kspairs(package.variables[type]) do +if (i==0) == v.required then +%> +
+
+ +

<%=k-%> + <%-if v.title then%> - <%=v.title%><%end%>

+
+
<%=v.description%>
+
Attributes:
+
    + <% if v.required then %> +
  • required
  • + <% end %> +
  • Type: <%=types[v.type] or v.type%>
  • +
  • Datatype: <%=datatypes[v.datatype] or v.datatype%>
  • + <% if v.multival then %> +
  • multiple values: space-separated
  • + <% end %> +
+ <% if v.depends then %> +
Dependencies (one of):
+
    + <% for i, d in ipairs(v.depends) do + local nf = false %> +
  • + <% for k2, v in luci.util.kspairs(d) do + local t = _parse_dep(k2, scheme, type, k) + %> + <% if nf then %>and<% end %> + <%if t then%><%end%><%=k2%><%if t then%><%end%><%if v~=true then%>=<%=v%><%end%> + <% nf = true + end %> +
  • + <% end %> +
+ <% end %> + <% if v.type == "enum" then %> +
Possible Values:
+
    + <% for k, d in pairs(v.values) do %> +
  • <%=k%><%if d then%> (<%=d%>)<%end%>
  • + <% end %> +
+ <% elseif v.type == "reference" then %> +
Value references:
+
    + <% for k, d in ipairs(v.valueof) do %> +
  • + <% local t, x = _parse_ref(d) + if t then %><%=x and "Value of" or "Section of type"%> <% end %> + <%=d%> + <% if t then%><% end %> +
  • + <% end %> +
+ <% end %> +
+ +
+<% end end end -%> +<%+footer.xml%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/uvldoc.css b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/uvldoc.css new file mode 100644 index 0000000..32a5e96 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/proto/xhtml/uvldoc.css @@ -0,0 +1,135 @@ +body { + font-family: sans-serif; + font-size: 0.85em; + color: #101010; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + font-weight: bold; +} + +h1 { + font-size: 1.5em; +} + +h2 { + font-size: 1.4em; +} + +h3 { + font-size: 1.2em; +} + +h4 { + font-size: 1.1em; +} + +h5 { + font-size: 1.0em; +} + +dfn { + font-weight: normal; + font-size: 0.9em; +} + +table { + border-collapse: collapse; +} + +tr, td, th { + border: 1px solid #e0e0ff; + padding: 3px; +} + +th { + background-color: #f0f0ff; + text-align: left; +} + + +hr { + border: none; + background-color: #cccccc; + height: 1px; +} + +ul, li { + margin-top: 0; +} + +div.clear { + clear: both; +} + +div.variable-declaration { + padding-left: 2em; +} + +div.variable-description { + margin-bottom: 1em; +} + +h3.section-variables { + margin-top: 2em; +} + +h4.variable-title { + margin-bottom: 0; +} + +div#menu { + float: left; + background-color: #f0f0ff; + margin: 0; + padding: 0; + border: 1px solid #e0e0ff; + width: 11.5em; +} + +#menu ul { + list-style-type: none; + margin-bottom: 0.5em; + padding-left: 1em; +} +#menu ul li { + margin-left: 0; + +} + +div.menu-title { + background-color: #e0e0ff; + color: #000000; + font-weight: bold; + padding: 2px; +} + +div#content { + margin-top: 0; + padding-top: 0; + margin-left: 12.5em; +} + +div#copy { + margin-top: 2.5em; + font-size: 0.7em; + text-align: center; + font-size: bold; +} + +a:link { + font-weight: bold; + color: #004080; + text-decoration: none; +} + +a:visited { + font-weight:bold; + color: #006699; + text-decoration: none; +} + +a:hover { + text-decoration:underline; +} diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/renderer.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/renderer.lua new file mode 100644 index 0000000..d005ba3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/uvldoc/renderer.lua @@ -0,0 +1,124 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ +]]-- + +local io = require "io" +local fs = require "luci.fs" +local uvl = require "luci.uvl" +local util = require "luci.util" +local ltn12 = require "luci.ltn12" +local template = require "luci.template" + +local ipairs, getfenv, pairs, require, unpack = ipairs, getfenv, pairs, require, unpack +local luci = luci + +module "luci.uvldoc.renderer" + + +Generator = util.class() + +function Generator.__init__(self, schemes, output, uvlpath) + self.names = schemes + self.output = output or "doc" + self.schemes = {} + self.uvl = uvl.UVL() + + self.extension = ".xml" + self.additionals = {"uvldoc.css"} + self.sourcedir = util.libpath() .. "/uvldoc/proto/xhtml/" +end + + +function Generator.make(self) + for i, scheme in ipairs(self.names) do + self.schemes[scheme] = self.uvl:get_scheme(scheme) + end + + fs.mkdir(self.output) + + for i, file in ipairs(self.additionals) do + fs.copy(self.sourcedir .. file, self.output .. "/" .. file) + end + + template.compiler_mode = "memory" + template.viewdir = self.sourcedir + template.context.viewns = { + include = function(name) template.Template(name):render(getfenv(2)) end, + pairs = pairs, + ipairs = ipairs, + unpack = unpack, + luci = luci, + require = require + } + + self:_make_index() + + for scheme, package in pairs(self.schemes) do + self:_make_package(scheme) + for type, section in pairs(package.sections) do + self:_make_section(scheme, type) + end + end +end + +function Generator._make_index(self) + local t = template.Template("index.xml") + local sink = ltn12.sink.file( + io.open(self.output .. "/" .. self:_index_filename(), "w") + ) + t:render({self = self, write = sink}) + sink() +end + +function Generator._make_package(self, scheme) + local t = template.Template("scheme.xml") + local sink = ltn12.sink.file( + io.open(self.output .. "/" .. self:_scheme_filename(scheme), "w") + ) + t:render({self = self, package = self.schemes[scheme], scheme = scheme, write = sink}) + sink() +end + +function Generator._make_section(self, scheme, section) + local t = template.Template("section.xml") + local sink = ltn12.sink.file( + io.open(self.output .. "/" .. self:_section_filename(scheme, section), "w") + ) + local pkg = self.schemes[scheme] + t:render({self = self, package = pkg, + scheme = scheme, type=section, section=pkg.sections[section], + write = sink}) + sink() +end + +function Generator._index_filename(self) + return "index%s" % self.extension +end + +function Generator._scheme_filename(self, scheme) + return "scheme.%s%s" % {scheme, self.extension} +end + +function Generator._section_filename(self, scheme, section) + if self.schemes[scheme] and self.schemes[scheme].sections[section] then + return "section.%s.%s%s" % {scheme, section, self.extension} + end +end + +function Generator._variable_target(self, scheme, section, variable) + if self.schemes[scheme] and self.schemes[scheme].variables[section] and + self.schemes[scheme].variables[section][variable] then + return "section.%s.%s%s#variable.%s" % {scheme, section, self.extension, variable} + end +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/version.lua b/openwrt/packages/luci/host/usr/lib/lua/luci/version.lua new file mode 100644 index 0000000..9e5cb71 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/version.lua @@ -0,0 +1,12 @@ +--[[ +LuCI - Lua Configuration Interface +Version definition - do not edit this file +]]-- + +module "luci.version" + +distname = "Host System" +distversion = "SDK" + +luciname = "LuCI" +luciversion = "SVN" diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/about.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/about.htm new file mode 100644 index 0000000..5de651f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/about.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: about.htm 3650 2008-10-29 19:40:40Z jow $ + +-%> +<%+header%> +

<%:about%> LuCI

+

<%:c_lucidesc%>

+ +

<%:c_projecthome%>: luci.freifunk-halle.net

+ +
+

<%:c_leaddev%>

+ +
+ +

<%:c_contributors%>

+ +
+ +

<%:c_thanksto%>

+
    +
  • Mono (Freifunk Halle)
  • +
  • tetzlav (Freifunk Leipzig)
  • +
  • Mickey Knox (Freifunk Hannover)
  • +
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_index/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_index/index.htm new file mode 100644 index 0000000..2f935ee --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_index/index.htm @@ -0,0 +1,24 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:a_i_i_hello%>

+

<%:a_i_i_admin1%>

+

<%:a_i_i_admin2%>
+<%:a_i_i_admin3%>

+

<%:a_i_i_admin4%>

+

<%:a_i_i_admin5%>

+

<%:a_i_i_admin6%>

+

<%:a_i_i_team%>

+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_services/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_services/index.htm new file mode 100644 index 0000000..a892d13 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_services/index.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:services%>

+

<%:a_srv_services1%>

+

<%:a_srv_services2%>

+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/index.htm new file mode 100644 index 0000000..3225753 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/index.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> + +

<%:stat_statistics Statistics%>

+ +

<%:stat_desc The statistics package is based on Collectd +and uses RRD Tool to render diagram images from collected data.%>

+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/networkplugins.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/networkplugins.htm new file mode 100644 index 0000000..0c7b448 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/networkplugins.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: networkplugins.htm 3987 2009-01-02 21:35:25Z Cyrus $ + +-%> +<%+header%> + +

<%:stat_networkplugins Network plugins%>

+ +

<%:stat_networkplugins_desc Network plugins are used to collect information +about open tcp connections, interface traffic, iptables rules etc.%>

+ +

<%:stat_networkplugins_installed Installed network plugins:%> +

    + <% for plugin, desc in pairs(plugins) do %> + <% if luci.fs.access("/usr/lib/collectd/" .. plugin .. ".so") then %> +
  • <%=desc%>
  • + <% end %> + <% end %> +
+

+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/outputplugins.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/outputplugins.htm new file mode 100644 index 0000000..18f7103 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/outputplugins.htm @@ -0,0 +1,33 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: outputplugins.htm 3987 2009-01-02 21:35:25Z Cyrus $ + +-%> +<%+header%> + +

<%:stat_outputplugins Output plugins%>

+ +

<%:stat_outputplugins_desc Output plugins provide different possibilities to store collected data. +It is possible to enable multiple plugin at one, for example to store collected data in rrd databases +and to transmit the data over the network to other collectd instances.%>

+ +

<%:stat_outputplugins_installed Installed output plugins:%> +

    + <% for plugin, desc in pairs(plugins) do %> + <% if luci.fs.access("/usr/lib/collectd/" .. plugin .. ".so") then %> +
  • <%=desc%>
  • + <% end %> + <% end %> +
+

+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/systemplugins.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/systemplugins.htm new file mode 100644 index 0000000..547a9fc --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_statistics/systemplugins.htm @@ -0,0 +1,29 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: systemplugins.htm 3987 2009-01-02 21:35:25Z Cyrus $ + +-%> +<%+header%> + +

<%:stat_systemplugins System plugins%>

+ +

<%:stat_systemplugins_desc System plugins collecting values about system state and ressource usage on the device.:%> +

    + <% for plugin, desc in pairs(plugins) do %> + <% if luci.fs.access("/usr/lib/collectd/" .. plugin .. ".so") then %> +
  • <%=desc%>
  • + <% end %> + <% end %> +
+

+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/dmesg.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/dmesg.htm new file mode 100644 index 0000000..4fa8673 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/dmesg.htm @@ -0,0 +1,20 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: syslog.htm 3622 2008-10-23 16:05:55Z jow $ + +-%> +<%+header%> +

<%:dmesg%>

+
+ +
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/index.htm new file mode 100644 index 0000000..4a3d938 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/index.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:status%>

+

<%:a_st_i_status1%>

+

<%:a_st_i_status2%>

+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/syslog.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/syslog.htm new file mode 100644 index 0000000..1da1c84 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_status/syslog.htm @@ -0,0 +1,20 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: syslog.htm 3792 2008-11-16 22:46:25Z jow $ + +-%> +<%+header%> +

<%:syslog%>

+
+ +
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/applyreboot.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/applyreboot.htm new file mode 100644 index 0000000..73cf4a7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/applyreboot.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: applyreboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+
+

<% if msg then %><%=msg%><% else %><%:a_s_applyreboot1%><% end %>

+

<%:a_s_reboot_running%>

+ +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/backup.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/backup.htm new file mode 100644 index 0000000..3162e73 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/backup.htm @@ -0,0 +1,40 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: backup.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_backup%>

+

<%:a_s_backup1%>

+
+
+ +
+ +
+ +
+
<%:a_s_backup_archive%>:
+
+ +
+
+ +
+
+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/ipkg.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/ipkg.htm new file mode 100644 index 0000000..2ebebfd --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/ipkg.htm @@ -0,0 +1,18 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ipkg.htm 2819 2008-08-14 17:16:56Z Cyrus $ + +-%> +
    +
  • <%:a_s_p_ipkg_pkglists%>: src Name URL
  • +
  • <%:a_s_p_ipkg_targets%>: dest Name Pfad
  • +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/packages.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/packages.htm new file mode 100644 index 0000000..de71a68 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/packages.htm @@ -0,0 +1,98 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: packages.htm 4065 2009-01-17 13:21:50Z Cyrus $ + +-%> +<%- +local rowcnt = 1 +function rowstyle() + rowcnt = rowcnt + 1 + return (rowcnt % 2) + 1 +end +-%> +<%+header%> +

<%:system%>

+

<%:a_s_packages%>

+ +
+ +<% if install or remove or update or upgrade then %> +
<%:status%>:
+<% if update then %> + <%:a_s_packages_update%>: <% if update == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=update%>)<% end %>
+<% end %> +<% if upgrade then%> + <%:a_s_packages_upgrade%>: <% if upgrade == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=upgrade%>)<% end %>
+<% end %> +<% if install then for k,v in pairs(install) do %> + <%:a_s_packages_install%> '<%=k%>': <% if v == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=v%>)<% end %>
+<% end end %> +<% if remove then for k,v in pairs(remove) do %> + <%:a_s_packages_remove%> '<%=k%>': <% if v == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=v%>)<% end %>
+<% end end %> +
+
+<% end %> + +
+
+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+ + + + + + + + + + <% for k, pkg in pairs(pkgs) do %> + + + + + + + + <% end %> +
<%:a_s_packages_name%><%:version%><%:install%><%:delete%><%:descr%>
<%=luci.util.pcdata(pkg.Package)%><%=luci.util.pcdata(pkg.Version)%><% if not pkg.Status or not pkg.Status.installed then %><% else %><%:installed%><% end %><% if pkg.Status and pkg.Status.installed then %><% else %><%:notinstalled%><% end %><%=luci.util.pcdata(pkg.Description)%>
+ +
+ +
+ +
+
+
+
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/reboot.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/reboot.htm new file mode 100644 index 0000000..115a918 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/reboot.htm @@ -0,0 +1,33 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: reboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:reboot%>

+

<%:a_s_reboot1%>

+<%- +local c = require("luci.model.uci").cursor():changes() +if c and next(c) then +-%> +

<%:a_s_reboot_u%>

+<%- +end +if not reboot then +-%> +

<%:a_s_reboot_do%>

+<%- else -%> +

<%:a_s_reboot_running%>

+ +<%- end -%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/upgrade.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/upgrade.htm new file mode 100644 index 0000000..080aa07 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_system/upgrade.htm @@ -0,0 +1,52 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upgrade.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_flash%>

+

<%:a_s_flash_upgrade1%>

+
+<% if sysupgrade and not ret then %> +
+
<%:a_s_flash_fwimage%>:
+
+ +
+
+ <% if keep_avail then -%> + + <%:a_s_flash_keepcfg%> + <% end -%> +
+
+ +
+
+<% elseif ret then %> +

<%:a_s_flash_received%>

+

<%:a_s_flash_inprogress%>

+ + + <% %> + <% local ret = ret() + if ret == 0 then %> +
<%:a_s_flash_flashed%>
+ <% else %> +
<%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)
+ <% end %> +<% else %> +
<%:a_s_flash_notimplemented%>
+<% end %> +<%+footer%> +<% if ret == 0 then luci.sys.reboot() end %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/apply.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/apply.htm new file mode 100644 index 0000000..ac2dd38 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/apply.htm @@ -0,0 +1,42 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: apply.htm 3871 2008-12-07 21:27:52Z jow $ + +-%> +<%+header%> + +

<%:config%>

+

<%:uci_applied%>:

+ +
+ <%=(changes or "-")%> +
+ +
+
    <%- + local fp = reload() + local line = fp:read() + while line do + write("
  • " .. luci.util.pcdata(line) .. "
  • \n") + line = fp:read() + end + fp:close() + -%>
+
+ +
+
"> + +
+
+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/changes.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/changes.htm new file mode 100644 index 0000000..3e6339b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/changes.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: changes.htm 3871 2008-12-07 21:27:52Z jow $ + +-%> + +<%+header%> + +

<%:config%>

+

<%:changes%>:

+ +
+ <%=changes%> +
+ +
+
+
"> + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/revert.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/revert.htm new file mode 100644 index 0000000..7f58c2a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/admin_uci/revert.htm @@ -0,0 +1,31 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: revert.htm 3871 2008-12-07 21:27:52Z jow $ + +-%> + +<%+header%> + +

<%:config%>

+

<%:uci_reverted%>:

+ +
+ <%=(changes or "-")%> +
+ +
+
"> + +
+
+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/browser.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/browser.htm new file mode 100644 index 0000000..224da0e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/browser.htm @@ -0,0 +1,23 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: browser.htm 3555 2008-10-10 21:52:22Z jow $ + +-%> + +<% + local t = require("luci.tools.webadmin") + local v = self:cfgvalue(section) +-%> +<%+cbi/valueheader%> + /> + '<%=self.default_path and ", '"..self.default_path.."'"%>);return false" alt="<%:cbi_browser%>" title="<%:cbi_browser%>" src="<%=resource%>/cbi/folder.png" style="vertical-align:bottom" /> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/button.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/button.htm new file mode 100644 index 0000000..99c3ba6 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/button.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: button.htm 3652 2008-10-29 19:41:33Z jow $ + +-%> +<%+cbi/valueheader%> + <% if self:cfgvalue(section) ~= false then %> + " type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.title)%> /> + <% else %> + - + <% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valuefooter.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valuefooter.htm new file mode 100644 index 0000000..43ce1c3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valuefooter.htm @@ -0,0 +1,34 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: cell_valuefooter.htm 3340 2008-09-16 15:51:35Z Cyrus $ + +-%> +
+
">
+ + +<% if #self.deps > 0 then -%> + +<%- end %> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valueheader.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valueheader.htm new file mode 100644 index 0000000..5d081e3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/cell_valueheader.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: cell_valueheader.htm 3340 2008-09-16 15:51:35Z Cyrus $ + +-%> + + +
"> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dvalue.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dvalue.htm new file mode 100644 index 0000000..2915a93 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dvalue.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: dvalue.htm 3369 2008-09-19 10:44:35Z Cyrus $ + +-%> + +<%+cbi/valueheader%> +<% if self.href then %><% end -%> + <%=luci.util.pcdata(self:cfgvalue(section))%> +<%- if self.href then %><%end%> +  + +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dynlist.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dynlist.htm new file mode 100644 index 0000000..a23a4eb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/dynlist.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<%+cbi/valueheader%> +<% + local vals = self:cfgvalue(section) or {} + for i=1, #vals + 1 do + local val = vals[i] +%> + /> + <% if i <= #vals then %> + " alt="<%:cbi_del%>" title="<%:cbi_del%>" src="<%=resource%>/cbi/remove.gif" /> + <% else %> + " alt="<%:cbi_add%>" title="<%:cbi_add%>" src="<%=resource%>/cbi/add.gif" /> + <% end %> + <% if #self.keylist > 0 then -%> + + <% end -%> +<% if i <= #vals then %>
+<% end end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/filebrowser.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/filebrowser.htm new file mode 100644 index 0000000..b106d6b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/filebrowser.htm @@ -0,0 +1,122 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: filebrowser.htm 3555 2008-10-10 21:52:22Z jow $ + +-%> + + + + + + Filebrowser - LuCI + + + + + + <% + require("luci.fs") + require("luci.http") + require("luci.dispatcher") + + local field = luci.http.formvalue('field') + local request = luci.dispatcher.context.path + local path = { '' } + + for i = 3, #request do + if request[i] ~= '..' and #request[i] > 0 then + path[#path+1] = request[i] + end + end + + local filepath = table.concat( path, '/' ) + local filestat = luci.fs.stat( filepath ) + local baseurl = luci.dispatcher.build_url('admin', 'filebrowser') + + if filestat and filestat.type == "regular" then + table.remove( path, #path ) + filepath = table.concat( path, '/' ) .. '/' + elseif not ( filestat and filestat.type == "directory" ) then + path = { '' } + filepath = '/' + else + filepath = filepath .. '/' + end + + local entries = luci.fs.dir(filepath) + -%> +
+ Location: + <% for i, dir in ipairs(path) do %> + <% if i == 1 then %> + (root) + <% elseif next(path, i) then %> + <% baseurl = baseurl .. '/' .. dir %> + / <%=dir%> + <% else %> + <% baseurl = baseurl .. '/' .. dir %> + / <%=dir%> + <% end %> + <% end %> +
+ +
+ +
+
    + <% for _, e in luci.util.vspairs(entries) do + local stat = luci.fs.stat(filepath..e) + if e ~= '.' and e ~= '..' and stat and stat.type == 'directory' then + -%> +
  • + Directory + <%=e%>/ +
  • + <% end end -%> + + <% for _, e in luci.util.vspairs(entries) do + local stat = luci.fs.stat(filepath..e) + if stat and stat.type ~= 'directory' then + -%> +
  • + File + <%=e%> +
  • + <% end end -%> +
+
+ + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/footer.htm new file mode 100644 index 0000000..7762124 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/footer.htm @@ -0,0 +1,26 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> + <%- if pageaction then -%> +
+ <% if not autoapply then%> + + <% end %> + + + +
+ <%- end -%> + +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valuefooter.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valuefooter.htm new file mode 100644 index 0000000..32e6d05 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valuefooter.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: full_valuefooter.htm 3657 2008-10-30 02:41:25Z jow $ + +-%> + + <% if self.description and #self.description > 0 then -%> + <% if not luci.util.instanceof( self, luci.cbi.Flag ) then -%> +
+ <%- end %> +
+ <%:help%> + <%=self.description%> +
+ <%- end %> + <%- if self.title and #self.title > 0 then -%> +
+ <%- end -%> + + +<% if #self.deps > 0 then -%> + +<%- end %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valueheader.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valueheader.htm new file mode 100644 index 0000000..dd2eb8e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/full_valueheader.htm @@ -0,0 +1,24 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: full_valueheader.htm 3171 2008-09-06 22:42:55Z jow $ + +-%> + +
"> + <%- if self.title and #self.title > 0 then -%> + +
+ <%- end -%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/fvalue.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/fvalue.htm new file mode 100644 index 0000000..5aade0c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/fvalue.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: fvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> + value="1" /> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/header.htm new file mode 100644 index 0000000..bc40e19 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/header.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> + +<%+header%> +
+
+ + + +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/lvalue.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/lvalue.htm new file mode 100644 index 0000000..90a5ca4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/lvalue.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: lvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + +<% elseif self.widget == "radio" then + local c = 0 + for i, key in pairs(self.keylist) do + c = c + 1 +%> + /> + ><%=self.vallist[i]%>
+<% if c == self.size then c = 0 %>
+<% end end %> +<% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/map.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/map.htm new file mode 100644 index 0000000..23d09a2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/map.htm @@ -0,0 +1,36 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: map.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> + +
+

<%=self.title%>

+
<%=self.description%>
+ <%- if self._apply then -%> +
+ <%:cbi_applying%> +
    <%- + local fp = self._apply() + self._apply = nil + local line = fp:read() + while line do + write("
  • " .. luci.util.pcdata(line) .. "
  • \n") + line = fp:read() + end + fp:close() + -%>
+
+ <%- end -%> + <%- self:render_children() %> +
+
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/mvalue.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/mvalue.htm new file mode 100644 index 0000000..9f1a8f3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/mvalue.htm @@ -0,0 +1,35 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: mvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<% +local v = self:valuelist(section) or {} +%> +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + +<% elseif self.widget == "checkbox" then + local c = 0; + for i, key in pairs(self.keylist) do + c = c + 1 +%> + /> + ><%=self.vallist[i]%>
+<% if c == self.size then c = 0 %>
+<% end end %> +<% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nsection.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nsection.htm new file mode 100644 index 0000000..5042a37 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nsection.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: nsection.htm 3652 2008-10-29 19:41:33Z jow $ + +-%> + +<% if self:cfgvalue(self.section) then section = self.section %> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> + <% if self.description and #self.description > 0 then -%> +
<%=self.description%>
+ <%- end %> + <% if self.addremove then -%> +
+ +
+ <%- end %> +
+ <%+cbi/ucisection%> +
+
+
+<% elseif self.addremove then %> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+ +
+ <%- end %> +<% end %> + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nullsection.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nullsection.htm new file mode 100644 index 0000000..9b2882a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/nullsection.htm @@ -0,0 +1,23 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: nullsection.htm 3340 2008-09-16 15:51:35Z Cyrus $ + +-%> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
+ <% self:render_children(1, scope or {}) %> +
+
+
\ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/simpleform.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/simpleform.htm new file mode 100644 index 0000000..0e9d535 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/simpleform.htm @@ -0,0 +1,46 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: simpleform.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> + + +
+ + +
+
+

<%=self.title%>

+
<%=self.description%>
+ <% self:render_children() %> +
+
+<%- if self.message then %> +
<%=self.message%>
+<%- end %> +<%- if self.errmessage then %> +
<%=self.errmessage%>
+<%- end %> +
+<%- if self.submit ~= false then %> + +<% end %> +<%- if self.reset ~= false then %> + +<% end %> + +
+ diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tblsection.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tblsection.htm new file mode 100644 index 0000000..fb00ed3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tblsection.htm @@ -0,0 +1,135 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tblsection.htm 4051 2009-01-16 20:29:47Z Cyrus $ + +-%> +<%- +local rowcnt = 1 +function rowstyle() + rowcnt = rowcnt + 1 + return (rowcnt % 2) + 1 +end +-%> + + +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+
+ <%- local count = 0 -%> + + + <%- if not self.anonymous then -%> + <%- if self.sectionhead then -%> + + <%- else -%> + + <%- end -%> + <%- end -%> + <%- for i, k in pairs(self.children) do if not k.optional then -%> + + <%- count = count + 1; end; end; if self.extedit or self.addremove then -%> + + <%- count = count + 1; end -%> + + + <%- if not self.anonymous then -%> + <%- if self.sectiondesc then -%> + + <%- else -%> + + <%- end -%> + <%- end -%> + <%- for i, k in pairs(self.children) do if not k.optional then -%> + + <%- end; end; if self.extedit or self.addremove then -%> + + <%- end -%> + + <%- local isempty = true + for i, k in ipairs(self:cfgsections()) do + section = k + isempty = false + scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" } + -%> + + <% if not self.anonymous then -%> + + <%- end %> + + + <%- + for k, node in ipairs(self.children) do + if not node.optional then + node:render(section, scope or {}) + end + end + -%> + + <%- if self.extedit or self.addremove then -%> + + <%- end -%> + + <%- end -%> + + <%- if isempty then -%> + + + + <%- end -%> +
<%=self.sectionhead%>  + <%- if k.titleref then -%><%- end -%> + <%-=k.title-%> + <%- if k.titleref then -%><%- end -%> +  
<%=self.sectiondesc%><%=k.description%>

<%=k%>

+ <%- if self.extedit then -%> + + <%=self.extedit:format(section)%> + <%- elseif type(self.extedit) == "function" then -%> + <%=self:extedit(section)%> + <%- end -%> + " title="<%:edit%>"><%:edit%> + <%- end; if self.addremove then %> + + <%- end -%> +

<%:cbi_sectempty%>
+ + <% if self.error then %> +
+
    <% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%> +
  • <%=luci.util.pcdata(e):gsub("\n","
    ")%>
  • + <%- end end %>
+
+ <% end %> + + <%- if self.addremove then -%> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.anonymous then %> + + <% else %> + <% if self.invalid_cts then -%>
<% end %> + + + <% if self.invalid_cts then -%> +
<%:cbi_invalid%>
+ <%- end %> + <% end %> +
+ <%- end %> + <%- end -%> +
+
+ diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tsection.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tsection.htm new file mode 100644 index 0000000..56a9b4e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tsection.htm @@ -0,0 +1,59 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tsection.htm 3652 2008-10-29 19:41:33Z jow $ + +-%> + +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+ <% local isempty = true for i, k in ipairs(self:cfgsections()) do -%> + <% if self.addremove then -%> +
+ +
+ <%- end %> + <% section = k; isempty = false %> + + <% if not self.anonymous then -%> +

<%=k:upper()%>

+ <%- end %> + +
+ <%+cbi/ucisection%> +
+
+ <%- end %> + + <% if isempty then -%> + <%:cbi_sectempty%>

+ <%- end %> + + <% if self.addremove then -%> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.anonymous then -%> + + <%- else -%> + <% if self.invalid_cts then -%>
<% end %> + + + <% if self.invalid_cts then -%> +
<%:cbi_invalid%>
+ <%- end %> + <%- end %> +
+ <%- end %> + <%- end %> +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tvalue.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tvalue.htm new file mode 100644 index 0000000..0cd3766 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/tvalue.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> + +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/ucisection.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/ucisection.htm new file mode 100644 index 0000000..f4c82a9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/ucisection.htm @@ -0,0 +1,66 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ucisection.htm 3475 2008-09-30 21:13:33Z Cyrus $ + +-%> + +<% self:render_children(section, scope or {}) %> + +<% if self.error and self.error[section] then -%> +
+
    <% for _, e in ipairs(self.error[section]) do %>
  • <%=luci.util.pcdata(e):gsub("\n","
    ")%>
  • <% end %>
+
+<%- end %> + +<% if self.optionals[section] and #self.optionals[section] > 0 or self.dynamic then %> +
+ <% if self.dynamic then %> + + <% if self.optionals[section] and #self.optionals[section] > 0 then %> + + <% end %> + <% else %> + + + <% end %> + +
+<% end %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/upload.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/upload.htm new file mode 100644 index 0000000..b56b84b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/upload.htm @@ -0,0 +1,28 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upload.htm 3530 2008-10-07 15:41:15Z jow $ + +-%> + +<% + local t = require("luci.tools.webadmin") + local v = self:cfgvalue(section) +-%> +<%+cbi/valueheader%> + <% if v then %> + <%:cbi_upload Uploaded File%> (<%=t.byte_format(luci.fs.stat(v).size or 0)%>) + /> + " alt="<%:cbi_replace%>" title="<%:cbi_replace%>" src="<%=resource%>/cbi/reload.gif" /> + <% else %> + /> + <% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/value.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/value.htm new file mode 100644 index 0000000..e6e9948 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/value.htm @@ -0,0 +1,38 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: value.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> + /> + <% if #self.keylist > 0 then -%> + + <% end -%> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valuefooter.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valuefooter.htm new file mode 100644 index 0000000..fd8f97c --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valuefooter.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: valuefooter.htm 2639 2008-07-20 15:16:13Z jow $ + +-%> + +<% include( valuefooter or "cbi/full_valuefooter" ) %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valueheader.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valueheader.htm new file mode 100644 index 0000000..4aa9f07 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/cbi/valueheader.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: valueheader.htm 2639 2008-07-20 15:16:13Z jow $ + +-%> + +<% include( valueheader or "cbi/full_valueheader" ) %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/error404.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/error404.htm new file mode 100644 index 0000000..0942341 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/error404.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: error404.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

404 Not Found

+

Sorry, the object you requested was not found.

+Unable to dispatch: <%=luci.http.request.env.PATH_INFO%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/error500.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/error500.htm new file mode 100644 index 0000000..bfa2e54 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/error500.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: error500.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

500 Internal Server Error

+

Sorry, the server encountered an unexpected error.

+
<%=message%>
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/footer.htm new file mode 100644 index 0000000..fc29595 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/footer.htm @@ -0,0 +1,15 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3655 2008-10-29 19:54:59Z jow $ + +-%> +<% include("themes/" .. theme .. "/footer") %> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/contact.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/contact.htm new file mode 100644 index 0000000..c83cd58 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/contact.htm @@ -0,0 +1,27 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: contact.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +<% local contact = luci.model.uci.cursor():get_all("freifunk", "contact") %> +

<%:contact%>

+ + + + + + + + +
<%:ff_nickname%>:<%=contact.nickname%>
<%:ff_name%>:<%=contact.name%>
<%:ff_mail%>:<%=contact.mail%>
<%:ff_phone%>:<%=contact.phone%>
<%:ff_location%>:<%=contact.location%>
<%:ff_geocoord%>:<%=contact.geo%>
<%:ff_note%>:<%=contact.note%>
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/index.htm new file mode 100644 index 0000000..9f9aff9 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/freifunk/index.htm @@ -0,0 +1,24 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> +<%+header%> +<% local ff = luci.model.uci.cursor():get_all("freifunk") %> +

<%:ff_hellonet%> <%=ff.community.name or 'Freifunk Deutschland'%>!

+

<%:ff_public1%>
+<%:ff_public2%> <%=luci.sys.hostname()%>. <%:ff_public3%> +"> <%=ff.contact.nickname%>.

+

<%:ff_public4%> Freifunk.net.
+<%:ff_public5%> <%=ff.community.name or 'Freifunk'%>.

+

<%:ff_note%>: <%:ff_public6%>

+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/header.htm new file mode 100644 index 0000000..84c6dc4 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/header.htm @@ -0,0 +1,15 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3650 2008-10-29 19:40:40Z jow $ + +-%> +<% include("themes/" .. theme .. "/header") %> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/indexer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/indexer.htm new file mode 100644 index 0000000..363802b --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/indexer.htm @@ -0,0 +1,15 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: indexer.htm 3552 2008-10-10 14:37:53Z Cyrus $ + +-%> +<% include("themes/" .. theme .. "/indexer") %> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/loadavg.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/loadavg.htm new file mode 100644 index 0000000..49f800e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/loadavg.htm @@ -0,0 +1,33 @@ +<%+header%> + + + + + + + + + + +
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/traffic.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/traffic.htm new file mode 100644 index 0000000..f0c194d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/traffic.htm @@ -0,0 +1,66 @@ +<%+header%> + + + + + + + + +<% + local interfaces = { } + local ifnames = {} + local uci = luci.model.uci.cursor_state() + + uci:foreach("network", "interface", + function(s) + if s.ifname ~= "lo" then + table.insert( interfaces, + "'" .. ( s.ifname or s['.name'] ) .. "'" + ) + ifnames[s.ifname or s['.name']] = s['.name'] + end + end + ) +-%> + + + +
+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/wireless.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/wireless.htm new file mode 100644 index 0000000..670d9fb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/livestats/wireless.htm @@ -0,0 +1,43 @@ +<%+header%> + + + + + + + + + + +
+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/applyreboot.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/applyreboot.htm new file mode 100644 index 0000000..73cf4a7 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/applyreboot.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: applyreboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+
+

<% if msg then %><%=msg%><% else %><%:a_s_applyreboot1%><% end %>

+

<%:a_s_reboot_running%>

+ +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/backup.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/backup.htm new file mode 100644 index 0000000..3162e73 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/backup.htm @@ -0,0 +1,40 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: backup.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_backup%>

+

<%:a_s_backup1%>

+
+
+ +
+ +
+ +
+
<%:a_s_backup_archive%>:
+
+ +
+
+ +
+
+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/index.htm new file mode 100644 index 0000000..d7c5bd3 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/index.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 4069 2009-01-17 13:26:07Z Cyrus $ + +-%> +

<%:a_i_i_hello%>

+

<%:a_i_i_admin1%>

+

<%:a_i_i_admin2%>
+<%:a_i_i_admin3%>

+

<%:a_i_i_admin5%>

+

<%:a_i_i_admin6%>

+

<%:a_i_i_team%>

diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/reboot.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/reboot.htm new file mode 100644 index 0000000..f5e3304 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/reboot.htm @@ -0,0 +1,33 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: reboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:reboot%>

+

<%:a_s_reboot1%>

+<%- +local c = require("luci.model.uci").cursor():changes() +if c and next(c) then +-%> +

<%:a_s_reboot_u%>

+<%- +end +if not reboot then +-%> +

<%:a_s_reboot_do%>

+<%- else -%> +

<%:a_s_reboot_running%>

+ +<%- end -%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/upgrade.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/upgrade.htm new file mode 100644 index 0000000..080aa07 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/mini/upgrade.htm @@ -0,0 +1,52 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upgrade.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_flash%>

+

<%:a_s_flash_upgrade1%>

+
+<% if sysupgrade and not ret then %> +
+
<%:a_s_flash_fwimage%>:
+
+ +
+
+ <% if keep_avail then -%> + + <%:a_s_flash_keepcfg%> + <% end -%> +
+
+ +
+
+<% elseif ret then %> +

<%:a_s_flash_received%>

+

<%:a_s_flash_inprogress%>

+ + + <% %> + <% local ret = ret() + if ret == 0 then %> +
<%:a_s_flash_flashed%>
+ <% else %> +
<%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)
+ <% end %> +<% else %> +
<%:a_s_flash_notimplemented%>
+<% end %> +<%+footer%> +<% if ret == 0 then luci.sys.reboot() end %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/public_statistics/graph.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/public_statistics/graph.htm new file mode 100644 index 0000000..83a8b61 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/public_statistics/graph.htm @@ -0,0 +1,39 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: graph.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> + +

<%:stat_statistics Statistics%>

+ +
+ + +
+ +
+
+
+ +
+ <% for i, img in ipairs(images) do %> + +
+ <% end %> +
+ +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash/splash.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash/splash.htm new file mode 100644 index 0000000..b906ec2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash/splash.htm @@ -0,0 +1,47 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: splash.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<% local c = luci.model.uci.cursor():get_all("freifunk", "community") %> + +

Willkommen!

+

+Du bist jetzt mit dem freien Funknetz +<%=c.name%> verbunden.
+Wir sind ein experimentelles Gemeinschaftsnetzwerk, aber kein Internetanbieter. +

+ +

+Ein Zugang ins Internet ist trotzdem möglich, +da einige Freifunker ihre privaten Internetzugänge zur Verfügung stellen. +Diese Zugänge müssen sich hier alle teilen. +Bitte sei Dir dessen bewusst und verhalte Dich dementsprechend: +

    +
  • bitte keine Filesharing-Programme betreiben!
  • +
  • bitte keine unnötigen Downloads oder Streams starten!
  • +
  • bitte keine illegalen Aktivitäten!
  • +
+

+ +

+Wenn Du unsere Idee gut findest, kannst Du uns unterstützen: +

+

+ +

+Mit einem Klick auf <%:accept%> kannst du für <%=c.leasetime%> Stunden +über unser Netz das Internet verwenden. Dann wirst du erneut aufgefordet, diese Bedingungen zu akzeptieren. +

\ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/index.htm new file mode 100644 index 0000000..e2ed857 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/index.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 2539 2008-07-07 22:08:34Z jow $ + +-%> +<%+header%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/splash.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/splash.htm new file mode 100644 index 0000000..7a873cf --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/splash_splash/splash.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: splash.htm 2539 2008-07-07 22:08:34Z jow $ + +-%> +<%+header%> +<%+splash/splash%> +
+ + +
+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/error_olsr.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/error_olsr.htm new file mode 100644 index 0000000..fbb0f11 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/error_olsr.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: error_olsr.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd%>

+

<%:olsrd_error%>

+

<%:olsrd_error_desc%>

+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/hna.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/hna.htm new file mode 100644 index 0000000..5108fe1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/hna.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: hna.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_hna2%>

+

<%:olsrd_hna_desc%>

+
+ + + + + +<% for k, route in ipairs(routes) do %> + + + + +<% end %> +
<%:olsrd_network%><%:olsrd_gateway%>
<%=route.Destination%><%=route.Gateway%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/index.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/index.htm new file mode 100644 index 0000000..e1fa009 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/index.htm @@ -0,0 +1,57 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_links%>

+

<%:olsrd_links_desc%>

+
+ + + + + + + + +<% for k, link in ipairs(links) do + local color = "#bb3333" + + link.Cost = tonumber(link.Cost) or 0 + if link.Cost == 0 then + color = "#bb3333" + elseif link.Cost < 4 then + color = "#00cc00" + elseif link.Cost < 10 then + color = "#ffcb05" + elseif link.Cost < 100 then + color = "#ff6600" + end +%> + + + + + + + +<% end %> +
<%:olsrd_neighbour_ip%><%:olsrd_local_ip%>LQNLQETX
"><%=link["Remote IP"]%><%=link["Local IP"]%><%=link.LQ%><%=link.NLQ%><%=string.format("%.3f", link.Cost)%>
+
+

<%:legend%>:

+
    +
  • LQ: <%:olsrd_links_lq_desc%>
  • +
  • NLQ: <%:olsrd_links_nlq_desc%>
  • +
  • ETX: <%:olsrd_links_etx_desc%>
  • +
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/mid.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/mid.htm new file mode 100644 index 0000000..9a3cf5f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/mid.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: mid.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_mid%>

+

<%:olsrd_mid_desc%>

+
+ + + + + +<% for k, mid in ipairs(mids) do %> + + + + +<% end %> +
<%:olsrd_node%><%:olsrd_mid_aliases%>
"><%=mid["IP address"]%><%=mid.Aliases%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/routes.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/routes.htm new file mode 100644 index 0000000..ae176ae --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/routes.htm @@ -0,0 +1,51 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: routes.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_routes%>

+

<%:olsrd_routes_desc%>

+
+ + + + + + + + +<% for k, route in ipairs(routes) do + local color = "#bb3333" + + route.ETX = tonumber(route.ETX) + if route.ETX == 0 then + color = "#bb3333" + elseif route.ETX < 4 then + color = "#00cc00" + elseif route.ETX < 10 then + color = "#ffcb05" + elseif route.ETX < 100 then + color = "#ff6600" + end +%> + + + + + + + +<% end %> +
<%:olsrd_network%><%:olsrd_gateway%><%:interface%><%:metric%>ETX
<%=route.Destination%><%=route["Gateway IP"]%><%=route.Interface%><%=route.Metric%><%=string.format("%.3f", tonumber(route.ETX) or 0)%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/topology.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/topology.htm new file mode 100644 index 0000000..f827ceb --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/status-olsr/topology.htm @@ -0,0 +1,39 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: topology.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:olsrd_topology%>

+

<%:olsrd_topology_desc%>

+
+ + + + + + + + +<% for k, route in ipairs(routes) do +%> + + + + + + + +<% end %> +
<%:olsrd_node%><%:olsrd_topology_lasthop%>LQILQETX
"><%=route["Dest. IP"]%>"><%=route["Last hop IP"]%><%=route.LQ%><%=route.NLQ%><%=string.format("%.3f", tonumber(route.Cost) or 0)%>
+
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/sysauth.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/sysauth.htm new file mode 100644 index 0000000..0c8cf30 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/sysauth.htm @@ -0,0 +1,49 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: sysauth.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> +<%+header%> +<% luci.i18n.loadc("sysauth") %> + +
"> +
+

<%:sysauth_head%>

+
+ <%:sysauth_prompt%> + <%- if fuser then %> +
<%:sysauth_failed%>
+
+ <% end -%> +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+ + +
+
+<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/footer.htm new file mode 100644 index 0000000..09eff44 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/footer.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 4185 2009-01-30 14:00:35Z jow $ + +-%> +
+
+
+ + + + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/header.htm new file mode 100644 index 0000000..194245f --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/fledermaus/header.htm @@ -0,0 +1,180 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3655 2008-10-29 19:54:59Z jow $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("text/html") + +-%> + + + + + + + <% if node and node.css then %><% end %> + + + <%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + +
+<%:path%>: <% +local c = tree +local url = controller +for k,v in pairs(request) do + if c.nodes and c.nodes[v] then + c = c.nodes[v] + url = url .. "/" .. v + %><%=c.title or v%> <% if k ~= #request then %>» <% end + end +end +%> +
+ + +
+
    <% + for k,node in pairs(tree.nodes) do + if node.title and not node.hidden then %> + class="active"<%end%>><%=node.title%> +<% end + end%> +
+
+ + <% + if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end + %> + + <% end %> + +
+ +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/footer.htm new file mode 100644 index 0000000..c8c630e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/footer.htm @@ -0,0 +1,29 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3464 2008-09-29 19:10:51Z jow $ + +-%> +
+
+ + + + +
+
+ + + + + + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/header.htm new file mode 100644 index 0000000..8ea3058 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk-bno/header.htm @@ -0,0 +1,196 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3529 2008-10-07 13:10:24Z jow $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("text/html") + +-%> + + + + + + + <% if node and node.css then %><% end %> + + + + <%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + +
+
+ +
+
+ + + + +
+<%:path%>: <% +local c = tree +local url = controller +for k,v in pairs(request) do + if c.nodes and c.nodes[v] then + c = c.nodes[v] + url = url .. "/" .. v + %><%=c.title or v%> <% if k ~= #request then %>» <% end + end +end +%> +
+ + +
+
    <% + for k,node in pairs(tree.nodes) do + if node.title and not node.hidden then %> + class="active"<%end%>><%=node.title%> +<% end + end%> +
+
+ + <% + if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end + %> + + <% end %> + +
+
+
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/footer.htm new file mode 100644 index 0000000..c8c630e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/footer.htm @@ -0,0 +1,29 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3464 2008-09-29 19:10:51Z jow $ + +-%> +
+
+
+ + + +
+
+ + + + + + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/header.htm new file mode 100644 index 0000000..13e35fa --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/freifunk/header.htm @@ -0,0 +1,196 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3529 2008-10-07 13:10:24Z jow $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("text/html") + +-%> + + + + + + + <% if node and node.css then %><% end %> + + + + <%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + +
+
+ +
+
+ + + + +
+<%:path%>: <% +local c = tree +local url = controller +for k,v in pairs(request) do + if c.nodes and c.nodes[v] then + c = c.nodes[v] + url = url .. "/" .. v + %><%=c.title or v%> <% if k ~= #request then %>» <% end + end +end +%> +
+ + +
+
    <% + for k,node in pairs(tree.nodes) do + if node.title and not node.hidden then %> + class="active"<%end%>><%=node.title%> +<% end + end%> +
+
+ + <% + if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end + %> + + <% end %> + +
+
+
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/footer.htm new file mode 100644 index 0000000..98d48ad --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/footer.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 4185 2009-01-30 14:00:35Z jow $ + +-%> +
+
+ +

Powered by <%= luci.__appname__ .. " (v" .. luci.__version__ .. ")" %>

+ + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/header.htm new file mode 100644 index 0000000..4e53f99 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt-light/header.htm @@ -0,0 +1,163 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 4079 2009-01-17 17:59:11Z Cyrus $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + + +<% if node and node.css then %> +<% end -%> + + + +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + + + +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/dashboard.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/dashboard.htm new file mode 100644 index 0000000..1e05575 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/dashboard.htm @@ -0,0 +1,46 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<% + local node = luci.dispatcher.context.requested + if node.nodes then +%> +
+<%- + for k, v in luci.util.spairs(node.nodes, function (a,b) + return (node.nodes[a].order or 100) < (node.nodes[b].order or 100) + end) do + if v.title and #v.title > 0 and not v.ignoreindex and (v.index or v.target) then + local csscl = "dashicon di_%s" % (v.style or k) + local iconl = v.icon + local pref = luci.util.clone(luci.dispatcher.context.request) + pref[#pref+1] = k + local target = luci.dispatcher.build_url(unpack(pref)) +%> + +<% + end + end +-%> +
+
+<% +end +%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/footer.htm new file mode 100644 index 0000000..8df68b1 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/footer.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +
+
+ +

Powered by <%= luci.__appname__ .. " (v" .. luci.__version__ .. ")" %>

+ + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/header.htm new file mode 100644 index 0000000..fe18214 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/header.htm @@ -0,0 +1,166 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local disp = node +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + + + +<% if node and node.css then %> +<% end -%> + + + +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + + + +
+<% if disp and disp.subindex then %><%+themes/openwrt.org-oxygen/dashboard%><% end %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/indexer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/indexer.htm new file mode 100644 index 0000000..8ba29e0 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org-oxygen/indexer.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<%+header%> +<%+themes/openwrt.org-oxygen/dashboard%> +<%+footer%> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/footer.htm new file mode 100644 index 0000000..98d48ad --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/footer.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 4185 2009-01-30 14:00:35Z jow $ + +-%> +
+
+ +

Powered by <%= luci.__appname__ .. " (v" .. luci.__version__ .. ")" %>

+ + + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/header.htm new file mode 100644 index 0000000..657d5e8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/openwrt.org/header.htm @@ -0,0 +1,163 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 4079 2009-01-17 17:59:11Z Cyrus $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + + +<% if node and node.css then %> +<% end -%> + + + +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + + + +
diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/dashboard.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/dashboard.htm new file mode 100644 index 0000000..1e05575 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/dashboard.htm @@ -0,0 +1,46 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<% + local node = luci.dispatcher.context.requested + if node.nodes then +%> +
+<%- + for k, v in luci.util.spairs(node.nodes, function (a,b) + return (node.nodes[a].order or 100) < (node.nodes[b].order or 100) + end) do + if v.title and #v.title > 0 and not v.ignoreindex and (v.index or v.target) then + local csscl = "dashicon di_%s" % (v.style or k) + local iconl = v.icon + local pref = luci.util.clone(luci.dispatcher.context.request) + pref[#pref+1] = k + local target = luci.dispatcher.build_url(unpack(pref)) +%> + +<% + end + end +-%> +
+
+<% +end +%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/footer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/footer.htm new file mode 100644 index 0000000..1666ee0 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/footer.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +
+
+ +

Powered by <%= luci.__appname__ .. " (v" .. luci.__version__ .. ")" %>

+ +
+ + diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/header.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/header.htm new file mode 100644 index 0000000..fa86096 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/header.htm @@ -0,0 +1,129 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<% +local hostname = require("luci.sys").hostname() +local crequest = luci.dispatcher.context.request +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + +<% if node and node.css then %> +<% end -%> +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + +
+ + + +<%- +local function ucimenu(prefix, node) + if not node.nodes or node.hidden then + return false + end + local index = {} + local count = 0 + for k, n in pairs(node.nodes) do + if n.title and n.target then + table.insert(index, {name=k, order=n.order or 100}) + count = count + 1 + end + end + + table.sort(index, function(a, b) return a.order < b.order end) + + if count > 0 then + for j, v in pairs(index) do + if #v.name > 0 then + local nnode = node.nodes[v.name] + local href = controller .. prefix .. v.name .. "/" + href = (nnode.query) and href .. luci.http.build_querystring(nnode.query) or href +%> + > <%=nnode.title%> +<%- + end + end +%> + +<% + end +end +%> + + + +<% +if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end +-%> +<% if ucic > 0 then %> +<% end %> +<% end %> + + + +
+<% if node.subindex then %><%+themes/oxygen/dashboard%><% end %> diff --git a/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/indexer.htm b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/indexer.htm new file mode 100644 index 0000000..6e290dd --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/luci/view/themes/oxygen/indexer.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<%+header%> +<%+themes/oxygen/dashboard%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lua/mime.lua b/openwrt/packages/luci/host/usr/lib/lua/mime.lua new file mode 100644 index 0000000..169eda2 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/mime.lua @@ -0,0 +1,87 @@ +----------------------------------------------------------------------------- +-- MIME support for the Lua language. +-- Author: Diego Nehab +-- Conforming to RFCs 2045-2049 +-- RCS ID: $Id: mime.lua,v 1.29 2007/06/11 23:44:54 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local ltn12 = require("ltn12") +local mime = require("mime.core") +local io = require("io") +local string = require("string") +module("mime") + +-- encode, decode and wrap algorithm tables +encodet = {} +decodet = {} +wrapt = {} + +-- creates a function that chooses a filter by name from a given table +local function choose(table) + return function(name, opt1, opt2) + if base.type(name) ~= "string" then + name, opt1, opt2 = "default", name, opt1 + end + local f = table[name or "nil"] + if not f then + base.error("unknown key (" .. base.tostring(name) .. ")", 3) + else return f(opt1, opt2) end + end +end + +-- define the encoding filters +encodet['base64'] = function() + return ltn12.filter.cycle(b64, "") +end + +encodet['quoted-printable'] = function(mode) + return ltn12.filter.cycle(qp, "", + (mode == "binary") and "=0D=0A" or "\r\n") +end + +-- define the decoding filters +decodet['base64'] = function() + return ltn12.filter.cycle(unb64, "") +end + +decodet['quoted-printable'] = function() + return ltn12.filter.cycle(unqp, "") +end + +local function format(chunk) + if chunk then + if chunk == "" then return "''" + else return string.len(chunk) end + else return "nil" end +end + +-- define the line-wrap filters +wrapt['text'] = function(length) + length = length or 76 + return ltn12.filter.cycle(wrp, length, length) +end +wrapt['base64'] = wrapt['text'] +wrapt['default'] = wrapt['text'] + +wrapt['quoted-printable'] = function() + return ltn12.filter.cycle(qpwrp, 76, 76) +end + +-- function that choose the encoding, decoding or wrap algorithm +encode = choose(encodet) +decode = choose(decodet) +wrap = choose(wrapt) + +-- define the end-of-line normalization filter +function normalize(marker) + return ltn12.filter.cycle(eol, 0, marker) +end + +-- high level stuffing filter +function stuff() + return ltn12.filter.cycle(dot, 2) +end diff --git a/openwrt/packages/luci/host/usr/lib/lua/socket.lua b/openwrt/packages/luci/host/usr/lib/lua/socket.lua new file mode 100644 index 0000000..211adcd --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/socket.lua @@ -0,0 +1,133 @@ +----------------------------------------------------------------------------- +-- LuaSocket helper module +-- Author: Diego Nehab +-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local string = require("string") +local math = require("math") +local socket = require("socket.core") +module("socket") + +----------------------------------------------------------------------------- +-- Exported auxiliar functions +----------------------------------------------------------------------------- +function connect(address, port, laddress, lport) + local sock, err = socket.tcp() + if not sock then return nil, err end + if laddress then + local res, err = sock:bind(laddress, lport, -1) + if not res then return nil, err end + end + local res, err = sock:connect(address, port) + if not res then return nil, err end + return sock +end + +function bind(host, port, backlog) + local sock, err = socket.tcp() + if not sock then return nil, err end + sock:setoption("reuseaddr", true) + local res, err = sock:bind(host, port) + if not res then return nil, err end + res, err = sock:listen(backlog) + if not res then return nil, err end + return sock +end + +try = newtry() + +function choose(table) + return function(name, opt1, opt2) + if base.type(name) ~= "string" then + name, opt1, opt2 = "default", name, opt1 + end + local f = table[name or "nil"] + if not f then base.error("unknown key (".. base.tostring(name) ..")", 3) + else return f(opt1, opt2) end + end +end + +----------------------------------------------------------------------------- +-- Socket sources and sinks, conforming to LTN12 +----------------------------------------------------------------------------- +-- create namespaces inside LuaSocket namespace +sourcet = {} +sinkt = {} + +BLOCKSIZE = 2048 + +sinkt["close-when-done"] = function(sock) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function(self, chunk, err) + if not chunk then + sock:close() + return 1 + else return sock:send(chunk) end + end + }) +end + +sinkt["keep-open"] = function(sock) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function(self, chunk, err) + if chunk then return sock:send(chunk) + else return 1 end + end + }) +end + +sinkt["default"] = sinkt["keep-open"] + +sink = choose(sinkt) + +sourcet["by-length"] = function(sock, length) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function() + if length <= 0 then return nil end + local size = math.min(socket.BLOCKSIZE, length) + local chunk, err = sock:receive(size) + if err then return nil, err end + length = length - string.len(chunk) + return chunk + end + }) +end + +sourcet["until-closed"] = function(sock) + local done + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function() + if done then return nil end + local chunk, err, partial = sock:receive(socket.BLOCKSIZE) + if not err then return chunk + elseif err == "closed" then + sock:close() + done = 1 + return partial + else return nil, err end + end + }) +end + + +sourcet["default"] = sourcet["until-closed"] + +source = choose(sourcet) + diff --git a/openwrt/packages/luci/host/usr/lib/lua/socket/ftp.lua b/openwrt/packages/luci/host/usr/lib/lua/socket/ftp.lua new file mode 100644 index 0000000..598f65d --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/socket/ftp.lua @@ -0,0 +1,281 @@ +----------------------------------------------------------------------------- +-- FTP support for the Lua language +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: ftp.lua,v 1.45 2007/07/11 19:25:47 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local table = require("table") +local string = require("string") +local math = require("math") +local socket = require("socket") +local url = require("socket.url") +local tp = require("socket.tp") +local ltn12 = require("ltn12") +module("socket.ftp") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +-- timeout in seconds before the program gives up on a connection +TIMEOUT = 60 +-- default port for ftp service +PORT = 21 +-- this is the default anonymous password. used when no password is +-- provided in url. should be changed to your e-mail. +USER = "ftp" +PASSWORD = "anonymous@anonymous.org" + +----------------------------------------------------------------------------- +-- Low level FTP API +----------------------------------------------------------------------------- +local metat = { __index = {} } + +function open(server, port, create) + local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT, create)) + local f = base.setmetatable({ tp = tp }, metat) + -- make sure everything gets closed in an exception + f.try = socket.newtry(function() f:close() end) + return f +end + +function metat.__index:portconnect() + self.try(self.server:settimeout(TIMEOUT)) + self.data = self.try(self.server:accept()) + self.try(self.data:settimeout(TIMEOUT)) +end + +function metat.__index:pasvconnect() + self.data = self.try(socket.tcp()) + self.try(self.data:settimeout(TIMEOUT)) + self.try(self.data:connect(self.pasvt.ip, self.pasvt.port)) +end + +function metat.__index:login(user, password) + self.try(self.tp:command("user", user or USER)) + local code, reply = self.try(self.tp:check{"2..", 331}) + if code == 331 then + self.try(self.tp:command("pass", password or PASSWORD)) + self.try(self.tp:check("2..")) + end + return 1 +end + +function metat.__index:pasv() + self.try(self.tp:command("pasv")) + local code, reply = self.try(self.tp:check("2..")) + local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" + local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) + self.try(a and b and c and d and p1 and p2, reply) + self.pasvt = { + ip = string.format("%d.%d.%d.%d", a, b, c, d), + port = p1*256 + p2 + } + if self.server then + self.server:close() + self.server = nil + end + return self.pasvt.ip, self.pasvt.port +end + +function metat.__index:port(ip, port) + self.pasvt = nil + if not ip then + ip, port = self.try(self.tp:getcontrol():getsockname()) + self.server = self.try(socket.bind(ip, 0)) + ip, port = self.try(self.server:getsockname()) + self.try(self.server:settimeout(TIMEOUT)) + end + local pl = math.mod(port, 256) + local ph = (port - pl)/256 + local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",") + self.try(self.tp:command("port", arg)) + self.try(self.tp:check("2..")) + return 1 +end + +function metat.__index:send(sendt) + self.try(self.pasvt or self.server, "need port or pasv first") + -- if there is a pasvt table, we already sent a PASV command + -- we just get the data connection into self.data + if self.pasvt then self:pasvconnect() end + -- get the transfer argument and command + local argument = sendt.argument or + url.unescape(string.gsub(sendt.path or "", "^[/\\]", "")) + if argument == "" then argument = nil end + local command = sendt.command or "stor" + -- send the transfer command and check the reply + self.try(self.tp:command(command, argument)) + local code, reply = self.try(self.tp:check{"2..", "1.."}) + -- if there is not a a pasvt table, then there is a server + -- and we already sent a PORT command + if not self.pasvt then self:portconnect() end + -- get the sink, source and step for the transfer + local step = sendt.step or ltn12.pump.step + local readt = {self.tp.c} + local checkstep = function(src, snk) + -- check status in control connection while downloading + local readyt = socket.select(readt, nil, 0) + if readyt[tp] then code = self.try(self.tp:check("2..")) end + return step(src, snk) + end + local sink = socket.sink("close-when-done", self.data) + -- transfer all data and check error + self.try(ltn12.pump.all(sendt.source, sink, checkstep)) + if string.find(code, "1..") then self.try(self.tp:check("2..")) end + -- done with data connection + self.data:close() + -- find out how many bytes were sent + local sent = socket.skip(1, self.data:getstats()) + self.data = nil + return sent +end + +function metat.__index:receive(recvt) + self.try(self.pasvt or self.server, "need port or pasv first") + if self.pasvt then self:pasvconnect() end + local argument = recvt.argument or + url.unescape(string.gsub(recvt.path or "", "^[/\\]", "")) + if argument == "" then argument = nil end + local command = recvt.command or "retr" + self.try(self.tp:command(command, argument)) + local code = self.try(self.tp:check{"1..", "2.."}) + if not self.pasvt then self:portconnect() end + local source = socket.source("until-closed", self.data) + local step = recvt.step or ltn12.pump.step + self.try(ltn12.pump.all(source, recvt.sink, step)) + if string.find(code, "1..") then self.try(self.tp:check("2..")) end + self.data:close() + self.data = nil + return 1 +end + +function metat.__index:cwd(dir) + self.try(self.tp:command("cwd", dir)) + self.try(self.tp:check(250)) + return 1 +end + +function metat.__index:type(type) + self.try(self.tp:command("type", type)) + self.try(self.tp:check(200)) + return 1 +end + +function metat.__index:greet() + local code = self.try(self.tp:check{"1..", "2.."}) + if string.find(code, "1..") then self.try(self.tp:check("2..")) end + return 1 +end + +function metat.__index:quit() + self.try(self.tp:command("quit")) + self.try(self.tp:check("2..")) + return 1 +end + +function metat.__index:close() + if self.data then self.data:close() end + if self.server then self.server:close() end + return self.tp:close() +end + +----------------------------------------------------------------------------- +-- High level FTP API +----------------------------------------------------------------------------- +local function override(t) + if t.url then + local u = url.parse(t.url) + for i,v in base.pairs(t) do + u[i] = v + end + return u + else return t end +end + +local function tput(putt) + putt = override(putt) + socket.try(putt.host, "missing hostname") + local f = open(putt.host, putt.port, putt.create) + f:greet() + f:login(putt.user, putt.password) + if putt.type then f:type(putt.type) end + f:pasv() + local sent = f:send(putt) + f:quit() + f:close() + return sent +end + +local default = { + path = "/", + scheme = "ftp" +} + +local function parse(u) + local t = socket.try(url.parse(u, default)) + socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'") + socket.try(t.host, "missing hostname") + local pat = "^type=(.)$" + if t.params then + t.type = socket.skip(2, string.find(t.params, pat)) + socket.try(t.type == "a" or t.type == "i", + "invalid type '" .. t.type .. "'") + end + return t +end + +local function sput(u, body) + local putt = parse(u) + putt.source = ltn12.source.string(body) + return tput(putt) +end + +put = socket.protect(function(putt, body) + if base.type(putt) == "string" then return sput(putt, body) + else return tput(putt) end +end) + +local function tget(gett) + gett = override(gett) + socket.try(gett.host, "missing hostname") + local f = open(gett.host, gett.port, gett.create) + f:greet() + f:login(gett.user, gett.password) + if gett.type then f:type(gett.type) end + f:pasv() + f:receive(gett) + f:quit() + return f:close() +end + +local function sget(u) + local gett = parse(u) + local t = {} + gett.sink = ltn12.sink.table(t) + tget(gett) + return table.concat(t) +end + +command = socket.protect(function(cmdt) + cmdt = override(cmdt) + socket.try(cmdt.host, "missing hostname") + socket.try(cmdt.command, "missing command") + local f = open(cmdt.host, cmdt.port, cmdt.create) + f:greet() + f:login(cmdt.user, cmdt.password) + f.try(f.tp:command(cmdt.command, cmdt.argument)) + if cmdt.check then f.try(f.tp:check(cmdt.check)) end + f:quit() + return f:close() +end) + +get = socket.protect(function(gett) + if base.type(gett) == "string" then return sget(gett) + else return tget(gett) end +end) + diff --git a/openwrt/packages/luci/host/usr/lib/lua/socket/http.lua b/openwrt/packages/luci/host/usr/lib/lua/socket/http.lua new file mode 100644 index 0000000..ad8db1e --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/socket/http.lua @@ -0,0 +1,350 @@ +----------------------------------------------------------------------------- +-- HTTP/1.1 client support for the Lua language. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: http.lua,v 1.71 2007/10/13 23:55:20 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +------------------------------------------------------------------------------- +local socket = require("socket") +local url = require("socket.url") +local ltn12 = require("ltn12") +local mime = require("mime") +local string = require("string") +local base = _G +local table = require("table") +module("socket.http") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +-- connection timeout in seconds +TIMEOUT = 60 +-- default port for document retrieval +PORT = 80 +-- user agent field sent in request +USERAGENT = socket._VERSION + +----------------------------------------------------------------------------- +-- Reads MIME headers from a connection, unfolding where needed +----------------------------------------------------------------------------- +local function receiveheaders(sock, headers) + local line, name, value, err + headers = headers or {} + -- get first line + line, err = sock:receive() + if err then return nil, err end + -- headers go until a blank line is found + while line ~= "" do + -- get field-name and value + name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) + if not (name and value) then return nil, "malformed reponse headers" end + name = string.lower(name) + -- get next line (value might be folded) + line, err = sock:receive() + if err then return nil, err end + -- unfold any folded values + while string.find(line, "^%s") do + value = value .. line + line = sock:receive() + if err then return nil, err end + end + -- save pair in table + if headers[name] then headers[name] = headers[name] .. ", " .. value + else headers[name] = value end + end + return headers +end + +----------------------------------------------------------------------------- +-- Extra sources and sinks +----------------------------------------------------------------------------- +socket.sourcet["http-chunked"] = function(sock, headers) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function() + -- get chunk size, skip extention + local line, err = sock:receive() + if err then return nil, err end + local size = base.tonumber(string.gsub(line, ";.*", ""), 16) + if not size then return nil, "invalid chunk size" end + -- was it the last chunk? + if size > 0 then + -- if not, get chunk and skip terminating CRLF + local chunk, err, part = sock:receive(size) + if chunk then sock:receive() end + return chunk, err + else + -- if it was, read trailers into headers table + headers, err = receiveheaders(sock, headers) + if not headers then return nil, err end + end + end + }) +end + +socket.sinkt["http-chunked"] = function(sock) + return base.setmetatable({ + getfd = function() return sock:getfd() end, + dirty = function() return sock:dirty() end + }, { + __call = function(self, chunk, err) + if not chunk then return sock:send("0\r\n\r\n") end + local size = string.format("%X\r\n", string.len(chunk)) + return sock:send(size .. chunk .. "\r\n") + end + }) +end + +----------------------------------------------------------------------------- +-- Low level HTTP API +----------------------------------------------------------------------------- +local metat = { __index = {} } + +function open(host, port, create) + -- create socket with user connect function, or with default + local c = socket.try((create or socket.tcp)()) + local h = base.setmetatable({ c = c }, metat) + -- create finalized try + h.try = socket.newtry(function() h:close() end) + -- set timeout before connecting + h.try(c:settimeout(TIMEOUT)) + h.try(c:connect(host, port or PORT)) + -- here everything worked + return h +end + +function metat.__index:sendrequestline(method, uri) + local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri) + return self.try(self.c:send(reqline)) +end + +function metat.__index:sendheaders(headers) + local h = "\r\n" + for i, v in base.pairs(headers) do + h = i .. ": " .. v .. "\r\n" .. h + end + self.try(self.c:send(h)) + return 1 +end + +function metat.__index:sendbody(headers, source, step) + source = source or ltn12.source.empty() + step = step or ltn12.pump.step + -- if we don't know the size in advance, send chunked and hope for the best + local mode = "http-chunked" + if headers["content-length"] then mode = "keep-open" end + return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step)) +end + +function metat.__index:receivestatusline() + local status = self.try(self.c:receive(5)) + -- identify HTTP/0.9 responses, which do not contain a status line + -- this is just a heuristic, but is what the RFC recommends + if status ~= "HTTP/" then return nil, status end + -- otherwise proceed reading a status line + status = self.try(self.c:receive("*l", status)) + local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) + return self.try(base.tonumber(code), status) +end + +function metat.__index:receiveheaders() + return self.try(receiveheaders(self.c)) +end + +function metat.__index:receivebody(headers, sink, step) + sink = sink or ltn12.sink.null() + step = step or ltn12.pump.step + local length = base.tonumber(headers["content-length"]) + local t = headers["transfer-encoding"] -- shortcut + local mode = "default" -- connection close + if t and t ~= "identity" then mode = "http-chunked" + elseif base.tonumber(headers["content-length"]) then mode = "by-length" end + return self.try(ltn12.pump.all(socket.source(mode, self.c, length), + sink, step)) +end + +function metat.__index:receive09body(status, sink, step) + local source = ltn12.source.rewind(socket.source("until-closed", self.c)) + source(status) + return self.try(ltn12.pump.all(source, sink, step)) +end + +function metat.__index:close() + return self.c:close() +end + +----------------------------------------------------------------------------- +-- High level HTTP API +----------------------------------------------------------------------------- +local function adjusturi(reqt) + local u = reqt + -- if there is a proxy, we need the full url. otherwise, just a part. + if not reqt.proxy and not PROXY then + u = { + path = socket.try(reqt.path, "invalid path 'nil'"), + params = reqt.params, + query = reqt.query, + fragment = reqt.fragment + } + end + return url.build(u) +end + +local function adjustproxy(reqt) + local proxy = reqt.proxy or PROXY + if proxy then + proxy = url.parse(proxy) + return proxy.host, proxy.port or 3128 + else + return reqt.host, reqt.port + end +end + +local function adjustheaders(reqt) + -- default headers + local lower = { + ["user-agent"] = USERAGENT, + ["host"] = reqt.host, + ["connection"] = "close, TE", + ["te"] = "trailers" + } + -- if we have authentication information, pass it along + if reqt.user and reqt.password then + lower["authorization"] = + "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password)) + end + -- override with user headers + for i,v in base.pairs(reqt.headers or lower) do + lower[string.lower(i)] = v + end + return lower +end + +-- default url parts +local default = { + host = "", + port = PORT, + path ="/", + scheme = "http" +} + +local function adjustrequest(reqt) + -- parse url if provided + local nreqt = reqt.url and url.parse(reqt.url, default) or {} + -- explicit components override url + for i,v in base.pairs(reqt) do nreqt[i] = v end + if nreqt.port == "" then nreqt.port = 80 end + socket.try(nreqt.host and nreqt.host ~= "", + "invalid host '" .. base.tostring(nreqt.host) .. "'") + -- compute uri if user hasn't overriden + nreqt.uri = reqt.uri or adjusturi(nreqt) + -- ajust host and port if there is a proxy + nreqt.host, nreqt.port = adjustproxy(nreqt) + -- adjust headers in request + nreqt.headers = adjustheaders(nreqt) + return nreqt +end + +local function shouldredirect(reqt, code, headers) + return headers.location and + string.gsub(headers.location, "%s", "") ~= "" and + (reqt.redirect ~= false) and + (code == 301 or code == 302) and + (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") + and (not reqt.nredirects or reqt.nredirects < 5) +end + +local function shouldreceivebody(reqt, code) + if reqt.method == "HEAD" then return nil end + if code == 204 or code == 304 then return nil end + if code >= 100 and code < 200 then return nil end + return 1 +end + +-- forward declarations +local trequest, tredirect + +function tredirect(reqt, location) + local result, code, headers, status = trequest { + -- the RFC says the redirect URL has to be absolute, but some + -- servers do not respect that + url = url.absolute(reqt.url, location), + source = reqt.source, + sink = reqt.sink, + headers = reqt.headers, + proxy = reqt.proxy, + nredirects = (reqt.nredirects or 0) + 1, + create = reqt.create + } + -- pass location header back as a hint we redirected + headers = headers or {} + headers.location = headers.location or location + return result, code, headers, status +end + +function trequest(reqt) + -- we loop until we get what we want, or + -- until we are sure there is no way to get it + local nreqt = adjustrequest(reqt) + local h = open(nreqt.host, nreqt.port, nreqt.create) + -- send request line and headers + h:sendrequestline(nreqt.method, nreqt.uri) + h:sendheaders(nreqt.headers) + -- if there is a body, send it + if nreqt.source then + h:sendbody(nreqt.headers, nreqt.source, nreqt.step) + end + local code, status = h:receivestatusline() + -- if it is an HTTP/0.9 server, simply get the body and we are done + if not code then + h:receive09body(status, nreqt.sink, nreqt.step) + return 1, 200 + end + local headers + -- ignore any 100-continue messages + while code == 100 do + headers = h:receiveheaders() + code, status = h:receivestatusline() + end + headers = h:receiveheaders() + -- at this point we should have a honest reply from the server + -- we can't redirect if we already used the source, so we report the error + if shouldredirect(nreqt, code, headers) and not nreqt.source then + h:close() + return tredirect(reqt, headers.location) + end + -- here we are finally done + if shouldreceivebody(nreqt, code) then + h:receivebody(headers, nreqt.sink, nreqt.step) + end + h:close() + return 1, code, headers, status +end + +local function srequest(u, b) + local t = {} + local reqt = { + url = u, + sink = ltn12.sink.table(t) + } + if b then + reqt.source = ltn12.source.string(b) + reqt.headers = { + ["content-length"] = string.len(b), + ["content-type"] = "application/x-www-form-urlencoded" + } + reqt.method = "POST" + end + local code, headers, status = socket.skip(1, trequest(reqt)) + return table.concat(t), code, headers, status +end + +request = socket.protect(function(reqt, body) + if base.type(reqt) == "string" then return srequest(reqt, body) + else return trequest(reqt) end +end) diff --git a/openwrt/packages/luci/host/usr/lib/lua/socket/smtp.lua b/openwrt/packages/luci/host/usr/lib/lua/socket/smtp.lua new file mode 100644 index 0000000..8f3cfcf --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/socket/smtp.lua @@ -0,0 +1,251 @@ +----------------------------------------------------------------------------- +-- SMTP client support for the Lua language. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: smtp.lua,v 1.46 2007/03/12 04:08:40 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local coroutine = require("coroutine") +local string = require("string") +local math = require("math") +local os = require("os") +local socket = require("socket") +local tp = require("socket.tp") +local ltn12 = require("ltn12") +local mime = require("mime") +module("socket.smtp") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +-- timeout for connection +TIMEOUT = 60 +-- default server used to send e-mails +SERVER = "localhost" +-- default port +PORT = 25 +-- domain used in HELO command and default sendmail +-- If we are under a CGI, try to get from environment +DOMAIN = os.getenv("SERVER_NAME") or "localhost" +-- default time zone (means we don't know) +ZONE = "-0000" + +--------------------------------------------------------------------------- +-- Low level SMTP API +----------------------------------------------------------------------------- +local metat = { __index = {} } + +function metat.__index:greet(domain) + self.try(self.tp:check("2..")) + self.try(self.tp:command("EHLO", domain or DOMAIN)) + return socket.skip(1, self.try(self.tp:check("2.."))) +end + +function metat.__index:mail(from) + self.try(self.tp:command("MAIL", "FROM:" .. from)) + return self.try(self.tp:check("2..")) +end + +function metat.__index:rcpt(to) + self.try(self.tp:command("RCPT", "TO:" .. to)) + return self.try(self.tp:check("2..")) +end + +function metat.__index:data(src, step) + self.try(self.tp:command("DATA")) + self.try(self.tp:check("3..")) + self.try(self.tp:source(src, step)) + self.try(self.tp:send("\r\n.\r\n")) + return self.try(self.tp:check("2..")) +end + +function metat.__index:quit() + self.try(self.tp:command("QUIT")) + return self.try(self.tp:check("2..")) +end + +function metat.__index:close() + return self.tp:close() +end + +function metat.__index:login(user, password) + self.try(self.tp:command("AUTH", "LOGIN")) + self.try(self.tp:check("3..")) + self.try(self.tp:command(mime.b64(user))) + self.try(self.tp:check("3..")) + self.try(self.tp:command(mime.b64(password))) + return self.try(self.tp:check("2..")) +end + +function metat.__index:plain(user, password) + local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password) + self.try(self.tp:command("AUTH", auth)) + return self.try(self.tp:check("2..")) +end + +function metat.__index:auth(user, password, ext) + if not user or not password then return 1 end + if string.find(ext, "AUTH[^\n]+LOGIN") then + return self:login(user, password) + elseif string.find(ext, "AUTH[^\n]+PLAIN") then + return self:plain(user, password) + else + self.try(nil, "authentication not supported") + end +end + +-- send message or throw an exception +function metat.__index:send(mailt) + self:mail(mailt.from) + if base.type(mailt.rcpt) == "table" then + for i,v in base.ipairs(mailt.rcpt) do + self:rcpt(v) + end + else + self:rcpt(mailt.rcpt) + end + self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step) +end + +function open(server, port, create) + local tp = socket.try(tp.connect(server or SERVER, port or PORT, + TIMEOUT, create)) + local s = base.setmetatable({tp = tp}, metat) + -- make sure tp is closed if we get an exception + s.try = socket.newtry(function() + s:close() + end) + return s +end + +-- convert headers to lowercase +local function lower_headers(headers) + local lower = {} + for i,v in base.pairs(headers or lower) do + lower[string.lower(i)] = v + end + return lower +end + +--------------------------------------------------------------------------- +-- Multipart message source +----------------------------------------------------------------------------- +-- returns a hopefully unique mime boundary +local seqno = 0 +local function newboundary() + seqno = seqno + 1 + return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'), + math.random(0, 99999), seqno) +end + +-- send_message forward declaration +local send_message + +-- yield the headers all at once, it's faster +local function send_headers(headers) + local h = "\r\n" + for i,v in base.pairs(headers) do + h = i .. ': ' .. v .. "\r\n" .. h + end + coroutine.yield(h) +end + +-- yield multipart message body from a multipart message table +local function send_multipart(mesgt) + -- make sure we have our boundary and send headers + local bd = newboundary() + local headers = lower_headers(mesgt.headers or {}) + headers['content-type'] = headers['content-type'] or 'multipart/mixed' + headers['content-type'] = headers['content-type'] .. + '; boundary="' .. bd .. '"' + send_headers(headers) + -- send preamble + if mesgt.body.preamble then + coroutine.yield(mesgt.body.preamble) + coroutine.yield("\r\n") + end + -- send each part separated by a boundary + for i, m in base.ipairs(mesgt.body) do + coroutine.yield("\r\n--" .. bd .. "\r\n") + send_message(m) + end + -- send last boundary + coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") + -- send epilogue + if mesgt.body.epilogue then + coroutine.yield(mesgt.body.epilogue) + coroutine.yield("\r\n") + end +end + +-- yield message body from a source +local function send_source(mesgt) + -- make sure we have a content-type + local headers = lower_headers(mesgt.headers or {}) + headers['content-type'] = headers['content-type'] or + 'text/plain; charset="iso-8859-1"' + send_headers(headers) + -- send body from source + while true do + local chunk, err = mesgt.body() + if err then coroutine.yield(nil, err) + elseif chunk then coroutine.yield(chunk) + else break end + end +end + +-- yield message body from a string +local function send_string(mesgt) + -- make sure we have a content-type + local headers = lower_headers(mesgt.headers or {}) + headers['content-type'] = headers['content-type'] or + 'text/plain; charset="iso-8859-1"' + send_headers(headers) + -- send body from string + coroutine.yield(mesgt.body) +end + +-- message source +function send_message(mesgt) + if base.type(mesgt.body) == "table" then send_multipart(mesgt) + elseif base.type(mesgt.body) == "function" then send_source(mesgt) + else send_string(mesgt) end +end + +-- set defaul headers +local function adjust_headers(mesgt) + local lower = lower_headers(mesgt.headers) + lower["date"] = lower["date"] or + os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE) + lower["x-mailer"] = lower["x-mailer"] or socket._VERSION + -- this can't be overriden + lower["mime-version"] = "1.0" + return lower +end + +function message(mesgt) + mesgt.headers = adjust_headers(mesgt) + -- create and return message source + local co = coroutine.create(function() send_message(mesgt) end) + return function() + local ret, a, b = coroutine.resume(co) + if ret then return a, b + else return nil, a end + end +end + +--------------------------------------------------------------------------- +-- High level SMTP API +----------------------------------------------------------------------------- +send = socket.protect(function(mailt) + local s = open(mailt.server, mailt.port, mailt.create) + local ext = s:greet(mailt.domain) + s:auth(mailt.user, mailt.password, ext) + s:send(mailt) + s:quit() + return s:close() +end) diff --git a/openwrt/packages/luci/host/usr/lib/lua/socket/tp.lua b/openwrt/packages/luci/host/usr/lib/lua/socket/tp.lua new file mode 100644 index 0000000..0683869 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/socket/tp.lua @@ -0,0 +1,123 @@ +----------------------------------------------------------------------------- +-- Unified SMTP/FTP subsystem +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: tp.lua,v 1.22 2006/03/14 09:04:15 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module and import dependencies +----------------------------------------------------------------------------- +local base = _G +local string = require("string") +local socket = require("socket") +local ltn12 = require("ltn12") +module("socket.tp") + +----------------------------------------------------------------------------- +-- Program constants +----------------------------------------------------------------------------- +TIMEOUT = 60 + +----------------------------------------------------------------------------- +-- Implementation +----------------------------------------------------------------------------- +-- gets server reply (works for SMTP and FTP) +local function get_reply(c) + local code, current, sep + local line, err = c:receive() + local reply = line + if err then return nil, err end + code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) + if not code then return nil, "invalid server reply" end + if sep == "-" then -- reply is multiline + repeat + line, err = c:receive() + if err then return nil, err end + current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) + reply = reply .. "\n" .. line + -- reply ends with same code + until code == current and sep == " " + end + return code, reply +end + +-- metatable for sock object +local metat = { __index = {} } + +function metat.__index:check(ok) + local code, reply = get_reply(self.c) + if not code then return nil, reply end + if base.type(ok) ~= "function" then + if base.type(ok) == "table" then + for i, v in base.ipairs(ok) do + if string.find(code, v) then + return base.tonumber(code), reply + end + end + return nil, reply + else + if string.find(code, ok) then return base.tonumber(code), reply + else return nil, reply end + end + else return ok(base.tonumber(code), reply) end +end + +function metat.__index:command(cmd, arg) + if arg then + return self.c:send(cmd .. " " .. arg.. "\r\n") + else + return self.c:send(cmd .. "\r\n") + end +end + +function metat.__index:sink(snk, pat) + local chunk, err = c:receive(pat) + return snk(chunk, err) +end + +function metat.__index:send(data) + return self.c:send(data) +end + +function metat.__index:receive(pat) + return self.c:receive(pat) +end + +function metat.__index:getfd() + return self.c:getfd() +end + +function metat.__index:dirty() + return self.c:dirty() +end + +function metat.__index:getcontrol() + return self.c +end + +function metat.__index:source(source, step) + local sink = socket.sink("keep-open", self.c) + local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step) + return ret, err +end + +-- closes the underlying c +function metat.__index:close() + self.c:close() + return 1 +end + +-- connect with server and return c object +function connect(host, port, timeout, create) + local c, e = (create or socket.tcp)() + if not c then return nil, e end + c:settimeout(timeout or TIMEOUT) + local r, e = c:connect(host, port) + if not r then + c:close() + return nil, e + end + return base.setmetatable({c = c}, metat) +end + diff --git a/openwrt/packages/luci/host/usr/lib/lua/socket/url.lua b/openwrt/packages/luci/host/usr/lib/lua/socket/url.lua new file mode 100644 index 0000000..0e31d8a --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lua/socket/url.lua @@ -0,0 +1,297 @@ +----------------------------------------------------------------------------- +-- URI parsing, composition and relative URL resolution +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: url.lua,v 1.38 2006/04/03 04:45:42 diego Exp $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module +----------------------------------------------------------------------------- +local string = require("string") +local base = _G +local table = require("table") +module("socket.url") + +----------------------------------------------------------------------------- +-- Module version +----------------------------------------------------------------------------- +_VERSION = "URL 1.0.1" + +----------------------------------------------------------------------------- +-- Encodes a string into its escaped hexadecimal representation +-- Input +-- s: binary string to be encoded +-- Returns +-- escaped representation of string binary +----------------------------------------------------------------------------- +function escape(s) + return string.gsub(s, "([^A-Za-z0-9_])", function(c) + return string.format("%%%02x", string.byte(c)) + end) +end + +----------------------------------------------------------------------------- +-- Protects a path segment, to prevent it from interfering with the +-- url parsing. +-- Input +-- s: binary string to be encoded +-- Returns +-- escaped representation of string binary +----------------------------------------------------------------------------- +local function make_set(t) + local s = {} + for i,v in base.ipairs(t) do + s[t[i]] = 1 + end + return s +end + +-- these are allowed withing a path segment, along with alphanum +-- other characters must be escaped +local segment_set = make_set { + "-", "_", ".", "!", "~", "*", "'", "(", + ")", ":", "@", "&", "=", "+", "$", ",", +} + +local function protect_segment(s) + return string.gsub(s, "([^A-Za-z0-9_])", function (c) + if segment_set[c] then return c + else return string.format("%%%02x", string.byte(c)) end + end) +end + +----------------------------------------------------------------------------- +-- Encodes a string into its escaped hexadecimal representation +-- Input +-- s: binary string to be encoded +-- Returns +-- escaped representation of string binary +----------------------------------------------------------------------------- +function unescape(s) + return string.gsub(s, "%%(%x%x)", function(hex) + return string.char(base.tonumber(hex, 16)) + end) +end + +----------------------------------------------------------------------------- +-- Builds a path from a base path and a relative path +-- Input +-- base_path +-- relative_path +-- Returns +-- corresponding absolute path +----------------------------------------------------------------------------- +local function absolute_path(base_path, relative_path) + if string.sub(relative_path, 1, 1) == "/" then return relative_path end + local path = string.gsub(base_path, "[^/]*$", "") + path = path .. relative_path + path = string.gsub(path, "([^/]*%./)", function (s) + if s ~= "./" then return s else return "" end + end) + path = string.gsub(path, "/%.$", "/") + local reduced + while reduced ~= path do + reduced = path + path = string.gsub(reduced, "([^/]*/%.%./)", function (s) + if s ~= "../../" then return "" else return s end + end) + end + path = string.gsub(reduced, "([^/]*/%.%.)$", function (s) + if s ~= "../.." then return "" else return s end + end) + return path +end + +----------------------------------------------------------------------------- +-- Parses a url and returns a table with all its parts according to RFC 2396 +-- The following grammar describes the names given to the URL parts +-- ::= :///;?# +-- ::= @: +-- ::= [:] +-- :: = {/} +-- Input +-- url: uniform resource locator of request +-- default: table with default values for each field +-- Returns +-- table with the following fields, where RFC naming conventions have +-- been preserved: +-- scheme, authority, userinfo, user, password, host, port, +-- path, params, query, fragment +-- Obs: +-- the leading '/' in {/} is considered part of +----------------------------------------------------------------------------- +function parse(url, default) + -- initialize default parameters + local parsed = {} + for i,v in base.pairs(default or parsed) do parsed[i] = v end + -- empty url is parsed to nil + if not url or url == "" then return nil, "invalid url" end + -- remove whitespace + -- url = string.gsub(url, "%s", "") + -- get fragment + url = string.gsub(url, "#(.*)$", function(f) + parsed.fragment = f + return "" + end) + -- get scheme + url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", + function(s) parsed.scheme = s; return "" end) + -- get authority + url = string.gsub(url, "^//([^/]*)", function(n) + parsed.authority = n + return "" + end) + -- get query stringing + url = string.gsub(url, "%?(.*)", function(q) + parsed.query = q + return "" + end) + -- get params + url = string.gsub(url, "%;(.*)", function(p) + parsed.params = p + return "" + end) + -- path is whatever was left + if url ~= "" then parsed.path = url end + local authority = parsed.authority + if not authority then return parsed end + authority = string.gsub(authority,"^([^@]*)@", + function(u) parsed.userinfo = u; return "" end) + authority = string.gsub(authority, ":([^:]*)$", + function(p) parsed.port = p; return "" end) + if authority ~= "" then parsed.host = authority end + local userinfo = parsed.userinfo + if not userinfo then return parsed end + userinfo = string.gsub(userinfo, ":([^:]*)$", + function(p) parsed.password = p; return "" end) + parsed.user = userinfo + return parsed +end + +----------------------------------------------------------------------------- +-- Rebuilds a parsed URL from its components. +-- Components are protected if any reserved or unallowed characters are found +-- Input +-- parsed: parsed URL, as returned by parse +-- Returns +-- a stringing with the corresponding URL +----------------------------------------------------------------------------- +function build(parsed) + local ppath = parse_path(parsed.path or "") + local url = build_path(ppath) + if parsed.params then url = url .. ";" .. parsed.params end + if parsed.query then url = url .. "?" .. parsed.query end + local authority = parsed.authority + if parsed.host then + authority = parsed.host + if parsed.port then authority = authority .. ":" .. parsed.port end + local userinfo = parsed.userinfo + if parsed.user then + userinfo = parsed.user + if parsed.password then + userinfo = userinfo .. ":" .. parsed.password + end + end + if userinfo then authority = userinfo .. "@" .. authority end + end + if authority then url = "//" .. authority .. url end + if parsed.scheme then url = parsed.scheme .. ":" .. url end + if parsed.fragment then url = url .. "#" .. parsed.fragment end + -- url = string.gsub(url, "%s", "") + return url +end + +----------------------------------------------------------------------------- +-- Builds a absolute URL from a base and a relative URL according to RFC 2396 +-- Input +-- base_url +-- relative_url +-- Returns +-- corresponding absolute url +----------------------------------------------------------------------------- +function absolute(base_url, relative_url) + if base.type(base_url) == "table" then + base_parsed = base_url + base_url = build(base_parsed) + else + base_parsed = parse(base_url) + end + local relative_parsed = parse(relative_url) + if not base_parsed then return relative_url + elseif not relative_parsed then return base_url + elseif relative_parsed.scheme then return relative_url + else + relative_parsed.scheme = base_parsed.scheme + if not relative_parsed.authority then + relative_parsed.authority = base_parsed.authority + if not relative_parsed.path then + relative_parsed.path = base_parsed.path + if not relative_parsed.params then + relative_parsed.params = base_parsed.params + if not relative_parsed.query then + relative_parsed.query = base_parsed.query + end + end + else + relative_parsed.path = absolute_path(base_parsed.path or "", + relative_parsed.path) + end + end + return build(relative_parsed) + end +end + +----------------------------------------------------------------------------- +-- Breaks a path into its segments, unescaping the segments +-- Input +-- path +-- Returns +-- segment: a table with one entry per segment +----------------------------------------------------------------------------- +function parse_path(path) + local parsed = {} + path = path or "" + --path = string.gsub(path, "%s", "") + string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) + for i = 1, table.getn(parsed) do + parsed[i] = unescape(parsed[i]) + end + if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end + if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end + return parsed +end + +----------------------------------------------------------------------------- +-- Builds a path component from its segments, escaping protected characters. +-- Input +-- parsed: path segments +-- unsafe: if true, segments are not protected before path is built +-- Returns +-- path: corresponding path stringing +----------------------------------------------------------------------------- +function build_path(parsed, unsafe) + local path = "" + local n = table.getn(parsed) + if unsafe then + for i = 1, n-1 do + path = path .. parsed[i] + path = path .. "/" + end + if n > 0 then + path = path .. parsed[n] + if parsed.is_directory then path = path .. "/" end + end + else + for i = 1, n-1 do + path = path .. protect_segment(parsed[i]) + path = path .. "/" + end + if n > 0 then + path = path .. protect_segment(parsed[n]) + if parsed.is_directory then path = path .. "/" end + end + end + if parsed.is_absolute then path = "/" .. path end + return path +end diff --git a/openwrt/packages/luci/host/usr/lib/lucittpd/plugins/httpd.lua b/openwrt/packages/luci/host/usr/lib/lucittpd/plugins/httpd.lua new file mode 100644 index 0000000..e40af98 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lucittpd/plugins/httpd.lua @@ -0,0 +1,34 @@ +function initialize() + local lucittpd = require "luci.ttpd.server" + server = lucittpd.Server(lucittpd.VHost()) +end + +function register() + local filehnd = require "luci.ttpd.handler.file" + local filehandler = filehnd.Simple(os.getenv("LUCI_SYSROOT") .. "/www") + server:get_default_vhost():set_default_handler(filehandler) +end + +function accept() + server:process({ + _read = function(...) + local chunk, err = webuci_read(...) + return chunk or (err and error(err, 0)) + end, + + _write = function(...) + local chunk, err = webuci_write(...) + return chunk or (err and error(err, 0)) + end, + + _close = function(...) + local chunk, err = webuci_close(...) + return chunk or (err and error(err, 0)) + end, + + _sendfile = function(...) + local chunk, err = webuci_sendfile(...) + return chunk or (err and error(err, 0)) + end + }) +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/lib/lucittpd/plugins/luci-webui.lua b/openwrt/packages/luci/host/usr/lib/lucittpd/plugins/luci-webui.lua new file mode 100644 index 0000000..073e567 --- /dev/null +++ b/openwrt/packages/luci/host/usr/lib/lucittpd/plugins/luci-webui.lua @@ -0,0 +1,29 @@ +function initialize() + pcall(function() + local SYSROOT = os.getenv("LUCI_SYSROOT") + require "uci" + require "luci.model.uci".cursor = function(config, save) + return uci.cursor(config or SYSROOT .. "/etc/config", save or SYSROOT .. "/tmp/.uci") + end + + local x = require "luci.uvl".UVL.__init__ + require "luci.uvl".UVL.__init__ = function(self, schemedir) + x(self, schemedir or SYSROOT .. "/lib/uci/schema") + end + + require("luci.sys") + luci.sys.user.checkpasswd = function() return true end + + require "luci.dispatcher" + require "luci.uvl" + require "luci.cbi" + require "luci.template" + require "luci.json" + end) +end + +-- Initialize LuCI +function register() + local lucihnd = require "luci.ttpd.handler.luci" + httpd.server:get_default_vhost():set_handler("/luci", lucihnd.Luci()) +end \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/sbin/ff_olsr_test_gw b/openwrt/packages/luci/host/usr/sbin/ff_olsr_test_gw new file mode 100755 index 0000000..5c47b49 --- /dev/null +++ b/openwrt/packages/luci/host/usr/sbin/ff_olsr_test_gw @@ -0,0 +1,41 @@ +#!/usr/bin/lua +local STRICT = true -- Only delete metric 0 routes +local PINGCMD = "ping -q -I%s -c3 -w3 '%s' >/dev/null 2>&1" +local PINGTRG = {"google.de", "www.de.debian.org", "eu.kernel.org", "freifunk.net"} +local ROUTECMD = "route del default gw '%s' >/dev/null 2>&1" +local THRESHOLD = 3 -- Maximum number of failed tests before dropping the route + +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor_state() +local ucisec = "ff_olsr_test_gw" +local section = nil + +uci:foreach("olsrd", "LoadPlugin", function(s) + if s.library == "olsrd_dyn_gw_plain.so.0.4" and s.ignore ~= "1" then + section = s[".name"] + end +end) + +local droute = sys.net.defaultroute() +if section and droute then -- dyn_gw is enabled and we have a defaultroute, test it + local state = false + + for _, host in ipairs(PINGTRG) do + state = state or (sys.call(PINGCMD % {droute.device, host}) == 0) + end + + if not state and (not STRICT or tonumber(droute.metric) == 0) then + local count = tonumber(uci:get("olsrd", ucisec, "noinet_count")) + if not THRESHOLD or (count and count >= THRESHOLD) then + sys.call(ROUTECMD % droute.gateway:string()) + else + if not count then + uci:set("olsrd", ucisec, "state") + end + uci:set("olsrd", ucisec, "noinet_count", (count or 0) + 1) + uci:save("olsrd") + end + else + uci:revert("olsrd", ucisec) + end +end diff --git a/openwrt/packages/luci/host/usr/sbin/luci-splash b/openwrt/packages/luci/host/usr/sbin/luci-splash new file mode 100755 index 0000000..82662c8 --- /dev/null +++ b/openwrt/packages/luci/host/usr/sbin/luci-splash @@ -0,0 +1,190 @@ +#!/usr/bin/lua + +require("luci.http") +require("luci.util") +require("luci.model.uci") + +-- Init state session +local uci = luci.model.uci.cursor_state() + + +function main(argv) + local cmd = argv[1] + local arg = argv[2] + + if cmd == "status" then + if not arg then + os.exit(1) + end + + if iswhitelisted(arg) then + print("whitelisted") + os.exit(0) + end + + if haslease(arg) then + print("lease") + os.exit(0) + end + + print("unknown") + os.exit(0) + elseif cmd == "add" then + if not arg then + os.exit(1) + end + + if not haslease(arg) then + add_lease(arg) + else + print("already leased!") + os.exit(2) + end + os.exit(0) + elseif cmd == "remove" then + if not arg then + os.exit(1) + end + + remove_lease(arg) + os.exit(0) + elseif cmd == "sync" then + sync() + os.exit(0) + else + print("Usage: " .. argv[0] .. " [MAC]") + os.exit(1) + end +end + +-- Add a lease to state and invoke add_rule +function add_lease(mac) + uci:section("luci_splash", "lease", nil, { + mac = mac, + start = os.time() + }) + add_rule(mac) + + uci:save("luci_splash") +end + + +-- Remove a lease from state and invoke remove_rule +function remove_lease(mac) + mac = mac:lower() + local del = {} + + uci:foreach("luci_splash", "lease", + function (section) + if section.mac:lower() == mac then + table.insert(del, section[".name"]) + end + end) + + for i,j in ipairs(del) do + remove_rule(j) + uci:delete("luci_splash", j) + end + + uci:save("luci_splash") +end + + +-- Add an iptables rule +function add_rule(mac) + return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN") +end + + +-- Remove an iptables rule +function remove_rule(mac) + return os.execute("iptables -t nat -D luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN") +end + + +-- Check whether a MAC-Address is listed in the lease state list +function haslease(mac) + mac = mac:lower() + local stat = false + + uci:foreach("luci_splash", "lease", + function (section) + if section.mac:lower() == mac then + stat = true + return + end + end) + + return stat +end + + +-- Check whether a MAC-Address is whitelisted +function iswhitelisted(mac) + mac = mac:lower() + + uci:foreach("luci_splash", "whitelist", + function (section) + if section.mac:lower() == mac then + stat = true + return + end + end) + + return false +end + + +-- Returns a list of MAC-Addresses for which a rule is existing +function listrules() + local cmd = "iptables -t nat -L luci_splash_leases | grep RETURN |" + cmd = cmd .. "egrep -io [0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+" + return luci.util.split(luci.util.exec(cmd)) +end + + +-- Synchronise leases, remove abandoned rules +function sync() + local written = {} + local time = os.time() + + -- Current leases in state files + local leases = uci:get_all("luci_splash") + + -- Convert leasetime to seconds + local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600 + + -- Clean state file + uci:load("luci_splash") + uci:revert("luci_splash") + + + -- For all leases + for k, v in pairs(leases) do + if v[".type"] == "lease" then + if os.difftime(time, tonumber(v.start)) > leasetime then + -- Remove expired + remove_rule(v.mac) + else + -- Rewrite state + uci:section("luci_splash", "lease", nil, { + mac = v.mac, + start = v.start + }) + written[v.mac:lower()] = 1 + end + end + end + + + -- Delete rules without state + for i, r in ipairs(listrules()) do + if #r > 0 and not written[r:lower()] then + remove_rule(r) + end + end + + uci:save("luci_splash") +end + +main(arg) \ No newline at end of file diff --git a/openwrt/packages/luci/host/usr/sbin/polipo_purge b/openwrt/packages/luci/host/usr/sbin/polipo_purge new file mode 100755 index 0000000..ce7c885 --- /dev/null +++ b/openwrt/packages/luci/host/usr/sbin/polipo_purge @@ -0,0 +1,18 @@ +#!/bin/sh + +DAEMON=/usr/sbin/polipo +PIDFILE=`uci get polipo.daemon.pidFile` +CFGFILE=/var/etc/polipo.conf + +[ -e "$PIDFILE" ] && { + PID=`cat $PID_FILE` + + # send Polipo USR1 signal to write its in-memory cache to disk + kill -USR1 $PID + sleep 2 + # start polipo with -x flag to purge the on-disk cache + polipo -c $CFGFILE -x + # send Polipo USR2 signal to discard its in-memory cache + kill -USR2 $PID +} + diff --git a/openwrt/packages/luci/host/www/cgi-bin-nodes.html b/openwrt/packages/luci/host/www/cgi-bin-nodes.html new file mode 100644 index 0000000..8dd86b0 --- /dev/null +++ b/openwrt/packages/luci/host/www/cgi-bin-nodes.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/openwrt/packages/luci/host/www/cgi-bin-status.html b/openwrt/packages/luci/host/www/cgi-bin-status.html new file mode 100644 index 0000000..8dd86b0 --- /dev/null +++ b/openwrt/packages/luci/host/www/cgi-bin-status.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/openwrt/packages/luci/host/www/cgi-bin/luci b/openwrt/packages/luci/host/www/cgi-bin/luci new file mode 100755 index 0000000..529d1d0 --- /dev/null +++ b/openwrt/packages/luci/host/www/cgi-bin/luci @@ -0,0 +1,5 @@ +#!/usr/bin/lua +require "luci.cacheloader" +require "luci.sgi.cgi" +luci.dispatcher.indexcache = "/tmp/luci-indexcache" +luci.sgi.cgi.run() \ No newline at end of file diff --git a/openwrt/packages/luci/host/www/index.html b/openwrt/packages/luci/host/www/index.html new file mode 100644 index 0000000..838da04 --- /dev/null +++ b/openwrt/packages/luci/host/www/index.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/openwrt/packages/luci/host/www/luci-static/fledermaus/cascade.css b/openwrt/packages/luci/host/www/luci-static/fledermaus/cascade.css new file mode 100644 index 0000000..f9adade --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/fledermaus/cascade.css @@ -0,0 +1,626 @@ +* { + margin: 0; + padding: 0; +} + +body { + background-color: #e5e6ec; + color: #ffffff; + font-family: Verdana, Arial, sans-serif; + font-size: 100%; + line-height: 100%; +} + +code { + font-family: monospace; + white-space: pre; +} + +div#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red !important; + font-weight: bold; +} + +.clear { + clear: both; + height: 1px; +} + +.hidden { + display: none; +} + +.error { + color: #ff0000; +} + +#header { + min-height: 98px; + background-image: url(logo.png); + background-repeat: no-repeat; + background-position: left center; + background-color: #000000; + text-align: center; + border-bottom: 1px solid #dc0067; +} + +#header2 { + min-height: 98px; + background-image: url(fledermaus.png); + background-repeat: no-repeat; + background-position: right center; +} + +#header3 { + font-size: 2.6em; + font-family: serif; + color: #FFCB05; + letter-spacing: 0.35em; + font-weight: bold; + line-height: 1.4em; +} + +#header4 { + font-size: 1.25em; + line-height: 1.2em; + letter-spacing: 0.2em; + color: white; +} + +.pathbar { + display: none; +} + +.menubar { + width: 100%; + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +.mainmenu { + float: left; + width: auto; + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +.mainmenu div { + float: left; +} + +.mainmenu li { + white-space: nowrap; +} + +.mainmenu div ul { + display: none; + position: absolute; + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + list-style-type: none; +} + +.mainmenu ul li:hover > ul, +.mainmenu div:hover > ul { + display: block; +} + +.mainmenu ul li > ul { + left: 100%; + margin-top: -1.8em; + border-width: 1px; +} + +.modemenu a, +.mainmenu a { + display: block; + padding: 0.5em; + color: #ffffff; + text-decoration: none; + font-size: 80%; +} + +.mainmenu .active a, +.modemenu .active a { + color: #ffff00; + font-weight: bold; +} + +.mainmenu li:hover > span > a, +.mainmenu div:hover > a { + font-weight: bold; +} + +.modemenu a:hover, +.modemenu a:focus, +.mainmenu a:hover, +.mainmenu a:focus { + color: #ffff00; + font-weight: bold; +} + +.mainmenu div.preactive > a { + color: #ffff00; + font-weight: bold; +} + +.modemenu ul { + width: auto; + background: #000000; + color: #ffffff; + list-style-type: none; +} + +.modemenu li { + float: right; +} + +#maincontent { + clear: both; + width: 90%; + margin: 0 auto; + padding: 0.5em; + background: #f8f9fe; + color: #000000; + font-size: 80%; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #f2f3f9; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +input[type=submit], +input[type=reset], +input[type=image], +label { + cursor: pointer; +} + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #f2f3f9; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { + background: #f5f5f5; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +.cbi-rowstyle-1 { + background-color: #eeeeff; +} + +.cbi-rowstyle-2 { + +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; +} + +div.cbi-value:last-child { + border: none; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin: 0.25em 0 0.25em 40%; +} + +div.cbi-value-description { + font-size: 90%; +} + +div.cbi-value-field > div.cbi-value-description { + display: none; +} + +div.cbi-value:hover div.cbi-value-field > div.cbi-value-description { + display: block; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + margin: 0.5em 0; + padding: 0 0.25em; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border: 1px dotted #bbbbbb; + padding-bottom: 0; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #FF0000; +} + +td.cbi-value-error { + border-color: red !important; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red !important; + background-color: #FFCCCC; +} + +.cbi-section-error { + color: red; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +ul.cbi-apply { + font-size: 90%; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a { + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #FF0000; + background-color: #FFFFFF; + padding: 0.5em; +} + +#memorybar { + width:200px; + height:8px; + border:1px solid #bbb; + background-color:red +} + +#memfree, #membuffers, #memcached { + float:right; + border:1px solid #bbb; + height:6px; +} + +#memfree { + background-color:green; +} + +#membuffers { + background-color:yellow; +} + +#memcached { + background-color:orange; +} + + +/* obligatory IE6 Voodoo Code */ +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.mainmenu div.hover ul, +* html div.mainmenu div li.hover ul, +* html div.mainmenu div li li.hover ul, +* html div.mainmenu div li li li.hover ul, +* html div.mainmenu div li li li li.hover ul { + display: block !important; + margin-left: 3em; +} + +* html div.mainmenu div.hover ul { + margin-left: 0; +} + +* html div.mainmenu .hover ul ul, +* html div.mainmenu .hover ul ul ul, +* html div.mainmenu .hover ul ul ul ul, +* html div.mainmenu .hover ul ul ul ul ul { + display: none !important; +} + +* html div.mainmenu li { + height: 1em !important; + width: 10em !important; +} + +* html .mainmenu { + height: 1.8em; +} + +* html div.cbi-value-description { + margin-left: 40%; +} diff --git a/openwrt/packages/luci/host/www/luci-static/fledermaus/fledermaus.png b/openwrt/packages/luci/host/www/luci-static/fledermaus/fledermaus.png new file mode 100644 index 0000000000000000000000000000000000000000..852e9d0c08adec21b5bef5a968383522aecd0ccd GIT binary patch literal 7321 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 IM6N<$g0fW6u>b%7 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk-bno/cascade.css b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/cascade.css new file mode 100644 index 0000000..3507777 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/cascade.css @@ -0,0 +1,726 @@ +* { + margin: 0; + padding: 0; +} + +body { + background-color: #ffffff; + color: #ffffff; + font-family: Verdana, Arial, sans-serif; + font-size: 100%; + line-height: 100%; + background-image: url(images/main-back.png); + background-repeat: repeat-x; + background-position: left bottom; + } +#all { + margin: 0px; + padding: 0px; + min-height: 800px; +} + +code { + font-family: monospace; + white-space: pre; +} + +a:link, a:visited { + color:#000000; + font-weight:bold; + text-decoration:none; + } +a:hover { + color:#333333; + font-weight:bold; + } + +/* Custom*/ + #wrapper +{ + width: 95%; + color: #333333; + margin-left: auto; + margin-right: auto; +/* background-image: url(images/corner-left.gif); */ +/* background-repeat: no-repeat; */ +/* background-position: left bottom; */ + background-color: #FffdF4; + min-width: 710px; + min-height: 710px; +} +#main { + clear: both; + width: 100%; + margin: 0; + padding: 0; + color: #333333; +/* background-image: url(images/corner-right.gif); */ +/* background-repeat: no-repeat; */ +/* background-position: right bottom; */ + min-height: 710px; +} + +div#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red !important; + font-weight: bold; +} + +.clear { + clear: both; + height: 1px; +} + +.hidden { + display: none; +} + +.error { + color: #ff0000; +} + +#header +{ + padding: 0px; + height: 100px; +} +#headerleft +{ + height: 100px; + background-color: #FFFfff; + background-image: url(images/header-left.gif); + background-repeat: no-repeat; + background-position: left top; +} +#headerright +{ + height: 100px; + background-color: #FFfffF; + + margin-left: 5px; + background-image: url(images/header-right.gif); + background-repeat: no-repeat; + background-position: right top; +} + +#headerback +{ + margin-right: 5px; + height: 100px; + background-color: #FFfffF; + background-image: url(images/header-back.gif); + background-repeat: repeat-x; + background-position: left top; +} +#schriftzug { + font-size : 1.5em; + text-align:left; + margin-bottom: 7px; + margin-top: 7px; + float:left; + width: 450px; +} + +#schriftzug a:hover{ + background-color:transparent; +} +#logo{ + margin-top: 5px; + float:right; + width: 115px; +} + +.pathbar { + display: none; +} + +.menubar { + width: 100%; + min-height: 1.8em; + background: #ffffff; + color: #000000; + border-top:0.4em solid #DC0067; +} + +.mainmenu { + float: left; + width: auto; + min-height: 1.8em; + background: #ffffff; + color: #000000; +} +.modemenu li { + border-top:0.3em solid #DC0067; + margin-left: 0.3em; + margin-top: -0.3em; +} +.mainmenu div { + float: left; + border-top:0.3em solid #DC0067; + margin-right: 0.3em; + margin-top: -0.3em; +} +.mainmenu div.preactive { + border-top: 0.3em solid #FFCB05; + margin-top: -0.2em; +} + +.mainmenu li { + white-space: nowrap; +} + +.mainmenu div ul { + display: none; + position: absolute; + background: #ffffff; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + list-style-type: none; +} + +.mainmenu ul li:hover > ul, +.mainmenu div:hover > ul { + display: block; +} + +.mainmenu ul li > ul { + left: 100%; + margin-top: -1.8em; + border-width: 1px; +} + +.modemenu a, +.mainmenu a { + display: block; + padding: 0.2em; + color: #000000; + text-decoration: none; + font-size: 70%; + font-weight: bold; +} + + +.modemenu .active a { + color: #000000; + font-weight: bold; + border-top:0.3em solid #FFCB05; + margin-top: -0.2em; +} +.mainmenu .active a{ + color: #000000; + font-weight: bold; + border-top:0.2em solid #FFCB05; +} +.mainmenu li > span:active { + background-color: #FFE990; +} + +.mainmenu li:hover > span > a, +.mainmenu div:hover > a { +color: #ffffff; +background-color: #FFCB05; +} + + +.modemenu a:focus, +.mainmenu a:focus { + color: #000000; +} + +.mainmenu a:hover, +.modemenu a:hover { +color: #ffffff; +background-color: #FFCB05; +} + +.mainmenu div.preactive > a { + color: #DC0067; + font-weight: bold; +} +.mainmenu div.preactive > a:hover, +.mainmenu div.preactive > a:focus { + color: #ffffff; + font-weight: bold; +} + +.modemenu ul { + width: auto; + background: #000000; + color: #ffffff; + list-style-type: none; +} + +.modemenu li { + float: right; + +} + +#maincontent { + clear: both; + width: 98%; + margin: 0 auto; + padding: 0.5em; + background: #FFF4BE; + color: #000000; + font-size: 80%; + border-top:1px solid #D2A800; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #D2A800; + background-color: #FFE990; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +input[type=submit], +input[type=reset], +input[type=image], +label { + cursor: pointer; +} + +select, +input, +textarea { + background: #FffdF4; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #FFF4BE; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { +background-color: #FFCB05; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { +background-color: #FFE990; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +.cbi-rowstyle-1 { + background-color: #FFF4BE; +} + +.cbi-rowstyle-2 { +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #FFCB05; +} + +div.cbi-value:hover { + background: #FFF4BE; +} + +div.cbi-value:last-child { + border: none; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin: 0.25em 0 0.25em 40%; +} + +div.cbi-value-description { + font-size: 90%; +} + +div.cbi-value-field > div.cbi-value-description { + display: none; +} + +div.cbi-value:hover div.cbi-value-field > div.cbi-value-description { + display: block; + color: #ffffff; + background-color: #FFCB05; +} + +option:active, +option:before, +option:after, +option:focus, +option:hover { + color: #ffffff; + background-color: #EEBA00; + background: url(images/bgoption.png); +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + margin: 0.5em 0; + padding: 0 0.25em; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border: 1px dotted #FFCB05; + padding-bottom: 0; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #FF0000; +} + +td.cbi-value-error { + border-color: red !important; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red !important; + background-color: #FFCCCC; +} + +.cbi-section-error { + color: red; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +ul.cbi-apply { + font-size: 90%; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a { + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #FF0000; + background-color: #FFFFFF; + padding: 0.5em; +} + +#memorybar { + width:200px; + height:8px; + border:1px solid #bbb; + background-color:red +} + +#memfree, #membuffers, #memcached { + float:right; + border:1px solid #bbb; + height:6px; +} + +#memfree { + background-color:green; +} + +#membuffers { + background-color:yellow; +} + +#memcached { + background-color:orange; +} + + +/* obligatory IE6 Voodoo Code */ +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.mainmenu div.hover ul, +* html div.mainmenu div li.hover ul, +* html div.mainmenu div li li.hover ul, +* html div.mainmenu div li li li.hover ul, +* html div.mainmenu div li li li li.hover ul { + display: block !important; + margin-left: 3em; +} + +* html div.mainmenu div.hover ul { + margin-left: 0; +} + +* html div.mainmenu .hover ul ul, +* html div.mainmenu .hover ul ul ul, +* html div.mainmenu .hover ul ul ul ul, +* html div.mainmenu .hover ul ul ul ul ul { + display: none !important; +} + +* html div.mainmenu li { + height: 1em !important; + width: 10em !important; +} + +* html .mainmenu { + height: 1.8em; +} + +* html div.cbi-value-description { + margin-left: 40%; +} diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/bgoption.png b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/bgoption.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd1e2f34787b200eb425e42fb98c75b039163e2 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaOClDyqr82*Fc zg1yTp14TFsJR*yMv=#_6DqH@!17xt5c>21s-{2Gz=HriQFMb9T;`MZK4B@z*T(N!D bLwg3cy-YKE&k4N(N-%i3`njxgN@xNAizFlF literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/favicon.ico b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7247cfac5fe279cf3e12c965f53483196bfb0e2f GIT binary patch literal 5310 zcmeHJd2AGA6n}uYe@I#)M*vMg2#O-0f)-FIh+q(ng4H&}NJygr4G0#oh0<*)Edo`b z6iWb+044>R6hb106t=XbT-CN%OS^OJebMf2ce|avW_;6GrrVuqHT-FIc4qVDeQ$o> zo8P+zU=aQ$OaS~J17#xtMgzbUyif)6@e=fpc7y`lUuE9%751GY^f^H10)yvPp!bY7 zXmXv8h8g|T!Iw-MfY=O_1TJpzEs)haT+x<~CX-iu8-XkYW(P3adrp*5$OM8nge6Q% zga7Co7U^~X!P?}fD!Zc%vVeO1V`|z;Ds?(NH=P-`k4c$KEto_sG1w)uf+uttKq7CF zMp0-z-}Ma;89<1ur)}PaT3gm`TlO^l?LF@OqYT@D&I9UJzN`6+_pH}fY;+epI|~jt za)4Y1T769)$K+eoAMX4L+O`1o>j+ax*t1>dYV8V0X2%v-aS8o&>3Ws-J^rU=wWbUw z8ovHd;jlIMGl7JI#Hlq730V}*u5ut(815K-cSGPnvUwzB^oDvP5@Qp6n_b(U^{PHv zBg)qcUEcvI#}`+RSUiQg$SWM0Wj?;hDn~%gXDtpg6jWTgSLVgE%mhkt6_uK;*M*_ z(KBXh19ar2q8~J}LC`QzNy48D+@awjF|>;53@UiSySev96B|YeuYj-!ekRS1<&P!# zK@z=gnK2qxlmlT7E@p3czc=TI9_i5#iz!(sWiR@Pn zSxNO~sHA$4r7f;dOPdsuq%PC>;bg&KgcZTDWnp`nl13WJeR6-`5((G(IxlX4%HK)3 zJyYRZI+ZMV*lERni1-PcNar=b+#W6w{o>=2?C3bp!d~rGAh9uGK8yJIKrbCb+OD%Q zb4+U{mVD9wtMssHoq|0;NxjQb%bM=6Efrn33-+|lK+buMXs=W7f1kmP2@}gdl5>GL zY4s}N7n$6W-gKAs+In)bQOEHL`GA(6G~0y~s-&T+=frSd&|;-aAkjhyLC`>U+;Fq^ zJPQ7chLs(@7w($iA_bS}m+Q@VD+7oqE*^K^2`k_PdA`v4FFm$lowFwOL4U}o=Uv<~ zX!{a~qjM}sezYa84Z$I8`FvZnGDfc5?W)@|kPjzPY*0ZJ0ge6Vb71En)e z*e(iydUJRi|3FYG9yow%cJ_-OXbCPFOKcg6Gp6jLmQ68(s9Ou>W-ZLSZug_&3%!iTHI)D>L<|pTK0N@GXAc?I#nr!b&3Ur z{l9G4Ks=Z7-WBP3wkdYdxOBm)Z3_4sQjCkIl0QD|2{=X->6Mh{-m#C(AU}GXIK9Ni zTYJNS4O64;kjzk^e8F7CIlJBZ6X>y_;b$1~+-X*5^3qd{$2~Y?am=lMl3w^0^_ZF{ znrN)q;xwQ1@jQQPtKk3N6RY3gmWBYgfjy9 z%u>-SC(-Xtr{J*mfY-C;2MgRJ_n&BAHJHeFzEA)8<7bb(S)sDzyI^!M0WgPg7fiN% z;iSLsVU?;7DmUC7Mprii;Woy`NRFnc!Re1fABzIV98MzKt8kd$t-U!ie35M=WZ*ne zM2=D73@uNy;|KZPXN2i#x*ehSMv=SWm?z}#jeg97;w`U9Xyv4$)s|=i4lgFv^gzGM+9>UGb xQE>^Gst_zl41wwwZqP!WAC%7Xx^(4+t>|f78D}8QK%9X%191l84E$dh_y^c+g?9h| literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/header-back.gif b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/header-back.gif new file mode 100644 index 0000000000000000000000000000000000000000..21fe02b1e9af89e64fea086b438e20e68b391927 GIT binary patch literal 127 zcmZ?wbhEHbWMxQU*v!E2|NsA=KYzY?^XA5l8~@KR?A^O}&YU?-O-*@ud5MXM3>ZN1 zCku-R!+!=HkPOHS1{R$OCp=g0wRnAY_x}WqzLd;)8LQUic&i!oocWx1+ijk>jr||{ P#sCQoF-DIR76xkomfbH1 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/header-left.gif b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/header-left.gif new file mode 100644 index 0000000000000000000000000000000000000000..a3258ccb6d2f6809c591cdcf5694b6d9557c0feb GIT binary patch literal 293 zcmZ?wbhEHbWMxQUxXQrr|Ns9#fByXb{rlIiUq65T{Qmv>=g*%%eE9JG{rh+C-o1JA z=EaK_PoF-0`0(M~yLWHiym{lsjk9OZ{y)QT^ytweM~)mgaA51!ty{KiS+Qcp!i5Vb zO`0@u;>7m$_J)Rr($dnBl9G&!3P#h)xJA`Jf-bU>DX{KUZKkR+M{QLX+`uh6$`T6(v_x1Jl^z`)e^YifV z@b2#J?Ck96>FMa`=;h_*$$O;Js L%*+7K&p`k?3O3Jl literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/logo.gif b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff00d6ddb8051a28a4430977069e240b8a0a741b GIT binary patch literal 2415 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/main-back.png b/openwrt/packages/luci/host/www/luci-static/freifunk-bno/images/main-back.png new file mode 100644 index 0000000000000000000000000000000000000000..34aca44e01c12fa9f63dcce8d5c6fa529133f7b2 GIT binary patch literal 404 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq*#ibJVQ8upoSx*1IXtr@Q5sC zU|@R#!i;jI7N$T!$r9IylHmNblJdl&REF~Ma=pyF?Be9af>gcyqV(DCY@~q33VOOY zhFJ7oo#US1*U2@MYIb&nx z7j1L=e0@Pc&DB5mntZq4Js@bC&FSr-N*r-~Y8NIoEjYmfrKd z_U%)X*5(#16DjY_@(guPnRKW$R-Q*OXZOm757+u=rXG_xAIFiH?Dg`X#N*4s47dFx zIgcJzzxUer|Ln$^J%4Y0d1lb2aKO$)b$h#;a7e>W&pfXgvBM|I7I5XnXu`k$nvB_Im$2>s^}-3_%7@S3j3^P6OUSZOE3oj^sirQ(63eK*9x>V0d0SV zHhIv`UTA|0Z8Srx)zE4cw3G`i{<3OkADgLbH+392uJSg{FNbCMKW>M`+>( zG~on|*+65~&N^beqI$cUpj_yr^Y7O4HN=YLNC0wQB6(NwH9gUQsO#l(}o;MLWZ`ySm8SYW%l_ zZnpWF3C?j>#v;4TC$}|f-@Z-Ny0cUG`zSBdLIPV+JIM6TKnX0mz|4_`AN^XxrVFw9 z&9cVYYi)IN#BU6$Qe9+Ha?N%photgRBFz2p^BDLq4Wnr z0gw2NG9DOmus#fPCkfjqIi)NtB!c%)_-8-;Lw&GU@8Y84XUh(G{Mk0^3;63H_2c7L ztO9y$jjH6M*{D!e@Aq5K+c8roqSD^( z8fGD`rHe7;bw%dDY;J|-RU}Ebv|9OC2iN>le(ewRj2ZP_8;=qsH2p|xTqP8rJ1`dG zlF`5Ye!jS5n@Gq`_UAmLVAcNP=^tOzhAhRN%Tm;u7(V%f_x;td@>O$7psiEy{oN{H)HP<{lU*yyqbKc zumZ7X_IRte6c#D*-~D}DZR543Yf}aHm;3{tGReb%HJKo=EeLZX_+Q?^x? z7JEu{Z*BWxf%j^IKvi*RsMoCU*Phw>uFj6#(T5d}k4qVyc&GDezOsK6Ur{r_u{pnK zqXAiJzcD+jeRSyAD1(1kI5vDE>yY==U5uT#Igx_xbFZD6-R;>?fkD*Fty zz>y7I^=Xgpd&M^ohuG+F|B|%vKpb@FC>*M9&p}1YDh_-~NH-8Ft)v`m%%4BhQd=AI zgftM~G>cg=y@dqE|6ZAJ8DBoF#IWRM^CtC025yP?o{2S*fixQM1`Ki8R*IUGCE=n_~fQECq zEYp3}VCV03zi&4cG%f-%UPcV;$3^YS!0m<2$-@}@TtP)NQSfO2Uy_;&VvlJ1`Lt*# znek&rP%9t64qgO8JfOd{@LE3MLZYjo!l9aUQ{zDjE7QM1;z+x=no~C2`__@q_H7=H-)Sa4zMLtpF87Y`354aC8hf~({;LO{y{*_9 zo0imruRM|0+Vup48j zMRMRKFfv7D=`w=f)%mEZYP$$wvcz0cN&8_8EJ3FK@uM-EqJR@z+~s0v4umNsp4l?e zj+l;jRG2vAdg>KU{(`iDX^VtEx_!T*1^Qqs z0D5wuSfrI5kb}E*qcci~d#TD{Hs8)Dsd`pLrReO#QgapC&e~1+3a@w(RQ{<|~( zL7D5a%aL-}4>v7XprWU8faN>Y&17*k@Xh}fY>X?4Z<&!>fn?$h+6bYThQ@4D5>>ZR9ZWbfS@aw1pd^u)pczx=e zAoD8_7MAYZQB>vUjm`R5i8m(&a`${DQ8t|?UoBl;hU-sGxXh(D%_=Rz3uTDtKujOq z5QhlbCn&8lHN+J;sX&rlatc_L(8aap7ei!zb0Ny`+dV;YRP=49XKzGxkk+D3xMk0y zEoVOe`N?@CdwXS>`$?%}UBm_5en3TT+%REAJEoD?;@rsk^m{fUq>HI_T_>fCa}=&m zylClZ$0;L$k|AL);4L;ZE9qT2`&&|P99XLEj2d0_^~1Omf<(Nn6r``0? z@P=2r@z#hRO{|kB*A|WYtK`*RU(0Vl=P8u_cx3I+XSQ`eO%6vfCXBPbSI+mF%G^z{ zeu;LybJz3kY2S)3P05b)r?_5fK~NY5Qm5s3Mt>*>k0(H8(8U@_Y!+9Sw!g-^`Bk8`D-+u|IWL>tl;n*s%OIh z37|u>>h8vaNZxz^4U3dqb6XR*dJ7S}TO3ZEkDNr1r{=`lG>k9mga+3wkS{Dhlfdp zr|2Lt7^gpl(FO!Dqv61R=)iG-hSH>%5F)nSDDw>JEG_B+G89WDp`_1Qwb74ndzQ`n z(uZKGCHG9zX-YM;gYI;gUSymNblq}1 zXvB8poD@@AkLj}DZ#L}l&c);Yb1HF|Nn2xjT_v1wXBY>=g`~YQGGZ`WQKzLt8n$Ej zr0)xq#0Cd5ziWpVZ&U9q_@Wn>n$nRpsaRD8t)75>C{4*xq308VGwhhRm=tZjSk?mR z{c|th5-84Ek3q%81nW^S!1_Z;Op*(bL4!y1Fk4P+kRE*)NgBOJ9lMtpq8CLgv``Et zD6rznrHK;0a3LPC=pI1^2h%OO_SdA_rF0@f({5QM{;(TE7YX?DgF!VI9FE<&8nH{b z|6R&amdBz=06q`G7grWF{~F9UPQ*M;?yV~p`2C!X*SBZTGm=);!jm}(a<)E~2uLb2 z4xxusRI-pBhADz%rTVDtIiy)g3U)2AyD$)ogL@8BpG&3SV??eg14$f`qic0uC)r{# z)~zkEbvq`;{Tv3DO0NUAu@5{?-K20+879E-2oi%%W0)f!r&+p=pqdZ?RC5mOwjENz z1}3=X0A~R)Cw~er!~98R95*wqjzr)j<5Z9di%11P%{`Jun9Y=~20|G?1Y=R!PGUJl zmz?y%@WOIWW%>mHLCnKwB2p2T`R8sX8o=Xl@cdHi*qv ul, +.mainmenu div:hover > ul { + display: block; +} + +.mainmenu ul li > ul { + left: 100%; + margin-top: -1.8em; + border-width: 1px; +} + +.modemenu a, +.mainmenu a { + display: block; + padding: 0.2em; + color: #000000; + text-decoration: none; + font-size: 70%; + font-weight: bold; +} + + +.modemenu .active a { + color: #000000; + font-weight: bold; + border-top:0.3em solid #FFCB05; + margin-top: -0.2em; +} +.mainmenu .active a{ + color: #000000; + font-weight: bold; + border-top:0.2em solid #FFCB05; +} +.mainmenu li > span:active { + background-color: #FFE990; +} + +.mainmenu li:hover > span > a, +.mainmenu div:hover > a { +color: #ffffff; +background-color: #FFCB05; +} + + +.modemenu a:focus, +.mainmenu a:focus { + color: #000000; +} + +.mainmenu a:hover, +.modemenu a:hover { +color: #ffffff; +background-color: #FFCB05; +} + +.mainmenu div.preactive > a { + color: #DC0067; + font-weight: bold; +} +.mainmenu div.preactive > a:hover, +.mainmenu div.preactive > a:focus { + color: #ffffff; + font-weight: bold; +} + +.modemenu ul { + width: auto; + background: #000000; + color: #ffffff; + list-style-type: none; +} + +.modemenu li { + float: right; + +} + +#maincontent { + clear: both; + width: 98%; + margin: 0 auto; + padding: 0.5em; + background: #FFF4BE; + color: #000000; + font-size: 80%; + border-top:1px solid #D2A800; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #D2A800; + background-color: #FFE990; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +input[type=submit], +input[type=reset], +input[type=image], +label { + cursor: pointer; +} + +select, +input, +textarea { + background: #FffdF4; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #FFF4BE; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { +background-color: #FFCB05; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { +background-color: #FFE990; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +.cbi-rowstyle-1 { + background-color: #FFF4BE; +} + +.cbi-rowstyle-2 { +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #FFCB05; +} + +div.cbi-value:hover { + background: #FFF4BE; +} + +div.cbi-value:last-child { + border: none; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin: 0.25em 0 0.25em 40%; +} + +div.cbi-value-description { + font-size: 90%; +} + +div.cbi-value-field > div.cbi-value-description { + display: none; +} + +div.cbi-value:hover div.cbi-value-field > div.cbi-value-description { + display: block; + color: #ffffff; + background-color: #FFCB05; +} + +option:active, +option:before, +option:after, +option:focus, +option:hover { + color: #ffffff; + background-color: #EEBA00; + background: url(images/bgoption.png); +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + margin: 0.5em 0; + padding: 0 0.25em; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border: 1px dotted #FFCB05; + padding-bottom: 0; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #FF0000; +} + +td.cbi-value-error { + border-color: red !important; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red !important; + background-color: #FFCCCC; +} + +.cbi-section-error { + color: red; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +ul.cbi-apply { + font-size: 90%; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a { + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #FF0000; + background-color: #FFFFFF; + padding: 0.5em; +} + +#memorybar { + width:200px; + height:8px; + border:1px solid #bbb; + background-color:red +} + +#memfree, #membuffers, #memcached { + float:right; + border:1px solid #bbb; + height:6px; +} + +#memfree { + background-color:green; +} + +#membuffers { + background-color:yellow; +} + +#memcached { + background-color:orange; +} + + +/* obligatory IE6 Voodoo Code */ +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.mainmenu div.hover ul, +* html div.mainmenu div li.hover ul, +* html div.mainmenu div li li.hover ul, +* html div.mainmenu div li li li.hover ul, +* html div.mainmenu div li li li li.hover ul { + display: block !important; + margin-left: 3em; +} + +* html div.mainmenu div.hover ul { + margin-left: 0; +} + +* html div.mainmenu .hover ul ul, +* html div.mainmenu .hover ul ul ul, +* html div.mainmenu .hover ul ul ul ul, +* html div.mainmenu .hover ul ul ul ul ul { + display: none !important; +} + +* html div.mainmenu li { + height: 1em !important; + width: 10em !important; +} + +* html .mainmenu { + height: 1.8em; +} + +* html div.cbi-value-description { + margin-left: 40%; +} diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk/images/bgoption.png b/openwrt/packages/luci/host/www/luci-static/freifunk/images/bgoption.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd1e2f34787b200eb425e42fb98c75b039163e2 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaOClDyqr82*Fc zg1yTp14TFsJR*yMv=#_6DqH@!17xt5c>21s-{2Gz=HriQFMb9T;`MZK4B@z*T(N!D bLwg3cy-YKE&k4N(N-%i3`njxgN@xNAizFlF literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk/images/favicon.ico b/openwrt/packages/luci/host/www/luci-static/freifunk/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f785830ff77a700ac1dbf153a11f638f32481171 GIT binary patch literal 4286 zcmeI0d2Ccw6o=0U6l@SdA_`?0cBpnGExS`F`x<0Xs31~6N;@qeDp9Z{7SM>4 z9ykpb;V(D@AAlF`g>bz{<3wa$fYH#rmi%43_l4(RXz-i-{s2xbDtWK2HFuKtC7^gC z`R>kqKD5s1V#p8qP^Pc4t;x zX$H^7&so9|#}a>bEY9cHsKN`D7gG|7vkP+N zApNzl5LUngl9@5^WFY3$9aZ(9L9ef`MUPlJQg&7=-qGk)fCC4hBUs`g#|FMrVcFeFqrDw{i_q%` zIuEk-IPrTk2b{E&UDfsRITW46ARDI=4>|+Jd(T>4>k{>VP|U3vPouWRlD8hC3(8%I zzc}NNFAwTTcNc7e4|^0lo7vMg6SJ@rQ!)zOUJ$C`4cJ&PeOOr(a*dOVo#W_~K_xio zt;N3lzZ&$vfoB}_r`D#=jXTz+_g7W*lYVk`Nd8779CngMynNB}+W77#?s4dk2-@3+ z9rd-O^mSJZxn|gy02kTA&&g}k%(Rm_hns`)`8;*T2V!R?`L91@&1GZ#vFIEL^S_Pp zBFKlu)J2QoD=%7ZTVFJK+P^+f1?rbE)W*}ZQ;*-#@3TsaKjI`)JHz9Db)rTtqyAe5 z>i=Wpl>hmV2CJdZJkHF7?6dN3Sx|g{>JEO{p#gf|0$?BW1Y#T+n0@8%dGg)K;QGW5BS#iLXiJrcm>q60ycHF`h8ld zvllqG_`Lp9Tq!%NEYrgta>me6-x~vCLH71Q$iJSw*`I~PFqyj0KF5RVbrned4{(F} ziE^o&+7m;|tnb#!z*&<|!PyC*{R!@&>`#OwSOc=R9>V==datK?JP)$5-DtxIc`?}N|?Zsf1_d`o1HgLFTFHt;Oy zuC0;97yEXd;Cx%2TDNL$GE{?XOoiG$ZuPEwscxme5p=g^z#Q;^eCcjbtO=lRx@Wq9 z{Dtmd^)VOR%3q}K3(%8)aR5{c>glSJX`u5t9aQ7$mEv6p>3qRB8Y0=g-8tp)Oqfmm z9kvXnfa>yL$OY}wB?$Rm$5=h!cKzH;PG@2ZsE38@-{@J4jB;}`d;j%YEOwW`m+%{0 z0QI%+;dK}aQ4rC7q`%4Q=IS!=e`Ua__2X}1p6?3n?p1zk*zUa5^Z3o>DVp!fFY*`7 zFW6p`R=|HIfV-f;-E8T0|JzIb{@pJ+e!t7{pLaP${1!Mx`MjCSLEovchR!u>=Q!r6 IZN1 zCku-R!+!=HkPOHS1{R$OCp=g0wRnAY_x}WqzLd;)8LQUic&i!oocWx1+ijk>jr||{ P#sCQoF-DIR76xkomfbH1 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk/images/header-left.gif b/openwrt/packages/luci/host/www/luci-static/freifunk/images/header-left.gif new file mode 100644 index 0000000000000000000000000000000000000000..a3258ccb6d2f6809c591cdcf5694b6d9557c0feb GIT binary patch literal 293 zcmZ?wbhEHbWMxQUxXQrr|Ns9#fByXb{rlIiUq65T{Qmv>=g*%%eE9JG{rh+C-o1JA z=EaK_PoF-0`0(M~yLWHiym{lsjk9OZ{y)QT^ytweM~)mgaA51!ty{KiS+Qcp!i5Vb zO`0@u;>7m$_J)Rr($dnBl9G&!3P#h)xJA`Jf-bU>DX{KUZKkR+M{QLX+`uh6$`T6(v_x1Jl^z`)e^YifV z@b2#J?Ck96>FMa`=;h_*$$O;Js L%*+7K&p`k?3O3Jl literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/freifunk/images/logo.png b/openwrt/packages/luci/host/www/luci-static/freifunk/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0beeb2fad1c99c2477c00b5ab5214f9a82769797 GIT binary patch literal 6400 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 Z`v1Ohi~S#mD^>si002ovPDHLkV1fesfFl3^ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt-light/cascade.css b/openwrt/packages/luci/host/www/luci-static/openwrt-light/cascade.css new file mode 100644 index 0000000..a26e662 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt-light/cascade.css @@ -0,0 +1,790 @@ +@charset "utf-8"; + +@media all { + +html, +body { + background-color: #4a6b7c; + color: #ffffff; +} + +body { + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + background-color: #557788; + color: #ffffff; + text-align: right; + padding: 0.5em; +} + +#header h1 { + display: inline; +} + +#header p { + display: inline; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +ul.dropdowns { + float: left; + margin: 0; + padding: 0; + width: auto; + list-style: none; +} + +html>body ul.dropdowns { + position: relative; +} + +ul.dropdowns li, +ul.dropdowns ul { + margin: 0; + padding: 0; + list-style: none; +} + +ul.dropdowns li { + float: left; + position: relative; + white-space: nowrap; +} + +ul.dropdowns li ul { + position: absolute; + z-index: 1000; + top: auto; + min-width: 10em; +} + +ul.dropdowns li li { + float: none; + position: relative; +} + +ul.dropdowns li a { + display: block; +} + +ul.dropdowns ul li ul { + top: 0; +} + +ul.dropdowns li ul, +ul.dropdowns li.over ul ul, +ul.dropdowns li.focus ul ul, +ul.dropdowns li:hover ul ul, +ul.dropdowns li.over ul ul ul, +ul.dropdowns li.focus ul ul ul, +ul.dropdowns li:hover ul ul ul, +ul.dropdowns li.over ul ul ul ul, +ul.dropdowns li.focus ul ul ul ul, +ul.dropdowns li:hover ul ul ul ul { + left: -3000px; +} + +ul.dropdowns li.over ul, +ul.dropdowns li.focus ul, +ul.dropdowns li:hover ul { + left: 0; +} + +ul.dropdowns ul li.over ul, +ul.dropdowns ul li.focus ul, +ul.dropdowns ul li:hover ul, +ul.dropdowns ul ul li.over ul, +ul.dropdowns ul ul li.focus ul, +ul.dropdowns ul ul li:hover ul, +ul.dropdowns ul ul ul li.over ul, +ul.dropdowns ul ul ul li.focus ul, +ul.dropdowns ul ul ul li:hover ul { + left: 100%; +} + +#menubar { + position: relative; + width: 100%; + background: #000000; + color: #ffffff; +} + +#menubar .warning { + color: red; + background-color: #557788; +} + +#menubar ul.dropdowns { + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +#menubar ul.dropdowns li ul { + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; +} + +#menubar ul.dropdowns ul li ul { + border-width: 1px; +} + +html #menubar a:link, +html #menubar a:visited { + position: relative; + display: block; + padding: 0.5em; + background: #000000; + color: #ffffff; + text-decoration: none; + font-size: 80%; + font-weight: normal; +} + + +html #menubar a:link:hover, +html #menubar a:visited:hover, +html #menubar a:link:active, +html #menubar a:visited:active, +#menubar a:link:focus, +#menubar a:visited:focus { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.active, +html #menubar a:visited.active, +html #menubar a:link.preactive, +html #menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.warning, +html #menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +#menubar ul.dropdowns li.over>a, +#menubar ul.dropdowns li.focus>a, +#menubar ul.dropdowns li:hover>a { + font-weight: bold; +} + +.lang_de #submenu_mini_system { min-width: 13.3em; } +* html .lang_de #submenu_mini_system { width: 13.3em; } + +.lang_pt-br #submenu_mini_network { min-width: 14em; } +* html .lang_pt-br #submenu_mini_network { width: 14em; } + +.lang_pt-br #submenu_mini_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_mini_system { width: 11.5em; } + +.lang_ru #submenu_mini_system { min-width: 18em; } +* html .lang_ru #submenu_mini_system { width: 18em; } + +.lang_pt-br #submenu_admin_index { min-width: 11em; } +* html .lang_pt-br #submenu_admin_index { width: 11em; } + +.lang_ru #submenu_admin_index { min-width: 15.5em; } +* html .lang_ru #submenu_admin_index { width: 15.5em; } + +.lang_ru #submenu_admin_status { min-width: 10.5em; } +* html .lang_ru #submenu_admin_status { width: 10.5em; } + +.lang_de #submenu_admin_system { min-width: 13.3em; } +* html .lang_de #submenu_admin_system { width: 13.3em; } + +.lang_fr #submenu_admin_system { min-width: 14.5em; } +* html .lang_fr #submenu_admin_system { width: 14.5em; } + +.lang_pt-br #submenu_admin_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_admin_system { width: 11.5em; } + +.lang_ru #submenu_admin_system { min-width: 18em; } +* html .lang_ru #submenu_admin_system { width: 18em; } + +#submenu_admin_services_chillispot { min-width: 15.5em; } +* html #submenu_admin_services_chillispot { width: 15.5em; } + +#submenu_admin_services_coovachilli { min-width: 15em; } +* html #submenu_admin_services_coovachilli { width: 15em; } + +.lang_ru #submenu_admin_network_routes { min-width: 15.3em; } +* html .lang_ru #submenu_admin_network_routes { width: 15.3em; } + +#submenu_admin_network_firewall { min-width: 14em; } +* html #submenu_admin_network_firewall { width: 14em; } + +.lang_de #submenu_admin_network_firewall { min-width: 16.5em; } +* html .lang_de #submenu_admin_network_firewall { width: 16.5em; } + +.lang_pt-br #submenu_admin_network_firewall { min-width: 15em; } +* html .lang_pt-br #submenu_admin_network_firewall { width: 15em; } + +#modemenu { + width: auto; + background: #000000; + color: #ffffff; + list-style: none; + margin-right: 1px; +} + +#modemenu li { + float: right; + list-style: none; +} + +#savemenu { + float: right; + margin-right: 2em; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + font-size: 80%; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + text-decoration: none !important; + font-weight: bold !important; + color: #555555 !important; + margin: 0.25em !important; + font-size: 100% !important; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table td, +table th { + color: #000000; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { + color: #000000; +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; + line-height: 1.8em; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; + vertical-align: top; +} + +div.cbi-tblsection-create { + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-create .cbi-button { + margin: 0.25em; +} + +input.cbi-section-create-name { + margin-right: -0.25em; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + +} diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt-light/ie6.css b/openwrt/packages/luci/host/www/luci-static/openwrt-light/ie6.css new file mode 100644 index 0000000..1c95185 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt-light/ie6.css @@ -0,0 +1,77 @@ +/* obligatory IE6 Voodoo Code */ + +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div#menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html ul.dropdowns li ul { + width: 10em; +} + +* html ul.dropdowns li li { + clear: both; + float: left; +} + +* html ul.dropdowns li li { + width: 100%; +} + +* html ul.dropdowns li li a { + height: 1%; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.cbi-value-description { + width: auto !important; +} + +* html div.cbi-value-field { + margin-left: 0 !important; + width: 100% !important; +} + +* html .cbi-input-text, +* html .cbi-input-user, +* html .cbi-input-select, +* html .cbi-input-password { + width: 50% !important; +} + +* html .cbi-input-user, +* html .cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; +} + +* html .cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +* html table.cbi-section-table td .cbi-input-text, +* html table.cbi-section-table td .cbi-input-select { + width: 100% !important; +} + +* html div.cbi-page-actions { + text-align: right !important; +} + +* html div.cbi-value-field input, +* html div.cbi-value-field select { + font-size: 90% !important; +} diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt-light/ie7.css b/openwrt/packages/luci/host/www/luci-static/openwrt-light/ie7.css new file mode 100644 index 0000000..67ed9fb --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt-light/ie7.css @@ -0,0 +1,20 @@ +div.cbi-value-field { + margin-left: 0 !important; +} + +.cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +table.cbi-section-table td .cbi-input-text, +table.cbi-section-table td .cbi-input-select { + width: 95% !important; +} + +.cbi-input-user, +.cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; + width: 18.5em !important; +} diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/bg.jpg b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dece957dfd82acae201397ebb04f7b3be93a5fd8 GIT binary patch literal 40537 zcmeFZc{r49|36Np&GyV~7o(a=qNE`^X|dgwJIa=b2}!bNiP5bh>yXM$i%2F*D>V^= zDaKy3C}t)kg)w9s{Lb^5QQgny`5wRHa~$8}_xtDRzRh)A=kk8P-mmv^o-=b@v-ozg zkLO>eh9-tQyu7?T#^67m#Sc9Dc$P0)2LA{DR)GKcR`c<#Si!e;)vA@N1=b1(@UP|P z7Zm#AUxGp?A%6aUiT?{FA}S^(CLk;!DK0Achp3n+6vDe4%vr&=hL3NJs35PiP z;tL+s>ScDTmo4Yr$g>Q^yBx*4SjQvF!^^WA{?E&^^pAJh@)avrt>#+;x}E>U%d?DU z#flZnmapO$;$Owb%ftJ}vgIg|6?_L>R<7D$pyGGq{sU3*jen<=fJs27-1q@E_+49$?FV z{`Y_E_~-EDCaTVR4y#JE@u{XBXy!E++#JCxs_H1V4_p`o?6KZ=U_zBoP@=6(w8LCN zHJNj*nrh;_5A>Nh?-6ZlkKp;M-Isfe5afk3_Z@g)Z6X1rNvQIvB1a$qj1)u^@K~Gk zK~+#H@~6tjH^FPZ2}lAm9Z?1W28TKhfEHv#TZgSG%3M`~?=RSIqU!il5)ixz!GQor zt{@(W#TVGnCaQ|`n%nXkaPR?4z)qyq0Ahh!fx(-A#12~shGQUv0!=r8syGUuIlvTE zM?O`=41^Y7+0o7XUrwx*-mxr`|I4!I%T?zTu2<$qWg1srSGaL=R(e^cF>I=eK35Pm z%To|FaIPRa{)^}O8#ntv>p6v+fma_wh9Em!M)&Rc3#tWpP>>NpXf}X~kOSZ&T`T@_ z-e+)#V;x``u?29&C-}=W!Oe*C0L=(R+#x_$Ds(6x_)}HAickz_0HdI%pa@_h#9{(m z2zp_UNInr*sGOgs2lmEH?BkTlvMLY zFBD59D)6n(cL(QD2@O}GQreL7i$7bEE^gRL^)y!CH-@ikkXJs8%I)>}qHuijL*&&8 zD{ZxQ@4@trWGivdkkro+d4VG)1-7p>#F-ixkHC@ISCTFwBDO>A8x)XNPw*<+XaGhT z?M=P{0dYWFxCNC3J0R0dp&kPc2+nwT{>5r7(vA#)1C9KX5iEZonzclKNkfcG=74~b zF*l4y9wOEwLpc+~Ie?)|BY#f&Z?+zU*8K5X0|zVuGjQu~EJ1*4p+N@5NV9C$PaP>e z`P&f&I3)fuHxO{}@0Q9oLL_@TICv1n2nNU~u=L8W7RY@RhrFbVhH+7 zOF{D+a1I&=#7<5uA=Yvu>L+a=x_&$V&FP2_gB3WI1akuF7aDFPMS-~>zBePpLlb3d zQ(SJF-X}I(-6k+0edrE$>95Vx>N@rJzxLav=XFN0?TKmiAzJJ*)K+`&vJn$v|eBak6%@Rtd@fBjh{08j^W&zoKaamF3n!JRJb1VY{Lom6~OCSK>KLJ1smnN8E0W(}y zfkF;nfadmsWDfHGAOJxRhARGhEad-AX$@CjDV1-+^g~4FlO9ot{9wag-$TwmmBxI0 zKju=Scn!ip?Laydq?biaL?y4~?|hxVEQ%S0deS2%kuQ4gFDG9EWU6RV-}UF~LEi)@ zoIsQaoNZwI8k`0x@LYe6*$XCjXlF�HIdk{QH!GEIfw_#6OH=f|-eH_iR-*mS1r; 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/cascade.css b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/cascade.css new file mode 100644 index 0000000..8aea909 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/cascade.css @@ -0,0 +1,803 @@ +@charset "utf-8"; + +@media all { + +html, +body { + background-color: #4a6b7c; + background-image: url(bg.jpg); + background-position: bottom center; + background-attachment: fixed; + background-repeat: repeat-x; + color: #ffffff; +} + +body { + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + min-height: 98px; + background-image: url(header.png); + background-repeat: no-repeat; + background-position: left center; + background-color: #557788; + color: #ffffff; + text-align: right; +} + +#header h1 { + padding: 1em 1em 0 1em; +} + +#header p { + padding: 0 1em 1em 1em; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +ul.dropdowns { + float: left; + margin: 0; + padding: 0; + width: auto; + list-style: none; +} + +html>body ul.dropdowns { + position: relative; +} + +ul.dropdowns li, +ul.dropdowns ul { + margin: 0; + padding: 0; + list-style: none; +} + +ul.dropdowns li { + float: left; + position: relative; + white-space: nowrap; +} + +ul.dropdowns li ul { + position: absolute; + z-index: 1000; + top: auto; + min-width: 10em; +} + +ul.dropdowns li li { + float: none; + position: relative; +} + +ul.dropdowns li a { + display: block; +} + +ul.dropdowns ul li ul { + top: 0; +} + +ul.dropdowns li ul, +ul.dropdowns li.over ul ul, +ul.dropdowns li.focus ul ul, +ul.dropdowns li:hover ul ul, +ul.dropdowns li.over ul ul ul, +ul.dropdowns li.focus ul ul ul, +ul.dropdowns li:hover ul ul ul, +ul.dropdowns li.over ul ul ul ul, +ul.dropdowns li.focus ul ul ul ul, +ul.dropdowns li:hover ul ul ul ul { + left: -3000px; +} + +ul.dropdowns li.over ul, +ul.dropdowns li.focus ul, +ul.dropdowns li:hover ul { + left: 0; +} + +ul.dropdowns ul li.over ul, +ul.dropdowns ul li.focus ul, +ul.dropdowns ul li:hover ul, +ul.dropdowns ul ul li.over ul, +ul.dropdowns ul ul li.focus ul, +ul.dropdowns ul ul li:hover ul, +ul.dropdowns ul ul ul li.over ul, +ul.dropdowns ul ul ul li.focus ul, +ul.dropdowns ul ul ul li:hover ul { + left: 100%; +} + +#menubar { + position: relative; + width: 100%; + background: #000000; + color: #ffffff; +} + +#menubar .warning { + color: red; + background-color: #557788; +} + +#menubar ul.dropdowns { + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +#menubar ul.dropdowns li ul { + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; +} + +#menubar ul.dropdowns ul li ul { + border-width: 1px; +} + +html #menubar a:link, +html #menubar a:visited { + position: relative; + display: block; + padding: 0.5em; + background: #000000; + color: #ffffff; + text-decoration: none; + font-size: 80%; + font-weight: normal; +} + + +html #menubar a:link:hover, +html #menubar a:visited:hover, +html #menubar a:link:active, +html #menubar a:visited:active, +#menubar a:link:focus, +#menubar a:visited:focus { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.active, +html #menubar a:visited.active, +html #menubar a:link.preactive, +html #menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.warning, +html #menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +#menubar ul.dropdowns li.over>a, +#menubar ul.dropdowns li.focus>a, +#menubar ul.dropdowns li:hover>a { + font-weight: bold; +} + +.lang_de #submenu_mini_system { min-width: 13.3em; } +* html .lang_de #submenu_mini_system { width: 13.3em; } + +.lang_pt-br #submenu_mini_network { min-width: 14em; } +* html .lang_pt-br #submenu_mini_network { width: 14em; } + +.lang_pt-br #submenu_mini_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_mini_system { width: 11.5em; } + +.lang_ru #submenu_mini_system { min-width: 18em; } +* html .lang_ru #submenu_mini_system { width: 18em; } + +.lang_pt-br #submenu_admin_index { min-width: 11em; } +* html .lang_pt-br #submenu_admin_index { width: 11em; } + +.lang_ru #submenu_admin_index { min-width: 15.5em; } +* html .lang_ru #submenu_admin_index { width: 15.5em; } + +.lang_ru #submenu_admin_status { min-width: 10.5em; } +* html .lang_ru #submenu_admin_status { width: 10.5em; } + +.lang_de #submenu_admin_system { min-width: 13.3em; } +* html .lang_de #submenu_admin_system { width: 13.3em; } + +.lang_fr #submenu_admin_system { min-width: 14.5em; } +* html .lang_fr #submenu_admin_system { width: 14.5em; } + +.lang_pt-br #submenu_admin_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_admin_system { width: 11.5em; } + +.lang_ru #submenu_admin_system { min-width: 18em; } +* html .lang_ru #submenu_admin_system { width: 18em; } + +#submenu_admin_services_chillispot { min-width: 15.5em; } +* html #submenu_admin_services_chillispot { width: 15.5em; } + +#submenu_admin_services_coovachilli { min-width: 15em; } +* html #submenu_admin_services_coovachilli { width: 15em; } + +.lang_ru #submenu_admin_network_routes { min-width: 15.3em; } +* html .lang_ru #submenu_admin_network_routes { width: 15.3em; } + +#submenu_admin_network_firewall { min-width: 14em; } +* html #submenu_admin_network_firewall { width: 14em; } + +.lang_de #submenu_admin_network_firewall { min-width: 16.5em; } +* html .lang_de #submenu_admin_network_firewall { width: 16.5em; } + +.lang_pt-br #submenu_admin_network_firewall { min-width: 15em; } +* html .lang_pt-br #submenu_admin_network_firewall { width: 15em; } + +#modemenu { + width: auto; + background: #000000; + color: #ffffff; + list-style: none; + margin-right: 1px; +} + +#modemenu li { + float: right; + list-style: none; +} + +#savemenu { + float: right; + margin-right: 2em; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + font-size: 80%; +} + +#maincontent h2 { + font-size: 150%; + font-family: Trebuchet MS, Verdana, sans-serif; + font-weight: bold; + margin: 0.25em 0 0.7em 0; + border-bottom: 1px solid; + padding-top: 10px; + padding-bottom: 4px; +} + +#maincontent h3 { + margin: 0.5em 0 1.1em 0; + font-size: 125%; + font-weight: bold; + font-style: italic; + font-family: Trebuchet MS, Verdana, sans-serif; + color: #27408B; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + text-decoration: none !important; + font-weight: bold !important; + color: #555555 !important; + margin: 0.25em !important; + font-size: 100% !important; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table td, +table th { + color: #000000; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { + color: #000000; +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; + line-height: 1.8em; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; + vertical-align: top; +} + +div.cbi-tblsection-create { + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-create .cbi-button { + margin: 0.25em; +} + +input.cbi-section-create-name { + margin-right: -0.25em; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + +} diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/dashboard.css b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/dashboard.css new file mode 100644 index 0000000..ba9691e --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/dashboard.css @@ -0,0 +1,99 @@ +@charset "utf-8"; + +@media all { + +div.dashicon { + float: left; +} + +div.dashicon a { + background-image: url(icons/default.png); + background-repeat: no-repeat; + background-position: top; + display: block; + width: 70px; + padding-top: 70px; + color: #000000; + text-decoration: none; + text-align: center; + margin: 2em; + font-weight: bold; +} + +div.di_network a { + background-image: url(icons/network.png); +} + +div.di_luci a { + background-image: url(icons/desktop.png); +} + +div.di_index a { + background-image: url(icons/overview.png); +} + +div.di_logout a { + background-image: url(icons/logout.png); +} + +div.di_freifunk a { + background-image: url(icons/freifunk.png); +} + +div.di_status a { + background-image: url(icons/status.png); +} + +div.di_system a { + background-image: url(icons/system.png); +} + +div.di_syslog a { + background-image: url(icons/shell.png); +} + +div.di_ntpc a { + background-image: url(icons/datetime.png); +} + +div.di_leds a { + background-image: url(icons/lightbulb.png); +} + +div.di_reboot a { + background-image: url(icons/restart.png); +} + +div.di_passwd a { + background-image: url(icons/login.png); +} + +div.di_statistics a { + background-image: url(icons/stats.png); +} + +div.di_packages a { + background-image: url(icons/package.png); +} + +div.di_sshkeys a { + background-image: url(icons/key.png); +} + +div.di_upgrade a { + background-image: url(icons/flash.png); +} + +div.di_services a { + background-image: url(icons/worker.png); +} + +div.di_backup a { + background-image: url(icons/switch.png); +} + +div.di_fstab a { + background-image: url(icons/harddisk.png); +} + +} \ No newline at end of file diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/header.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/header.png new file mode 100644 index 0000000000000000000000000000000000000000..5a7c9a10d99fa7b005f8ea3cec34fed279cf4d53 GIT binary patch literal 33244 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 W3tk86V&WM90000 + Copyright (C) 2007 Johann Ollivier Lapeyre + Copyright (C) 2007 Kenneth Wimer + Copyright (C) 2007 Nuno Fernades Pinheiro + Copyright (C) 2007 Riccardo Iaconelli + Copyright (C) 2007 David Miller + +and others + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library. If not, see . + +Clarification: + + The GNU Lesser General Public License or LGPL is written for + software libraries in the first place. We expressly want the LGPL to + be valid for this artwork library too. + + KDE Oxygen theme icons is a special kind of software library, it is an + artwork library, it's elements can be used in a Graphical User Interface, or + GUI. + + Source code, for this library means: + - where they exist, SVG; + - otherwise, if applicable, the multi-layered formats xcf or psd, or + otherwise png. + + The LGPL in some sections obliges you to make the files carry + notices. With images this is in some cases impossible or hardly useful. + + With this library a notice is placed at a prominent place in the directory + containing the elements. You may follow this practice. + + The exception in section 5 of the GNU Lesser General Public License covers + the use of elements of this art library in a GUI. + + kde-artists [at] kde.org diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/datetime.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/datetime.png new file mode 100644 index 0000000000000000000000000000000000000000..641653c07025465c8b090a2eff56f1557a26e88c GIT binary patch literal 5250 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 IM6N<$g51#QkpKVy literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/default.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/default.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe97ae308fdf6b431eb3e92eb95851589a9df07 GIT binary patch literal 5022 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 oEsqiaLPi}MG{G#OQ4v=$ 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/flash.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/flash.png new file mode 100644 index 0000000000000000000000000000000000000000..7e9dc7861d1158a272920e0ca5c5e9bf0bcf969a GIT binary patch literal 5065 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/key.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/key.png new file mode 100644 index 0000000000000000000000000000000000000000..1ebfaa43a42d4834cdcbde4716e37c09a55e8126 GIT binary patch literal 4129 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/lightbulb.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/lightbulb.png new file mode 100644 index 0000000000000000000000000000000000000000..3a6755bc3c404c33fa5980c62865ae5f3f4b1134 GIT binary patch literal 5550 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/login.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/login.png new file mode 100644 index 0000000000000000000000000000000000000000..8e881ba3b391eb6460206e8694a24325ef3a769d GIT binary patch literal 2918 zcmV-s3z_tZP))5xvchtv{H}~@jpa)oD!r+k>J1~mnc%CNL+FuLP>J~KS#}*xjscte(Jq-})p{7*C1VZ%c z=WHDSAOJYQ5LF{F7m6_eJ%5q_ZrBUkE*R}Xw&^;N76T2I=2MOB^z|4b`gK?`0EAp? z05Q&)V#w5A5kla55O^&JgAO%F!d^-$z+P=F{;ExbWwDUgbD}*AnZ0)G6&HWc?Et5omNXm zTm90iLJRUdjCHTzv?vmA z0=`=GmEx zcmN|KBas(S1R%`tT-_J#NoXhB@F5`^5K_r9I8hyx8zh}HB;eSwWAOO#V+?c#!Sg(t z95F*jQ}WvLq~YOV0zpXtfkGs(tfNxOeIX)PG&brxGc!YFl8D%}elnoFe*n5G<9d_;C zL(2xxY7-@$I>>mn%^{T%^2CRMT5W5m${;Z}NULBTS_mce=E2C$c>xar$c6w87vKmS zSuu@d#sx|)69Ayn1Yk`LX%{=Yj7a%k9du~X)Dl21RSq9M9K9g<%*XAd0=IA9hJk?r z6$(3QVM~0{jr3hO@_yAD4!(R~j81 zjco+y=jW9d$VB@As%fSrX~roBkx(csxX^>(zkrd>bG;EE74QT!J#Kn|erI>Fy#YN- z8^Mh90ulr{yk!Gan_%*K5}P5%wgGCuZW|z7lK?Xiid5j4;@@huVnu%RtmwH|mBh&g zfMo+{Zl*CzKmzo!k{noOnsJS~1W6b+;O5Pnl9Em|2A32~uS+^rIYAp>i?Ln>!}6*+ z7iS+F-{4kyJQ|sXz=tNke*QFZ}FpEeKl`5IpF9&7~)b$$Uj-w^?=7kGUyG z4;CS}cQ3Z35CGK|gy9A)8^E_&1#};pU>Z_`d%;N$f(U&ON;lMH`}LP9>uc6qWJOGa z;xJtO0dO<;e3q6ThjF3L|CnV1k}`r2TLN5Q=^U_B=Gm_+ET*;2(nX7DO>{+zHn~;m zVA+7pt~sIIAkz{MPZF3L=ashoR!6@@?z+aJ&N?X%z?fkJnB|%w={O+yq&qHh}aN-x3GCvqhjm)yH|kG>In1^_QWx^?Ro0YG~Td3bvA z1xP;+j*X2;#`F0+k^D5bTrSheuavyy00#cqaRv--+A0PiZi9Mb0T0oH4 z(`W7UGKG%74xc}N{+npj9^k!I>{~?_S37s^Tno04wrm8iUcEYkD>RLhn#M`JhWAcm zGZE=*5viakPdwS@f28BYxYB=V3&4!| zq-GQKI|v{MLZkrOYjESn4e732B$*>10Yz=pCk!wTVE_L8Ff}!W>VSP*7bPZ*YVicL zVFZTM#7YRF50BS3B&~0hF*c~Jw>|IYAH4tV9|1r}guL>8DnJZVn@R4KD_1`CJnsXq z)&ADco(e>+p{?GFAVx1W6L2aZBl7wCWxE27eEfIZlMHuX4 zP?rY_g;K6qD&$av2k~uj7F}VcSS)47#$Fj2du43AhKwyOFRxb1y3g*acu0fR{G?7w&>pTMh37 Qz5oCK07*qoM6N<$f<{9 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/logout.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..9f44fd0ef916610a15efbdf654beecced4e429ca GIT binary patch literal 3577 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/network.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/network.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8033452536c47cc213b637991c5847df7a9abf GIT binary patch literal 6602 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 IM6N<$g0J|yl>h($ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/overview.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..0f3edc162668a0943be97cd0ef27e7c020660950 GIT binary patch literal 4553 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/services.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/services.png new file mode 100644 index 0000000000000000000000000000000000000000..54e17dd09f1f2dee8d619edcbd8326390852ac57 GIT binary patch literal 4630 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 M07*qoM6N<$f}0eNO#lD@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/shell.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/icons/shell.png new file mode 100644 index 0000000000000000000000000000000000000000..8e2f3c17f81528ba01f5e9691bd00e2d3fba3ebf GIT binary patch literal 2110 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 M07*qoM6N<$f}0eNO#lD@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie6.css b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie6.css new file mode 100644 index 0000000..1c95185 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie6.css @@ -0,0 +1,77 @@ +/* obligatory IE6 Voodoo Code */ + +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div#menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html ul.dropdowns li ul { + width: 10em; +} + +* html ul.dropdowns li li { + clear: both; + float: left; +} + +* html ul.dropdowns li li { + width: 100%; +} + +* html ul.dropdowns li li a { + height: 1%; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.cbi-value-description { + width: auto !important; +} + +* html div.cbi-value-field { + margin-left: 0 !important; + width: 100% !important; +} + +* html .cbi-input-text, +* html .cbi-input-user, +* html .cbi-input-select, +* html .cbi-input-password { + width: 50% !important; +} + +* html .cbi-input-user, +* html .cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; +} + +* html .cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +* html table.cbi-section-table td .cbi-input-text, +* html table.cbi-section-table td .cbi-input-select { + width: 100% !important; +} + +* html div.cbi-page-actions { + text-align: right !important; +} + +* html div.cbi-value-field input, +* html div.cbi-value-field select { + font-size: 90% !important; +} diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie7.css b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie7.css new file mode 100644 index 0000000..67ed9fb --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt.org-oxygen/ie7.css @@ -0,0 +1,20 @@ +div.cbi-value-field { + margin-left: 0 !important; +} + +.cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +table.cbi-section-table td .cbi-input-text, +table.cbi-section-table td .cbi-input-select { + width: 95% !important; +} + +.cbi-input-user, +.cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; + width: 18.5em !important; +} diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org/bg.jpg b/openwrt/packages/luci/host/www/luci-static/openwrt.org/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dece957dfd82acae201397ebb04f7b3be93a5fd8 GIT binary patch literal 40537 zcmeFZc{r49|36Np&GyV~7o(a=qNE`^X|dgwJIa=b2}!bNiP5bh>yXM$i%2F*D>V^= zDaKy3C}t)kg)w9s{Lb^5QQgny`5wRHa~$8}_xtDRzRh)A=kk8P-mmv^o-=b@v-ozg zkLO>eh9-tQyu7?T#^67m#Sc9Dc$P0)2LA{DR)GKcR`c<#Si!e;)vA@N1=b1(@UP|P z7Zm#AUxGp?A%6aUiT?{FA}S^(CLk;!DK0Achp3n+6vDe4%vr&=hL3NJs35PiP z;tL+s>ScDTmo4Yr$g>Q^yBx*4SjQvF!^^WA{?E&^^pAJh@)avrt>#+;x}E>U%d?DU z#flZnmapO$;$Owb%ftJ}vgIg|6?_L>R<7D$pyGGq{sU3*jen<=fJs27-1q@E_+49$?FV z{`Y_E_~-EDCaTVR4y#JE@u{XBXy!E++#JCxs_H1V4_p`o?6KZ=U_zBoP@=6(w8LCN zHJNj*nrh;_5A>Nh?-6ZlkKp;M-Isfe5afk3_Z@g)Z6X1rNvQIvB1a$qj1)u^@K~Gk zK~+#H@~6tjH^FPZ2}lAm9Z?1W28TKhfEHv#TZgSG%3M`~?=RSIqU!il5)ixz!GQor zt{@(W#TVGnCaQ|`n%nXkaPR?4z)qyq0Ahh!fx(-A#12~shGQUv0!=r8syGUuIlvTE zM?O`=41^Y7+0o7XUrwx*-mxr`|I4!I%T?zTu2<$qWg1srSGaL=R(e^cF>I=eK35Pm z%To|FaIPRa{)^}O8#ntv>p6v+fma_wh9Em!M)&Rc3#tWpP>>NpXf}X~kOSZ&T`T@_ z-e+)#V;x``u?29&C-}=W!Oe*C0L=(R+#x_$Ds(6x_)}HAickz_0HdI%pa@_h#9{(m z2zp_UNInr*sGOgs2lmEH?BkTlvMLY zFBD59D)6n(cL(QD2@O}GQreL7i$7bEE^gRL^)y!CH-@ikkXJs8%I)>}qHuijL*&&8 zD{ZxQ@4@trWGivdkkro+d4VG)1-7p>#F-ixkHC@ISCTFwBDO>A8x)XNPw*<+XaGhT z?M=P{0dYWFxCNC3J0R0dp&kPc2+nwT{>5r7(vA#)1C9KX5iEZonzclKNkfcG=74~b zF*l4y9wOEwLpc+~Ie?)|BY#f&Z?+zU*8K5X0|zVuGjQu~EJ1*4p+N@5NV9C$PaP>e z`P&f&I3)fuHxO{}@0Q9oLL_@TICv1n2nNU~u=L8W7RY@RhrFbVhH+7 zOF{D+a1I&=#7<5uA=Yvu>L+a=x_&$V&FP2_gB3WI1akuF7aDFPMS-~>zBePpLlb3d zQ(SJF-X}I(-6k+0edrE$>95Vx>N@rJzxLav=XFN0?TKmiAzJJ*)K+`&vJn$v|eBak6%@Rtd@fBjh{08j^W&zoKaamF3n!JRJb1VY{Lom6~OCSK>KLJ1smnN8E0W(}y zfkF;nfadmsWDfHGAOJxRhARGhEad-AX$@CjDV1-+^g~4FlO9ot{9wag-$TwmmBxI0 zKju=Scn!ip?Laydq?biaL?y4~?|hxVEQ%S0deS2%kuQ4gFDG9EWU6RV-}UF~LEi)@ zoIsQaoNZwI8k`0x@LYe6*$XCjXlF�HIdk{QH!GEIfw_#6OH=f|-eH_iR-*mS1r; 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org/cascade.css b/openwrt/packages/luci/host/www/luci-static/openwrt.org/cascade.css new file mode 100644 index 0000000..90081a6 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/openwrt.org/cascade.css @@ -0,0 +1,804 @@ +@charset "utf-8"; + +@media all { + +html { + min-height: 100%; + height: auto; +} + +body { + color: #ffffff; + background-color: #4a6b7c; + background-image: url(bg.jpg); + background-position: bottom center; + background-repeat: repeat-x; + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; + padding-bottom: 1.5em; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + min-height: 98px; + background-image: url(header.png); + background-repeat: no-repeat; + background-position: left center; + background-color: #557788; + color: #ffffff; + text-align: right; +} + +#header h1 { + padding: 1em 1em 0 1em; +} + +#header p { + padding: 0 1em 1em 1em; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +ul.dropdowns { + float: left; + margin: 0; + padding: 0; + width: auto; + list-style: none; +} + +html>body ul.dropdowns { + position: relative; +} + +ul.dropdowns li, +ul.dropdowns ul { + margin: 0; + padding: 0; + list-style: none; +} + +ul.dropdowns li { + float: left; + position: relative; + white-space: nowrap; +} + +ul.dropdowns li ul { + position: absolute; + z-index: 1000; + top: auto; + min-width: 10em; +} + +ul.dropdowns li li { + float: none; + position: relative; +} + +ul.dropdowns li a { + display: block; +} + +ul.dropdowns ul li ul { + top: 0; +} + +ul.dropdowns li ul, +ul.dropdowns li.over ul ul, +ul.dropdowns li.focus ul ul, +ul.dropdowns li:hover ul ul, +ul.dropdowns li.over ul ul ul, +ul.dropdowns li.focus ul ul ul, +ul.dropdowns li:hover ul ul ul, +ul.dropdowns li.over ul ul ul ul, +ul.dropdowns li.focus ul ul ul ul, +ul.dropdowns li:hover ul ul ul ul { + left: -3000px; +} + +ul.dropdowns li.over ul, +ul.dropdowns li.focus ul, +ul.dropdowns li:hover ul { + left: 0; +} + +ul.dropdowns ul li.over ul, +ul.dropdowns ul li.focus ul, +ul.dropdowns ul li:hover ul, +ul.dropdowns ul ul li.over ul, +ul.dropdowns ul ul li.focus ul, +ul.dropdowns ul ul li:hover ul, +ul.dropdowns ul ul ul li.over ul, +ul.dropdowns ul ul ul li.focus ul, +ul.dropdowns ul ul ul li:hover ul { + left: 100%; +} + +#menubar { + position: relative; + width: 100%; + background: #000000; + color: #ffffff; +} + +#menubar .warning { + color: red; + background-color: #557788; +} + +#menubar ul.dropdowns { + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +#menubar ul.dropdowns li ul { + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; +} + +#menubar ul.dropdowns ul li ul { + border-width: 1px; +} + +html #menubar a:link, +html #menubar a:visited { + position: relative; + display: block; + padding: 0.5em; + background: #000000; + color: #ffffff; + text-decoration: none; + font-size: 80%; + font-weight: normal; +} + + +html #menubar a:link:hover, +html #menubar a:visited:hover, +html #menubar a:link:active, +html #menubar a:visited:active, +#menubar a:link:focus, +#menubar a:visited:focus { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.active, +html #menubar a:visited.active, +html #menubar a:link.preactive, +html #menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.warning, +html #menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +#menubar ul.dropdowns li.over>a, +#menubar ul.dropdowns li.focus>a, +#menubar ul.dropdowns li:hover>a { + font-weight: bold; +} + +.lang_de #submenu_mini_system { min-width: 13.3em; } +* html .lang_de #submenu_mini_system { width: 13.3em; } + +.lang_pt-br #submenu_mini_network { min-width: 14em; } +* html .lang_pt-br #submenu_mini_network { width: 14em; } + +.lang_pt-br #submenu_mini_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_mini_system { width: 11.5em; } + +.lang_ru #submenu_mini_system { min-width: 18em; } +* html .lang_ru #submenu_mini_system { width: 18em; } + +.lang_pt-br #submenu_admin_index { min-width: 11em; } +* html .lang_pt-br #submenu_admin_index { width: 11em; } + +.lang_ru #submenu_admin_index { min-width: 15.5em; } +* html .lang_ru #submenu_admin_index { width: 15.5em; } + +.lang_ru #submenu_admin_status { min-width: 10.5em; } +* html .lang_ru #submenu_admin_status { width: 10.5em; } + +.lang_de #submenu_admin_system { min-width: 13.3em; } +* html .lang_de #submenu_admin_system { width: 13.3em; } + +.lang_fr #submenu_admin_system { min-width: 14.5em; } +* html .lang_fr #submenu_admin_system { width: 14.5em; } + +.lang_pt-br #submenu_admin_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_admin_system { width: 11.5em; } + +.lang_ru #submenu_admin_system { min-width: 18em; } +* html .lang_ru #submenu_admin_system { width: 18em; } + +#submenu_admin_services_chillispot { min-width: 15.5em; } +* html #submenu_admin_services_chillispot { width: 15.5em; } + +#submenu_admin_services_coovachilli { min-width: 15em; } +* html #submenu_admin_services_coovachilli { width: 15em; } + +.lang_ru #submenu_admin_network_routes { min-width: 15.3em; } +* html .lang_ru #submenu_admin_network_routes { width: 15.3em; } + +#submenu_admin_network_firewall { min-width: 14em; } +* html #submenu_admin_network_firewall { width: 14em; } + +.lang_de #submenu_admin_network_firewall { min-width: 16.5em; } +* html .lang_de #submenu_admin_network_firewall { width: 16.5em; } + +.lang_pt-br #submenu_admin_network_firewall { min-width: 15em; } +* html .lang_pt-br #submenu_admin_network_firewall { width: 15em; } + +#modemenu { + width: auto; + background: #000000; + color: #ffffff; + list-style: none; + margin-right: 1px; +} + +#modemenu li { + float: right; + list-style: none; +} + +#savemenu { + float: right; + margin-right: 2em; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + font-size: 80%; +} + +#maincontent h2 { + font-size: 150%; + font-family: Trebuchet MS, Verdana, sans-serif; + font-weight: bold; + margin: 0.25em 0 0.7em 0; + border-bottom: 1px solid; + padding-top: 10px; + padding-bottom: 4px; +} + +#maincontent h3 { + margin: 0.5em 0 1.1em 0; + font-size: 125%; + font-weight: bold; + font-style: italic; + font-family: Trebuchet MS, Verdana, sans-serif; + color: #27408B; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + text-decoration: none !important; + font-weight: bold !important; + color: #555555 !important; + margin: 0.25em !important; + font-size: 100% !important; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table td, +table th { + color: #000000; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { + color: #000000; +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; + line-height: 1.8em; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; + vertical-align: top; +} + +div.cbi-tblsection-create { + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-create .cbi-button { + margin: 0.25em; +} + +input.cbi-section-create-name { + margin-right: -0.25em; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + +} diff --git a/openwrt/packages/luci/host/www/luci-static/openwrt.org/header.png b/openwrt/packages/luci/host/www/luci-static/openwrt.org/header.png new file mode 100644 index 0000000000000000000000000000000000000000..5a7c9a10d99fa7b005f8ea3cec34fed279cf4d53 GIT binary patch literal 33244 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 W3tk86V&WM90000&6s+|hR1 zZnq`1B#NZCv&iDBz3Oe49{}V--URN&adTmWzuI-kdKf#^E5g%8Smiok0v9h3XH-4^qb0N&FNg8Kv^ zz5{S%onHg7@Y%}|*ZL}<-BkU&lyPp%A|^85j~P#YBh+L}CAb@?uQ!Ey;=5M3y#R1B z`G4&9|5AlEPLYWFUFH0CsM@;()%r$->sjutjW(r!+sU1uE|f9HhQ4CkkxLCBB;-8P zp9}i$WdI*aDd(=8yYq~lAeSbqpGVw#?jbKNm>ftcQzz1g1osd9fs+Uz8tMgo(`PB= z72<0Hz})UI<@a{AKpUr=WS(DQ9G8e)Y+4H-A+*>S&*2*5o&^v?v2jf4eC$p>r_(Xl zp}HrIW6t7~AIF7V{8#Tik~dK!|^P zPC`2$vba-fBXX~w(~jKsQ=4MU|9`xo1^HdTJwgSb-0=_qZblsc>C9)P1*#+gL=!52 zQ2Z{a1Q267D)Bpw`Oaf_L3pho!8ntt24n>7!g2m3x}!It$@Luc*2bzV2_UV7j*$C? zv@hlQB|i_vm|+05P|j&VzChmYE=Ag%GtvAs;yN{UrM~v&>^5DKcB$V2m0JEmq4ojg z{41UiUaR=xt{wL5XFB?sSlDcoU?>43aChFDcA>aNVKjVSP^fQ5FO+C&i~hUJFt$&~ z2MZI^7X6C!}P+SGFL^a&s-Z91s5 zxQ9BT`lvm>#`>-FF#k)>d$wOv5AB?5?_T4Yd_$c|b4hhPO>I|gA%yC)sTRb0t`Ook zNY^G%|4?P5-@>O6$1b%w=7%n%l&>ZBF(wQ#cYH|%5be8?8ZzE$GWVIfQq6Nz=Bzn# z9Z_o&tpVv^aS!pe=}ikV8byVsm@g+qNQjMc$%%*wY3C?H$h0p;2sr@oqlI(MtaEEH zH`X6ST!&K49^3aM0Yt0XDce2QkE@}My#b^MsVx^9>Pc{fNSLbQt+kM`Rgf$=&rUHoT%c2$nQb-X-Y6>CL=lXs`62O}aJCDDwJT`N@9dYd3gk5?P$yt!5 z0!Yb8hRT0|x{bEVyGEW3=e;BP-jfEz*ZvyLvbppqfb@*>ch`X?sTsBa;uAhXpfsh# z+$;3h)P9AYQ!?U4O#WWO%#K|MaftKDuV(126DeiTB&D?phq0F@>RZl4Iu$@D$9&p9 zstJEd-Ja8j>xBI;MU4qRcX6yCBu!a^24qUli+j&)tAY_ga)pmp#0Vm(=Z5x`dK`QX zsUcdB?}*!y)5jR?!sn6qrusf|Cer7V|CiK&P&uML)_+U;k!a{jxob5EtpGYn7L3(YNz9%>uD9G&p)BG`Z84m0&EwiOKE55IV45O zgb*iKUT9+bQTqF#stzkqXIC5(X+)hMFO?JQ@nTqsq0+IJX2}T^5uZwH7hR--AZL1;}F3aEDPOJmd9Z-Gh!qB>6}$jvcYGBVTN z-V)Kd8?&Bt>|Kp(&Gz}6P-AaiD+G6XztCfI`c~_@v4WMvve_VKVWj#l1>y?6rR>5e z1gr}gJI2^%%GC1M$(zf*(7^y)T?SwsAxOq!=N^=$05Y4A=Kr z&nmHLPLP|JpGZHBxaJhfN%5+bGIYTs-RVa5A+?-*&7CgQ;$9+GjG;!R(Iu94$2A0y zT16JASfdH1*SUO%Hd>1GJ(F%1$x z7SyVxzvol|95G$gvE zMf6L^xha$uPRy}6(HnF3r3}#o;(Qkl3Hp@6t(2355HH|%E^{89`Tk9!zLpf4N(dk+ zIcQo_(%GH9u|gODB>27^q!C|yE;?vqRD1V{lsq6YP-r%&{5_UF&j~TEjctlqT96)1 z&T&B{mCu=NV)ASpW{yt?uKwkOxz@^vN@aqf%&Re_rT{`6%|nS;`2W)TBcx+*?c^EK z-kt=Il=iQdlsq7aSX*dweK~(hQzY(!qNj&+P*FUh=@p- z8j~7z9vF(~9iK0b{r<&>aa>}wTp*MSdJXMD?!?{O_`7H=fQ-1HGn&wcr_>K2M{pU% z!K>uhnZHXV(3e6kYo(zNz0aICeks!ipoFBHYA#sN@c5k_eibg znwt$ZMmVgc0iixG7s@(8BP;|hwF{y1*$5ht)@@t^)$@Ra+_Y4dR7#Uh)0z;(Z5A{C zzA0-yHRk{0^h@;kv zdx#Ti>ozhTa=w^aSyF2{oz{lZjC5nheDM9kb*OWG__z~sETtoA45<+uHM5~og}IKP z1+bwU;~I-nZep+2=8X_q&#k^_wqBp@Ufb1#)J&+gQ?!R@L#Xdp>e?lcn9+a;As%5_ z$e{AAn7hxCuZj(o0215IQ~{)>e*)FLM%x+s1d!Nht+{h330-V@sRd)-H?-}o=f=_V zfb2CTCZLkhFeQYLksnTbtZUcbNYRYM2q08`E3xftr2&xSF?KEvHx_D}5>YN>V>$x_hJ+0fg3JpkS>Ef#q`vatQN=>c( zvX@`h1Xo7X7Wa=Krj03P28x9==h>PHd8JhAR07D7)+Wa+SHgdRT41QLdmn9wzEu6R zH}mvp<2x!%qF^W+80yE7o9%S%W*A>2%%z2Xlq|mX~S;GhWMr?wcpuHp-J?pi=6A?w~40$G#cqQ1){!O?S!KA0bEp zqVNxmB5XA0`v_eiW7}CO5n0Ld>ooh%3IRYy?C4S!FpBRz=QmNyA&=@lMgS?X=(KiD?1j-5^wHYO3`~h)bkwwT zh;6C4NwL3Qo>}0ZS;w`cCn1j71T*zpDdht~wYXE8G;C_-u;?*;J{7fpuhhxudZ6TU zP69ijrqgr8ObKchtcztX@}O3=)+KUtBT%11d5u!Z$fnN@bt?7}&*lif{T4nTy=9l( z2SyZ{_JWc>z!- z^Y1K%(H!4Pn&lW~i#4mJ_UQ){(%00*CPiSR5FUDTdR`**_e3F}G5OS(|8mVdBbbSL zXN2F?KCM?9)+~T9tz-xWn4Df8Cs<*sHRN+x1s+G5X7{5$NFsQ}U{{dKK-ubnw{E%k1%bU1RW zQtCM>@7#*SwbRs>6iRFUo>Tk5=8auOTdZ@+b})?z)qs=;*PFhm*++q9Zbz3>oz(RM zP8ASBC;b%dT&!?Q9gS7W1T$?DwE#k;{udeNwxC8EM_v3z`2ObTIU=jK_B5lU38vQv zxYu@3^k+^0xx93tzB>tm$39y6NjRpSysN@zM_qFrK+W6n9o{Fs>Un#!b=B;-Z> z&{`!e%eiN*IyY2{dun7Xq03jw6}c_r3V+PXiZ1X3^#d|zJchiZ;g;Ul+CJ!@qomIaWd#j!@)pGF*elc=4s zi`LROx*H|s#fW>wYLBMxQ!VbPn}x;jXdy(7GjD8rlCC3!C@O&H-EPhfz2|wD+sI@y zCq1VAC`x|Wt$a;-eSmE<#gcZRhg9s3BaXcuaV#ZC0tnK4R#Kr_I7d?l$L@Ap|87II zAHMIQMbuC1GqHxqB&HFm>Z=eTg!0E9ay{z%QBrz`BQUeLODS(IoL?){`BB8NzNnqj zi)N|-Qgbn{G3mDqfA^7-&9_A#a-WG29C>>a@_K9|~%` z_WHtgYb~BJ8W5_m;n?plHJv);;8GE-v4xQAqTxy1=b&@QxY<7hr0POaDg z&Z$M#!3)Uqsi2H%ah=nn!)gs;g)WKt#r>6v?Vi*2#5kdrHo^GX`6TgrB?XY_&t|D_-G|^-YGW>~+ZdAjr*#_{53LiC zvRM@6>weJ+lF)k6MGbML^ zWhYdc_V%O!akiHekYh{b)$G?)uT#?&d(tfEw! zys4m_BP3Dvx7BZpN&t}FkwMSyDsQ_$`w0q_ph^p9C$X zd@rM&l+ioiM;uG3nM)~{mqKW@;oN5>HA-i@5mGLtVb6J1O3eX20VL&qHPYsfr~w(R zjiWoE?lsddkJ8_R8mfEOO!`yO{9Md2j)P~e#-@c6YV7yk+EI421%0&k7HxA%EtnLi z(^O)w(IQD2^+FvwCg$Id7OwYl!M?|EKjK(l)K2L>ca0*H@LvrsJoB!`%2r(9B> ziBxCf7(&f*zV~bRspQhD2Bd~YE`^@j(wv-PR1~Uh$~p;a$@LN2=Fo-RrwynTbrdw2 z>YeVb!hP`ZFy$mEM=PcnHoj$rtjP1B>;RkIo z&73ypo@@R-!o1(YPYd=Vh8Gc$8*|Qqu@hsgaG9h5!LF*kBvjAll7B*uz*^G;le$>; z6o%W&f*l)O;ZjFC)X;$Bwz-uCWKHz8xU&Ytf;taK zY3+f1pWJrm`VzDfy3BnAfNy5ZFIRAG8mQ6MxqHM2Ag?Cg!$r)_GG{?5=}$3*YH{yn z*BwfV$;kV>6cUnlZWG#`P8cei?@Y$zUL8;YcYUDV+E@+yfs1u4ox>hbifdBu(n<;+ zDWAn?nT!zf7%Bz3kDq7sqh)&gHwdpCb6-jUglhbz*EtnJQ0?49$}r@#l^QBDSCu4W z6k)>+oF`i+EG$9qZLYCt&!Ol>Wh(K`2_g2*I|kR_ra0r}+;8c#)*6D)bL@w8DY4g5 z1zgHL%=RsGx2Y#>s$^5K$EW�O4k%UXqa2)QnL%wTI3 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

10D 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%0AEM4f&!17EkA3D5d>_59ymTFO-X^ zKVzwL!6$G(cHhNE-Mu}c@lSab7~_>wAeXSiuA%Yt)wA7_43qv$L#l-qWh|-82Sm~{ z6PW0^*qgZ<8-DK;5Xb z;TaK}z?c`zDowcMAb3`b5M*8WCoXuk9<0k}zS6Jffh8>`U{Nu!zVrd)=&t=W9@X_r zCnF8yr#(x4YRk)>WKHRSXx6WD-JkJLewgYsA96A}v#p(3jZFdT`>P$p+Ks>6wSNv{ zVBJixw3s;-=&pHtZd~>9)5n!An0&T^7m?HFp_}eAB`)mI!j&k47V`97%(4o)ms#yB z$STX(j^ojcVyh+TXjBf01~#7|x-pNsx!h;rQ!1$Uo3e?IAm%(3HxaZv5tD5cYk^As z=K6J)*ojNz^hRD!tr{+sTkv+Rk-l{8Qdz+t7oF+HuFO9a83B8K^Hod3%ZXjh>>A+w#ZufLY#IT=cBO)OT`#aG}p-Gw^zj2rQ zrj2u*{=y%ATixa6WG3H4hlHij^_Tcv{1b{|O!d>pCAao+=gu`ioS%5lC7?Uq%@r-T z68iWoM)h7&W1m_pc{Adh9mdDb8gD`(S~i*^5E=?stDrSqkux}d!0=kzrvg)tz~go6 z1Jr`ED99$S96zJYB|Ztb-i~VQdzejD>J6Q2s#<2MC_exnX&u4%z07|3nO7iY^gZdo zq9lWP_8jxuDE8`k}altrgMpymG(C)QZ9QlG1mR=P|#BF zWykgDhNvxE?LR2rB5*yl7K!l!OLIW<2IDwqryr!PF3q*?v}xsih_KCCF0cr>x?A_I@Gw^^iY?Xq|CzWv?P&N$!x zD*E=Bg3fS(!_EK%;lg=55qKzMTkl*@Z$xp2X1Pee39X+AP|L;iE$$+B&#i22g;oLv=!O?>rtRGT8yScJWM5FkXfW(X6JvWhOZUm1Nayis_;v_>y@s=o+bVJ1L> zU;|D_@t|(kYl8CRcm3G8pB^Bl6MSn`0^qUU(U%a@%~z#>H8{e! z5Dno!q9NtmT4F4~)AEJ^BJyD;)ZMZt+7A zo^E|V4Wv0zP4b(SJnl^2r~YKg?KLD;%aSPV^en^BoJTt3N{_IHyxnmMcZwvJ(g^-x z`L->wg_)#40sy@FSKQ3*pgS6-7Fe&=^)@SDa*VN=vQMD8qf)ZSJrn^!^K*=4!UL67 zqB3elQcSe+zTZ5-pKtDbb7vPtfP(6OJ@T%-DJ~zNlPR80j^!E}m>KcfYmtum;`DCV zS1sE-iQLXiVgxqXo>AWUzf(VAbu@FqNtL9q8_YI;QYZwM()l~xi{)X|@htQZ=$nKw zOyt@V9LK}U|J`=K)i%LF52q-)c=TJBPSWUp2I$UAgzLPKXr>(YN%9+DKMl zqc3q;-|~{ShgmCiB7V~%j#oa_ylrS&Ikx6)F|B?gN*MT1iZ za1?ikyja$7XMBYVP{s)s@J`)eqtg#l=vvj_dUfbH&ZJ`6e1j=sAg|slnC^!y-SD11 zXT*GPldFWk@ABrga%f)*KYU*bybUz|wH?6-jQtYw6kdMc)X$N1T;%P*mHU^@bK-+S zS|#e(?LmU`4wt<1g52^U*a^@3O~LgR5eKd$VM{`Ur?|0Rp>))(JoF`Cloyb%Jf64}?%STu&n&WBDo( z5g+A4#bfVJRFK+!>%q~PFj5W3rHMxxC9$S7rK#eJ+pO61zMHgIx8eWoP2tj`?1oe3 zdVl^!2MCbj@fl#CEV-6V)FgY@guGeMLf?JL$<3I-BhhhXEn*k%1(t&C%rrL9DPSXs zjIip%s)hhmg$ zuZREn_K!^Jq0-q1D1NS`U*n;8B#6-$)d%geSPs3c20hc6g|zlQPk5Gvb-ec9b>sus zMxObQ>%bD+U@Rn`m9&4H*yVO`6aC{Tnd)&?cta6Qk-bQrO{ojxX5^H`MUK9odOAB0 zP3+7->xg$|p_G5HgGhH}SiygKTVsMSA&+AIPVLO1jyf)XBY&p^K8WrkRm+)Qi#@~$ zJAMwk& zs-i_9(nNJ68Y^NYSn9$-tXTB&#UF|qXDX_w(fmP-oJ$h;UF7B^94SE1`?~vWLpylrtB)-^ zL7h0>$+&vgCX#y~x7;v&fuVxnXf%Sd$8zIwopGR*-5WoA`pGNx{e!kZZHYYwIkNtul6#Lu1brCP-*{uTy0}3n%N{u!^#JA7m0#0 ztriwnfDsGH3Dr5??arJ@PRc;_rzPOjSCanDx}8e8KJRYCS`w5iY0v~DBwJS<^&W|s zSQc8g(ZD4Ec#I7$n7qilrkwA@g05gDt%DOAh#2#vVCE+UZrlN+R7cl1&+J7o7P=qiS7*cHjR7NDz^czl()oGtZQUG8 z1toj709`hfiW&L{RWCv_4(Kio^xJ^hC89FET7w|Svk?a?q4WQp9p~@WZMGSiozW`KK@)^&mghcK!`qwtUyl{S)ssm6f=OM8 z09YU=Xa01%l{}W*L_dp*Wt&jt(`&sW%1#2g?JUMgt_5l5&HU{ULJ?=bG4?IBA=otl zkGm{SJFXXSUU(5Rt?PdC&Us>jED7-(m>bqkwrX`}@b(egEL`W^k;OeN?v$#>%p}A! zKyYLgBZr5bd8{inC7cVni4rJ<16)FEY{D;qzx?{U?nlW;?4h1Ok}L~MJm%lpS?VIM z++79~^ALLW6X3BkSiy-tNjz}|BY-|L8pp6{_8JoCD2Vs#g%fAn5SFG$h?5`>`pk$^ z_|jYauJw~2p+qMy1acnKae^~z2%g4RythY~`MVw}gYzsl)Z*($f5X3oNFyPFkb91# zCc7U&$z8{>n8m^DSuQ=TTtIp+I3jgMDn6-V zn>*IsCr@2@XfkSA?MSG63hW4iIyHI)ESHC$%KF$0p!#hQOorN;7z|+8*+vU^yTT-IjnR z3~EC#Ru-(jE-HQe1~V-xQDXQw21uEd@nu`;`=d9(e5$4P#|B~>45n6L z4WluL@lrpZI`V`q<51WGo9}ov%uo=_@|OrC#}DO`AD8Jb zu6hF3!iq^ZLAA~Dv@_(5bq|7Kq176-bGftk;ebRjBm04=_Z{~g&Wt$bdqb-1)pBV} zXFaP5*kn~;fwFYu1+xc31~awkhUlYSzfXDYAg1=Wfov9(4|yRbJ^5D?l7M=TJ{?K$ zd3dM`Ca}f`W2*Vt)Qu0-JW4j7D9%LOQANGeB%uBS;+1y-ItkaSz)qrhlLDpmI**_z zH5duO4xtqV@V;;?$yYE54fapk5nnAICJFXYDeVaMFbgl1{T4!A{Zw0*+S2 zc*#L^vsKwi;5H@}lF5Imo^(q&Xn`bFn#y6tTG5)Rp&?SUZ1Y(~!1+w(F77$1A$7nsIR|p44!&yOb0BOYB`iO=Y4Wvqt?S^xeTYg3>{u!W& z1c(^c7mefi-2nzrPD-`0j`RsiJXG|yO$ z!XgYYqZQXhfB=5n+zWxM_W;qZ-UYq5&-G*uf}90pqt!vJIpZD%vQ7rIq)3{8w_kZ* zWF-e0vQ!1Nx|TIU5Z!dZL_`P8Ph(^gT2zJ!gCaXCxHJ1C2by8?>nsE&MEl?ZkWbl@ z?M$s7{uaG}%oRX*x)*JUU|a=~RsdU=B+f;U`*;>aexOLuq1Oc(gdiAo zId@h8!-D%@KE*SER;t;M5D6m~zhMEEP7B8lLHz}E0%A!aieG(q)N*s5a!}qy!?$w^ z+%{EqtUs0Vnt{npMp1&EWy}I6d`AD+2kaMv{wZLviDhiE{9}WoFvUc;kE07(j1&*0 zRee2!6;W(kj3u}5S3ZAma;f)174>p|ixYu{`2WSPxA0M%`{(vk(iW0z5b$GeYHjky H2o?W7nrw|~ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/cascade.css b/openwrt/packages/luci/host/www/luci-static/oxygen/cascade.css new file mode 100644 index 0000000..c1b19f7 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/oxygen/cascade.css @@ -0,0 +1,660 @@ +@charset "utf-8"; + +@media all { + +html, body { + height: 100%; +} + +body { + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; + background: #dddddd; +} + +div#screen { + min-height: 100%; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + min-height: 98px; + background-image: url(flukso.png); + background-repeat: no-repeat; + background-position: 12% center; + background-color: #dddddd; + color: #ffffff; + text-align: right; +} + +#header h1 { + padding: 1em 1em 0 1em; +} + +#header p { + padding: 0 1em 1em 1em; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +.menubar { + background: #000000; + background: rgba(100, 100, 100, 0.8); + color: #ffffff; + width: 80%; + font-size: 0.8em; + + margin: 0.5em auto; + + padding: 0.4em; + padding-left: 0.5em; + padding-right: 0.5em; + + border-radius: 0.8em; + -khtml-border-radius: 0.8em; + -moz-border-radius: 0.8em; + -webkit-border-radius:0.8em; + -opera-border-radius: 0.8em; +} + +.menubar .warning { + color: red; + background-color: #557788; +} + +html .menubar a:link, +html .menubar a:visited { + color: #ffffff; + text-decoration: none; + font-weight: bold; +} + +html .menubar a.menulink { + margin-left: 1em; +} + + +html .menubar a:link:hover, +html .menubar a:visited:hover, +html .menubar a:link:active, +html .menubar a:visited:active, +.menubar a:link:focus, +.menubar a:visited:focus { +} + +html .menubar a:link.active, +html .menubar a:visited.active, +html .menubar a:link.preactive, +html .menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html .menubar a:link.warning, +html .menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + background: rgba(245, 245, 245, 0.9); + color: #000000; + border-width: 1px solid #444444; + font-size: 80%; + + border-radius: 1em; + -khtml-border-radius: 1em; + -moz-border-radius: 1em; + -webkit-border-radius: 1em; + -opera-border-radius: 1em; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +*+html .cbi-section legend { + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #555555; +} + +* html .cbi-section legend { + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; + color: #ffffff; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #ffffff; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + + +/* obligatory IE6 Voodoo Code */ + +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.cbi-value-description { + margin-left: 40%; +} + +} diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/dashboard.css b/openwrt/packages/luci/host/www/luci-static/oxygen/dashboard.css new file mode 100644 index 0000000..1ac147f --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/oxygen/dashboard.css @@ -0,0 +1,108 @@ +@charset "utf-8"; + +@media all { + +div.dashicon { + float: left; +} + +div.dashicon a { + background-image: url(icons/default.png); + background-repeat: no-repeat; + background-position: top; + display: block; + width: 70px; + padding-top: 70px; + color: #000000; + text-decoration: none; + text-align: center; + margin: 2em; + font-weight: bold; +} + +div.di_index a { + background-image: url(icons/network.png); +} + +div.di_wifi a { + background-image: url(icons/wifi.png); +} + + +div.di_network a { + background-image: url(icons/network.png); +} + +div.di_luci a { + background-image: url(icons/desktop.png); +} + +/**div.di_index a { + background-image: url(icons/overview.png); +}**/ + +div.di_logout a { + background-image: url(icons/logout.png); +} + +/**div.di_freifunk a { + background-image: url(icons/freifunk.png); +}**/ + +div.di_status a { + background-image: url(icons/status.png); +} + +div.di_system a { + background-image: url(icons/system.png); +} + +div.di_syslog a { + background-image: url(icons/shell.png); +} + +div.di_ntpc a { + background-image: url(icons/datetime.png); +} + +div.di_leds a { + background-image: url(icons/lightbulb.png); +} + +div.di_reboot a { + background-image: url(icons/restart.png); +} + +div.di_passwd a { + background-image: url(icons/login.png); +} + +div.di_statistics a { + background-image: url(icons/stats.png); +} + +div.di_packages a { + background-image: url(icons/package.png); +} + +div.di_sshkeys a { + background-image: url(icons/key.png); +} + +div.di_upgrade a { + background-image: url(icons/flash.png); +} + +div.di_services a { + background-image: url(icons/worker.png); +} + +div.di_backup a { + background-image: url(icons/switch.png); +} + +div.di_fstab a { + background-image: url(icons/harddisk.png); +} + +} diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/flukso.png b/openwrt/packages/luci/host/www/luci-static/oxygen/flukso.png new file mode 100755 index 0000000000000000000000000000000000000000..d3710f397f788800e1eb5b21b684f82ca8069da2 GIT binary patch literal 1830 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 W3tk86V&WM90000 + Copyright (C) 2007 Johann Ollivier Lapeyre + Copyright (C) 2007 Kenneth Wimer + Copyright (C) 2007 Nuno Fernades Pinheiro + Copyright (C) 2007 Riccardo Iaconelli + Copyright (C) 2007 David Miller + +and others + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library. If not, see . + +Clarification: + + The GNU Lesser General Public License or LGPL is written for + software libraries in the first place. We expressly want the LGPL to + be valid for this artwork library too. + + KDE Oxygen theme icons is a special kind of software library, it is an + artwork library, it's elements can be used in a Graphical User Interface, or + GUI. + + Source code, for this library means: + - where they exist, SVG; + - otherwise, if applicable, the multi-layered formats xcf or psd, or + otherwise png. + + The LGPL in some sections obliges you to make the files carry + notices. With images this is in some cases impossible or hardly useful. + + With this library a notice is placed at a prominent place in the directory + containing the elements. You may follow this practice. + + The exception in section 5 of the GNU Lesser General Public License covers + the use of elements of this art library in a GUI. + + kde-artists [at] kde.org diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/datetime.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/datetime.png new file mode 100644 index 0000000000000000000000000000000000000000..641653c07025465c8b090a2eff56f1557a26e88c GIT binary patch literal 5250 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 IM6N<$g51#QkpKVy literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/default.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/default.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe97ae308fdf6b431eb3e92eb95851589a9df07 GIT binary patch literal 5022 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 oEsqiaLPi}MG{G#OQ4v=$ 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/flash.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/flash.png new file mode 100644 index 0000000000000000000000000000000000000000..7e9dc7861d1158a272920e0ca5c5e9bf0bcf969a GIT binary patch literal 5065 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/key.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/key.png new file mode 100644 index 0000000000000000000000000000000000000000..1ebfaa43a42d4834cdcbde4716e37c09a55e8126 GIT binary patch literal 4129 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/lightbulb.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/lightbulb.png new file mode 100644 index 0000000000000000000000000000000000000000..3a6755bc3c404c33fa5980c62865ae5f3f4b1134 GIT binary patch literal 5550 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/login.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/login.png new file mode 100644 index 0000000000000000000000000000000000000000..8e881ba3b391eb6460206e8694a24325ef3a769d GIT binary patch literal 2918 zcmV-s3z_tZP))5xvchtv{H}~@jpa)oD!r+k>J1~mnc%CNL+FuLP>J~KS#}*xjscte(Jq-})p{7*C1VZ%c z=WHDSAOJYQ5LF{F7m6_eJ%5q_ZrBUkE*R}Xw&^;N76T2I=2MOB^z|4b`gK?`0EAp? z05Q&)V#w5A5kla55O^&JgAO%F!d^-$z+P=F{;ExbWwDUgbD}*AnZ0)G6&HWc?Et5omNXm zTm90iLJRUdjCHTzv?vmA z0=`=GmEx zcmN|KBas(S1R%`tT-_J#NoXhB@F5`^5K_r9I8hyx8zh}HB;eSwWAOO#V+?c#!Sg(t z95F*jQ}WvLq~YOV0zpXtfkGs(tfNxOeIX)PG&brxGc!YFl8D%}elnoFe*n5G<9d_;C zL(2xxY7-@$I>>mn%^{T%^2CRMT5W5m${;Z}NULBTS_mce=E2C$c>xar$c6w87vKmS zSuu@d#sx|)69Ayn1Yk`LX%{=Yj7a%k9du~X)Dl21RSq9M9K9g<%*XAd0=IA9hJk?r z6$(3QVM~0{jr3hO@_yAD4!(R~j81 zjco+y=jW9d$VB@As%fSrX~roBkx(csxX^>(zkrd>bG;EE74QT!J#Kn|erI>Fy#YN- z8^Mh90ulr{yk!Gan_%*K5}P5%wgGCuZW|z7lK?Xiid5j4;@@huVnu%RtmwH|mBh&g zfMo+{Zl*CzKmzo!k{noOnsJS~1W6b+;O5Pnl9Em|2A32~uS+^rIYAp>i?Ln>!}6*+ z7iS+F-{4kyJQ|sXz=tNke*QFZ}FpEeKl`5IpF9&7~)b$$Uj-w^?=7kGUyG z4;CS}cQ3Z35CGK|gy9A)8^E_&1#};pU>Z_`d%;N$f(U&ON;lMH`}LP9>uc6qWJOGa z;xJtO0dO<;e3q6ThjF3L|CnV1k}`r2TLN5Q=^U_B=Gm_+ET*;2(nX7DO>{+zHn~;m zVA+7pt~sIIAkz{MPZF3L=ashoR!6@@?z+aJ&N?X%z?fkJnB|%w={O+yq&qHh}aN-x3GCvqhjm)yH|kG>In1^_QWx^?Ro0YG~Td3bvA z1xP;+j*X2;#`F0+k^D5bTrSheuavyy00#cqaRv--+A0PiZi9Mb0T0oH4 z(`W7UGKG%74xc}N{+npj9^k!I>{~?_S37s^Tno04wrm8iUcEYkD>RLhn#M`JhWAcm zGZE=*5viakPdwS@f28BYxYB=V3&4!| zq-GQKI|v{MLZkrOYjESn4e732B$*>10Yz=pCk!wTVE_L8Ff}!W>VSP*7bPZ*YVicL zVFZTM#7YRF50BS3B&~0hF*c~Jw>|IYAH4tV9|1r}guL>8DnJZVn@R4KD_1`CJnsXq z)&ADco(e>+p{?GFAVx1W6L2aZBl7wCWxE27eEfIZlMHuX4 zP?rY_g;K6qD&$av2k~uj7F}VcSS)47#$Fj2du43AhKwyOFRxb1y3g*acu0fR{G?7w&>pTMh37 Qz5oCK07*qoM6N<$f<{9 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/logout.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..9f44fd0ef916610a15efbdf654beecced4e429ca GIT binary patch literal 3577 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/network.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/network.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8033452536c47cc213b637991c5847df7a9abf GIT binary patch literal 6602 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 IM6N<$g0J|yl>h($ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/overview.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..0f3edc162668a0943be97cd0ef27e7c020660950 GIT binary patch literal 4553 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/services.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/services.png new file mode 100644 index 0000000000000000000000000000000000000000..54e17dd09f1f2dee8d619edcbd8326390852ac57 GIT binary patch literal 4630 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 M07*qoM6N<$f}0eNO#lD@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/shell.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/shell.png new file mode 100644 index 0000000000000000000000000000000000000000..8e2f3c17f81528ba01f5e9691bd00e2d3fba3ebf GIT binary patch literal 2110 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/wireless.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/wireless.png new file mode 100644 index 0000000000000000000000000000000000000000..f35dace81a4cb1532f83551079ea28eb98458ab8 GIT binary patch literal 8431 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 R3~T@Z002ovPDHLkV1gm||9b!c literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/oxygen/icons/worker.png b/openwrt/packages/luci/host/www/luci-static/oxygen/icons/worker.png new file mode 100644 index 0000000000000000000000000000000000000000..54e17dd09f1f2dee8d619edcbd8326390852ac57 GIT binary patch literal 4630 zcmV+x66x)UP)+z5jDX` ztdPY*5-SlDq!NSCLQoTpm53TERFO)S+JICNV;)5X(I}P{52Iy-O(lQ{5I`Q;urGEO zc4udI9{ujV_nve7`kvF=>ontpZ9q!)RQ>y$zCGK0e*f?L&ONvLE;Gj9&D=QYgaIcE zIAOq>w@JLg8l#3q%~1RQW5Dvj4Bdb8ni(SB0MIO}MaPU2T(46@UL7Ok|1mUQByral zETW15j4hj90@5W{i2gz*$D3qvyZ>tJf5~ z!t`{sE)6r}nQwPAgfllI`2fTGE(!qgNBYOB~W%8b_AHM&dBS#Pc&`u^b;*DTH zH#pCL%U%Ea_A6JcjII;D+`w4Fm$_kZkq1W=&_{u27r`4SEvXk!v4)Cb#Bm75SDBD) zdgRHc>VNX?4?g@5kQkwsGNE?^dIuM6{rk4nXPx)9so(3L@ZKwmr{tJ_62TMzQvr0D z`YKGc2da4xt(HNf8lhgUqFD`5uNkx&2Am5B#-pK$W@B))Am`@QZJ)nYZU5r8>ho!N zI1_p|pm*^1zGW!?nd_#0V{(0PePQj`DSY^+!Se3_OlYBXmBtO|crR4_5dsfUIl6$O zhYq7!t|OOc7#iU4JOYP=iX@_jM5V+L#l{pTYL&t9+}wh`=+hTn{tth5=n%qANwnMR zWk3p_g7>w-$0rIOFP=KFN>2Sc(D#c8EOd!fNg@t)h`_%^(S8vNM`kg9crW5GM4<=_ z3^L>c2I+G!Fc>YNBY~I<2pc}C3qH#83{BlMlN*Dw;wOK0>+gK$wq3hW&zkTW8{pv6 zsLQ9mw0Y~)sN9}gIj}Z=$|kUpj{$Nuz==xNT*_Brn%_lK{u@*)A&%^M7WK+JMn{0r zalj*RAsCW()|^NHqgguxteQR|GNHZ@pj48mG+GFTn++ohxBk|)=RfoK@i-B|3C*XGubF@N<1V13ciT zSawZt2J{Sn%e8C9f9=A-yS>2M(tp}Yh%u^jxyC{ZqT)_a6#UPjUVa9LpL-6~V@KK% zPn0hJoOSO5jWr-OL2;;1l03?S0C9~>DCJSD0}HhX@L2WmJU;OL8}>W^AY85#WUp!e z!FLW7uDEdUo1SD_`Zf%L51$4wV{1K0VP-=b?SyW81GQ=yFFf-UTGa)tB#%Z2-p{35 zp~a1`?b~USBsGss+X#|^^dgvmBiH9aMFCWfp;U|d`-R!Ib}fGHzyW(^py?(q^p*kL z1_+XT@y^q~T*!&5{8gjKttA@K)-aeHrhX_HLp=s#en54uap3Vsp_*l^Tn7w}12Wfn zCuab2T0AWcn2$&IPKOMo12^l!Lo#YEo6JG~J=#rqIP z4eIOAjXf}p`+(?iyW*=B%F~B&Z13|JT?q`W0%Tu0t!0~W;2{m`3}`YiZEU4*Lk|R> z7(vH`wkD7Q!NfV6`abIH<*(i%=nVMfpBnrH8VXsQMcg7#RKR!%zN|tR10w(?14N;Z zW4rgEFrYCy1$ceNLN&9Ic4O8()f658$z1{^(1rJYBuurBttUbBtc^-kQhK(ck_n_F8JT_O&;%#&zION{5s;uAPfmU z=8)Qh ztOo;ZoPKlb=oo+%%xf=v1Ruu)9}%#EQg-uW0Fq9O@H_@?I+1rhgL`mHIwJ+(C0V1g zJ40lpZ7(^%IkO8Cx8f{`c|1HIF3GF~=+ywW_1wYpq8Ko|0b>YLE9f|aRw0dJD6Q=t z-WYHVa92G>aTiGvb8;YyTKDlZ`gSL1m=k~Lm}D#grw+W62}bK6;OBMLfyG%MkLL_9 zG9b>14PaQ9Kr$%6gir)X`~+{3`BG^lQ8C6ryGb)<(hQ(+=QVVTeQCtGpj`Xsia{xn)%yZw4^e^SqDKglCIaaN}0v7)D2l01ah;u&&{I9Gs<5vOpyM z$}%7eZb%kdr0|^{NcI6ak0%Bc3ra}O^aBvbSpwZ(czDdL7k&h-ZSaI_M>+;fXiYFW z$%1B8!xI7woyj?P!|a5?x`4aDQ{(<8tP&*dBoe{!6pY(X>kBl~2>2ggk=y9z&wE}3 zNmDY2?HjPR47k)_WP&j<0FxLKRsl~+zz90t0d^oSMbp*uVrWt}vfc0`E$s7HB+54C z1z2q*BU>Xntkiw7@IMcSSsi_vDp#alq zgc4xIfH;N2A}}lhN7|-vmbH8(JHYRLk>64nG^ZEGeWAcXy6)dmecK(|fM05>*GLnLEBXMfUIdiBrNeqvw>uOkmeu7DUE0L#^2 znhzmfXeOVbsf$`bi+W>P7+;Y`v$XSa0AC;}C&-^P`u}k&e#HyS)eHhd6Gst8mLtu0 zx58*U;jqjg;KL-7REaAZc0**CyRL_Wr{|26Hh1dO?cPN{oBk#boj(H@@WIS9bo~kF z`3leop+h8@8IzhVB)ig)&6lDzvja`dW)@!;$e$$oxBn?t27UO($QToqr(>va-k!Q+ zfP2ma4hz{<)E0+?4;G7L%-!m*HM786!*sw&CNUz7e!6c+OF(;@p@MN3E}&~a2C8!u z={c~t2^GcA3Q#c+hCocc@QWy}ITPXZ-4Ml~@%E22KDuZ_1i2jimp+NXQ`X~IH4o8u zG65XTz$!qIgxh3tlF$a)Gw^}{Oy;0tf`}9}!7xn{Jb?!(0p|wHWkK4k0R{n#w;r)5 z&^V8{{sK(v08BVfs)8GW);5_VWuxAx(-;F7UUxnkGmoKm_)#+x4Ly4K@0LEbmy!hl zUnT=m_#L<5B9X_v%^CRPD;bOe!Ws}164(Fanb!K+h1Yuvaa9o_KT6t!c!SImG1|s2UMP z^`y?2`wULfZ7HBy1&$rF@cqLRm^%Gz)aQPLBRh9M1;ox8KL)!~$r}@FZY(#@fu*p67EA z`2gO)N#x=bm{fpSNJtoyFd76~MO-Zra2dK;1ypSJ@y<-{daW&ZxlAe%iSjVKY7_bh zes=$psMqT8p84FaKl@twfrB$tut1GeA{`^mIL(qOq>!WxHD^Ey|NYx>dp^RIQrg<) zl0o+OW8{n*ksG}baq~sY?|%#jzV}rO&}6S$~gG!lco}~@_j$VBip}Oe$rj+G+e~X zqS>N%*uJD+PXv0Ol>LS13RB~q2Gw|9_>y$utv*SH^2mg95Fjp|nF}&eA44m{K zf}Vv+;HP0?>f;v>F5CmHt2XL_q17}f%`!CRHFQfu00=z5C*^ztk9tqK#Z%cePbrdi zJxLoMkc060MiJ0j;rEYFUx1*`oZa^$9D1?d;EHKx%HcWJ;j0d);ozz+!sQHf#hKC~ zg&lYjUd{kP@~^%GtN-Y7_D?IfeDd_d)cc^r8G@fC__k)qfN4b4`vE-*=1PPM7j;2n zZZikMrfwJu#34tkE)iEGqLu)M2O)hjBoFE5$ecWxRX{FBukbn;BD7mvn@4kY+8mtL z^V|P1e)ubQ*Y;e$6({dKilg^Fg53_T(gDwmt7*h7_)>R~utez@Ax9c|%Lbfs(?{4R z&OGnjpD(WcB_9mXv4xN8KZH?-2pkr?4V@a1j@@g_nZt|^6MKLn#XgvJW9_$l`y3n$ z3UPG?wT0REnZ5jlYj37Be=b~b5K$-99q>Z-d*#e(-&zdb1;50NOL@{TX(egR1!v;S zk6+C%JAcdCGyRcu+(ZY-hyxBT3z{{+8sf(GH6|RagH{$gJ2uTanR^uFa;xz#|A}X> z`E=>wR)m&=2pv?@!MhrF3tI{vIw>c;6nJ+Aqy`LXdjHXtp7 z9I4+yk2;Nz2AnxLXOu@0E60$(^c`%~IUDJUbA7%ruH8YdVf`_DL2C$M*ZP9N=VOP|9yiG1O!GZ-2wn!Rs8qAoG&ln*|JbRhhy$f)C zH*}QNZT56Va<%Q?o0&+fOs}0Bc<;B$8d98@Y?MjIvNNFHnb4Ot!HHXS8DN$GcXjR} z-<{r#Or({QS)`tCm0jvyKjEN!2b#CgBxis-=4VPmqWd>qof>Q5yMO*nwJ6o&Y<*`l zs#ox=0n7am${m>JKm(^-X6!l1OewG>q8~1)w5Fp>wDoa7_hP{E_xd`e(5XcCoj%>Q zzgUaT+p32Y@6mwejaZx+4%lhwH9$L=6f{*9xYua+Zou+JAOpzL=b3R=b5PkjPKDPC z`c=M7uKO^SX^UZBYv|YiZt-QCgM9wucJkxJOBUy M07*qoM6N<$f}0eNO#lD@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/Dropdowns.js b/openwrt/packages/luci/host/www/luci-static/resources/Dropdowns.js new file mode 100644 index 0000000..ff2f0e6 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/Dropdowns.js @@ -0,0 +1,120 @@ +/* +Copyright (C) 2008 Alina Friedrichsen + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +function initDropdowns() { + var aSelects = XHTML1.getElementsByTagName("select"); + var isIE6 = false /*@cc_on || @_jscript_version < 5.7 @*/; + + function showPlaceholder(sel) { + if( ! sel._ph ) { + var box = sel.getBoundingClientRect(); + sel._dm = sel.currentStyle.display; + sel._ph = document.createElement('input'); + sel.parentNode.insertBefore(sel._ph, sel); + sel._ph.style.width = ( box.right - box.left ) + 'px'; + sel._ph.style.height = ( box.bottom - box.top ) + 'px'; + sel._ph.style.margin = sel.currentStyle.margin; + } + + sel._ph.value = sel.options[sel.selectedIndex].text; + sel._ph.style.display = sel._dm; + sel.style.display = 'none'; + } + + function hidePlaceholder(sel) { + if( sel._ph ) sel._ph.style.display = 'none'; + sel.style.display = sel._dm; + } + + function hideSelects() { + for(var i = 0; i < aSelects.length; i++) { + showPlaceholder(aSelects[i]); + } + } + + function showSelects() { + for(var i = 0; i < aSelects.length; i++) { + hidePlaceholder(aSelects[i]); + } + } + + function onmouseover(evt) { + XHTML1.addClass(evt.currentTarget, "over"); + if( isIE6 ) hideSelects(); + } + + function onmouseout(evt) { + XHTML1.removeClass(evt.currentTarget, "over"); + if( isIE6 ) showSelects(); + } + + function onfocus(evt) { + for(var element = evt.currentTarget; element; element = element.parentNode) { + if(XHTML1.isElement(element, "li")) { + XHTML1.addClass(element, "focus"); + } + } + if( isIE6 ) hideSelects(); + } + + function onblur(evt) { + for(var element = evt.currentTarget; element; element = element.parentNode) { + if(XHTML1.isElement(element, "li")) { + XHTML1.removeClass(element, "focus"); + } + } + if( isIE6 ) showSelects(); + } + + if(document.all) { + var liElements = XHTML1.getElementsByTagName("li"); + for(var i = 0; i < liElements.length; i++) { + var li = liElements[i]; + for(var element = li.parentNode; element; element = element.parentNode) { + if(XHTML1.isElement(element, "ul") && XHTML1.containsClass(element, "dropdowns")) { + XHTML1.addEventListener(li, "mouseover", onmouseover); + XHTML1.addEventListener(li, "mouseout", onmouseout); + break; + } + } + } + } + + var aElements = XHTML1.getElementsByTagName("a"); + for(var i = 0; i < aElements.length; i++) { + var a = aElements[i]; + for(var element = a.parentNode; element; element = element.parentNode) { + if(XHTML1.isElement(element, "ul") && XHTML1.containsClass(element, "dropdowns")) { + XHTML1.addEventListener(a, "focus", onfocus); + XHTML1.addEventListener(a, "blur", onblur); + break; + } + } + } +} + +if(XHTML1.isDOMSupported()) { + XHTML1.addEventListener(window, "load", initDropdowns); +} diff --git a/openwrt/packages/luci/host/www/luci-static/resources/VarType.js b/openwrt/packages/luci/host/www/luci-static/resources/VarType.js new file mode 100644 index 0000000..d466810 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/VarType.js @@ -0,0 +1,91 @@ +/* +Copyright (C) 2008 Alina Friedrichsen + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +function VarType() { +} + +VarType.isNull = function(obj) { + if(typeof obj == "undefined") return true; + if(typeof obj == "object" && (!obj)) return true; + return false; +}; + +VarType.toFloat = function(value) { + value = Number(value); + return value; +}; + +VarType.toDecimal = function(value) { + value = Number(value); + if(!isFinite(value)) value = 0.0; + return value; +}; + +VarType.toInt = function(value) { + value = Number(value); + if(!isFinite(value)) value = 0.0; + value = Math.floor(value); + return value; +}; + +VarType.toUInt = function(value) { + value = Number(value); + if(!isFinite(value)) value = 0.0; + else if(value < 0.0) value = 0.0; + value = Math.floor(value); + return value; +}; + +VarType.toStr = function(value) { + if(VarType.isNull(value)) value = ""; + value = String(value); + return value; +}; + +VarType.toBool = function(value) { + value = Boolean(value); + return value; +}; + +VarType.needObject = function(obj) { + if(typeof obj != "object" || (!obj)) throw new TypeError(); +}; + +VarType.needInstanceOf = function(obj, type) { + if(!(obj instanceof type)) throw new TypeError(); +}; + +VarType.needFunction = function(obj) { + if(typeof obj != "function") throw new TypeError(); +}; + +VarType.needNode = function(obj, type) { + VarType.needObject(obj); + if(VarType.isNull(obj.nodeType)) throw new TypeError(); + if(!VarType.isNull(type)) { + type = VarType.toInt(type); + if(obj.nodeType != type) throw new TypeError(); + } +}; diff --git a/openwrt/packages/luci/host/www/luci-static/resources/XHTML1.js b/openwrt/packages/luci/host/www/luci-static/resources/XHTML1.js new file mode 100644 index 0000000..a7d4f7d --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/XHTML1.js @@ -0,0 +1,271 @@ +/* +Copyright (C) 2007, 2008 Alina Friedrichsen + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +var XMLNS_XMLNS = "http://www.w3.org/2000/xmlns/"; +var XMLNS_XML = "http://www.w3.org/XML/1998/namespace"; +var XMLNS_XHTML = "http://www.w3.org/1999/xhtml"; + +function W3CDOM_Event(currentTarget) { + VarType.needObject(currentTarget); + this.currentTarget = currentTarget; + this.preventDefault = function() { window.event.returnValue = false; }; + return this; +} + +function XHTML1() { +} + +XHTML1.isDOMSupported = function() { + if(!document.getElementById) return false; + if(!(window.addEventListener || window.attachEvent)) return false; + return true; +}; + +XHTML1.isXHTML = function() { + if(document.documentElement.nodeName == "HTML") return false; + return true; +}; + +XHTML1.addEventListener = function(target, type, listener) { + VarType.needObject(target); + type = VarType.toStr(type); + VarType.needFunction(listener); + + if(target.addEventListener) { + target.addEventListener(type, listener, false); + } + else if(target.attachEvent) { + target.attachEvent("on" + type, function() { listener(new W3CDOM_Event(target)); } ); + } +}; + +XHTML1.createElement = function(tagName) { + tagName = VarType.toStr(tagName); + + if(XHTML1.isXHTML()) { + return document.createElementNS(XMLNS_XHTML, tagName.toLowerCase()); + } + + return document.createElement(tagName.toUpperCase()); +}; + +XHTML1.getElementsByTagName = function(tagName) { + tagName = VarType.toStr(tagName); + + if(XHTML1.isXHTML()) { + return document.getElementsByTagNameNS(XMLNS_XHTML, tagName.toLowerCase()); + } + + return document.getElementsByTagName(tagName.toUpperCase()); +}; + +XHTML1.isElement = function(node, tagName) { + VarType.needNode(node); + tagName = VarType.toStr(tagName); + + if(node.nodeType == 1) { + if(XHTML1.isXHTML()) { + if(node.namespaceURI == XMLNS_XHTML) { + if(node.localName == tagName.toLowerCase()) return true; + } + } else { + if(node.nodeName == tagName.toUpperCase()) return true; + } + } + + return false; +}; + +XHTML1.getAttribute = function(element, name) { + VarType.needNode(element, 1); + name = VarType.toStr(name); + + name = name.toLowerCase(); + + if(XHTML1.isXHTML()) { + return element.getAttributeNS(null, name); + } + + if(name == "class") { + return element.className; + } + + return element.getAttribute(name); +}; + +XHTML1.setAttribute = function(element, name, value) { + VarType.needNode(element, 1); + name = VarType.toStr(name); + value = VarType.toStr(value); + + name = name.toLowerCase(); + + if(XHTML1.isXHTML()) { + element.setAttributeNS(null, name, value); + return; + } + + if(name == "class") { + element.className = value; + return; + } + + element.setAttribute(name, value); +}; + +XHTML1.removeAttribute = function(element, name) { + VarType.needNode(element, 1); + name = VarType.toStr(name); + + name = name.toLowerCase(); + + if(XHTML1.isXHTML()) { + element.removeAttributeNS(null, name); + return; + } + + if(name == "class") { + element.className = ""; + return; + } + + element.removeAttribute(name); +}; + +XHTML1.containsClass = function(element, className) { + VarType.needNode(element, 1); + className = VarType.toStr(className).replace(/^\s+/g, "").replace(/\s+$/g, ""); + + var classString = XHTML1.getAttribute(element, "class").replace(/\s+/g, " ").replace(/^\s+/g, "").replace(/\s+$/g, ""); + var classArray = classString.split(" "); + for(var i = 0; i < classArray.length; i++) { + if(classArray[i] == className) return true; + } + + return false; +}; + +XHTML1.addClass = function(element, className) { + VarType.needNode(element, 1); + className = VarType.toStr(className).replace(/^\s+/g, "").replace(/\s+$/g, ""); + + var classString = XHTML1.getAttribute(element, "class").replace(/\s+/g, " ").replace(/^\s+/g, "").replace(/\s+$/g, ""); + var classArray = classString.split(" "); + classString = ""; + for(var i = 0; i < classArray.length; i++) { + if(classArray[i] != className) { + if(classString == "") classString = classArray[i]; + else classString += " " + classArray[i]; + } + } + + if(classString == "") classString = className; + else classString += " " + className; + + XHTML1.setAttribute(element, "class", classString); +}; + +XHTML1.removeClass = function(element, className) { + VarType.needNode(element, 1); + className = VarType.toStr(className).replace(/^\s+/g, "").replace(/\s+$/g, ""); + + var classString = XHTML1.getAttribute(element, "class").replace(/\s+/g, " ").replace(/^\s+/g, "").replace(/\s+$/g, ""); + var classArray = classString.split(" "); + classString = ""; + for(var i = 0; i < classArray.length; i++) { + if(classArray[i] != className) { + if(classString == "") classString = classArray[i]; + else classString += " " + classArray[i]; + } + } + + XHTML1.setAttribute(element, "class", classString); +}; + +XHTML1.removeAllChildren = function(node) { + VarType.needNode(node); + + while(node.lastChild) { + node.removeChild(node.lastChild); + } +}; + +XHTML1.getTextContent = function(node) { + VarType.needNode(node); + + if(typeof node.textContent != "undefined") { + return node.textContent; + } + + switch(node.nodeType) { + case 1: + case 2: + case 5: + case 6: + case 11: + var textContent = ""; + for(node = node.firstChild; node; node = node.nextSibling) { + if(node.nodeType == 7) continue; + if(node.nodeType == 8) continue; + textContent += VarType.toStr(XHTML1.getTextContent(node)); + } + return textContent; + case 3: + case 4: + case 7: + case 8: + return node.nodeValue; + } + + return null; +}; + +XHTML1.setTextContent = function(node, value) { + VarType.needNode(node); + value = VarType.toStr(value); + + if(typeof node.textContent != "undefined") { + node.textContent = value; + } + + switch(node.nodeType) { + case 1: + case 2: + case 5: + case 6: + case 11: + XHTML1.removeAllChildren(node); + if(value != "") { + node.appendChild(document.createTextNode(value)); + } + break; + case 3: + case 4: + case 7: + case 8: + node.nodeValue = value; + break; + } +}; diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi.js b/openwrt/packages/luci/host/www/luci-static/resources/cbi.js new file mode 100644 index 0000000..77c59e5 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/cbi.js @@ -0,0 +1,221 @@ +/* + LuCI - Lua Configuration Interface + + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + + 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$ +*/ + +var cbi_d = []; + +function cbi_d_add(field, dep, next) { + var obj = document.getElementById(field); + if (obj) { + var entry + for (var i=0; iRNr-FN=3zVdt9tv~<4fPor7@h1x-1A_*G z4#+T&pBUJtADCR=A+xAY{q)Mqma1&c{a=cmxa4~mroT4KS#`QgUof=)~+&T;I{j*sYXaTd%6BpddF%U0!DD^qC5h za!gM1`zFkilw?>wPi9)j8Wt9I))h*%tJiLm*{Loqq9hZ|aDstdhKpl`^aUv?Mn)zk OR#uKC*E=qb4Aua>fQ#$^ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/apply.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/apply.gif new file mode 100644 index 0000000000000000000000000000000000000000..82ae7ed821f7524c0356e40f79a0379fc634d535 GIT binary patch literal 268 zcmV+n0rUPxNk%w1VGsZi0K^{vM3g9B!ajxBR(;h{C|4L|#z9W1FZTQNam`88@5?V| z96pC8chOCN)>Mw(T#DRUiQ8Fv(@#mEENRI^ZOca`PZo5~OEz>Nz2>iuw1BeWp~dOA zBTNzi%BC{z2#%%nWDQ(& zkP#APQYdIRbsbb52orn(e?S)g~J1 z%8r<(-QeVRgO&gP{{R30A^8LW000gEEC2ui01E&M06+vZ(8)=q0AK`A2tAn4V1q?& p9d!Z1mQ}E{1V<7C3PltEGGGP@1A|xv9lPESaCFRSx11yb06WwgHGu#C literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/download.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/download.gif new file mode 100644 index 0000000000000000000000000000000000000000..f99a5383b23fc4270a45048cea54b7d84e4c632b GIT binary patch literal 189 zcmZ?wbhEHb6krfw*v!umwaLqI!OQM5F>k&+Z^fq|bvhXDvcW-zd1eeis_YHo#<8bh&USm7b|HfiTo^1C<- zB2&*9?YY;WqkfgAr7?@)##fnMrp5vd5e9?B>jf-W))_Q3ne(cwV{E9XUS-Jmz%6-U ohKzU%--1K~l{<@Algzi@uNL9X;o>Z>(Bsa^YtS>66lAal0Is`BfB*mh literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/edit.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b02b6e72a8d3b7f8add18f94fdd25e6d705ddac GIT binary patch literal 280 zcmV+z0q6clNk%w1VGsZi0K@>ugJjP{dk$Tr~sLS5q=$-yaxZ#SE11S zRIB!<(fT-LmH+?$A^8LV00000EC2ui01yBW000G*;3tk`DMpS%Nm39Du;)pl6A@EB z5xm!Np4!AfBnlcnph84J6a~km2eJG}oCYZJ=Ydc~*KCvvDSSTxgcd_Cm=B`#5u?d; z3!M!C{uwM9bQu_Bd3p~bei3zpcpDoG6^DHb2?~}900Ru06&HvI2?=-w0|2G~3!WbU e5ePdx1QoIi4i<=*mj?$A4;L2}RVKnBApko)oOWvf literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/fieldadd.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/fieldadd.gif new file mode 100644 index 0000000000000000000000000000000000000000..431ff64d1f07ea8368ff38ac49941794a3fdd849 GIT binary patch literal 379 zcmZ?wbhEHb6krfwxXQrr|GeMpEk^&ppZIqp{q-#2*GpypKk@m0DeV7?)PKK@zCNA$ z`dro2lOEGfdA01Zo^;&3Zkzdpqptt|eeXPA|NqbH{v$3`n~kTR_U=C5@c+lT*LU_b z?6CO%>(2l8{r~^I{r|G{^@*_mA7}snwCwdU*P=DL|Gypj|E%Km1>^spH~#;&>;M1% z43q)IpDbVlbU-A?PYi4`9Htg{=x~{833+Y}XmD73G1F_0L0j|T!~?dRp1tm=n^ZC5We%>aw-FvmvIpt(dOEPIJ XU%@iXKOm5ik(HI@w%c77M+R#EbrzH@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/find.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/find.gif new file mode 100644 index 0000000000000000000000000000000000000000..9ae5e3489bb888d198eb923bb095b48b04403705 GIT binary patch literal 273 zcmV+s0q*`sNk%w1VGsZi0K^{vc9*og-TcMk{nhCBh_A@i+vHYljktnV?e+bOcW6yp zbLH*z_4)kq_4;Q^Gl{$GpO1s<@%ZNQ{aZUCuG8g1OkMl^{;_vPn!whm%ie)&TXr4L_o{y)q5EzYtB;xTCWf;e!643y9FwiJ6z-cH%*eE2C&?LHF520~{Ks*+N*(+Kf z6ATMOGH`g(00>C|cno`e9u*=05rZ2M2z-c&9*lzt8600y!Ov?p4qk8 z_sQn}X|3gLf|Hfa{4HFBMq+vzJXv+X|6!-#{r&xKvgu!?-l)&;*zNvYc8feuU~I4F zQ<~I5R%ieJ|NsC0A^8LW0018VEC2ui01yBW000Gt;3s}wX?kNyLPFa#5UP3^wk(CC zKe9+;gdm|(VMuts4zO}DT@VOK1m)={2pi9Zf$&VC9jdjm*+RV&K$v9RFu0|I!2+1F z6;Q;%BcIpB1z!^u289U*e{2p3gL?-F2^@(e8U&FXn3w5$p!k!8k%2*+K?fuc zvXg-|`GIQRqSUCAs4#&;3tm~By~MCQ%rwwORo7gy-yy?BWny%m`4$Z=kEQF}JtY=+ zUfLA?(#?Ar^XBeQKBmcC4v)^p`DK_cQ206RTqffIk;3UrB1Hyj7R*hC%3_Rs)g7Jc Jeaeaq)&Qp@T0Z~) literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/link.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/link.gif new file mode 100644 index 0000000000000000000000000000000000000000..f0bb78da6b1e2cb17aa1a0e21c80e02979f6321a GIT binary patch literal 279 zcmV+y0qFimNk%w1VGsZi0K^{vm&^Qekgn|U_T}yMiLlDm+vLaN{=MG)S8$O@RcrG0 z`m5CYWS!x)+5Dr>`-!{kQek_q(&TBN;zLVZ)#vbFn&Fzj)~L(g-skTrF+)B@RpROJ ze4)L|%+de<|NsC0A^8LW0018VEC2ui01yBW000G)peK&x_?;dVMVDm}1jhw|hep&O z==8z~GHrORSgnM6@HQ4;4*@!6xGR+fIw4vg zByI*g?ikQL90EyhXA2I80}~>FNeyv^hX5Oj9sz=0a*zN37#bo03T1_nn*yF52n7l~ d8?74{0v#Ej2(=Ip2?-Mu8X6f_CBY>j06X7qcdP&a literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/reload.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/reload.gif new file mode 100644 index 0000000000000000000000000000000000000000..8268958a19e016741fffb8309b1174e548f5ce19 GIT binary patch literal 248 zcmV51h?dP)!|<#Vc>gJ1)O z9Y&Xm98YHe08|T}nE5Daq{Qc(Rx3cM5 zjz9kQ*3j_j+pnL#{d)WH+j&{p|6ssC8=&};g^__li9rWsJjhQBZ1WCGDDaT!>RZ^( zEEK83!O|Nd>|`Z3*C*`uOEs;l0!ub)PUp?=f27@0VfU<`vGKzV%|l1oS?<>Z^@_<= zC~_&t)O6G|iMKeh$aQzhi;0Q%F-^$to;pK9LUxv-l;q?Z@dd)N%uel7=1K?)Gp=1y z$56M4m6eCxNh-frev|MX$^D9=LUJ*T=NWksPtC-3SYNk)IzaCG{5wQd4hOTmQRpBi`QrZFzZjOw5(w z;B+Ua|6ri_lZBCiL7qW}0SG{LGO*S^P_K*2tV;HB^Xpa+Tva9QCeXgnd6P%76fc9p zOamsHcy;@YDln|Vuw<0nl$s8=rCxw48uw_56lMa6}$ zEFa1XibC1A+uFH>WUA~WrMhG$PUPgWRp}FBoy96PRn(YYfNQZp@O&*5b=4JX)+#bs F0{{l~XioqD literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/save.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/save.gif new file mode 100644 index 0000000000000000000000000000000000000000..35e949963e4b7a5f04fd1c8932a980901e3d4385 GIT binary patch literal 263 zcmV+i0r>t$Nk%w1VGsZi0K^{vcEd+Ya4xgmmXXkDk(iA6{P)e~xr@?RgUwTMzeLpS z#Wqhu{H$s5p4O4v<)^3=A2^0_EulhRp%QGjIf`R%Ru$RUj;1k~O1%3=|$g0$`b{ z1p`T8E1%cF0ssJ7eF+Hu(2Z{06R}5X@39! literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/host/www/luci-static/resources/cbi/user.gif b/openwrt/packages/luci/host/www/luci-static/resources/cbi/user.gif new file mode 100644 index 0000000000000000000000000000000000000000..dcb5c2a899c84ee0be36e6b92222cdde6fbb8ad3 GIT binary patch literal 246 zcmV5VArX{>gpqy}ZQ3xBIb z?{>Ooo8TtXQxO=NV3P1sT@;64^wK0*F2c"){var d="/"+a.tagName,e;while((e=a.nextSibling)&&e.tagName!=d){e.removeNode()}if(e){e.removeNode()}}a.parentNode.replaceChild(c,a);return c},initElement:function(a){a=this.q(a);a.getContext=function(){if(this.l){return this.l}return this.l=new K(this)};a.attachEvent("onpropertychange",V);a.attachEvent("onresize", +W);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+"px"}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+"px"}else{a.height=a.clientHeight}return a}};function V(a){var b=a.srcElement;switch(a.propertyName){case "width":b.style.width=b.attributes.width.nodeValue+"px";b.getContext().clearRect();break;case "height":b.style.height=b.attributes.height.nodeValue+"px";b.getContext().clearRect();break}}function W(a){var b=a.srcElement; +if(b.firstChild){b.firstChild.style.width=b.clientWidth+"px";b.firstChild.style.height=b.clientHeight+"px"}}Q.init();var R=[];for(var E=0;E<16;E++){for(var F=0;F<16;F++){R[E*16+F]=E.toString(16)+F.toString(16)}}function J(){return[[1,0,0],[0,1,0],[0,0,1]]}function G(a,b){var c=J();for(var d=0;d<3;d++){for(var e=0;e<3;e++){var g=0;for(var h=0;h<3;h++){g+=a[d][h]*b[h][e]}c[d][e]=g}}return c}function N(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit= +a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.d=a.d;b.e=a.e}function O(a){var b,c=1;a=String(a);if(a.substring(0,3)=="rgb"){var d=a.indexOf("(",3),e=a.indexOf(")",d+1),g=a.substring(d+1,e).split(",");b="#";for(var h=0;h<3;h++){b+=R[Number(g[h])]}if(g.length==4&&a.substr(3,1)=="a"){c=g[3]}}else{b=a}return[b,c]}function S(a){switch(a){case "butt":return"flat";case "round":return"round"; +case "square":default:return"square"}}function K(a){this.a=J();this.m=[];this.k=[];this.c=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=m*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement("div");b.style.width=a.clientWidth+"px";b.style.height=a.clientHeight+"px";b.style.overflow="hidden";b.style.position="absolute";a.appendChild(b);this.j=b;this.d=1;this.e=1}var j=K.prototype;j.clearRect=function(){this.j.innerHTML= +"";this.c=[]};j.beginPath=function(){this.c=[]};j.moveTo=function(a,b){this.c.push({type:"moveTo",x:a,y:b});this.f=a;this.g=b};j.lineTo=function(a,b){this.c.push({type:"lineTo",x:a,y:b});this.f=a;this.g=b};j.bezierCurveTo=function(a,b,c,d,e,g){this.c.push({type:"bezierCurveTo",cp1x:a,cp1y:b,cp2x:c,cp2y:d,x:e,y:g});this.f=e;this.g=g};j.quadraticCurveTo=function(a,b,c,d){var e=this.f+0.6666666666666666*(a-this.f),g=this.g+0.6666666666666666*(b-this.g),h=e+(c-this.f)/3,l=g+(d-this.g)/3;this.bezierCurveTo(e, +g,h,l,c,d)};j.arc=function(a,b,c,d,e,g){c*=m;var h=g?"at":"wa",l=a+M(d)*c-A,n=b+L(d)*c-A,o=a+M(e)*c-A,f=b+L(e)*c-A;if(l==o&&!g){l+=0.125}this.c.push({type:h,x:a,y:b,radius:c,xStart:l,yStart:n,xEnd:o,yEnd:f})};j.rect=function(a,b,c,d){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath()};j.strokeRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.stroke()};j.fillRect=function(a, +b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill()};j.createLinearGradient=function(a,b,c,d){var e=new H("gradient");return e};j.createRadialGradient=function(a,b,c,d,e,g){var h=new H("gradientradial");h.n=c;h.o=g;h.i.x=a;h.i.y=b;return h};j.drawImage=function(a,b){var c,d,e,g,h,l,n,o,f=a.runtimeStyle.width,k=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var q=a.width,r=a.height;a.runtimeStyle.width= +f;a.runtimeStyle.height=k;if(arguments.length==3){c=arguments[1];d=arguments[2];h=(l=0);n=(e=q);o=(g=r)}else if(arguments.length==5){c=arguments[1];d=arguments[2];e=arguments[3];g=arguments[4];h=(l=0);n=q;o=r}else if(arguments.length==9){h=arguments[1];l=arguments[2];n=arguments[3];o=arguments[4];c=arguments[5];d=arguments[6];e=arguments[7];g=arguments[8]}else{throw"Invalid number of arguments";}var s=this.b(c,d),t=[],v=10,w=10;t.push(" ','","");this.j.insertAdjacentHTML("BeforeEnd",t.join(""))};j.stroke=function(a){var b=[],c=O(a?this.fillStyle:this.strokeStyle),d=c[0],e=c[1]*this.globalAlpha,g=10,h=10;b.push("n.x){n.x=k.x}if(l.y== +null||k.yn.y){n.y=k.y}}}b.push(' ">');if(typeof this.fillStyle=="object"){var v={x:"50%",y:"50%"},w=n.x-l.x,x=n.y-l.y,p=w>x?w:x;v.x=i(this.fillStyle.i.x/w*100+50)+"%";v.y=i(this.fillStyle.i.y/x*100+50)+"%";var y=[];if(this.fillStyle.p=="gradientradial"){var z=this.fillStyle.n/p*100,B=this.fillStyle.o/p*100-z}else{var z=0,B=100}var C={offset:null,color:null},D={offset:null,color:null};this.fillStyle.h.sort(function(T,U){return T.offset-U.offset});for(var o=0;oC.offset||C.offset==null){C.offset=u.offset;C.color=u.color}if(u.offset')}else if(a){b.push('')}else{b.push("')}b.push("");this.j.insertAdjacentHTML("beforeEnd",b.join(""));this.c=[]};j.fill=function(){this.stroke(true)};j.closePath=function(){this.c.push({type:"close"})};j.b=function(a,b){return{x:m*(a*this.a[0][0]+b*this.a[1][0]+this.a[2][0])-A,y:m*(a*this.a[0][1]+b*this.a[1][1]+this.a[2][1])-A}};j.save=function(){var a={};N(this,a); +this.k.push(a);this.m.push(this.a);this.a=G(J(),this.a)};j.restore=function(){N(this.k.pop(),this);this.a=this.m.pop()};j.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];this.a=G(c,this.a)};j.rotate=function(a){var b=M(a),c=L(a),d=[[b,c,0],[-c,b,0],[0,0,1]];this.a=G(d,this.a)};j.scale=function(a,b){this.d*=a;this.e*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];this.a=G(c,this.a)};j.clip=function(){};j.arcTo=function(){};j.createPattern=function(){return new P};function H(a){this.p=a;this.n=0;this.o= +0;this.h=[];this.i={x:0,y:0}}H.prototype.addColorStop=function(a,b){b=O(b);this.h.push({offset:1-a,color:b})};function P(){}G_vmlCanvasManager=Q;CanvasRenderingContext2D=K;CanvasGradient=H;CanvasPattern=P})()}; diff --git a/openwrt/packages/luci/host/www/luci-static/resources/livestats/GraphRPC.js b/openwrt/packages/luci/host/www/luci-static/resources/livestats/GraphRPC.js new file mode 100644 index 0000000..712d8b1 --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/livestats/GraphRPC.js @@ -0,0 +1,204 @@ +function Graph(container, id, options, transform, legend) { + if( !options ) options = { }; + + this.id = id; + this.cols = 100; + this.type = "line"; + this.options = options; + this.transform = transform; + this.dataset = {}; + this.legend = legend; + this.lastvalue = {}; + + var name = (options.instanceNames && options.instanceNames[id]) + ? options.instanceNames[id] : id; + var graph = document.createElement('div'); + var label = document.createElement('h2'); + label.innerHTML = options.title + ? options.title.replace("%s", name) : name; + + container.appendChild( label ); + container.appendChild( graph ); + + this.canvas = document.createElement('canvas'); + graph.appendChild( this.canvas ); + + this.canvas.id = id; + this.canvas.width = ( options.width || graph.offsetWidth - 20 ); + this.canvas.height = ( options.height || 300 ); +} + +Graph.prototype.addDataset = function(name, ds) { + if( !this.layout ) { + this.layout = new PlotKit.Layout( this.type, this.options ); + } + + if( !ds ) { + ds = new Array(); + for( var i = 0; i < this.cols; i++ ) + ds[i] = new Array( i, 0 ); + } + + this.dataset[name] = ds; + this.layout.addDataset(name, ds); +} + +Graph.prototype.updateDataset = function(name, value) { + if( this.dataset[name] ) { + var ds = this.dataset[name]; + + for( var i = 1; i < this.cols; i++ ) + ds[i-1][1] = ds[i][1]; + + value = Math.abs( parseFloat(value) || 0 ); + + if( this.transform ) { + var orgvalue = value; + value = (this.lastvalue[name]) ? this.transform(value, this.lastvalue[name]) : 0; + this.lastvalue[name] = orgvalue; + } + + ds[this.cols-1][1] = value; + this.layout.addDataset(name, ds); + } +} + +Graph.prototype.draw = function( options ) { + if( this.layout ) { + this.plotter = new PlotKit.CanvasRenderer( + this.canvas, this.layout, this.options || options || {} + ); + + this.layout.evaluate(); + this.plotter.render(); + + legend_opt = { + "legendStyle": 'li' + }; + + legend = new LegendRenderer(this.legend, this.layout, legend_opt); + legend.render(); + } +} + +Graph.prototype.redraw = function() { + if( this.layout && this.plotter ) { + this.layout.evaluate(); + this.plotter.clear(); + this.plotter.render(); + } +} + + +function GraphRPC(container, uri, action, interval, datasources, options, transform, legend) { + this.ds = datasources; + this.uri = uri + this.action = action; + this.options = options || { }; + this.container = container; + this.transform = transform; + this.proxy = new MochiKit.JsonRpc.JsonRpcProxy(uri, [action]); + this.graphs = new Object(); + this.legend = legend; + + this.requestData(); + + if( interval ) { + var self = this; + window.setInterval(function(){self.requestData()}, interval); + } +} + +GraphRPC.prototype.requestData = function() { + var r = this.proxy[this.action](); var self = this; + r.addCallback(function(r){ self.dispatchResponse(r) }); + r.addErrback(function(e){ throw('Error: ' + e) }); +} + +GraphRPC.prototype.dispatchResponse = function(response) { + var instances; + if( this.options.instances ) { + instances = this.options.instances; + } + else { + instances = new Array(); + for( var instance in response ) { + instances[instances.length] = instance; + } + } + + for( var j = 0; j < instances.length; j++ ) { + var instance = instances[j]; + + if( this.options.separateDS ) { + for( var i = 0; i < this.ds.length; i += 2 ) { + var name = this.ds[i+1] || this.ds[i]; + var gid = instance + '-' + name; + var otle = this.options.title || instance; + + if( !this.graphs[gid] ) { + this.options.title = otle.replace('%s', instance) + ': ' + name; + this.graphs[gid] = new Graph( + this.container, gid, this.options, this.transform, this.legend + ); + + this.graphs[gid].addDataset(name); + this.graphs[gid].draw(); + this.options.title = otle; + } + else + { + var datum = null; + if (typeof (this.ds[i]) == "function") { + datum = this.ds[i]( + instance ? response[instance] : response + ); + } else { + datum = instance + ? response[instance][this.ds[i]] + : response[this.ds[i]] + } + this.graphs[gid].updateDataset( + name, datum + ); + this.graphs[gid].redraw(); + } + } + } + else { + var gid = instance || 'livegraph'; + if( !this.graphs[gid] ) { + this.graphs[gid] = new Graph( + this.container, gid, this.options, this.transform, this.legend + ); + + for( var i = 0; i < this.ds.length; i += 2 ) { + var name = this.ds[i+1] || this.ds[i]; + this.graphs[gid].addDataset(name); + } + + this.graphs[gid].draw(); + } + else { + for( var i = 0; i < this.ds.length; i += 2 ) { + var name = this.ds[i+1] || this.ds[i]; + var datum = null; + if (typeof (this.ds[i]) == "function") { + datum = this.ds[i]( + instance ? response[instance] : response + ); + } else { + datum = instance + ? response[instance][this.ds[i]] + : response[this.ds[i]] + } + this.graphs[gid].updateDataset( + name, datum + ); + } + + this.graphs[gid].redraw(); + } + } + } +} diff --git a/openwrt/packages/luci/host/www/luci-static/resources/livestats/JsonRpc.js b/openwrt/packages/luci/host/www/luci-static/resources/livestats/JsonRpc.js new file mode 100644 index 0000000..f1723ec --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/livestats/JsonRpc.js @@ -0,0 +1,220 @@ +/* MochiKit.JsonRpc */ + +if (typeof(dojo) != 'undefined') { + dojo.provide("MochiKit.JsonRpc"); + dojo.require("MochiKit.Base"); + dojo.require("MochiKit.DOM"); + dojo.require("MochiKit.Async"); +} + +if (typeof(JSAN) != 'undefined') { + JSAN.use("MochiKit.Base", []); + JSAN.use("MochiKit.DOM", []); + JSAN.use("MochiKit.Async", []); +} + +try { + if (typeof(MochiKit.Base) == 'undefined' || + typeof(MochiKit.DOM) == 'undefined' || + typeof(MochiKit.Async) == 'undefined') { + throw ""; + } +} catch (e) { + throw "MochiKit.JsonRpc depends on MochiKit.Base, MochiKit.DOM and MochiKit.Async"; +} + +if (typeof(MochiKit.JsonRpc) == 'undefined') { + MochiKit.JsonRpc = {}; +} + +MochiKit.JsonRpc.NAME = "MochiKit.JsonRpc"; +MochiKit.JsonRpc.VERSION = "0.90"; + +MochiKit.JsonRpc.__repr__ = function () { + return "[" + this.NAME + " " + this.VERSION + "]"; +} + +MochiKit.JsonRpc.toString = function () { + return this.__repr__(); +} + +MochiKit.JsonRpc.JsonRpcError = function (message) { + this.message = message; + this.name = 'JsonRpcError'; +} + +MochiKit.JsonRpc.JsonRpcError.prototype = new Error(); +MochiKit.JsonRpc.JsonRpcError.prototype.repr = function () { + return 'JsonRpcError(' + this.message + ')'; +} + +MochiKit.JsonRpc.JsonRpcError.prototype.toString = function () { + return this.repr(); +} + +MochiKit.JsonRpc.jsonObject = function (o) { + var attrs=[]; + for(attr in o){ + if(typeof o[attr] != "function"){ + attrs.push('"' + attr + '": ' + json(o[attr])); + } + } + return "{" + attrs.join(", ") + "}"; +} + +MochiKit.JsonRpc.isObject = function (o) { + return true; +} + +MochiKit.JsonRpc.jsonArray = function (o) { + return "[" + MochiKit.Base.map(json, o).join(", ") + "]"; +} + +var MB = MochiKit.Base + +MochiKit.JsonRpc.jsonRegistry = new MochiKit.Base.AdapterRegistry(); +MochiKit.JsonRpc.jsonRegistry.register('arrayLike',MB.isArrayLike,MochiKit.JsonRpc.jsonArray); +MochiKit.JsonRpc.jsonRegistry.register("string", MB.typeMatcher("string"), MB.reprString); +MochiKit.JsonRpc.jsonRegistry.register("numbers", MB.typeMatcher("number", "boolean"), MB.reprNumber); +MochiKit.JsonRpc.jsonRegistry.register("undefined", MB.isUndefined, MB.reprUndefined); +MochiKit.JsonRpc.jsonRegistry.register("null", MB.isNull, MB.reprNull); +MochiKit.JsonRpc.jsonRegistry.register("objectLike", MochiKit.JsonRpc.isObject, MochiKit.JsonRpc.jsonObject); + +MochiKit.JsonRpc.json = function (o) { + try { + if (typeof(o.__json__) == 'function') { + return o.__json__(); + } else if (typeof(o.json) == 'function' && o.json != arguments.callee) { + return o.json(); + } + return jsonRegistry.match(o); + } catch (e) { + if (typeof(o.NAME) == 'string' && ( + o.toString == Function.prototype.toString || + o.toString == Object.prototype.toString + )) { + return o.NAME; + } + return o; + } + +} + + +MochiKit.JsonRpc.JsonRpcCall = function (method,params) { + this.method = method; + this.params = params; + this.id = '0'; +} + +MochiKit.JsonRpc.JsonRpcProxy = function (url,methNames) { + MochiKit.Base.bindMethods(this); + this.url = url; + if (methNames) { + MochiKit.Base.map(this._proxyMethod,methNames); + } +} + +update(MochiKit.JsonRpc.JsonRpcProxy.prototype, { + 'call': function () { + var arglist = MochiKit.Base.map(null,arguments) + var methname = arglist.shift() + log(arglist); + var callobj = new MochiKit.JsonRpc.JsonRpcCall(methname,arglist); + var callstr = json(callobj); + var req = MochiKit.Async.getXMLHttpRequest(); + req.open("POST",this.url,true); + req.setRequestHeader("Content-Type","text/plain"); + req.setRequestHeader("Content-Length",callstr.length); + var d = MochiKit.Async.sendXMLHttpRequest(req,callstr); + d.addCallback(MochiKit.Async.evalJSONRequest); + d.addCallback(this._extractResult); + + return d + }, + 'addSingleMethod': function (methName) { + if (methName) { + this._proxyMethod(methName); + } + }, + 'addMethods': function (methNames) { + if (methNames) { + MochiKit.Base.map(this._proxyMethod,methNames); + } + }, + '_extractResult': function (resp) { + if (!resp.error){ + return resp.result; + } else { + throw new MochiKit.JsonRpc.JsonRpcError(resp.error); + } + }, + '_proxyMethod': function (methname) { + this[methname] = MochiKit.Base.partial(this.call,methname); + } +}); + +MochiKit.JsonRpc.DomObjectFromJson = function (){ + var retval = false; + if (arguments.length == 1) { + var arg = arguments[0]; + if (typeof(arg) == 'string'){ + retval = MochiKit.DOM.SPAN(null,arg); + } else { + var objrepr = arguments[0]; + var elem = document.createElement(objrepr[0]); + var attrs = objrepr[1]; + if (attrs) { + MochiKit.DOM.updateNodeAttributes(elem, attrs); + } + if (objrepr.length >= 3){ + var extraobj = objrepr[2] + for (var i=0;i + For use under the BSD license. + +*/ + +try { + if (typeof(MochiKit.Base) == 'undefined' || + typeof(MochiKit.DOM) == 'undefined' || + typeof(MochiKit.Color) == 'undefined' || + typeof(MochiKit.Format) == 'undefined' || + typeof(PlotKit.Layout) == 'undefined' || + typeof(PlotKit.Base) == 'undefined') + { + throw ""; + } +} +catch (e) { + throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format}" +} + +if (typeof(PlotKit.LegendRenderer) == 'undefined') { + PlotKit.LegendRenderer = {}; +} + +PlotKit.LegendRenderer = function(element, layout, options) { + if (arguments.length > 0) + this.__init__(element, layout, options); +}; + + +PlotKit.LegendRenderer.NAME = "PlotKit.LegendRenderer"; +PlotKit.LegendRenderer.VERSION = PlotKit.VERSION; + +PlotKit.LegendRenderer.__repr__ = function() { + return "[" + this.NAME + " " + this.VERSION + "]"; +}; + +PlotKit.LegendRenderer.toString = function() { + return this.__repr__(); +} + +PlotKit.LegendRenderer.prototype.__init__ = function(element, layout, +options) { + var isNil = MochiKit.Base.isUndefinedOrNull; + var Color = MochiKit.Color.Color; + + this.options = { + "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors() +[0]), + "legendStyle": "table", + "tableColumns": 1 + }; + MochiKit.Base.update(this.options, options ? options : {}); + + this.layout = layout; + this.element = MochiKit.DOM.getElement(element); + // --- check whether everything is ok before we return + + if (isNil(this.element)) + throw "CRILegend() - passed legend is not found"; +}; + +PlotKit.LegendRenderer.prototype.render = function() { + var colorScheme = this.options.colorScheme; + var setNames = PlotKit.Base.keys(this.layout.datasets); + + MochiKit.DOM.updateNodeAttributes(this.element, + {"style": + {"margin":"0" + ,"padding":"0" + } + }); + + + var ul = null; + if (this.options.legendStyle == "table") + ul = this._renderListTable(colorScheme, setNames); + else + ul = this._renderList(colorScheme, setNames); + MochiKit.DOM.appendChildNodes(this.element, ul); + +}; + +PlotKit.LegendRenderer.prototype._renderList = function(colorScheme, +setNames) { + var ul = document.createElement("ul"); + ul.style.listStyle="none"; + ul.style.margin="0"; + ul.style.padding="0"; + + var colorCount = colorScheme.length; + var setCount = setNames.length; + + for (var i = 0; i < setCount; i++) { + var setName = setNames[i]; + var color = colorScheme[i%colorCount]; + var le = this._renderElement(setName, color.toRGBString()); + ul.appendChild(le); + } + + return ul; +}; + +PlotKit.LegendRenderer.prototype._renderElement = function(title, +color) { + var le = MochiKit.DOM.createDOM("li"); + le.style.listStyle="none"; + le.style.margin="0 0 5px 0"; + le.style.padding="0"; + + var box = MochiKit.DOM.createDOM("div"); + box.style.backgroundColor=color; + box.style.width="2em"; + box.style.height=".9em"; + box.style.border="1px solid black"; + box.style.margin="0 5px 0 0"; + box.style.padding="0"; + box.style.float="left"; + box.style.cssFloat="left"; + box.style.clear="left"; + box.style.cssClear="left"; + + var span = MochiKit.DOM.createDOM("span"); + MochiKit.DOM.appendChildNodes(span, +document.createTextNode(title)); + + MochiKit.DOM.appendChildNodes(le, box, span); + + return le; +}; + +PlotKit.LegendRenderer.prototype._renderListTable = +function(colorScheme, setNames) { + var tabhead = THEAD(null); + var tabfoot = TFOOT(null); + + var tabbody = partial(TBODY, null); + var i = 0; + var colorcount = colorScheme.length; + var tabrow; + var columns = this.options.tableColumns; + for (var label in setNames) + { + var legendcolor = colorScheme[i%colorcount]; + var legendbox = DIV({'class': 'legendbox', 'className': +'legendbox'}); + legendbox.style.width = "10px"; + legendbox.style.height = "10px"; + legendbox.style.backgroundColor = legendcolor.toHexString(); + legendbox.style.borderWidth = "1px"; + legendbox.style.borderStyle = "solid"; + legendbox.style.borderColor = "#000000"; + var boxcell = TD(null, legendbox); + + var labelcell = TD({'class': 'legendlabel', 'className': +'legendlabel'}, setNames[i]); + labelcell.style.font = 'normal 10pt arial'; + + if (!(i % columns)) + { + tabrow = partial(TR, null); + } + tabrow = partial(tabrow, boxcell, labelcell); + if (i % columns) + { + tabrow = tabrow(null); + tabbody = partial(tabbody, tabrow); + } + i++; + } + if ((setNames % columns)) + { + tabrow = tabrow(TD(null), TD(null)); + tabbody = partial(tabbody, tabrow); + } + tabbody = tabbody(null); + + tab = TABLE({'class': 'legendcontainer', 'className': +'legendcontainer'}, tabhead, tabfoot, tabbody); + tab.style.marginTop = '1em'; + tab.style.marginLeft = '1.5em'; + tab.style.marginBottom = '1em'; + tab.style.borderWidth = '1px'; + tab.style.borderStyle = 'solid'; + tab.style.borderColor = '#000000'; + + return tab; +}; + +// Namespace Iniitialisation + +PlotKit.Legend = {} +PlotKit.Legend.LegendRenderer = PlotKit.LegendRenderer; + + +PlotKit.Legend.EXPORT = [ + "LegendRenderer" +]; + +PlotKit.Legend.EXPORT_OK = [ + "LegendRenderer" +]; + +PlotKit.Legend.__new__ = function() { + var m = MochiKit.Base; + + m.nameFunctions(this); + + this.EXPORT_TAGS = { + ":common": this.EXPORT, + ":all": m.concat(this.EXPORT, this.EXPORT_OK) + }; +}; + +PlotKit.Legend.__new__(); +MochiKit.Base._exportSymbols(this, PlotKit.Legend); \ No newline at end of file diff --git a/openwrt/packages/luci/host/www/luci-static/resources/livestats/MochiKit.js b/openwrt/packages/luci/host/www/luci-static/resources/livestats/MochiKit.js new file mode 100644 index 0000000..c023c1e --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/livestats/MochiKit.js @@ -0,0 +1,4800 @@ +/*** + + MochiKit.MochiKit 1.3.1 : PACKED VERSION + + THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please + diff against the source tree, not this file. + + See for documentation, downloads, license, etc. + + (c) 2005 Bob Ippolito. All rights Reserved. + +***/ + +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Base"); +} +if(typeof (MochiKit)=="undefined"){ +MochiKit={}; +} +if(typeof (MochiKit.Base)=="undefined"){ +MochiKit.Base={}; +} +MochiKit.Base.VERSION="1.3.1"; +MochiKit.Base.NAME="MochiKit.Base"; +MochiKit.Base.update=function(_1,_2){ +if(_1===null){ +_1={}; +} +for(var i=1;i=0;i--){ +_12.unshift(o[i]); +} +}else{ +res.push(o); +} +} +return res; +},extend:function(_13,obj,_15){ +if(!_15){ +_15=0; +} +if(obj){ +var l=obj.length; +if(typeof (l)!="number"){ +if(typeof (MochiKit.Iter)!="undefined"){ +obj=MochiKit.Iter.list(obj); +l=obj.length; +}else{ +throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); +} +} +if(!_13){ +_13=[]; +} +for(var i=_15;i>b; +},zrshift:function(a,b){ +return a>>>b; +},eq:function(a,b){ +return a==b; +},ne:function(a,b){ +return a!=b; +},gt:function(a,b){ +return a>b; +},ge:function(a,b){ +return a>=b; +},lt:function(a,b){ +return al){ +_41=l; +} +} +_40=[]; +for(i=0;i<_41;i++){ +var _42=[]; +for(var j=1;j0){ +_57=m.concat(me.im_preargs,_57); +} +var _52=me.im_self; +if(!_52){ +_52=this; +} +return me.im_func.apply(_52,_57); +}; +_56.im_self=_55; +_56.im_func=_53; +_56.im_preargs=_54; +return _56; +},bindMethods:function(_58){ +var _59=MochiKit.Base.bind; +for(var k in _58){ +var _60=_58[k]; +if(typeof (_60)=="function"){ +_58[k]=_59(_60,_58); +} +} +},registerComparator:function(_61,_62,_63,_64){ +MochiKit.Base.comparatorRegistry.register(_61,_62,_63,_64); +},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){ +if(a==b){ +return 0; +} +var _65=(typeof (a)=="undefined"||a===null); +var _66=(typeof (b)=="undefined"||b===null); +if(_65&&_66){ +return 0; +}else{ +if(_65){ +return -1; +}else{ +if(_66){ +return 1; +} +} +} +var m=MochiKit.Base; +var _67=m._primitives; +if(!(typeof (a) in _67&&typeof (b) in _67)){ +try{ +return m.comparatorRegistry.match(a,b); +} +catch(e){ +if(e!=m.NotFound){ +throw e; +} +} +} +if(ab){ +return 1; +} +} +var _68=m.repr; +throw new TypeError(_68(a)+" and "+_68(b)+" can not be compared"); +},compareDateLike:function(a,b){ +return MochiKit.Base.compare(a.getTime(),b.getTime()); +},compareArrayLike:function(a,b){ +var _69=MochiKit.Base.compare; +var _70=a.length; +var _71=0; +if(_70>b.length){ +_71=1; +_70=b.length; +}else{ +if(_700))){ +var kv=MochiKit.DOM.formContents(_113); +_113=kv[0]; +_114=kv[1]; +}else{ +if(arguments.length==1){ +var o=_113; +_113=[]; +_114=[]; +for(var k in o){ +var v=o[k]; +if(typeof (v)!="function"){ +_113.push(k); +_114.push(v); +} +} +} +} +var rval=[]; +var len=Math.min(_113.length,_114.length); +var _118=MochiKit.Base.urlEncode; +for(var i=0;i=stop){ +throw self.StopIteration; +} +_147+=step; +return rval; +}}; +},imap:function(fun,p,q){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +var _151=m.map(self.iter,m.extend(null,arguments,1)); +var map=m.map; +var next=self.next; +return {repr:function(){ +return "imap(...)"; +},toString:m.forwardCall("repr"),next:function(){ +return fun.apply(this,map(next,_151)); +}}; +},applymap:function(fun,seq,self){ +seq=MochiKit.Iter.iter(seq); +var m=MochiKit.Base; +return {repr:function(){ +return "applymap(...)"; +},toString:m.forwardCall("repr"),next:function(){ +return fun.apply(self,seq.next()); +}}; +},chain:function(p,q){ +var self=MochiKit.Iter; +var m=MochiKit.Base; +if(arguments.length==1){ +return self.iter(arguments[0]); +} +var _153=m.map(self.iter,arguments); +return {repr:function(){ +return "chain(...)"; +},toString:m.forwardCall("repr"),next:function(){ +while(_153.length>1){ +try{ +return _153[0].next(); +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +_153.shift(); +} +} +if(_153.length==1){ +var arg=_153.shift(); +this.next=m.bind("next",arg); +return this.next(); +} +throw self.StopIteration; +}}; +},takewhile:function(pred,seq){ +var self=MochiKit.Iter; +seq=self.iter(seq); +return {repr:function(){ +return "takewhile(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +var rval=seq.next(); +if(!pred(rval)){ +this.next=function(){ +throw self.StopIteration; +}; +this.next(); +} +return rval; +}}; +},dropwhile:function(pred,seq){ +seq=MochiKit.Iter.iter(seq); +var m=MochiKit.Base; +var bind=m.bind; +return {"repr":function(){ +return "dropwhile(...)"; +},"toString":m.forwardCall("repr"),"next":function(){ +while(true){ +var rval=seq.next(); +if(!pred(rval)){ +break; +} +} +this.next=bind("next",seq); +return rval; +}}; +},_tee:function(_155,sync,_157){ +sync.pos[_155]=-1; +var m=MochiKit.Base; +var _158=m.listMin; +return {repr:function(){ +return "tee("+_155+", ...)"; +},toString:m.forwardCall("repr"),next:function(){ +var rval; +var i=sync.pos[_155]; +if(i==sync.max){ +rval=_157.next(); +sync.deque.push(rval); +sync.max+=1; +sync.pos[_155]+=1; +}else{ +rval=sync.deque[i-sync.min]; +sync.pos[_155]+=1; +if(i==sync.min&&_158(sync.pos)!=sync.min){ +sync.min+=1; +sync.deque.shift(); +} +} +return rval; +}}; +},tee:function(_159,n){ +var rval=[]; +var sync={"pos":[],"deque":[],"max":-1,"min":-1}; +if(arguments.length==1){ +n=2; +} +var self=MochiKit.Iter; +_159=self.iter(_159); +var _tee=self._tee; +for(var i=0;i0&&_165>=stop)||(step<0&&_165<=stop)){ +throw MochiKit.Iter.StopIteration; +} +var rval=_165; +_165+=step; +return rval; +},repr:function(){ +return "range("+[_165,stop,step].join(", ")+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +},sum:function(_166,_167){ +var x=_167||0; +var self=MochiKit.Iter; +_166=self.iter(_166); +try{ +while(true){ +x+=_166.next(); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +return x; +},exhaust:function(_168){ +var self=MochiKit.Iter; +_168=self.iter(_168); +try{ +while(true){ +_168.next(); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +},forEach:function(_169,func,self){ +var m=MochiKit.Base; +if(arguments.length>2){ +func=m.bind(func,self); +} +if(m.isArrayLike(_169)){ +try{ +for(var i=0;i<_169.length;i++){ +func(_169[i]); +} +} +catch(e){ +if(e!=MochiKit.Iter.StopIteration){ +throw e; +} +} +}else{ +self=MochiKit.Iter; +self.exhaust(self.imap(func,_169)); +} +},every:function(_171,func){ +var self=MochiKit.Iter; +try{ +self.ifilterfalse(func,_171).next(); +return false; +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +return true; +} +},sorted:function(_172,cmp){ +var rval=MochiKit.Iter.list(_172); +if(arguments.length==1){ +cmp=MochiKit.Base.compare; +} +rval.sort(cmp); +return rval; +},reversed:function(_173){ +var rval=MochiKit.Iter.list(_173); +rval.reverse(); +return rval; +},some:function(_174,func){ +var self=MochiKit.Iter; +try{ +self.ifilter(func,_174).next(); +return true; +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +return false; +} +},iextend:function(lst,_175){ +if(MochiKit.Base.isArrayLike(_175)){ +for(var i=0;i<_175.length;i++){ +lst.push(_175[i]); +} +}else{ +var self=MochiKit.Iter; +_175=self.iter(_175); +try{ +while(true){ +lst.push(_175.next()); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +} +return lst; +},groupby:function(_176,_177){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +if(arguments.length<2){ +_177=m.operator.identity; +} +_176=self.iter(_176); +var pk=undefined; +var k=undefined; +var v; +function fetch(){ +v=_176.next(); +k=_177(v); +} +function eat(){ +var ret=v; +v=undefined; +return ret; +} +var _180=true; +return {repr:function(){ +return "groupby(...)"; +},next:function(){ +while(k==pk){ +fetch(); +if(_180){ +_180=false; +break; +} +} +pk=k; +return [k,{next:function(){ +if(v==undefined){ +fetch(); +} +if(k!=pk){ +throw self.StopIteration; +} +return eat(); +}}]; +}}; +},groupby_as_array:function(_181,_182){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +if(arguments.length<2){ +_182=m.operator.identity; +} +_181=self.iter(_181); +var _183=[]; +var _184=true; +var _185; +while(true){ +try{ +var _186=_181.next(); +var key=_182(_186); +} +catch(e){ +if(e==self.StopIteration){ +break; +} +throw e; +} +if(_184||key!=_185){ +var _187=[]; +_183.push([key,_187]); +} +_187.push(_186); +_184=false; +_185=key; +} +return _183; +},arrayLikeIter:function(_188){ +var i=0; +return {repr:function(){ +return "arrayLikeIter(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +if(i>=_188.length){ +throw MochiKit.Iter.StopIteration; +} +return _188[i++]; +}}; +},hasIterateNext:function(_189){ +return (_189&&typeof (_189.iterateNext)=="function"); +},iterateNextIter:function(_190){ +return {repr:function(){ +return "iterateNextIter(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +var rval=_190.iterateNext(); +if(rval===null||rval===undefined){ +throw MochiKit.Iter.StopIteration; +} +return rval; +}}; +}}); +MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter",]; +MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"]; +MochiKit.Iter.__new__=function(){ +var m=MochiKit.Base; +this.StopIteration=new m.NamedError("StopIteration"); +this.iteratorRegistry=new m.AdapterRegistry(); +this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter); +this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Iter.__new__(); +if(!MochiKit.__compat__){ +reduce=MochiKit.Iter.reduce; +} +MochiKit.Base._exportSymbols(this,MochiKit.Iter); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Logging"); +dojo.require("MochiKit.Base"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Logging depends on MochiKit.Base!"; +} +if(typeof (MochiKit.Logging)=="undefined"){ +MochiKit.Logging={}; +} +MochiKit.Logging.NAME="MochiKit.Logging"; +MochiKit.Logging.VERSION="1.3.1"; +MochiKit.Logging.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Logging.toString=function(){ +return this.__repr__(); +}; +MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"]; +MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"]; +MochiKit.Logging.LogMessage=function(num,_192,info){ +this.num=num; +this.level=_192; +this.info=info; +this.timestamp=new Date(); +}; +MochiKit.Logging.LogMessage.prototype={repr:function(){ +var m=MochiKit.Base; +return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_194){ +var self=MochiKit.Logging; +if(typeof (_194)=="string"){ +_194=self.LogLevel[_194]; +} +return function(msg){ +var _196=msg.level; +if(typeof (_196)=="string"){ +_196=self.LogLevel[_196]; +} +return _196>=_194; +}; +},isLogMessage:function(){ +var _197=MochiKit.Logging.LogMessage; +for(var i=0;i=0&&this._messages.length>this.maxSize){ +this._messages.shift(); +} +},getMessages:function(_206){ +var _207=0; +if(!(typeof (_206)=="undefined"||_206===null)){ +_207=Math.max(0,this._messages.length-_206); +} +return this._messages.slice(_207); +},getMessageText:function(_208){ +if(typeof (_208)=="undefined"||_208===null){ +_208=30; +} +var _209=this.getMessages(_208); +if(_209.length){ +var lst=map(function(m){ +return "\n ["+m.num+"] "+m.level+": "+m.info.join(" "); +},_209); +lst.unshift("LAST "+_209.length+" MESSAGES:"); +return lst.join(""); +} +return ""; +},debuggingBookmarklet:function(_210){ +if(typeof (MochiKit.LoggingPane)=="undefined"){ +alert(this.getMessageText()); +}else{ +MochiKit.LoggingPane.createLoggingPane(_210||false); +} +}}; +MochiKit.Logging.__new__=function(){ +this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10}; +var m=MochiKit.Base; +m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage); +var _211=m.partial; +var _212=this.Logger; +var _213=_212.prototype.baseLog; +m.update(this.Logger.prototype,{debug:_211(_213,"DEBUG"),log:_211(_213,"INFO"),error:_211(_213,"ERROR"),fatal:_211(_213,"FATAL"),warning:_211(_213,"WARNING")}); +var self=this; +var _214=function(name){ +return function(){ +self.logger[name].apply(self.logger,arguments); +}; +}; +this.log=_214("log"); +this.logError=_214("error"); +this.logDebug=_214("debug"); +this.logFatal=_214("fatal"); +this.logWarning=_214("warning"); +this.logger=new _212(); +this.logger.useNativeConsole=true; +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){ +printfire=function(){ +printfire.args=arguments; +var ev=document.createEvent("Events"); +ev.initEvent("printfire",false,true); +dispatchEvent(ev); +}; +} +MochiKit.Logging.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.Logging); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.DateTime"); +} +if(typeof (MochiKit)=="undefined"){ +MochiKit={}; +} +if(typeof (MochiKit.DateTime)=="undefined"){ +MochiKit.DateTime={}; +} +MochiKit.DateTime.NAME="MochiKit.DateTime"; +MochiKit.DateTime.VERSION="1.3.1"; +MochiKit.DateTime.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.DateTime.toString=function(){ +return this.__repr__(); +}; +MochiKit.DateTime.isoDate=function(str){ +str=str+""; +if(typeof (str)!="string"||str.length===0){ +return null; +} +var iso=str.split("-"); +if(iso.length===0){ +return null; +} +return new Date(iso[0],iso[1]-1,iso[2]); +}; +MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/; +MochiKit.DateTime.isoTimestamp=function(str){ +str=str+""; +if(typeof (str)!="string"||str.length===0){ +return null; +} +var res=str.match(MochiKit.DateTime._isoRegexp); +if(typeof (res)=="undefined"||res===null){ +return null; +} +var year,month,day,hour,min,sec,msec; +year=parseInt(res[1],10); +if(typeof (res[2])=="undefined"||res[2]===""){ +return new Date(year); +} +month=parseInt(res[2],10)-1; +day=parseInt(res[3],10); +if(typeof (res[4])=="undefined"||res[4]===""){ +return new Date(year,month,day); +} +hour=parseInt(res[4],10); +min=parseInt(res[5],10); +sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0; +if(typeof (res[7])!="undefined"&&res[7]!==""){ +msec=Math.round(1000*parseFloat("0."+res[7])); +}else{ +msec=0; +} +if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){ +return new Date(year,month,day,hour,min,sec,msec); +} +var ofs; +if(typeof (res[9])!="undefined"&&res[9]!==""){ +ofs=parseInt(res[10],10)*3600000; +if(typeof (res[11])!="undefined"&&res[11]!==""){ +ofs+=parseInt(res[11],10)*60000; +} +if(res[9]=="-"){ +ofs=-ofs; +} +}else{ +ofs=0; +} +return new Date(Date.UTC(year,month,day,hour,min,sec,msec)-ofs); +}; +MochiKit.DateTime.toISOTime=function(date,_221){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var hh=date.getHours(); +var mm=date.getMinutes(); +var ss=date.getSeconds(); +var lst=[((_221&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)]; +return lst.join(":"); +}; +MochiKit.DateTime.toISOTimestamp=function(date,_225){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var sep=_225?"T":" "; +var foot=_225?"Z":""; +if(_225){ +date=new Date(date.getTime()+(date.getTimezoneOffset()*60000)); +} +return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_225)+foot; +}; +MochiKit.DateTime.toISODate=function(date){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var _228=MochiKit.DateTime._padTwo; +return [date.getFullYear(),_228(date.getMonth()+1),_228(date.getDate())].join("-"); +}; +MochiKit.DateTime.americanDate=function(d){ +d=d+""; +if(typeof (d)!="string"||d.length===0){ +return null; +} +var a=d.split("/"); +return new Date(a[2],a[0]-1,a[1]); +}; +MochiKit.DateTime._padTwo=function(n){ +return (n>9)?n:"0"+n; +}; +MochiKit.DateTime.toPaddedAmericanDate=function(d){ +if(typeof (d)=="undefined"||d===null){ +return null; +} +var _230=MochiKit.DateTime._padTwo; +return [_230(d.getMonth()+1),_230(d.getDate()),d.getFullYear()].join("/"); +}; +MochiKit.DateTime.toAmericanDate=function(d){ +if(typeof (d)=="undefined"||d===null){ +return null; +} +return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/"); +}; +MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"]; +MochiKit.DateTime.EXPORT_OK=[]; +MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT}; +MochiKit.DateTime.__new__=function(){ +var base=this.NAME+"."; +for(var k in this){ +var o=this[k]; +if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ +try{ +o.NAME=base+k; +} +catch(e){ +} +} +} +}; +MochiKit.DateTime.__new__(); +if(typeof (MochiKit.Base)!="undefined"){ +MochiKit.Base._exportSymbols(this,MochiKit.DateTime); +}else{ +(function(_231,_232){ +if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){ +var all=_232.EXPORT_TAGS[":all"]; +for(var i=0;i_240){ +var i=_246.length-_240; +res=fmt.separator+_246.substring(i,_246.length)+res; +_246=_246.substring(0,i); +} +} +res=_246+res; +if(_238>0){ +while(frac.length<_241){ +frac=frac+"0"; +} +res=res+fmt.decimal+frac; +} +return _242+res+_243; +}; +}; +MochiKit.Format.numberFormatter=function(_248,_249,_250){ +if(typeof (_249)=="undefined"){ +_249=""; +} +var _251=_248.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/); +if(!_251){ +throw TypeError("Invalid pattern"); +} +var _252=_248.substr(0,_251.index); +var _253=_248.substr(_251.index+_251[0].length); +if(_252.search(/-/)==-1){ +_252=_252+"-"; +} +var _254=_251[1]; +var frac=(typeof (_251[2])=="string"&&_251[2]!="")?_251[2]:""; +var _255=(typeof (_251[3])=="string"&&_251[3]!=""); +var tmp=_254.split(/,/); +var _257; +if(typeof (_250)=="undefined"){ +_250="default"; +} +if(tmp.length==1){ +_257=null; +}else{ +_257=tmp[1].length; +} +var _258=_254.length-_254.replace(/0/g,"").length; +var _259=frac.length-frac.replace(/0/g,"").length; +var _260=frac.length; +var rval=MochiKit.Format._numberFormatter(_249,_252,_253,_250,_255,_260,_258,_257,_259); +var m=MochiKit.Base; +if(m){ +var fn=arguments.callee; +var args=m.concat(arguments); +rval.repr=function(){ +return [self.NAME,"(",map(m.repr,args).join(", "),")"].join(""); +}; +} +return rval; +}; +MochiKit.Format.formatLocale=function(_262){ +if(typeof (_262)=="undefined"||_262===null){ +_262="default"; +} +if(typeof (_262)=="string"){ +var rval=MochiKit.Format.LOCALE[_262]; +if(typeof (rval)=="string"){ +rval=arguments.callee(rval); +MochiKit.Format.LOCALE[_262]=rval; +} +return rval; +}else{ +return _262; +} +}; +MochiKit.Format.twoDigitAverage=function(_263,_264){ +if(_264){ +var res=_263/_264; +if(!isNaN(res)){ +return MochiKit.Format.twoDigitFloat(_263/_264); +} +} +return "0"; +}; +MochiKit.Format.twoDigitFloat=function(_265){ +var sign=(_265<0?"-":""); +var s=Math.floor(Math.abs(_265)*100).toString(); +if(s=="0"){ +return s; +} +if(s.length<3){ +while(s.charAt(s.length-1)=="0"){ +s=s.substring(0,s.length-1); +} +return sign+"0."+s; +} +var head=sign+s.substring(0,s.length-2); +var tail=s.substring(s.length-2,s.length); +if(tail=="00"){ +return head; +}else{ +if(tail.charAt(1)=="0"){ +return head+"."+tail.charAt(0); +}else{ +return head+"."+tail; +} +} +}; +MochiKit.Format.lstrip=function(str,_270){ +str=str+""; +if(typeof (str)!="string"){ +return null; +} +if(!_270){ +return str.replace(/^\s+/,""); +}else{ +return str.replace(new RegExp("^["+_270+"]+"),""); +} +}; +MochiKit.Format.rstrip=function(str,_271){ +str=str+""; +if(typeof (str)!="string"){ +return null; +} +if(!_271){ +return str.replace(/\s+$/,""); +}else{ +return str.replace(new RegExp("["+_271+"]+$"),""); +} +}; +MochiKit.Format.strip=function(str,_272){ +var self=MochiKit.Format; +return self.rstrip(self.lstrip(str,_272),_272); +}; +MochiKit.Format.truncToFixed=function(_273,_274){ +_273=Math.floor(_273*Math.pow(10,_274)); +var res=(_273*Math.pow(10,-_274)).toFixed(_274); +if(res.charAt(0)=="."){ +res="0"+res; +} +return res; +}; +MochiKit.Format.roundToFixed=function(_275,_276){ +return MochiKit.Format.truncToFixed(_275+0.5*Math.pow(10,-_276),_276); +}; +MochiKit.Format.percentFormat=function(_277){ +return MochiKit.Format.twoDigitFloat(100*_277)+"%"; +}; +MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"]; +MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"}; +MochiKit.Format.EXPORT_OK=[]; +MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT}; +MochiKit.Format.__new__=function(){ +var base=this.NAME+"."; +var k,v,o; +for(k in this.LOCALE){ +o=this.LOCALE[k]; +if(typeof (o)=="object"){ +o.repr=function(){ +return this.NAME; +}; +o.NAME=base+"LOCALE."+k; +} +} +for(k in this){ +o=this[k]; +if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ +try{ +o.NAME=base+k; +} +catch(e){ +} +} +} +}; +MochiKit.Format.__new__(); +if(typeof (MochiKit.Base)!="undefined"){ +MochiKit.Base._exportSymbols(this,MochiKit.Format); +}else{ +(function(_278,_279){ +if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(typeof (MochiKit.__compat__)=="boolean"&&MochiKit.__compat__)){ +var all=_279.EXPORT_TAGS[":all"]; +for(var i=0;i=0)){ +this._fire(); +} +},_continue:function(res){ +this._resback(res); +this._unpause(); +},_resback:function(res){ +this.fired=((res instanceof Error)?1:0); +this.results[this.fired]=res; +this._fire(); +},_check:function(){ +if(this.fired!=-1){ +if(!this.silentlyCancelled){ +throw new MochiKit.Async.AlreadyCalledError(this); +} +this.silentlyCancelled=false; +return; +} +},callback:function(res){ +this._check(); +if(res instanceof MochiKit.Async.Deferred){ +throw new Error("Deferred instances can only be chained if they are the result of a callback"); +} +this._resback(res); +},errback:function(res){ +this._check(); +var self=MochiKit.Async; +if(res instanceof self.Deferred){ +throw new Error("Deferred instances can only be chained if they are the result of a callback"); +} +if(!(res instanceof Error)){ +res=new self.GenericError(res); +} +this._resback(res); +},addBoth:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(fn,fn); +},addCallback:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(fn,null); +},addErrback:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(null,fn); +},addCallbacks:function(cb,eb){ +if(this.chained){ +throw new Error("Chained Deferreds can not be re-used"); +} +this.chain.push([cb,eb]); +if(this.fired>=0){ +this._fire(); +} +return this; +},_fire:function(){ +var _284=this.chain; +var _285=this.fired; +var res=this.results[_285]; +var self=this; +var cb=null; +while(_284.length>0&&this.paused===0){ +var pair=_284.shift(); +var f=pair[_285]; +if(f===null){ +continue; +} +try{ +res=f(res); +_285=((res instanceof Error)?1:0); +if(res instanceof MochiKit.Async.Deferred){ +cb=function(res){ +self._continue(res); +}; +this._pause(); +} +} +catch(err){ +_285=1; +if(!(err instanceof Error)){ +err=new MochiKit.Async.GenericError(err); +} +res=err; +} +} +this.fired=_285; +this.results[_285]=res; +if(cb&&this.paused){ +res.addBoth(cb); +res.chained=true; +} +}}; +MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(){ +return eval("("+arguments[0].responseText+")"); +},succeed:function(_287){ +var d=new MochiKit.Async.Deferred(); +d.callback.apply(d,arguments); +return d; +},fail:function(_288){ +var d=new MochiKit.Async.Deferred(); +d.errback.apply(d,arguments); +return d; +},getXMLHttpRequest:function(){ +var self=arguments.callee; +if(!self.XMLHttpRequest){ +var _289=[function(){ +return new XMLHttpRequest(); +},function(){ +return new ActiveXObject("Msxml2.XMLHTTP"); +},function(){ +return new ActiveXObject("Microsoft.XMLHTTP"); +},function(){ +return new ActiveXObject("Msxml2.XMLHTTP.4.0"); +},function(){ +throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); +}]; +for(var i=0;i<_289.length;i++){ +var func=_289[i]; +try{ +self.XMLHttpRequest=func; +return func(); +} +catch(e){ +} +} +} +return self.XMLHttpRequest(); +},_nothing:function(){ +},_xhr_onreadystatechange:function(d){ +if(this.readyState==4){ +try{ +this.onreadystatechange=null; +} +catch(e){ +try{ +this.onreadystatechange=MochiKit.Async._nothing; +} +catch(e){ +} +} +var _290=null; +try{ +_290=this.status; +if(!_290&&MochiKit.Base.isNotEmpty(this.responseText)){ +_290=304; +} +} +catch(e){ +} +if(_290==200||_290==304){ +d.callback(this); +}else{ +var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed"); +if(err.number){ +d.errback(err); +}else{ +d.errback(err); +} +} +} +},_xhr_canceller:function(req){ +try{ +req.onreadystatechange=null; +} +catch(e){ +try{ +req.onreadystatechange=MochiKit.Async._nothing; +} +catch(e){ +} +} +req.abort(); +},sendXMLHttpRequest:function(req,_293){ +if(typeof (_293)=="undefined"||_293===null){ +_293=""; +} +var m=MochiKit.Base; +var self=MochiKit.Async; +var d=new self.Deferred(m.partial(self._xhr_canceller,req)); +try{ +req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d); +req.send(_293); +} +catch(e){ +try{ +req.onreadystatechange=null; +} +catch(ignore){ +} +d.errback(e); +} +return d; +},doSimpleXMLHttpRequest:function(url){ +var self=MochiKit.Async; +var req=self.getXMLHttpRequest(); +if(arguments.length>1){ +var m=MochiKit.Base; +var qs=m.queryString.apply(null,m.extend(null,arguments,1)); +if(qs){ +url+="?"+qs; +} +} +req.open("GET",url,true); +return self.sendXMLHttpRequest(req); +},loadJSONDoc:function(url){ +var self=MochiKit.Async; +var d=self.doSimpleXMLHttpRequest.apply(self,arguments); +d=d.addCallback(self.evalJSONRequest); +return d; +},wait:function(_296,_297){ +var d=new MochiKit.Async.Deferred(); +var m=MochiKit.Base; +if(typeof (_297)!="undefined"){ +d.addCallback(function(){ +return _297; +}); +} +var _298=setTimeout(m.bind("callback",d),Math.floor(_296*1000)); +d.canceller=function(){ +try{ +clearTimeout(_298); +} +catch(e){ +} +}; +return d; +},callLater:function(_299,func){ +var m=MochiKit.Base; +var _300=m.partial.apply(m,m.extend(null,arguments,1)); +return MochiKit.Async.wait(_299).addCallback(function(res){ +return _300(); +}); +}}); +MochiKit.Async.DeferredLock=function(){ +this.waiting=[]; +this.locked=false; +this.id=this._nextId(); +}; +MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){ +d=new MochiKit.Async.Deferred(); +if(this.locked){ +this.waiting.push(d); +}else{ +this.locked=true; +d.callback(this); +} +return d; +},release:function(){ +if(!this.locked){ +throw TypeError("Tried to release an unlocked DeferredLock"); +} +this.locked=false; +if(this.waiting.length>0){ +this.locked=true; +this.waiting.shift().callback(this); +} +},_nextId:MochiKit.Base.counter(),repr:function(){ +var _301; +if(this.locked){ +_301="locked, "+this.waiting.length+" waiting"; +}else{ +_301="unlocked"; +} +return "DeferredLock("+this.id+", "+_301+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +MochiKit.Async.DeferredList=function(list,_303,_304,_305,_306){ +this.list=list; +this.resultList=new Array(this.list.length); +this.chain=[]; +this.id=this._nextId(); +this.fired=-1; +this.paused=0; +this.results=[null,null]; +this.canceller=_306; +this.silentlyCancelled=false; +if(this.list.length===0&&!_303){ +this.callback(this.resultList); +} +this.finishedCount=0; +this.fireOnOneCallback=_303; +this.fireOnOneErrback=_304; +this.consumeErrors=_305; +var _307=0; +MochiKit.Base.map(MochiKit.Base.bind(function(d){ +d.addCallback(MochiKit.Base.bind(this._cbDeferred,this),_307,true); +d.addErrback(MochiKit.Base.bind(this._cbDeferred,this),_307,false); +_307+=1; +},this),this.list); +}; +MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,MochiKit.Async.Deferred.prototype); +MochiKit.Base.update(MochiKit.Async.DeferredList.prototype,{_cbDeferred:function(_308,_309,_310){ +this.resultList[_308]=[_309,_310]; +this.finishedCount+=1; +if(this.fired!==0){ +if(_309&&this.fireOnOneCallback){ +this.callback([_308,_310]); +}else{ +if(!_309&&this.fireOnOneErrback){ +this.errback(_310); +}else{ +if(this.finishedCount==this.list.length){ +this.callback(this.resultList); +} +} +} +} +if(!_309&&this.consumeErrors){ +_310=null; +} +return _310; +}}); +MochiKit.Async.gatherResults=function(_311){ +var d=new MochiKit.Async.DeferredList(_311,false,true,false); +d.addCallback(function(_312){ +var ret=[]; +for(var i=0;i<_312.length;i++){ +ret.push(_312[i][1]); +} +return ret; +}); +return d; +}; +MochiKit.Async.maybeDeferred=function(func){ +var self=MochiKit.Async; +var _313; +try{ +var r=func.apply(null,MochiKit.Base.extend([],arguments,1)); +if(r instanceof self.Deferred){ +_313=r; +}else{ +if(r instanceof Error){ +_313=self.fail(r); +}else{ +_313=self.succeed(r); +} +} +} +catch(e){ +_313=self.fail(e); +} +return _313; +}; +MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred"]; +MochiKit.Async.EXPORT_OK=["evalJSONRequest"]; +MochiKit.Async.__new__=function(){ +var m=MochiKit.Base; +var ne=m.partial(m._newNamedError,this); +ne("AlreadyCalledError",function(_316){ +this.deferred=_316; +}); +ne("CancelledError",function(_317){ +this.deferred=_317; +}); +ne("BrowserComplianceError",function(msg){ +this.message=msg; +}); +ne("GenericError",function(msg){ +this.message=msg; +}); +ne("XMLHttpRequestError",function(req,msg){ +this.req=req; +this.message=msg; +try{ +this.number=req.status; +} +catch(e){ +} +}); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Async.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.Async); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.DOM"); +dojo.require("MochiKit.Iter"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Iter",[]); +} +try{ +if(typeof (MochiKit.Iter)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.DOM depends on MochiKit.Iter!"; +} +if(typeof (MochiKit.DOM)=="undefined"){ +MochiKit.DOM={}; +} +MochiKit.DOM.NAME="MochiKit.DOM"; +MochiKit.DOM.VERSION="1.3.1"; +MochiKit.DOM.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.DOM.toString=function(){ +return this.__repr__(); +}; +MochiKit.DOM.EXPORT=["formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","getNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","replaceChildNodes","removeElement","swapDOM","BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG","getElement","$","computedStyle","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","escapeHTML","toHTML","emitHTML","setDisplayForElement","hideElement","showElement","scrapeText","elementDimensions","elementPosition","setElementDimensions","setElementPosition","getViewportDimensions","setOpacity"]; +MochiKit.DOM.EXPORT_OK=["domConverters"]; +MochiKit.DOM.Dimensions=function(w,h){ +this.w=w; +this.h=h; +}; +MochiKit.DOM.Dimensions.prototype.repr=function(){ +var repr=MochiKit.Base.repr; +return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}"; +}; +MochiKit.DOM.Coordinates=function(x,y){ +this.x=x; +this.y=y; +}; +MochiKit.DOM.Coordinates.prototype.repr=function(){ +var repr=MochiKit.Base.repr; +return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}"; +}; +MochiKit.DOM.Coordinates.prototype.toString=function(){ +return this.repr(); +}; +MochiKit.Base.update(MochiKit.DOM,{setOpacity:function(elem,o){ +elem=MochiKit.DOM.getElement(elem); +MochiKit.DOM.updateNodeAttributes(elem,{"style":{"opacity":o,"-moz-opacity":o,"-khtml-opacity":o,"filter":" alpha(opacity="+(o*100)+")"}}); +},getViewportDimensions:function(){ +var d=new MochiKit.DOM.Dimensions(); +var w=MochiKit.DOM._window; +var b=MochiKit.DOM._document.body; +if(w.innerWidth){ +d.w=w.innerWidth; +d.h=w.innerHeight; +}else{ +if(b.parentElement.clientWidth){ +d.w=b.parentElement.clientWidth; +d.h=b.parentElement.clientHeight; +}else{ +if(b&&b.clientWidth){ +d.w=b.clientWidth; +d.h=b.clientHeight; +} +} +} +return d; +},elementDimensions:function(elem){ +var self=MochiKit.DOM; +if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){ +return new self.Dimensions(elem.w||0,elem.h||0); +} +elem=self.getElement(elem); +if(!elem){ +return undefined; +} +if(self.computedStyle(elem,"display")!="none"){ +return new self.Dimensions(elem.offsetWidth||0,elem.offsetHeight||0); +} +var s=elem.style; +var _322=s.visibility; +var _323=s.position; +s.visibility="hidden"; +s.position="absolute"; +s.display=""; +var _324=elem.offsetWidth; +var _325=elem.offsetHeight; +s.display="none"; +s.position=_323; +s.visibility=_322; +return new self.Dimensions(_324,_325); +},elementPosition:function(elem,_326){ +var self=MochiKit.DOM; +elem=self.getElement(elem); +if(!elem){ +return undefined; +} +var c=new self.Coordinates(0,0); +if(elem.x&&elem.y){ +c.x+=elem.x||0; +c.y+=elem.y||0; +return c; +}else{ +if(elem.parentNode===null||self.computedStyle(elem,"display")=="none"){ +return undefined; +} +} +var box=null; +var _329=null; +var d=MochiKit.DOM._document; +var de=d.documentElement; +var b=d.body; +if(elem.getBoundingClientRect){ +box=elem.getBoundingClientRect(); +c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||b.clientLeft); +c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||b.clientTop); +}else{ +if(d.getBoxObjectFor){ +box=d.getBoxObjectFor(elem); +c.x+=box.x; +c.y+=box.y; +}else{ +if(elem.offsetParent){ +c.x+=elem.offsetLeft; +c.y+=elem.offsetTop; +_329=elem.offsetParent; +if(_329!=elem){ +while(_329){ +c.x+=_329.offsetLeft; +c.y+=_329.offsetTop; +_329=_329.offsetParent; +} +} +var ua=navigator.userAgent.toLowerCase(); +if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("safari")!=-1&&self.computedStyle(elem,"position")=="absolute")){ +c.x-=b.offsetLeft; +c.y-=b.offsetTop; +} +} +} +} +if(typeof (_326)!="undefined"){ +_326=arguments.callee(_326); +if(_326){ +c.x-=(_326.x||0); +c.y-=(_326.y||0); +} +} +if(elem.parentNode){ +_329=elem.parentNode; +}else{ +_329=null; +} +while(_329&&_329.tagName!="BODY"&&_329.tagName!="HTML"){ +c.x-=_329.scrollLeft; +c.y-=_329.scrollTop; +if(_329.parentNode){ +_329=_329.parentNode; +}else{ +_329=null; +} +} +return c; +},setElementDimensions:function(elem,_332,_333){ +elem=MochiKit.DOM.getElement(elem); +if(typeof (_333)=="undefined"){ +_333="px"; +} +MochiKit.DOM.updateNodeAttributes(elem,{"style":{"width":_332.w+_333,"height":_332.h+_333}}); +},setElementPosition:function(elem,_334,_335){ +elem=MochiKit.DOM.getElement(elem); +if(typeof (_335)=="undefined"){ +_335="px"; +} +MochiKit.DOM.updateNodeAttributes(elem,{"style":{"left":_334.x+_335,"top":_334.y+_335}}); +},currentWindow:function(){ +return MochiKit.DOM._window; +},currentDocument:function(){ +return MochiKit.DOM._document; +},withWindow:function(win,func){ +var self=MochiKit.DOM; +var _337=self._document; +var _338=self._win; +var rval; +try{ +self._window=win; +self._document=win.document; +rval=func(); +} +catch(e){ +self._window=_338; +self._document=_337; +throw e; +} +self._window=_338; +self._document=_337; +return rval; +},formContents:function(elem){ +var _339=[]; +var _340=[]; +var m=MochiKit.Base; +var self=MochiKit.DOM; +if(typeof (elem)=="undefined"||elem===null){ +elem=self._document; +}else{ +elem=self.getElement(elem); +} +m.nodeWalk(elem,function(elem){ +var name=elem.name; +if(m.isNotEmpty(name)){ +var _341=elem.nodeName; +if(_341=="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){ +return null; +} +if(_341=="SELECT"){ +if(elem.selectedIndex>=0){ +var opt=elem.options[elem.selectedIndex]; +_339.push(name); +_340.push((opt.value)?opt.value:opt.text); +return null; +} +_339.push(name); +_340.push(""); +return null; +} +if(_341=="FORM"||_341=="P"||_341=="SPAN"||_341=="DIV"){ +return elem.childNodes; +} +_339.push(name); +_340.push(elem.value||""); +return null; +} +return elem.childNodes; +}); +return [_339,_340]; +},withDocument:function(doc,func){ +var self=MochiKit.DOM; +var _344=self._document; +var rval; +try{ +self._document=doc; +rval=func(); +} +catch(e){ +self._document=_344; +throw e; +} +self._document=_344; +return rval; +},registerDOMConverter:function(name,_345,wrap,_346){ +MochiKit.DOM.domConverters.register(name,_345,wrap,_346); +},coerceToDOM:function(node,ctx){ +var im=MochiKit.Iter; +var self=MochiKit.DOM; +var iter=im.iter; +var _350=im.repeat; +var imap=im.imap; +var _352=self.domConverters; +var _353=self.coerceToDOM; +var _354=MochiKit.Base.NotFound; +while(true){ +if(typeof (node)=="undefined"||node===null){ +return null; +} +if(typeof (node.nodeType)!="undefined"&&node.nodeType>0){ +return node; +} +if(typeof (node)=="number"||typeof (node)=="boolean"){ +node=node.toString(); +} +if(typeof (node)=="string"){ +return self._document.createTextNode(node); +} +if(typeof (node.toDOM)=="function"){ +node=node.toDOM(ctx); +continue; +} +if(typeof (node)=="function"){ +node=node(ctx); +continue; +} +var _355=null; +try{ +_355=iter(node); +} +catch(e){ +} +if(_355){ +return imap(_353,_355,_350(ctx)); +} +try{ +node=_352.match(node,ctx); +continue; +} +catch(e){ +if(e!=_354){ +throw e; +} +} +return self._document.createTextNode(node.toString()); +} +return undefined; +},setNodeAttribute:function(node,attr,_357){ +var o={}; +o[attr]=_357; +try{ +return MochiKit.DOM.updateNodeAttributes(node,o); +} +catch(e){ +} +return null; +},getNodeAttribute:function(node,attr){ +var self=MochiKit.DOM; +var _358=self.attributeArray.renames[attr]; +node=self.getElement(node); +try{ +if(_358){ +return node[_358]; +} +return node.getAttribute(attr); +} +catch(e){ +} +return null; +},updateNodeAttributes:function(node,_359){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +} +if(_359){ +var _360=MochiKit.Base.updatetree; +if(self.attributeArray.compliant){ +for(var k in _359){ +var v=_359[k]; +if(typeof (v)=="object"&&typeof (elem[k])=="object"){ +_360(elem[k],v); +}else{ +if(k.substring(0,2)=="on"){ +if(typeof (v)=="string"){ +v=new Function(v); +} +elem[k]=v; +}else{ +elem.setAttribute(k,v); +} +} +} +}else{ +var _361=self.attributeArray.renames; +for(k in _359){ +v=_359[k]; +var _362=_361[k]; +if(k=="style"&&typeof (v)=="string"){ +elem.style.cssText=v; +}else{ +if(typeof (_362)=="string"){ +elem[_362]=v; +}else{ +if(typeof (elem[k])=="object"&&typeof (v)=="object"){ +_360(elem[k],v); +}else{ +if(k.substring(0,2)=="on"){ +if(typeof (v)=="string"){ +v=new Function(v); +} +elem[k]=v; +}else{ +elem.setAttribute(k,v); +} +} +} +} +} +} +} +return elem; +},appendChildNodes:function(node){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +} +var _363=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; +var _364=MochiKit.Base.concat; +while(_363.length){ +var n=_363.shift(); +if(typeof (n)=="undefined"||n===null){ +}else{ +if(typeof (n.nodeType)=="number"){ +elem.appendChild(n); +}else{ +_363=_364(n,_363); +} +} +} +return elem; +},replaceChildNodes:function(node){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +arguments[0]=elem; +} +var _365; +while((_365=elem.firstChild)){ +elem.removeChild(_365); +} +if(arguments.length<2){ +return elem; +}else{ +return self.appendChildNodes.apply(this,arguments); +} +},createDOM:function(name,_366){ +var elem; +var self=MochiKit.DOM; +var m=MochiKit.Base; +if(typeof (_366)=="string"||typeof (_366)=="number"){ +var args=m.extend([name,null],arguments,1); +return arguments.callee.apply(this,args); +} +if(typeof (name)=="string"){ +if(_366&&"name" in _366&&!self.attributeArray.compliant){ +name=("<"+name+" name=\""+self.escapeHTML(_366.name)+"\">"); +} +elem=self._document.createElement(name); +}else{ +elem=name; +} +if(_366){ +self.updateNodeAttributes(elem,_366); +} +if(arguments.length<=2){ +return elem; +}else{ +var args=m.extend([elem],arguments,2); +return self.appendChildNodes.apply(this,args); +} +},createDOMFunc:function(){ +var m=MochiKit.Base; +return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments)); +},swapDOM:function(dest,src){ +var self=MochiKit.DOM; +dest=self.getElement(dest); +var _369=dest.parentNode; +if(src){ +src=self.getElement(src); +_369.replaceChild(src,dest); +}else{ +_369.removeChild(dest); +} +return src; +},getElement:function(id){ +var self=MochiKit.DOM; +if(arguments.length==1){ +return ((typeof (id)=="string")?self._document.getElementById(id):id); +}else{ +return MochiKit.Base.map(self.getElement,arguments); +} +},computedStyle:function(_371,_372,_373){ +if(arguments.length==2){ +_373=_372; +} +var self=MochiKit.DOM; +var el=self.getElement(_371); +var _375=self._document; +if(!el||el==_375){ +return undefined; +} +if(el.currentStyle){ +return el.currentStyle[_372]; +} +if(typeof (_375.defaultView)=="undefined"){ +return undefined; +} +if(_375.defaultView===null){ +return undefined; +} +var _376=_375.defaultView.getComputedStyle(el,null); +if(typeof (_376)=="undefined"||_376===null){ +return undefined; +} +return _376.getPropertyValue(_373); +},getElementsByTagAndClassName:function(_377,_378,_379){ +var self=MochiKit.DOM; +if(typeof (_377)=="undefined"||_377===null){ +_377="*"; +} +if(typeof (_379)=="undefined"||_379===null){ +_379=self._document; +} +_379=self.getElement(_379); +var _380=(_379.getElementsByTagName(_377)||self._document.all); +if(typeof (_378)=="undefined"||_378===null){ +return MochiKit.Base.extend(null,_380); +} +var _381=[]; +for(var i=0;i<_380.length;i++){ +var _382=_380[i]; +var _383=_382.className.split(" "); +for(var j=0;j<_383.length;j++){ +if(_383[j]==_378){ +_381.push(_382); +break; +} +} +} +return _381; +},_newCallStack:function(path,once){ +var rval=function(){ +var _386=arguments.callee.callStack; +for(var i=0;i<_386.length;i++){ +if(_386[i].apply(this,arguments)===false){ +break; +} +} +if(once){ +try{ +this[path]=null; +} +catch(e){ +} +} +}; +rval.callStack=[]; +return rval; +},addToCallStack:function(_387,path,func,once){ +var self=MochiKit.DOM; +var _388=_387[path]; +var _389=_388; +if(!(typeof (_388)=="function"&&typeof (_388.callStack)=="object"&&_388.callStack!==null)){ +_389=self._newCallStack(path,once); +if(typeof (_388)=="function"){ +_389.callStack.push(_388); +} +_387[path]=_389; +} +_389.callStack.push(func); +},addLoadEvent:function(func){ +var self=MochiKit.DOM; +self.addToCallStack(self._window,"onload",func,true); +},focusOnLoad:function(_390){ +var self=MochiKit.DOM; +self.addLoadEvent(function(){ +_390=self.getElement(_390); +if(_390){ +_390.focus(); +} +}); +},setElementClass:function(_391,_392){ +var self=MochiKit.DOM; +var obj=self.getElement(_391); +if(self.attributeArray.compliant){ +obj.setAttribute("class",_392); +}else{ +obj.setAttribute("className",_392); +} +},toggleElementClass:function(_393){ +var self=MochiKit.DOM; +for(var i=1;i/g,">"); +},toHTML:function(dom){ +return MochiKit.DOM.emitHTML(dom).join(""); +},emitHTML:function(dom,lst){ +if(typeof (lst)=="undefined"||lst===null){ +lst=[]; +} +var _409=[dom]; +var self=MochiKit.DOM; +var _410=self.escapeHTML; +var _411=self.attributeArray; +while(_409.length){ +dom=_409.pop(); +if(typeof (dom)=="string"){ +lst.push(dom); +}else{ +if(dom.nodeType==1){ +lst.push("<"+dom.nodeName.toLowerCase()); +var _412=[]; +var _413=_411(dom); +for(var i=0;i<_413.length;i++){ +var a=_413[i]; +_412.push([" ",a.name,"=\"",_410(a.value),"\""]); +} +_412.sort(); +for(i=0;i<_412.length;i++){ +var _414=_412[i]; +for(var j=0;j<_414.length;j++){ +lst.push(_414[j]); +} +} +if(dom.hasChildNodes()){ +lst.push(">"); +_409.push(""); +var _415=dom.childNodes; +for(i=_415.length-1;i>=0;i--){ +_409.push(_415[i]); +} +}else{ +lst.push("/>"); +} +}else{ +if(dom.nodeType==3){ +lst.push(_410(dom.nodeValue)); +} +} +} +} +return lst; +},setDisplayForElement:function(_416,_417){ +var m=MochiKit.Base; +var _418=m.extend(null,arguments,1); +MochiKit.Iter.forEach(m.filter(null,m.map(MochiKit.DOM.getElement,_418)),function(_417){ +_417.style.display=_416; +}); +},scrapeText:function(node,_419){ +var rval=[]; +(function(node){ +var cn=node.childNodes; +if(cn){ +for(var i=0;i0){ +var _424=m.filter; +_423=function(node){ +return _424(_423.ignoreAttrFilter,node.attributes); +}; +_423.ignoreAttr={}; +MochiKit.Iter.forEach(_422.attributes,function(a){ +_423.ignoreAttr[a.name]=a.value; +}); +_423.ignoreAttrFilter=function(a){ +return (_423.ignoreAttr[a.name]!=a.value); +}; +_423.compliant=false; +_423.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor"}; +}else{ +_423=function(node){ +return node.attributes; +}; +_423.compliant=true; +_423.renames={}; +} +this.attributeArray=_423; +var _425=this.createDOMFunc; +this.UL=_425("ul"); +this.OL=_425("ol"); +this.LI=_425("li"); +this.TD=_425("td"); +this.TR=_425("tr"); +this.TBODY=_425("tbody"); +this.THEAD=_425("thead"); +this.TFOOT=_425("tfoot"); +this.TABLE=_425("table"); +this.TH=_425("th"); +this.INPUT=_425("input"); +this.SPAN=_425("span"); +this.A=_425("a"); +this.DIV=_425("div"); +this.IMG=_425("img"); +this.BUTTON=_425("button"); +this.TT=_425("tt"); +this.PRE=_425("pre"); +this.H1=_425("h1"); +this.H2=_425("h2"); +this.H3=_425("h3"); +this.BR=_425("br"); +this.HR=_425("hr"); +this.LABEL=_425("label"); +this.TEXTAREA=_425("textarea"); +this.FORM=_425("form"); +this.P=_425("p"); +this.SELECT=_425("select"); +this.OPTION=_425("option"); +this.OPTGROUP=_425("optgroup"); +this.LEGEND=_425("legend"); +this.FIELDSET=_425("fieldset"); +this.STRONG=_425("strong"); +this.CANVAS=_425("canvas"); +this.hideElement=m.partial(this.setDisplayForElement,"none"); +this.showElement=m.partial(this.setDisplayForElement,"block"); +this.removeElement=this.swapDOM; +this.$=this.getElement; +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}}); +MochiKit.DOM.__new__(((typeof (window)=="undefined")?this:window)); +if(!MochiKit.__compat__){ +withWindow=MochiKit.DOM.withWindow; +withDocument=MochiKit.DOM.withDocument; +} +MochiKit.Base._exportSymbols(this,MochiKit.DOM); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.LoggingPane"); +dojo.require("MochiKit.Logging"); +dojo.require("MochiKit.Base"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Logging",[]); +JSAN.use("MochiKit.Base",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.Logging)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!"; +} +if(typeof (MochiKit.LoggingPane)=="undefined"){ +MochiKit.LoggingPane={}; +} +MochiKit.LoggingPane.NAME="MochiKit.LoggingPane"; +MochiKit.LoggingPane.VERSION="1.3.1"; +MochiKit.LoggingPane.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.LoggingPane.toString=function(){ +return this.__repr__(); +}; +MochiKit.LoggingPane.createLoggingPane=function(_426){ +var m=MochiKit.LoggingPane; +_426=!(!_426); +if(m._loggingPane&&m._loggingPane.inline!=_426){ +m._loggingPane.closePane(); +m._loggingPane=null; +} +if(!m._loggingPane||m._loggingPane.closed){ +m._loggingPane=new m.LoggingPane(_426,MochiKit.Logging.logger); +} +return m._loggingPane; +}; +MochiKit.LoggingPane.LoggingPane=function(_427,_428){ +if(typeof (_428)=="undefined"||_428===null){ +_428=MochiKit.Logging.logger; +} +this.logger=_428; +var _429=MochiKit.Base.update; +var _430=MochiKit.Base.updatetree; +var bind=MochiKit.Base.bind; +var _431=MochiKit.Base.clone; +var win=window; +var uid="_MochiKit_LoggingPane"; +if(typeof (MochiKit.DOM)!="undefined"){ +win=MochiKit.DOM.currentWindow(); +} +if(!_427){ +var url=win.location.href.split("?")[0].replace(/[:\/.><&]/g,"_"); +var name=uid+"_"+url; +var nwin=win.open("",name,"dependent,resizable,height=200"); +if(!nwin){ +alert("Not able to open debugging window due to pop-up blocking."); +return undefined; +} +nwin.document.write(""+"[MochiKit.LoggingPane]"+""); +nwin.document.close(); +nwin.document.title+=" "+win.document.title; +win=nwin; +} +var doc=win.document; +this.doc=doc; +var _434=doc.getElementById(uid); +var _435=!!_434; +if(_434&&typeof (_434.loggingPane)!="undefined"){ +_434.loggingPane.logger=this.logger; +_434.loggingPane.buildAndApplyFilter(); +return _434.loggingPane; +} +if(_435){ +var _436; +while((_436=_434.firstChild)){ +_434.removeChild(_436); +} +}else{ +_434=doc.createElement("div"); +_434.id=uid; +} +_434.loggingPane=this; +var _437=doc.createElement("input"); +var _438=doc.createElement("input"); +var _439=doc.createElement("button"); +var _440=doc.createElement("button"); +var _441=doc.createElement("button"); +var _442=doc.createElement("button"); +var _443=doc.createElement("div"); +var _444=doc.createElement("div"); +var _445=uid+"_Listener"; +this.colorTable=_431(this.colorTable); +var _446=[]; +var _447=null; +var _448=function(msg){ +var _449=msg.level; +if(typeof (_449)=="number"){ +_449=MochiKit.Logging.LogLevel[_449]; +} +return _449; +}; +var _450=function(msg){ +return msg.info.join(" "); +}; +var _451=bind(function(msg){ +var _452=_448(msg); +var text=_450(msg); +var c=this.colorTable[_452]; +var p=doc.createElement("span"); +p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_452; +p.style.cssText="margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: "+c; +p.appendChild(doc.createTextNode(_452+": "+text)); +_444.appendChild(p); +_444.appendChild(doc.createElement("br")); +if(_443.offsetHeight>_443.scrollHeight){ +_443.scrollTop=0; +}else{ +_443.scrollTop=_443.scrollHeight; +} +},this); +var _454=function(msg){ +_446[_446.length]=msg; +_451(msg); +}; +var _455=function(){ +var _456,infore; +try{ +_456=new RegExp(_437.value); +infore=new RegExp(_438.value); +} +catch(e){ +logDebug("Error in filter regex: "+e.message); +return null; +} +return function(msg){ +return (_456.test(_448(msg))&&infore.test(_450(msg))); +}; +}; +var _457=function(){ +while(_444.firstChild){ +_444.removeChild(_444.firstChild); +} +}; +var _458=function(){ +_446=[]; +_457(); +}; +var _459=bind(function(){ +if(this.closed){ +return; +} +this.closed=true; +if(MochiKit.LoggingPane._loggingPane==this){ +MochiKit.LoggingPane._loggingPane=null; +} +this.logger.removeListener(_445); +_434.loggingPane=null; +if(_427){ +_434.parentNode.removeChild(_434); +}else{ +this.win.close(); +} +},this); +var _460=function(){ +_457(); +for(var i=0;i<_446.length;i++){ +var msg=_446[i]; +if(_447===null||_447(msg)){ +_451(msg); +} +} +}; +this.buildAndApplyFilter=function(){ +_447=_455(); +_460(); +this.logger.removeListener(_445); +this.logger.addListener(_445,_447,_454); +}; +var _461=bind(function(){ +_446=this.logger.getMessages(); +_460(); +},this); +var _462=bind(function(_463){ +_463=_463||window.event; +key=_463.which||_463.keyCode; +if(key==13){ +this.buildAndApplyFilter(); +} +},this); +var _464="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont; +if(_427){ +_464+="; height: 10em; border-top: 2px solid black"; +}else{ +_464+="; height: 100%;"; +} +_434.style.cssText=_464; +if(!_435){ +doc.body.appendChild(_434); +} +_464={"cssText":"width: 33%; display: inline; font: "+this.logFont}; +_430(_437,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_462,"style":_464}); +_434.appendChild(_437); +_430(_438,{"value":".*","onkeypress":_462,"style":_464}); +_434.appendChild(_438); +_464="width: 8%; display:inline; font: "+this.logFont; +_439.appendChild(doc.createTextNode("Filter")); +_439.onclick=bind("buildAndApplyFilter",this); +_439.style.cssText=_464; +_434.appendChild(_439); +_440.appendChild(doc.createTextNode("Load")); +_440.onclick=_461; +_440.style.cssText=_464; +_434.appendChild(_440); +_441.appendChild(doc.createTextNode("Clear")); +_441.onclick=_458; +_441.style.cssText=_464; +_434.appendChild(_441); +_442.appendChild(doc.createTextNode("Close")); +_442.onclick=_459; +_442.style.cssText=_464; +_434.appendChild(_442); +_443.style.cssText="overflow: auto; width: 100%"; +_444.style.cssText="width: 100%; height: "+(_427?"8em":"100%"); +_443.appendChild(_444); +_434.appendChild(_443); +this.buildAndApplyFilter(); +_461(); +if(_427){ +this.win=undefined; +}else{ +this.win=win; +} +this.inline=_427; +this.closePane=_459; +this.closed=false; +return this; +}; +MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}}; +MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"]; +MochiKit.LoggingPane.EXPORT=["createLoggingPane"]; +MochiKit.LoggingPane.__new__=function(){ +this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; +MochiKit.Base.nameFunctions(this); +MochiKit.LoggingPane._loggingPane=null; +}; +MochiKit.LoggingPane.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Color"); +dojo.require("MochiKit.Base"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Color depends on MochiKit.Base"; +} +if(typeof (MochiKit.Color)=="undefined"){ +MochiKit.Color={}; +} +MochiKit.Color.NAME="MochiKit.Color"; +MochiKit.Color.VERSION="1.3.1"; +MochiKit.Color.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Color.toString=function(){ +return this.__repr__(); +}; +MochiKit.Color.Color=function(red,_466,blue,_468){ +if(typeof (_468)=="undefined"||_468===null){ +_468=1; +} +this.rgb={r:red,g:_466,b:blue,a:_468}; +}; +MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_469){ +var rgb=this.rgb; +var m=MochiKit.Color; +return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_469); +},colorWithHue:function(hue){ +var hsl=this.asHSL(); +hsl.h=hue; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},colorWithSaturation:function(_473){ +var hsl=this.asHSL(); +hsl.s=_473; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},colorWithLightness:function(_474){ +var hsl=this.asHSL(); +hsl.l=_474; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},darkerColorWithLevel:function(_475){ +var hsl=this.asHSL(); +hsl.l=Math.max(hsl.l-_475,0); +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},lighterColorWithLevel:function(_476){ +var hsl=this.asHSL(); +hsl.l=Math.min(hsl.l+_476,1); +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},blendedColor:function(_477,_478){ +if(typeof (_478)=="undefined"||_478===null){ +_478=0.5; +} +var sf=1-_478; +var s=this.rgb; +var d=_477.rgb; +var df=_478; +return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df)); +},compareRGB:function(_481){ +var a=this.asRGB(); +var b=_481.asRGB(); +return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]); +},isLight:function(){ +return this.asHSL().b>0.5; +},isDark:function(){ +return (!this.isLight()); +},toHSLString:function(){ +var c=this.asHSL(); +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._hslString; +if(!rval){ +var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%"); +var a=c.a; +if(a>=1){ +a=1; +rval="hsl("+mid+")"; +}else{ +if(a<=0){ +a=0; +} +rval="hsla("+mid+","+a+")"; +} +this._hslString=rval; +} +return rval; +},toRGBString:function(){ +var c=this.rgb; +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._rgbString; +if(!rval){ +var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0)); +if(c.a!=1){ +rval="rgba("+mid+","+c.a+")"; +}else{ +rval="rgb("+mid+")"; +} +this._rgbString=rval; +} +return rval; +},asRGB:function(){ +return MochiKit.Base.clone(this.rgb); +},toHexString:function(){ +var m=MochiKit.Color; +var c=this.rgb; +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._hexString; +if(!rval){ +rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255))); +this._hexString=rval; +} +return rval; +},asHSV:function(){ +var hsv=this.hsv; +var c=this.rgb; +if(typeof (hsv)=="undefined"||hsv===null){ +hsv=MochiKit.Color.rgbToHSV(this.rgb); +this.hsv=hsv; +} +return MochiKit.Base.clone(hsv); +},asHSL:function(){ +var hsl=this.hsl; +var c=this.rgb; +if(typeof (hsl)=="undefined"||hsl===null){ +hsl=MochiKit.Color.rgbToHSL(this.rgb); +this.hsl=hsl; +} +return MochiKit.Base.clone(hsl); +},toString:function(){ +return this.toRGBString(); +},repr:function(){ +var c=this.rgb; +var col=[c.r,c.g,c.b,c.a]; +return this.__class__.NAME+"("+col.join(", ")+")"; +}}; +MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_486,blue,_487){ +var _488=MochiKit.Color.Color; +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_486=rgb.g; +blue=rgb.b; +if(typeof (rgb.a)=="undefined"){ +_487=undefined; +}else{ +_487=rgb.a; +} +} +return new _488(red,_486,blue,_487); +},fromHSL:function(hue,_489,_490,_491){ +var m=MochiKit.Color; +return m.Color.fromRGB(m.hslToRGB.apply(m,arguments)); +},fromHSV:function(hue,_492,_493,_494){ +var m=MochiKit.Color; +return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments)); +},fromName:function(name){ +var _495=MochiKit.Color.Color; +if(name.charAt(0)=="\""){ +name=name.substr(1,name.length-2); +} +var _496=_495._namedColors[name.toLowerCase()]; +if(typeof (_496)=="string"){ +return _495.fromHexString(_496); +}else{ +if(name=="transparent"){ +return _495.transparentColor(); +} +} +return null; +},fromString:function(_497){ +var self=MochiKit.Color.Color; +var _498=_497.substr(0,3); +if(_498=="rgb"){ +return self.fromRGBString(_497); +}else{ +if(_498=="hsl"){ +return self.fromHSLString(_497); +}else{ +if(_497.charAt(0)=="#"){ +return self.fromHexString(_497); +} +} +} +return self.fromName(_497); +},fromHexString:function(_499){ +if(_499.charAt(0)=="#"){ +_499=_499.substring(1); +} +var _500=[]; +var i,hex; +if(_499.length==3){ +for(i=0;i<3;i++){ +hex=_499.substr(i,1); +_500.push(parseInt(hex+hex,16)/255); +} +}else{ +for(i=0;i<6;i+=2){ +hex=_499.substr(i,2); +_500.push(parseInt(hex,16)/255); +} +} +var _501=MochiKit.Color.Color; +return _501.fromRGB.apply(_501,_500); +},_fromColorString:function(pre,_503,_504,_505){ +if(_505.indexOf(pre)===0){ +_505=_505.substring(_505.indexOf("(",3)+1,_505.length-1); +} +var _506=_505.split(/\s*,\s*/); +var _507=[]; +for(var i=0;i<_506.length;i++){ +var c=_506[i]; +var val; +var _508=c.substring(c.length-3); +if(c.charAt(c.length-1)=="%"){ +val=0.01*parseFloat(c.substring(0,c.length-1)); +}else{ +if(_508=="deg"){ +val=parseFloat(c)/360; +}else{ +if(_508=="rad"){ +val=parseFloat(c)/(Math.PI*2); +}else{ +val=_504[i]*parseFloat(c); +} +} +} +_507.push(val); +} +return this[_503].apply(this,_507); +},fromComputedStyle:function(elem,_509,_510){ +var d=MochiKit.DOM; +var cls=MochiKit.Color.Color; +for(elem=d.getElement(elem);elem;elem=elem.parentNode){ +var _511=d.computedStyle.apply(d,arguments); +if(!_511){ +continue; +} +var _512=cls.fromString(_511); +if(!_512){ +break; +} +if(_512.asRGB().a>0){ +return _512; +} +} +return null; +},fromBackground:function(elem){ +var cls=MochiKit.Color.Color; +return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor(); +},fromText:function(elem){ +var cls=MochiKit.Color.Color; +return cls.fromComputedStyle(elem,"color","color")||cls.blackColor(); +},namedColors:function(){ +return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); +}}); +MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_513){ +v*=_513; +if(v<0){ +return 0; +}else{ +if(v>_513){ +return _513; +}else{ +return v; +} +} +},_hslValue:function(n1,n2,hue){ +if(hue>6){ +hue-=6; +}else{ +if(hue<0){ +hue+=6; +} +} +var val; +if(hue<1){ +val=n1+(n2-n1)*hue; +}else{ +if(hue<3){ +val=n2; +}else{ +if(hue<4){ +val=n1+(n2-n1)*(4-hue); +}else{ +val=n1; +} +} +} +return val; +},hsvToRGB:function(hue,_516,_517,_518){ +if(arguments.length==1){ +var hsv=hue; +hue=hsv.h; +_516=hsv.s; +_517=hsv.v; +_518=hsv.a; +} +var red; +var _519; +var blue; +if(_516===0){ +red=0; +_519=0; +blue=0; +}else{ +var i=Math.floor(hue*6); +var f=(hue*6)-i; +var p=_517*(1-_516); +var q=_517*(1-(_516*f)); +var t=_517*(1-(_516*(1-f))); +switch(i){ +case 1: +red=q; +_519=_517; +blue=p; +break; +case 2: +red=p; +_519=_517; +blue=t; +break; +case 3: +red=p; +_519=q; +blue=_517; +break; +case 4: +red=t; +_519=p; +blue=_517; +break; +case 5: +red=_517; +_519=p; +blue=q; +break; +case 6: +case 0: +red=_517; +_519=t; +blue=p; +break; +} +} +return {r:red,g:_519,b:blue,a:_518}; +},hslToRGB:function(hue,_521,_522,_523){ +if(arguments.length==1){ +var hsl=hue; +hue=hsl.h; +_521=hsl.s; +_522=hsl.l; +_523=hsl.a; +} +var red; +var _524; +var blue; +if(_521===0){ +red=_522; +_524=_522; +blue=_522; +}else{ +var m2; +if(_522<=0.5){ +m2=_522*(1+_521); +}else{ +m2=_522+_521-(_522*_521); +} +var m1=(2*_522)-m2; +var f=MochiKit.Color._hslValue; +var h6=hue*6; +red=f(m1,m2,h6+2); +_524=f(m1,m2,h6); +blue=f(m1,m2,h6-2); +} +return {r:red,g:_524,b:blue,a:_523}; +},rgbToHSV:function(red,_528,blue,_529){ +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_528=rgb.g; +blue=rgb.b; +_529=rgb.a; +} +var max=Math.max(Math.max(red,_528),blue); +var min=Math.min(Math.min(red,_528),blue); +var hue; +var _532; +var _533=max; +if(min==max){ +hue=0; +_532=0; +}else{ +var _534=(max-min); +_532=_534/max; +if(red==max){ +hue=(_528-blue)/_534; +}else{ +if(_528==max){ +hue=2+((blue-red)/_534); +}else{ +hue=4+((red-_528)/_534); +} +} +hue/=6; +if(hue<0){ +hue+=1; +} +if(hue>1){ +hue-=1; +} +} +return {h:hue,s:_532,v:_533,a:_529}; +},rgbToHSL:function(red,_535,blue,_536){ +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_535=rgb.g; +blue=rgb.b; +_536=rgb.a; +} +var max=Math.max(red,Math.max(_535,blue)); +var min=Math.min(red,Math.min(_535,blue)); +var hue; +var _537; +var _538=(max+min)/2; +var _539=max-min; +if(_539===0){ +hue=0; +_537=0; +}else{ +if(_538<=0.5){ +_537=_539/(max+min); +}else{ +_537=_539/(2-max-min); +} +if(red==max){ +hue=(_535-blue)/_539; +}else{ +if(_535==max){ +hue=2+((blue-red)/_539); +}else{ +hue=4+((red-_535)/_539); +} +} +hue/=6; +if(hue<0){ +hue+=1; +} +if(hue>1){ +hue-=1; +} +} +return {h:hue,s:_537,l:_538,a:_536}; +},toColorPart:function(num){ +num=Math.round(num); +var _540=num.toString(16); +if(num<16){ +return "0"+_540; +} +return _540; +},__new__:function(){ +var m=MochiKit.Base; +this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]); +this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]); +var _541=1/3; +var _542={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_541,_541,_541],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_541,2*_541,2*_541],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]}; +var _543=function(name,r,g,b,a){ +var rval=this.fromRGB(r,g,b,a); +this[name]=function(){ +return rval; +}; +return rval; +}; +for(var k in _542){ +var name=k+"Color"; +var _545=m.concat([_543,this.Color,name],_542[k]); +this.Color[name]=m.bind.apply(null,_545); +} +var _546=function(){ +for(var i=0;i1){ +var src=MochiKit.DOM.getElement(arguments[0]); +var sig=arguments[1]; +var obj=arguments[2]; +var func=arguments[3]; +for(var i=_562.length-1;i>=0;i--){ +var o=_562[i]; +if(o[0]===src&&o[1]===sig&&o[4]===obj&&o[5]===func){ +self._disconnect(o); +_562.splice(i,1); +return true; +} +} +}else{ +var idx=m.findIdentical(_562,_561); +if(idx>=0){ +self._disconnect(_561); +_562.splice(idx,1); +return true; +} +} +return false; +},disconnectAll:function(src,sig){ +src=MochiKit.DOM.getElement(src); +var m=MochiKit.Base; +var _563=m.flattenArguments(m.extend(null,arguments,1)); +var self=MochiKit.Signal; +var _564=self._disconnect; +var _565=self._observers; +if(_563.length===0){ +for(var i=_565.length-1;i>=0;i--){ +var _566=_565[i]; +if(_566[0]===src){ +_564(_566); +_565.splice(i,1); +} +} +}else{ +var sigs={}; +for(var i=0;i<_563.length;i++){ +sigs[_563[i]]=true; +} +for(var i=_565.length-1;i>=0;i--){ +var _566=_565[i]; +if(_566[0]===src&&_566[1] in sigs){ +_564(_566); +_565.splice(i,1); +} +} +} +},signal:function(src,sig){ +var _568=MochiKit.Signal._observers; +src=MochiKit.DOM.getElement(src); +var args=MochiKit.Base.extend(null,arguments,2); +var _569=[]; +for(var i=0;i<_568.length;i++){ +var _570=_568[i]; +if(_570[0]===src&&_570[1]===sig){ +try{ +_570[2].apply(src,args); +} +catch(e){ +_569.push(e); +} +} +} +if(_569.length==1){ +throw _569[0]; +}else{ +if(_569.length>1){ +var e=new Error("Multiple errors thrown in handling 'sig', see errors property"); +e.errors=_569; +throw e; +} +} +}}); +MochiKit.Signal.EXPORT_OK=[]; +MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll"]; +MochiKit.Signal.__new__=function(win){ +var m=MochiKit.Base; +this._document=document; +this._window=win; +try{ +this.connect(window,"onunload",this._unloadCache); +} +catch(e){ +} +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Signal.__new__(this); +if(!MochiKit.__compat__){ +connect=MochiKit.Signal.connect; +disconnect=MochiKit.Signal.disconnect; +disconnectAll=MochiKit.Signal.disconnectAll; +signal=MochiKit.Signal.signal; +} +MochiKit.Base._exportSymbols(this,MochiKit.Signal); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Visual"); +dojo.require("MochiKit.Base"); +dojo.require("MochiKit.DOM"); +dojo.require("MochiKit.Color"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +JSAN.use("MochiKit.DOM",[]); +JSAN.use("MochiKit.Color",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM and MochiKit.Color!"; +} +if(typeof (MochiKit.Visual)=="undefined"){ +MochiKit.Visual={}; +} +MochiKit.Visual.NAME="MochiKit.Visual"; +MochiKit.Visual.VERSION="1.3.1"; +MochiKit.Visual.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Visual.toString=function(){ +return this.__repr__(); +}; +MochiKit.Visual._RoundCorners=function(e,_571){ +e=MochiKit.DOM.getElement(e); +this._setOptions(_571); +if(this.options.__unstable__wrapElement){ +e=this._doWrap(e); +} +var _572=this.options.color; +var C=MochiKit.Color.Color; +if(this.options.color=="fromElement"){ +_572=C.fromBackground(e); +}else{ +if(!(_572 instanceof C)){ +_572=C.fromString(_572); +} +} +this.isTransparent=(_572.asRGB().a<=0); +var _574=this.options.bgColor; +if(this.options.bgColor=="fromParent"){ +_574=C.fromBackground(e.offsetParent); +}else{ +if(!(_574 instanceof C)){ +_574=C.fromString(_574); +} +} +this._roundCornersImpl(e,_572,_574); +}; +MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){ +var _575=e.parentNode; +var doc=MochiKit.DOM.currentDocument(); +if(typeof (doc.defaultView)=="undefined"||doc.defaultView===null){ +return e; +} +var _576=doc.defaultView.getComputedStyle(e,null); +if(typeof (_576)=="undefined"||_576===null){ +return e; +} +var _577=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_576.getPropertyValue("padding-top"),marginRight:_576.getPropertyValue("padding-right"),marginBottom:_576.getPropertyValue("padding-bottom"),marginLeft:_576.getPropertyValue("padding-left"),padding:"0px"}}); +_577.innerHTML=e.innerHTML; +e.innerHTML=""; +e.appendChild(_577); +return e; +},_roundCornersImpl:function(e,_578,_579){ +if(this.options.border){ +this._renderBorder(e,_579); +} +if(this._isTopRounded()){ +this._roundTopCorners(e,_578,_579); +} +if(this._isBottomRounded()){ +this._roundBottomCorners(e,_578,_579); +} +},_renderBorder:function(el,_580){ +var _581="1px solid "+this._borderColor(_580); +var _582="border-left: "+_581; +var _583="border-right: "+_581; +var _584="style='"+_582+";"+_583+"'"; +el.innerHTML="

"; +},_roundTopCorners:function(el,_585,_586){ +var _587=this._createCorner(_586); +for(var i=0;i=0;i--){ +_590.appendChild(this._createCornerSlice(_588,_589,i,"bottom")); +} +el.style.paddingBottom=0; +el.appendChild(_590); +},_createCorner:function(_591){ +var dom=MochiKit.DOM; +return dom.DIV({style:{backgroundColor:_591.toString()}}); +},_createCornerSlice:function(_592,_593,n,_594){ +var _595=MochiKit.DOM.SPAN(); +var _596=_595.style; +_596.backgroundColor=_592.toString(); +_596.display="block"; +_596.height="1px"; +_596.overflow="hidden"; +_596.fontSize="1px"; +var _597=this._borderColor(_592,_593); +if(this.options.border&&n===0){ +_596.borderTopStyle="solid"; +_596.borderTopWidth="1px"; +_596.borderLeftWidth="0px"; +_596.borderRightWidth="0px"; +_596.borderBottomWidth="0px"; +_596.height="0px"; +_596.borderColor=_597.toString(); +}else{ +if(_597){ +_596.borderColor=_597.toString(); +_596.borderStyle="solid"; +_596.borderWidth="0px 1px"; +} +} +if(!this.options.compact&&(n==(this.options.numSlices-1))){ +_596.height="2px"; +} +this._setMargin(_595,n,_594); +this._setBorder(_595,n,_594); +return _595; +},_setOptions:function(_598){ +this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false}; +MochiKit.Base.update(this.options,_598); +this.options.numSlices=(this.options.compact?2:4); +},_whichSideTop:function(){ +var _599=this.options.corners; +if(this._hasString(_599,"all","top")){ +return ""; +} +var _600=(_599.indexOf("tl")!=-1); +var _601=(_599.indexOf("tr")!=-1); +if(_600&&_601){ +return ""; +} +if(_600){ +return "left"; +} +if(_601){ +return "right"; +} +return ""; +},_whichSideBottom:function(){ +var _602=this.options.corners; +if(this._hasString(_602,"all","bottom")){ +return ""; +} +var _603=(_602.indexOf("bl")!=-1); +var _604=(_602.indexOf("br")!=-1); +if(_603&&_604){ +return ""; +} +if(_603){ +return "left"; +} +if(_604){ +return "right"; +} +return ""; +},_borderColor:function(_605,_606){ +if(_605=="transparent"){ +return _606; +}else{ +if(this.options.border){ +return this.options.border; +}else{ +if(this.options.blend){ +return _606.blendedColor(_605); +} +} +} +return ""; +},_setMargin:function(el,n,_607){ +var _608=this._marginSize(n)+"px"; +var _609=(_607=="top"?this._whichSideTop():this._whichSideBottom()); +var _610=el.style; +if(_609=="left"){ +_610.marginLeft=_608; +_610.marginRight="0px"; +}else{ +if(_609=="right"){ +_610.marginRight=_608; +_610.marginLeft="0px"; +}else{ +_610.marginLeft=_608; +_610.marginRight=_608; +} +} +},_setBorder:function(el,n,_611){ +var _612=this._borderSize(n)+"px"; +var _613=(_611=="top"?this._whichSideTop():this._whichSideBottom()); +var _614=el.style; +if(_613=="left"){ +_614.borderLeftWidth=_612; +_614.borderRightWidth="0px"; +}else{ +if(_613=="right"){ +_614.borderRightWidth=_612; +_614.borderLeftWidth="0px"; +}else{ +_614.borderLeftWidth=_612; +_614.borderRightWidth=_612; +} +} +},_marginSize:function(n){ +if(this.isTransparent){ +return 0; +} +var o=this.options; +if(o.compact&&o.blend){ +var _615=[1,0]; +return _615[n]; +}else{ +if(o.compact){ +var _616=[2,1]; +return _616[n]; +}else{ +if(o.blend){ +var _617=[3,2,1,0]; +return _617[n]; +}else{ +var _618=[5,3,2,1]; +return _618[n]; +} +} +} +},_borderSize:function(n){ +var o=this.options; +var _619; +if(o.compact&&(o.blend||this.isTransparent)){ +return 1; +}else{ +if(o.compact){ +_619=[1,0]; +}else{ +if(o.blend){ +_619=[2,1,1,1]; +}else{ +if(o.border){ +_619=[0,2,0,0]; +}else{ +if(this.isTransparent){ +_619=[5,3,2,1]; +}else{ +return 0; +} +} +} +} +} +return _619[n]; +},_hasString:function(str){ +for(var i=1;i"); +} +} +})(); +} diff --git a/openwrt/packages/luci/host/www/luci-static/resources/livestats/PlotKit.js b/openwrt/packages/luci/host/www/luci-static/resources/livestats/PlotKit.js new file mode 100644 index 0000000..363042a --- /dev/null +++ b/openwrt/packages/luci/host/www/luci-static/resources/livestats/PlotKit.js @@ -0,0 +1,2177 @@ +/*** + + PlotKit.PlotKit 0.9.1 : PACKED VERSION + + THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please + diff against the source tree, not this file. + + For more information, . + + Copyright (c) 2006. Alastair Tse. + +***/ + +try{ +if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"||typeof (MochiKit.Format)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format}"; +} +MochiKit.Base.update(MochiKit.Color.Color.prototype,{asFillColor:function(){ +return this.lighterColorWithLevel(0.3); +},asStrokeColor:function(){ +return this.darkerColorWithLevel(0.1); +},asPointColor:function(){ +return this.lighterColorWithLevel(0.1); +}}); +if(typeof (PlotKit)=="undefined"){ +PlotKit={}; +} +PlotKit.NAME="PlotKit"; +PlotKit.VERSION="0.8"; +PlotKit.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.toString=function(){ +return this.__repr__(); +}; +if(typeof (PlotKit.Base)=="undefined"){ +PlotKit.Base={}; +} +PlotKit.Base.NAME="PlotKit.Base"; +PlotKit.Base.VERSION=PlotKit.VERSION; +PlotKit.Base.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.Base.toString=function(){ +return this.__repr__(); +}; +PlotKit.Base.usingPrototype=function(){ +try{ +return (typeof (Object.extend)=="function"); +} +catch(e){ +return false; +} +}; +MochiKit.Base.update(PlotKit.Base,{roundInterval:function(_1,_2,_3){ +var _4=MochiKit.Format.roundToFixed; +var _5=_1/_2; +return parseFloat(_4(_5,_3)); +},collapse:function(_6){ +var m=MochiKit.Base; +var _8=new Array(); +for(var i=0;i<_6.length;i++){ +_8=m.concat(_8,_6[i]); +} +if(PlotKit.Base.usingPrototype()){ +delete _8.extend; +delete _8.from; +delete _8.inspect; +} +return _8; +},uniq:function(_10){ +var m=MochiKit.Base; +if(!m.isArrayLike(_10)||(_10.length<1)){ +return new Array(); +} +var _11=new Array(); +var _12=_10[0]; +_11.push(_10[0]); +for(var i=1;i<_10.length;i++){ +if(m.compare(_10[i],_12)!=0){ +_12=_10[i]; +_11.push(_10[i]); +} +} +return _11; +},colorScheme:function(){ +var mb=MochiKit.Base; +var mc=MochiKit.Color; +var _15=["red","orange","yellow","green","cyan","blue","purple","magenta"]; +var _16=function(_17){ +return mc.Color[_17+"Color"](); +}; +return mb.map(_16,_15); +},baseDarkPrimaryColors:function(){ +var _18=MochiKit.Color.Color.fromHexString; +return [_18("#ad3f40"),_18("#ddac2c"),_18("#dfdd0c"),_18("#5276c4"),_18("#739c5a")]; +},basePrimaryColors:function(){ +var _19=MochiKit.Color.Color.fromHexString; +return [_19("#d24c4d"),_19("#f2b32f"),_19("#ece90e"),_19("#5d83da"),_19("#78a15d")]; +},baseBlueColors:function(){ +var _20=MochiKit.Color.Color.fromHexString; +return [_20("#4b6b94"),_20("#5d81b4"),_20("#acbad2")]; +},palette:function(_21,_22,_23,_24){ +var _25=MochiKit.Base.isUndefinedOrNull; +var _26=new Array(); +if(_25(_24)){ +_24=0.1; +} +if(_25(_23)){ +_23=0.4; +} +if(_25(_22)){ +_22=-0.2; +} +var _27=_22; +while(_27<=_23){ +_26.push(_27); +_27+=_24; +} +var _28=function(_29,_30){ +return _29.lighterColorWithLevel(_30); +}; +return MochiKit.Base.map(partial(_28,_21),_26); +},excanvasSupported:function(){ +if(/MSIE/.test(navigator.userAgent)&&!window.opera){ +return true; +} +return false; +},findPosX:function(obj){ +var _32=0; +if(obj.offsetParent){ +while(obj.offsetParent){ +_32+=obj.offsetLeft; +obj=obj.offsetParent; +} +}else{ +if(obj.x){ +_32+=obj.x; +} +} +return _32; +},findPosY:function(obj){ +var _33=0; +if(obj.offsetParent){ +while(obj.offsetParent){ +_33+=obj.offsetTop; +obj=obj.offsetParent; +} +}else{ +if(obj.y){ +_33+=obj.y; +} +} +return _33; +},isFuncLike:function(obj){ +return (typeof (obj)=="function"); +}}); +PlotKit.Base.map=function(fn,lst){ +if(PlotKit.Base.usingPrototype()){ +var _36=[]; +for(var x in lst){ +if(typeof (lst[x])=="function"){ +continue; +} +_36.push(fn(lst[x])); +} +return _36; +}else{ +return MochiKit.Base.map(fn,lst); +} +}; +PlotKit.Base.items=function(lst){ +if(PlotKit.Base.usingPrototype()){ +var _38=[]; +for(var x in lst){ +if(typeof (lst[x])=="function"){ +continue; +} +_38.push([x,lst[x]]); +} +return _38; +}else{ +return MochiKit.Base.items(lst); +} +}; +PlotKit.Base.keys=function(lst){ +if(PlotKit.Base.usingPrototype()){ +var _39=[]; +for(var x in lst){ +if(typeof (lst[x])=="function"){ +continue; +} +_39.push(x); +} +return _39; +}else{ +return MochiKit.Base.keys(lst); +} +}; +PlotKit.Base.baseColors=function(){ +var _40=MochiKit.Color.Color.fromHexString; +return [_40("#476fb2"),_40("#be2c2b"),_40("#85b730"),_40("#734a99"),_40("#26a1c5"),_40("#fb8707"),_40("#000000")]; +}; +PlotKit.Base.officeBaseStyle={"axisLineWidth":2,"axisLabelColor":Color.grayColor(),"axisLineColor":Color.whiteColor(),"padding":{top:5,bottom:10,left:30,right:30}}; +MochiKit.Base.update(PlotKit.Base,{officeBlue:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"backgroundColor":PlotKit.Base.baseColors()[0].lighterColorWithLevel(0.45)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeRed:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),"backgroundColor":PlotKit.Base.baseColors()[1].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeGreen:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[2]),"backgroundColor":PlotKit.Base.baseColors()[2].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officePurple:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[3]),"backgroundColor":PlotKit.Base.baseColors()[3].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeCyan:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[4]),"backgroundColor":PlotKit.Base.baseColors()[4].lighterColorWithLevel(0.5)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeOrange:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[5]),"backgroundColor":PlotKit.Base.baseColors()[5].lighterColorWithLevel(0.4)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +},officeBlack:function(){ +var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[6],0,0.6),"backgroundColor":PlotKit.Base.baseColors()[6].lighterColorWithLevel(0.9)}; +MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle); +return r; +}}); +PlotKit.Base.EXPORT=["baseColors","collapse","colorScheme","findPosX","findPosY","officeBaseStyle","officeBlue","officeRed","officeGreen","officePurple","officeCyan","officeOrange","officeBlack","roundInterval","uniq","isFuncLike","excanvasSupported"]; +PlotKit.Base.EXPORT_OK=[]; +PlotKit.Base.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.Base.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.Base); +try{ +if(typeof (PlotKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Base"; +} +if(typeof (PlotKit.Layout)=="undefined"){ +PlotKit.Layout={}; +} +PlotKit.Layout.NAME="PlotKit.Layout"; +PlotKit.Layout.VERSION=PlotKit.VERSION; +PlotKit.Layout.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.Layout.toString=function(){ +return this.__repr__(); +}; +PlotKit.Layout.valid_styles=["bar","line","pie","point"]; +PlotKit.Layout=function(_42,_43){ +this.options={"barWidthFillFraction":0.75,"barOrientation":"vertical","xOriginIsZero":true,"yOriginIsZero":true,"xAxis":null,"yAxis":null,"xTicks":null,"yTicks":null,"xNumberOfTicks":10,"yNumberOfTicks":5,"xTickPrecision":1,"yTickPrecision":1,"pieRadius":0.4}; +this.style=_42; +MochiKit.Base.update(this.options,_43?_43:{}); +if(!MochiKit.Base.isUndefinedOrNull(this.options.xAxis)){ +this.minxval=this.options.xAxis[0]; +this.maxxval=this.options.xAxis[1]; +this.xscale=this.maxxval-this.minxval; +}else{ +this.minxval=0; +this.maxxval=null; +this.xscale=null; +} +if(!MochiKit.Base.isUndefinedOrNull(this.options.yAxis)){ +this.minyval=this.options.yAxis[0]; +this.maxyval=this.options.yAxis[1]; +this.yscale=this.maxyval-this.minyval; +}else{ +this.minyval=0; +this.maxyval=null; +this.yscale=null; +} +this.bars=new Array(); +this.points=new Array(); +this.slices=new Array(); +this.xticks=new Array(); +this.yticks=new Array(); +this.datasets=new Array(); +this.minxdelta=0; +this.xrange=1; +this.yrange=1; +this.hitTestCache={x2maxy:null}; +}; +PlotKit.Layout.prototype.addDataset=function(_44,_45){ +this.datasets[_44]=_45; +}; +PlotKit.Layout.prototype.removeDataset=function(_46,_47){ +delete this.datasets[_46]; +}; +PlotKit.Layout.prototype.addDatasetFromTable=function(_48,_49,_50,_51,_52){ +var _53=MochiKit.Base.isUndefinedOrNull; +var _54=MochiKit.DOM.scrapeText; +var _55=MochiKit.Format.strip; +if(_53(_50)){ +_50=0; +} +if(_53(_51)){ +_51=1; +} +if(_53(_52)){ +_52=-1; +} +var _56=_49.tBodies[0].rows; +var _57=new Array(); +var _58=new Array(); +if(!_53(_56)){ +for(var i=0;i<_56.length;i++){ +_57.push([parseFloat(_55(_54(_56[i].cells[_50]))),parseFloat(_55(_54(_56[i].cells[_51])))]); +if(_52>=0){ +_58.push({v:parseFloat(_55(_54(_56[i].cells[_50]))),label:_55(_54(_56[i].cells[_52]))}); +} +} +this.addDataset(_48,_57); +if(_52>=0){ +this.options.xTicks=_58; +} +return true; +} +return false; +}; +PlotKit.Layout.prototype.evaluate=function(){ +this._evaluateLimits(); +this._evaluateScales(); +if(this.style=="bar"){ +if(this.options.barOrientation=="horizontal"){ +this._evaluateHorizBarCharts(); +}else{ +this._evaluateBarCharts(); +} +this._evaluateBarTicks(); +}else{ +if(this.style=="line"){ +this._evaluateLineCharts(); +this._evaluateLineTicks(); +}else{ +if(this.style=="pie"){ +this._evaluatePieCharts(); +this._evaluatePieTicks(); +} +} +} +}; +PlotKit.Layout.prototype.hitTest=function(x,y){ +var f=MochiKit.Format.twoDigitFloat; +if((this.style=="bar")&&this.bars&&(this.bars.length>0)){ +for(var i=0;i=bar.x)&&(x<=bar.x+bar.w)&&(y>=bar.y)&&(y-bar.y<=bar.h)){ +return bar; +} +} +}else{ +if(this.style=="line"){ +if(this.hitTestCache.x2maxy==null){ +this._regenerateHitTestCache(); +} +var _62=x/this.xscale; +var _63=this.hitTestCache.xvalues; +var _64=null; +var _65=null; +for(var i=1;i<_63.length;i++){ +if(_63[i]>_62){ +_64=_63[i-1]; +_65=_63[i]; +break; +} +} +if((_64!=null)){ +var _66=this.hitTestCache.x2maxy[_64]; +var _67=this.hitTestCache.x2maxy[_65]; +var _68=(1-y)/this.yscale; +var _69=(_67-_66)/(_65-_64); +var _70=_66+_69*(_62-_64); +if(_70>=_68){ +var obj={xval:_62,yval:_68,xafter:_65,yafter:_67,xbefore:_64,ybefore:_66,yprojected:_70}; +return obj; +} +} +}else{ +if(this.style=="pie"){ +var _71=Math.sqrt((y-0.5)*(y-0.5)+(x-0.5)*(x-0.5)); +if(_71>this.options.pieRadius){ +return null; +} +var _72=Math.atan2(y-0.5,x-0.5)-Math.PI/2; +for(var i=0;i=_72){ +return _73; +} +} +} +} +} +return null; +}; +PlotKit.Layout.prototype.rectForX=function(x){ +return null; +}; +PlotKit.Layout.prototype.angleRangeForX=function(x){ +return null; +}; +PlotKit.Layout.prototype._evaluateLimits=function(){ +var map=PlotKit.Base.map; +var _75=PlotKit.Base.items; +var _76=MochiKit.Base.itemgetter; +var _77=PlotKit.Base.collapse; +var _78=MochiKit.Base.listMin; +var _79=MochiKit.Base.listMax; +var _80=MochiKit.Base.isUndefinedOrNull; +var all=_77(map(_76(1),_75(this.datasets))); +if(_80(this.options.xAxis)){ +if(this.options.xOriginIsZero){ +this.minxval=0; +}else{ +this.minxval=_78(map(parseFloat,map(_76(0),all))); +} +this.maxxval=_79(map(parseFloat,map(_76(0),all))); +}else{ +this.minxval=this.options.xAxis[0]; +this.maxxval=this.options.xAxis[1]; +this.xscale=this.maxval-this.minxval; +} +if(_80(this.options.yAxis)){ +if(this.options.yOriginIsZero){ +this.minyval=0; +}else{ +this.minyval=_78(map(parseFloat,map(_76(1),all))); +} +this.maxyval=_79(map(parseFloat,map(_76(1),all))); +}else{ +this.minyval=this.options.yAxis[0]; +this.maxyval=this.options.yAxis[1]; +this.yscale=this.maxyval-this.minyval; +} +}; +PlotKit.Layout.prototype._evaluateScales=function(){ +var _82=MochiKit.Base.isUndefinedOrNull; +this.xrange=this.maxxval-this.minxval; +if(this.xrange==0){ +this.xscale=1; +}else{ +this.xscale=1/this.xrange; +} +this.yrange=this.maxyval-this.minyval; +if(this.yrange==0){ +this.yscale=1; +}else{ +this.yscale=1/this.yrange; +} +}; +PlotKit.Layout.prototype._uniqueXValues=function(){ +var _83=PlotKit.Base.collapse; +var map=PlotKit.Base.map; +var _84=PlotKit.Base.uniq; +var _85=MochiKit.Base.itemgetter; +var _86=PlotKit.Base.items; +var _87=map(parseFloat,map(_85(0),_83(map(_85(1),_86(this.datasets))))); +_87.sort(MochiKit.Base.compare); +return _84(_87); +}; +PlotKit.Layout.prototype._evaluateBarCharts=function(){ +var _88=PlotKit.Base.items; +var _89=_88(this.datasets).length; +var _90=10000000; +var _91=this._uniqueXValues(); +for(var i=1;i<_91.length;i++){ +_90=Math.min(Math.abs(_91[i]-_91[i-1]),_90); +} +var _92=0; +var _93=0; +var _94=0; +if(_91.length==1){ +_90=1; +this.xscale=1; +this.minxval=_91[0]; +_92=1*this.options.barWidthFillFraction; +_93=_92/_89; +_94=(1-this.options.barWidthFillFraction)/2; +}else{ +if(this.xrange==1){ +this.xscale=0.5; +}else{ +if(this.xrange==2){ +this.xscale=1/3; +}else{ +this.xscale=(1-_90/this.xrange)/this.xrange; +} +} +_92=_90*this.xscale*this.options.barWidthFillFraction; +_93=_92/_89; +_94=_90*this.xscale*(1-this.options.barWidthFillFraction)/2; +} +this.minxdelta=_90; +this.bars=new Array(); +var i=0; +for(var _95 in this.datasets){ +var _96=this.datasets[_95]; +if(PlotKit.Base.isFuncLike(_96)){ +continue; +} +for(var j=0;j<_96.length;j++){ +var _98=_96[j]; +var _99={x:((parseFloat(_98[0])-this.minxval)*this.xscale)+(i*_93)+_94,y:1-((parseFloat(_98[1])-this.minyval)*this.yscale),w:_93,h:((parseFloat(_98[1])-this.minyval)*this.yscale),xval:parseFloat(_98[0]),yval:parseFloat(_98[1]),name:_95}; +if((_99.x>=0)&&(_99.x<=1)&&(_99.y>=0)&&(_99.y<=1)){ +this.bars.push(_99); +} +} +i++; +} +}; +PlotKit.Layout.prototype._evaluateHorizBarCharts=function(){ +var _100=PlotKit.Base.items; +var _101=_100(this.datasets).length; +var _102=10000000; +var _103=this._uniqueXValues(); +for(var i=1;i<_103.length;i++){ +_102=Math.min(Math.abs(_103[i]-_103[i-1]),_102); +} +var _104=0; +var _105=0; +var _106=0; +if(_103.length==1){ +_102=1; +this.xscale=1; +this.minxval=_103[0]; +_104=1*this.options.barWidthFillFraction; +_105=_104/_101; +_106=(1-this.options.barWidthFillFraction)/2; +}else{ +this.xscale=(1-_102/this.xrange)/this.xrange; +_104=_102*this.xscale*this.options.barWidthFillFraction; +_105=_104/_101; +_106=_102*this.xscale*(1-this.options.barWidthFillFraction)/2; +} +this.minxdelta=_102; +this.bars=new Array(); +var i=0; +for(var _107 in this.datasets){ +var _108=this.datasets[_107]; +if(PlotKit.Base.isFuncLike(_108)){ +continue; +} +for(var j=0;j<_108.length;j++){ +var item=_108[j]; +var rect={y:((parseFloat(item[0])-this.minxval)*this.xscale)+(i*_105)+_106,x:0,h:_105,w:((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_107}; +if(rect.y<=0){ +rect.y=0; +} +if(rect.y>=1){ +rect.y=1; +} +if((rect.x>=0)&&(rect.x<=1)){ +this.bars.push(rect); +} +} +i++; +} +}; +PlotKit.Layout.prototype._evaluateLineCharts=function(){ +var _111=PlotKit.Base.items; +var _112=_111(this.datasets).length; +this.points=new Array(); +var i=0; +for(var _113 in this.datasets){ +var _114=this.datasets[_113]; +if(PlotKit.Base.isFuncLike(_114)){ +continue; +} +_114.sort(function(a,b){ +return compare(parseFloat(a[0]),parseFloat(b[0])); +}); +for(var j=0;j<_114.length;j++){ +var item=_114[j]; +var _117={x:((parseFloat(item[0])-this.minxval)*this.xscale),y:1-((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_113}; +if(_117.y<=0){ +_117.y=0; +} +if(_117.y>=1){ +_117.y=1; +} +if((_117.x>=0)&&(_117.x<=1)){ +this.points.push(_117); +} +} +i++; +} +}; +PlotKit.Layout.prototype._evaluatePieCharts=function(){ +var _118=PlotKit.Base.items; +var sum=MochiKit.Iter.sum; +var _120=MochiKit.Base.itemgetter; +var _121=_118(this.datasets).length; +var _122=_118(this.datasets)[0][1]; +var _123=sum(map(_120(1),_122)); +this.slices=new Array(); +var _124=0; +for(var i=0;i<_122.length;i++){ +var _125=_122[i][1]/_123; +var _126=_124*Math.PI*2; +var _127=(_124+_125)*Math.PI*2; +var _128={fraction:_125,xval:_122[i][0],yval:_122[i][1],startAngle:_126,endAngle:_127}; +if(_122[i][1]!=0){ +this.slices.push(_128); +} +_124+=_125; +} +}; +PlotKit.Layout.prototype._evaluateLineTicksForXAxis=function(){ +var _129=MochiKit.Base.isUndefinedOrNull; +if(this.options.xTicks){ +this.xticks=new Array(); +var _130=function(tick){ +var _132=tick.label; +if(_129(_132)){ +_132=tick.v.toString(); +} +var pos=this.xscale*(tick.v-this.minxval); +if((pos>=0)&&(pos<=1)){ +this.xticks.push([pos,_132]); +} +}; +MochiKit.Iter.forEach(this.options.xTicks,bind(_130,this)); +}else{ +if(this.options.xNumberOfTicks){ +var _134=this._uniqueXValues(); +var _135=this.xrange/this.options.xNumberOfTicks; +var _136=0; +this.xticks=new Array(); +for(var i=0;i<=_134.length;i++){ +if((_134[i]-this.minxval)>=(_136*_135)){ +var pos=this.xscale*(_134[i]-this.minxval); +if((pos>1)||(pos<0)){ +continue; +} +this.xticks.push([pos,_134[i]]); +_136++; +} +if(_136>this.options.xNumberOfTicks){ +break; +} +} +} +} +}; +PlotKit.Layout.prototype._evaluateLineTicksForYAxis=function(){ +var _137=MochiKit.Base.isUndefinedOrNull; +if(this.options.yTicks){ +this.yticks=new Array(); +var _138=function(tick){ +var _139=tick.label; +if(_137(_139)){ +_139=tick.v.toString(); +} +var pos=1-(this.yscale*(tick.v-this.minyval)); +if((pos>=0)&&(pos<=1)){ +this.yticks.push([pos,_139]); +} +}; +MochiKit.Iter.forEach(this.options.yTicks,bind(_138,this)); +}else{ +if(this.options.yNumberOfTicks){ +this.yticks=new Array(); +var _140=PlotKit.Base.roundInterval; +var prec=this.options.yTickPrecision; +var _142=_140(this.yrange,this.options.yNumberOfTicks,prec); +for(var i=0;i<=this.options.yNumberOfTicks;i++){ +var yval=this.minyval+(i*_142); +var pos=1-((yval-this.minyval)*this.yscale); +if((pos>1)||(pos<0)){ +continue; +} +this.yticks.push([pos,MochiKit.Format.roundToFixed(yval,prec)]); +} +} +} +}; +PlotKit.Layout.prototype._evaluateLineTicks=function(){ +this._evaluateLineTicksForXAxis(); +this._evaluateLineTicksForYAxis(); +}; +PlotKit.Layout.prototype._evaluateBarTicks=function(){ +this._evaluateLineTicks(); +var _144=function(tick){ +return [tick[0]+(this.minxdelta*this.xscale)/2,tick[1]]; +}; +this.xticks=MochiKit.Base.map(bind(_144,this),this.xticks); +if(this.options.barOrientation=="horizontal"){ +var _145=this.xticks; +this.xticks=this.yticks; +this.yticks=_145; +var _146=function(tick){ +return [1-tick[0],tick[1]]; +}; +this.xticks=MochiKit.Base.map(_146,this.xticks); +} +}; +PlotKit.Layout.prototype._evaluatePieTicks=function(){ +var _147=MochiKit.Base.isUndefinedOrNull; +var _148=MochiKit.Format.numberFormatter("#%"); +this.xticks=new Array(); +if(this.options.xTicks){ +var _149=new Array(); +for(var i=0;i0){ +this.__init__(_158,_159,_160); +} +}; +PlotKit.CanvasRenderer.prototype.__init__=function(_161,_162,_163){ +var _164=MochiKit.Base.isUndefinedOrNull; +var _165=MochiKit.Color.Color; +this.options={"drawBackground":true,"backgroundColor":_165.whiteColor(),"padding":{left:30,right:30,top:5,bottom:10},"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"strokeColor":_165.whiteColor(),"strokeColorTransform":"asStrokeColor","strokeWidth":0.5,"shouldFill":true,"shouldStroke":true,"drawXAxis":true,"drawYAxis":true,"axisLineColor":_165.blackColor(),"axisLineWidth":0.5,"axisTickSize":3,"axisLabelColor":_165.blackColor(),"axisLabelFont":"Arial","axisLabelFontSize":9,"axisLabelWidth":50,"pieRadius":0.4,"enableEvents":true}; +MochiKit.Base.update(this.options,_163?_163:{}); +this.layout=_162; +this.element=MochiKit.DOM.getElement(_161); +this.container=this.element.parentNode; +this.isIE=PlotKit.Base.excanvasSupported(); +if(this.isIE&&!_164(G_vmlCanvasManager)){ +this.IEDelay=0.5; +this.maxTries=5; +this.renderDelay=null; +this.clearDelay=null; +this.element=G_vmlCanvasManager.initElement(this.element); +} +this.height=this.element.height; +this.width=this.element.width; +if(_164(this.element)){ +throw "CanvasRenderer() - passed canvas is not found"; +} +if(!this.isIE&&!(PlotKit.CanvasRenderer.isSupported(this.element))){ +throw "CanvasRenderer() - Canvas is not supported."; +} +if(_164(this.container)||(this.container.nodeName.toLowerCase()!="div")){ +throw "CanvasRenderer() - needs to be enclosed in +
">
+ + +<% if #self.deps > 0 then -%> + +<%- end %> \ No newline at end of file diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valueheader.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valueheader.htm new file mode 100644 index 0000000..5d081e3 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valueheader.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: cell_valueheader.htm 3340 2008-09-16 15:51:35Z Cyrus $ + +-%> + + +
"> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dvalue.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dvalue.htm new file mode 100644 index 0000000..2915a93 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dvalue.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: dvalue.htm 3369 2008-09-19 10:44:35Z Cyrus $ + +-%> + +<%+cbi/valueheader%> +<% if self.href then %><% end -%> + <%=luci.util.pcdata(self:cfgvalue(section))%> +<%- if self.href then %><%end%> +  + +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dynlist.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dynlist.htm new file mode 100644 index 0000000..a23a4eb --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/dynlist.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<%+cbi/valueheader%> +<% + local vals = self:cfgvalue(section) or {} + for i=1, #vals + 1 do + local val = vals[i] +%> + /> + <% if i <= #vals then %> + " alt="<%:cbi_del%>" title="<%:cbi_del%>" src="<%=resource%>/cbi/remove.gif" /> + <% else %> + " alt="<%:cbi_add%>" title="<%:cbi_add%>" src="<%=resource%>/cbi/add.gif" /> + <% end %> + <% if #self.keylist > 0 then -%> + + <% end -%> +<% if i <= #vals then %>
+<% end end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/filebrowser.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/filebrowser.htm new file mode 100644 index 0000000..b106d6b --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/filebrowser.htm @@ -0,0 +1,122 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: filebrowser.htm 3555 2008-10-10 21:52:22Z jow $ + +-%> + + + + + + Filebrowser - LuCI + + + + + + <% + require("luci.fs") + require("luci.http") + require("luci.dispatcher") + + local field = luci.http.formvalue('field') + local request = luci.dispatcher.context.path + local path = { '' } + + for i = 3, #request do + if request[i] ~= '..' and #request[i] > 0 then + path[#path+1] = request[i] + end + end + + local filepath = table.concat( path, '/' ) + local filestat = luci.fs.stat( filepath ) + local baseurl = luci.dispatcher.build_url('admin', 'filebrowser') + + if filestat and filestat.type == "regular" then + table.remove( path, #path ) + filepath = table.concat( path, '/' ) .. '/' + elseif not ( filestat and filestat.type == "directory" ) then + path = { '' } + filepath = '/' + else + filepath = filepath .. '/' + end + + local entries = luci.fs.dir(filepath) + -%> +
+ Location: + <% for i, dir in ipairs(path) do %> + <% if i == 1 then %> + (root) + <% elseif next(path, i) then %> + <% baseurl = baseurl .. '/' .. dir %> + / <%=dir%> + <% else %> + <% baseurl = baseurl .. '/' .. dir %> + / <%=dir%> + <% end %> + <% end %> +
+ +
+ +
+
    + <% for _, e in luci.util.vspairs(entries) do + local stat = luci.fs.stat(filepath..e) + if e ~= '.' and e ~= '..' and stat and stat.type == 'directory' then + -%> +
  • + Directory + <%=e%>/ +
  • + <% end end -%> + + <% for _, e in luci.util.vspairs(entries) do + local stat = luci.fs.stat(filepath..e) + if stat and stat.type ~= 'directory' then + -%> +
  • + File + <%=e%> +
  • + <% end end -%> +
+
+ + diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/footer.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/footer.htm new file mode 100644 index 0000000..7762124 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/footer.htm @@ -0,0 +1,26 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> + <%- if pageaction then -%> +
+ <% if not autoapply then%> + + <% end %> + + + +
+ <%- end -%> + +<%+footer%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valuefooter.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valuefooter.htm new file mode 100644 index 0000000..32e6d05 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valuefooter.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: full_valuefooter.htm 3657 2008-10-30 02:41:25Z jow $ + +-%> + + <% if self.description and #self.description > 0 then -%> + <% if not luci.util.instanceof( self, luci.cbi.Flag ) then -%> +
+ <%- end %> +
+ <%:help%> + <%=self.description%> +
+ <%- end %> + <%- if self.title and #self.title > 0 then -%> +
+ <%- end -%> +
"; +} +this.xlabels=new Array(); +this.ylabels=new Array(); +this.isFirstRender=true; +this.area={x:this.options.padding.left,y:this.options.padding.top,w:this.width-this.options.padding.left-this.options.padding.right,h:this.height-this.options.padding.top-this.options.padding.bottom}; +MochiKit.DOM.updateNodeAttributes(this.container,{"style":{"position":"relative","width":this.width+"px"}}); +}; +PlotKit.CanvasRenderer.prototype.render=function(){ +if(this.isIE){ +try{ +if(this.renderDelay){ +this.renderDelay.cancel(); +this.renderDelay=null; +} +var _166=this.element.getContext("2d"); +} +catch(e){ +this.isFirstRender=false; +if(this.maxTries-->0){ +this.renderDelay=MochiKit.Async.wait(this.IEDelay); +this.renderDelay.addCallback(bind(this.render,this)); +} +return; +} +} +if(this.options.drawBackground){ +this._renderBackground(); +} +if(this.layout.style=="bar"){ +this._renderBarChart(); +this._renderBarAxis(); +}else{ +if(this.layout.style=="pie"){ +this._renderPieChart(); +this._renderPieAxis(); +}else{ +if(this.layout.style=="line"){ +this._renderLineChart(); +this._renderLineAxis(); +} +} +} +}; +PlotKit.CanvasRenderer.prototype._renderBarChartWrap=function(data,_168){ +var _169=this.element.getContext("2d"); +var _170=this.options.colorScheme.length; +var _171=this.options.colorScheme; +var _172=MochiKit.Base.keys(this.layout.datasets); +var _173=_172.length; +for(var i=0;i<_173;i++){ +var _174=_172[i]; +var _175=_171[i%_170]; +_169.save(); +_169.fillStyle=_175.toRGBString(); +if(this.options.strokeColor){ +_169.strokeStyle=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_169.strokeStyle=_175[this.options.strokeColorTransform]().toRGBString(); +} +} +_169.lineWidth=this.options.strokeWidth; +var _176=function(obj){ +if(obj.name==_174){ +_168(_169,obj); +} +}; +MochiKit.Iter.forEach(data,bind(_176,this)); +_169.restore(); +} +}; +PlotKit.CanvasRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _178=function(_179,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +if((w<1)||(h<1)){ +return; +} +if(this.options.shouldFill){ +_179.fillRect(x,y,w,h); +} +if(this.options.shouldStroke){ +_179.strokeRect(x,y,w,h); +} +}; +this._renderBarChartWrap(this.layout.bars,bind(_178,this)); +}; +PlotKit.CanvasRenderer.prototype._renderLineChart=function(){ +var _182=this.element.getContext("2d"); +var _183=this.options.colorScheme.length; +var _184=this.options.colorScheme; +var _185=MochiKit.Base.keys(this.layout.datasets); +var _186=_185.length; +var bind=MochiKit.Base.bind; +var _187=MochiKit.Base.partial; +for(var i=0;i<_186;i++){ +var _188=_185[i]; +var _189=_184[i%_183]; +var _190=this.options.strokeColorTransform; +_182.save(); +_182.fillStyle=_189.toRGBString(); +if(this.options.strokeColor){ +_182.strokeStyle=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_182.strokeStyle=_189[_190]().toRGBString(); +} +} +_182.lineWidth=this.options.strokeWidth; +var _191=function(ctx){ +ctx.beginPath(); +ctx.moveTo(this.area.x,this.area.y+this.area.h); +var _193=function(ctx_,_195){ +if(_195.name==_188){ +ctx_.lineTo(this.area.w*_195.x+this.area.x,this.area.h*_195.y+this.area.y); +} +}; +MochiKit.Iter.forEach(this.layout.points,_187(_193,ctx),this); +ctx.lineTo(this.area.w+this.area.x,this.area.h+this.area.y); +ctx.lineTo(this.area.x,this.area.y+this.area.h); +ctx.closePath(); +}; +if(this.options.shouldFill){ +bind(_191,this)(_182); +_182.fill(); +} +if(this.options.shouldStroke){ +bind(_191,this)(_182); +_182.stroke(); +} +_182.restore(); +} +}; +PlotKit.CanvasRenderer.prototype._renderPieChart=function(){ +var _196=this.element.getContext("2d"); +var _197=this.options.colorScheme.length; +var _198=this.layout.slices; +var _199=this.area.x+this.area.w*0.5; +var _200=this.area.y+this.area.h*0.5; +var _201=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +if(this.isIE){ +_199=parseInt(_199); +_200=parseInt(_200); +_201=parseInt(_201); +} +for(var i=0;i<_198.length;i++){ +var _202=this.options.colorScheme[i%_197]; +_196.save(); +_196.fillStyle=_202.toRGBString(); +var _203=function(){ +_196.beginPath(); +_196.moveTo(_199,_200); +_196.arc(_199,_200,_201,_198[i].startAngle-Math.PI/2,_198[i].endAngle-Math.PI/2,false); +_196.lineTo(_199,_200); +_196.closePath(); +}; +if(Math.abs(_198[i].startAngle-_198[i].endAngle)>0.001){ +if(this.options.shouldFill){ +_203(); +_196.fill(); +} +if(this.options.shouldStroke){ +_203(); +_196.lineWidth=this.options.strokeWidth; +if(this.options.strokeColor){ +_196.strokeStyle=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_196.strokeStyle=_202[this.options.strokeColorTransform]().toRGBString(); +} +} +_196.stroke(); +} +} +_196.restore(); +} +}; +PlotKit.CanvasRenderer.prototype._renderBarAxis=function(){ +this._renderAxis(); +}; +PlotKit.CanvasRenderer.prototype._renderLineAxis=function(){ +this._renderAxis(); +}; +PlotKit.CanvasRenderer.prototype._renderAxis=function(){ +if(!this.options.drawXAxis&&!this.options.drawYAxis){ +return; +} +var _204=this.element.getContext("2d"); +var _205={"style":{"position":"absolute","fontSize":this.options.axisLabelFontSize+"px","zIndex":10,"color":this.options.axisLabelColor.toRGBString(),"width":this.options.axisLabelWidth+"px","overflow":"hidden"}}; +_204.save(); +_204.strokeStyle=this.options.axisLineColor.toRGBString(); +_204.lineWidth=this.options.axisLineWidth; +if(this.options.drawYAxis){ +if(this.layout.yticks){ +var _206=function(tick){ +if(typeof (tick)=="function"){ +return; +} +var x=this.area.x; +var y=this.area.y+tick[0]*this.area.h; +_204.beginPath(); +_204.moveTo(x,y); +_204.lineTo(x-this.options.axisTickSize,y); +_204.closePath(); +_204.stroke(); +var _207=DIV(_205,tick[1]); +_207.style.top=(y-this.options.axisLabelFontSize)+"px"; +_207.style.left=(x-this.options.padding.left-this.options.axisTickSize)+"px"; +_207.style.textAlign="right"; +_207.style.width=(this.options.padding.left-this.options.axisTickSize*2)+"px"; +MochiKit.DOM.appendChildNodes(this.container,_207); +this.ylabels.push(_207); +}; +MochiKit.Iter.forEach(this.layout.yticks,bind(_206,this)); +} +_204.beginPath(); +_204.moveTo(this.area.x,this.area.y); +_204.lineTo(this.area.x,this.area.y+this.area.h); +_204.closePath(); +_204.stroke(); +} +if(this.options.drawXAxis){ +if(this.layout.xticks){ +var _206=function(tick){ +if(typeof (dataset)=="function"){ +return; +} +var x=this.area.x+tick[0]*this.area.w; +var y=this.area.y+this.area.h; +_204.beginPath(); +_204.moveTo(x,y); +_204.lineTo(x,y+this.options.axisTickSize); +_204.closePath(); +_204.stroke(); +var _208=DIV(_205,tick[1]); +_208.style.top=(y+this.options.axisTickSize)+"px"; +_208.style.left=(x-this.options.axisLabelWidth/2)+"px"; +_208.style.textAlign="center"; +_208.style.width=this.options.axisLabelWidth+"px"; +MochiKit.DOM.appendChildNodes(this.container,_208); +this.xlabels.push(_208); +}; +MochiKit.Iter.forEach(this.layout.xticks,bind(_206,this)); +} +_204.beginPath(); +_204.moveTo(this.area.x,this.area.y+this.area.h); +_204.lineTo(this.area.x+this.area.w,this.area.y+this.area.h); +_204.closePath(); +_204.stroke(); +} +_204.restore(); +}; +PlotKit.CanvasRenderer.prototype._renderPieAxis=function(){ +if(!this.options.drawXAxis){ +return; +} +if(this.layout.xticks){ +var _209=new Array(); +for(var i=0;iMath.PI*2){ +_216=_216-Math.PI*2; +}else{ +if(_216<0){ +_216=_216+Math.PI*2; +} +} +var _217=_210+Math.sin(_216)*(_212+10); +var _218=_211-Math.cos(_216)*(_212+10); +var _219={"position":"absolute","zIndex":11,"width":_213+"px","fontSize":this.options.axisLabelFontSize+"px","overflow":"hidden","color":this.options.axisLabelColor.toHexString()}; +if(_216<=Math.PI*0.5){ +_219["textAlign"]="left"; +_219["verticalAlign"]="top"; +_219["left"]=_217+"px"; +_219["top"]=(_218-this.options.axisLabelFontSize)+"px"; +}else{ +if((_216>Math.PI*0.5)&&(_216<=Math.PI)){ +_219["textAlign"]="left"; +_219["verticalAlign"]="bottom"; +_219["left"]=_217+"px"; +_219["top"]=_218+"px"; +}else{ +if((_216>Math.PI)&&(_216<=Math.PI*1.5)){ +_219["textAlign"]="right"; +_219["verticalAlign"]="bottom"; +_219["left"]=(_217-_213)+"px"; +_219["top"]=_218+"px"; +}else{ +_219["textAlign"]="right"; +_219["verticalAlign"]="bottom"; +_219["left"]=(_217-_213)+"px"; +_219["top"]=(_218-this.options.axisLabelFontSize)+"px"; +} +} +} +var _220=DIV({"style":_219},this.layout.xticks[i][1]); +this.xlabels.push(_220); +MochiKit.DOM.appendChildNodes(this.container,_220); +} +} +}; +PlotKit.CanvasRenderer.prototype._renderBackground=function(){ +var _221=this.element.getContext("2d"); +_221.save(); +_221.fillStyle=this.options.backgroundColor.toRGBString(); +_221.fillRect(0,0,this.width,this.height); +_221.restore(); +}; +PlotKit.CanvasRenderer.prototype.clear=function(){ +if(this.isIE){ +try{ +if(this.clearDelay){ +this.clearDelay.cancel(); +this.clearDelay=null; +} +var _222=this.element.getContext("2d"); +} +catch(e){ +this.isFirstRender=false; +this.clearDelay=MochiKit.Async.wait(this.IEDelay); +this.clearDelay.addCallback(bind(this.clear,this)); +return; +} +} +var _222=this.element.getContext("2d"); +_222.clearRect(0,0,this.width,this.height); +MochiKit.Iter.forEach(this.xlabels,MochiKit.DOM.removeElement); +MochiKit.Iter.forEach(this.ylabels,MochiKit.DOM.removeElement); +this.xlabels=new Array(); +this.ylabels=new Array(); +}; +PlotKit.CanvasRenderer.prototype._initialiseEvents=function(){ +var _223=MochiKit.Signal.connect; +var bind=MochiKit.Base.bind; +_223(this.element,"onclick",bind(this.onclick,this)); +}; +PlotKit.CanvasRenderer.prototype._resolveObject=function(e){ +var x=(e.mouse().page.x-PlotKit.Base.findPosX(this.element)-this.area.x)/this.area.w; +var y=(e.mouse().page.y-PlotKit.Base.findPosY(this.element)-this.area.y)/this.area.h; +var _225=this.layout.hitTest(x,y); +if(_225){ +return _225; +} +return null; +}; +PlotKit.CanvasRenderer.prototype._createEventObject=function(_226,e){ +if(_226==null){ +return null; +} +e.chart=_226; +return e; +}; +PlotKit.CanvasRenderer.prototype.onclick=function(e){ +var _227=this._resolveObject(e); +var _228=this._createEventObject(_227,e); +if(_228!=null){ +MochiKit.Signal.signal(this,"onclick",_228); +} +}; +PlotKit.CanvasRenderer.prototype.onmouseover=function(e){ +var _229=this._resolveObject(e); +var _230=this._createEventObject(_229,e); +if(_230!=null){ +signal(this,"onmouseover",_230); +} +}; +PlotKit.CanvasRenderer.prototype.onmouseout=function(e){ +var _231=this._resolveObject(e); +var _232=this._createEventObject(_231,e); +if(_232==null){ +signal(this,"onmouseout",e); +}else{ +signal(this,"onmouseout",_232); +} +}; +PlotKit.CanvasRenderer.prototype.onmousemove=function(e){ +var _233=this._resolveObject(e); +var _234=this._createEventObject(_233,e); +if((_233==null)&&(this.event_isinside==null)){ +return; +} +if((_233!=null)&&(this.event_isinside==null)){ +signal(this,"onmouseover",_234); +} +if((_233==null)&&(this.event_isinside!=null)){ +signal(this,"onmouseout",_234); +} +if((_233!=null)&&(this.event_isinside!=null)){ +signal(this,"onmousemove",_234); +} +this.event_isinside=_233; +}; +PlotKit.CanvasRenderer.isSupported=function(_235){ +var _236=null; +try{ +if(MochiKit.Base.isUndefinedOrNull(_235)){ +_236=MochiKit.DOM.CANVAS({}); +}else{ +_236=MochiKit.DOM.getElement(_235); +} +var _237=_236.getContext("2d"); +} +catch(e){ +var ie=navigator.appVersion.match(/MSIE (\d\.\d)/); +var _239=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1); +if((!ie)||(ie[1]<6)||(_239)){ +return false; +} +return true; +} +return true; +}; +PlotKit.Canvas={}; +PlotKit.Canvas.CanvasRenderer=PlotKit.CanvasRenderer; +PlotKit.Canvas.EXPORT=["CanvasRenderer"]; +PlotKit.Canvas.EXPORT_OK=["CanvasRenderer"]; +PlotKit.Canvas.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.Canvas.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.Canvas); +try{ +if(typeof (PlotKit.Layout)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout"; +} +PlotKit.SVGRenderer=function(_240,_241,_242){ +if(arguments.length>0){ +this.__init__(_240,_241,_242); +} +}; +PlotKit.SVGRenderer.NAME="PlotKit.SVGRenderer"; +PlotKit.SVGRenderer.VERSION=PlotKit.VERSION; +PlotKit.SVGRenderer.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.SVGRenderer.toString=function(){ +return this.__repr__(); +}; +PlotKit.SVGRenderer.SVGNS="http://www.w3.org/2000/svg"; +PlotKit.SVGRenderer.prototype.__init__=function(_243,_244,_245){ +var _246=MochiKit.Base.isUndefinedOrNull; +this.options={"drawBackground":true,"backgroundColor":Color.whiteColor(),"padding":{left:30,right:30,top:5,bottom:10},"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),"strokeColor":Color.whiteColor(),"strokeColorTransform":"asStrokeColor","strokeWidth":0.5,"shouldFill":true,"shouldStroke":true,"drawXAxis":true,"drawYAxis":true,"axisLineColor":Color.blackColor(),"axisLineWidth":0.5,"axisTickSize":3,"axisLabelColor":Color.blackColor(),"axisLabelFont":"Arial","axisLabelFontSize":9,"axisLabelWidth":50,"axisLabelUseDiv":true,"pieRadius":0.4,"enableEvents":true}; +MochiKit.Base.update(this.options,_245?_245:{}); +this.layout=_244; +this.element=MochiKit.DOM.getElement(_243); +this.container=this.element.parentNode; +this.height=parseInt(this.element.getAttribute("height")); +this.width=parseInt(this.element.getAttribute("width")); +this.document=document; +this.root=this.element; +try{ +this.document=this.element.getSVGDocument(); +this.root=_246(this.document.documentElement)?this.element:this.document.documentElement; +} +catch(e){ +} +this.element.style.zIndex=1; +if(_246(this.element)){ +throw "SVGRenderer() - passed SVG object is not found"; +} +if(_246(this.container)||this.container.nodeName.toLowerCase()!="div"){ +throw "SVGRenderer() - No DIV's around the SVG."; +} +this.xlabels=new Array(); +this.ylabels=new Array(); +this.defs=this.createSVGElement("defs"); +this.area={x:this.options.padding.left,y:this.options.padding.top,w:this.width-this.options.padding.left-this.options.padding.right,h:this.height-this.options.padding.top-this.options.padding.bottom}; +MochiKit.DOM.updateNodeAttributes(this.container,{"style":{"position":"relative","width":this.width+"px"}}); +}; +PlotKit.SVGRenderer.prototype.render=function(){ +if(this.options.drawBackground){ +this._renderBackground(); +} +if(this.layout.style=="bar"){ +this._renderBarChart(); +this._renderBarAxis(); +}else{ +if(this.layout.style=="pie"){ +this._renderPieChart(); +this._renderPieAxis(); +}else{ +if(this.layout.style=="line"){ +this._renderLineChart(); +this._renderLineAxis(); +} +} +} +}; +PlotKit.SVGRenderer.prototype._renderBarOrLine=function(data,_247,_248,_249){ +var _250=this.options.colorScheme.length; +var _251=this.options.colorScheme; +var _252=MochiKit.Base.keys(this.layout.datasets); +var _253=_252.length; +for(var i=0;i<_253;i++){ +var _254=_252[i]; +var _255=new Array(); +var _256=_251[i%_250]; +if(this.options.shouldFill){ +_255["fill"]=_256.toRGBString(); +}else{ +_255["fill"]="none"; +} +if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){ +if(this.options.strokeColor){ +_255["stroke"]=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_255["stroke"]=_256[this.options.strokeColorTransform]().toRGBString(); +} +} +_255["strokeWidth"]=this.options.strokeWidth; +} +if(_248){ +_248(_255); +} +var _257=function(obj){ +if(obj.name==_254){ +_247(_255,obj); +} +}; +MochiKit.Iter.forEach(data,bind(_257,this)); +if(_249){ +_249(_255); +} +} +}; +PlotKit.SVGRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _258=function(_259,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +this._drawRect(x,y,w,h,_259); +}; +this._renderBarOrLine(this.layout.bars,bind(_258,this)); +}; +PlotKit.SVGRenderer.prototype._renderLineChart=function(){ +var bind=MochiKit.Base.bind; +var _260=function(_261,_262){ +this._tempPointsBuffer+=(this.area.w*_262.x+this.area.x)+","+(this.area.h*_262.y+this.area.y)+" "; +}; +var _263=function(_264){ +this._tempPointsBuffer=""; +this._tempPointsBuffer+=(this.area.x)+","+(this.area.y+this.area.h)+" "; +}; +var _265=function(_266){ +this._tempPointsBuffer+=(this.area.w+this.area.x)+","+(this.area.h+this.area.y); +_266["points"]=this._tempPointsBuffer; +var elem=this.createSVGElement("polygon",_266); +this.root.appendChild(elem); +}; +this._renderBarOrLine(this.layout.points,bind(_260,this),bind(_263,this),bind(_265,this)); +}; +PlotKit.SVGRenderer.prototype._renderPieChart=function(){ +var _268=this.options.colorScheme.length; +var _269=this.layout.slices; +var _270=this.area.x+this.area.w*0.5; +var _271=this.area.y+this.area.h*0.5; +var _272=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +if(_269.length==1&&(Math.abs(_269[0].startAngle)-Math.abs(_269[0].endAngle)<0.1)){ +var _273={"cx":_270,"cy":_271,"r":_272}; +var _274=this.options.colorScheme[0]; +if(this.options.shouldFill){ +_273["fill"]=_274.toRGBString(); +}else{ +_273["fill"]="none"; +} +if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){ +if(this.options.strokeColor){ +_273["stroke"]=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_273["stroke"]=_274[this.options.strokeColorTransform]().toRGBString(); +} +} +_273["style"]="stroke-width: "+this.options.strokeWidth; +} +this.root.appendChild(this.createSVGElement("circle",_273)); +return; +} +for(var i=0;i<_269.length;i++){ +var _273=new Array(); +var _274=this.options.colorScheme[i%_268]; +if(this.options.shouldFill){ +_273["fill"]=_274.toRGBString(); +}else{ +_273["fill"]="none"; +} +if(this.options.shouldStroke&&(this.options.strokeColor||this.options.strokeColorTransform)){ +if(this.options.strokeColor){ +_273["stroke"]=this.options.strokeColor.toRGBString(); +}else{ +if(this.options.strokeColorTransform){ +_273["stroke"]=_274[this.options.strokeColorTransform]().toRGBString(); +} +} +_273["style"]="stroke-width:"+this.options.strokeWidth; +} +var _275=0; +if(Math.abs(_269[i].endAngle-_269[i].startAngle)>Math.PI){ +_275=1; +} +var x1=Math.cos(_269[i].startAngle-Math.PI/2)*_272; +var y1=Math.sin(_269[i].startAngle-Math.PI/2)*_272; +var x2=Math.cos(_269[i].endAngle-Math.PI/2)*_272; +var y2=Math.sin(_269[i].endAngle-Math.PI/2)*_272; +var rx=x2-x1; +var ry=y2-y1; +var _282="M"+_270+","+_271+" "; +_282+="l"+x1+","+y1+" "; +_282+="a"+_272+","+_272+" 0 "+_275+",1 "+rx+","+ry+" z"; +_273["d"]=_282; +var elem=this.createSVGElement("path",_273); +this.root.appendChild(elem); +} +}; +PlotKit.SVGRenderer.prototype._renderBarAxis=function(){ +this._renderAxis(); +}; +PlotKit.SVGRenderer.prototype._renderLineAxis=function(){ +this._renderAxis(); +}; +PlotKit.SVGRenderer.prototype._renderAxis=function(){ +if(!this.options.drawXAxis&&!this.options.drawYAxis){ +return; +} +var _283={"style":{"position":"absolute","textAlign":"center","fontSize":this.options.axisLabelFontSize+"px","zIndex":10,"color":this.options.axisLabelColor.toRGBString(),"width":this.options.axisLabelWidth+"px","overflow":"hidden"}}; +var _284={"stroke":this.options.axisLineColor.toRGBString(),"strokeWidth":this.options.axisLineWidth}; +if(this.options.drawYAxis){ +if(this.layout.yticks){ +var _285=function(tick){ +var x=this.area.x; +var y=this.area.y+tick[0]*this.area.h; +this._drawLine(x,y,x-3,y,_284); +if(this.options.axisLabelUseDiv){ +var _286=DIV(_283,tick[1]); +_286.style.top=(y-this.options.axisLabelFontSize)+"px"; +_286.style.left=(x-this.options.padding.left+this.options.axisTickSize)+"px"; +_286.style.textAlign="left"; +_286.style.width=(this.options.padding.left-3)+"px"; +MochiKit.DOM.appendChildNodes(this.container,_286); +this.ylabels.push(_286); +}else{ +var _287={y:y+3,x:(x-this.options.padding.left+3),width:(this.options.padding.left-this.options.axisTickSize)+"px",height:(this.options.axisLabelFontSize+3)+"px",fontFamily:"Arial",fontSize:this.options.axisLabelFontSize+"px",fill:this.options.axisLabelColor.toRGBString()}; +var _286=this.createSVGElement("text",_287); +_286.appendChild(this.document.createTextNode(tick[1])); +this.root.appendChild(_286); +} +}; +MochiKit.Iter.forEach(this.layout.yticks,bind(_285,this)); +} +this._drawLine(this.area.x,this.area.y,this.area.x,this.area.y+this.area.h,_284); +} +if(this.options.drawXAxis){ +if(this.layout.xticks){ +var _285=function(tick){ +var x=this.area.x+tick[0]*this.area.w; +var y=this.area.y+this.area.h; +this._drawLine(x,y,x,y+this.options.axisTickSize,_284); +if(this.options.axisLabelUseDiv){ +var _288=DIV(_283,tick[1]); +_288.style.top=(y+this.options.axisTickSize)+"px"; +_288.style.left=(x-this.options.axisLabelWidth/2)+"px"; +_288.style.textAlign="center"; +_288.style.width=this.options.axisLabelWidth+"px"; +MochiKit.DOM.appendChildNodes(this.container,_288); +this.xlabels.push(_288); +}else{ +var _289={y:(y+this.options.axisTickSize+this.options.axisLabelFontSize),x:x-3,width:this.options.axisLabelWidth+"px",height:(this.options.axisLabelFontSize+3)+"px",fontFamily:"Arial",fontSize:this.options.axisLabelFontSize+"px",fill:this.options.axisLabelColor.toRGBString(),textAnchor:"middle"}; +var _288=this.createSVGElement("text",_289); +_288.appendChild(this.document.createTextNode(tick[1])); +this.root.appendChild(_288); +} +}; +MochiKit.Iter.forEach(this.layout.xticks,bind(_285,this)); +} +this._drawLine(this.area.x,this.area.y+this.area.h,this.area.x+this.area.w,this.area.y+this.area.h,_284); +} +}; +PlotKit.SVGRenderer.prototype._renderPieAxis=function(){ +if(this.layout.xticks){ +var _290=new Array(); +for(var i=0;iMath.PI*2){ +_297=_297-Math.PI*2; +}else{ +if(_297<0){ +_297=_297+Math.PI*2; +} +} +var _298=_291+Math.sin(_297)*(_293+10); +var _299=_292-Math.cos(_297)*(_293+10); +var _300={"position":"absolute","zIndex":11,"width":_294+"px","fontSize":this.options.axisLabelFontSize+"px","overflow":"hidden","color":this.options.axisLabelColor.toHexString()}; +var _301={"width":_294+"px","fontSize":this.options.axisLabelFontSize+"px","height":(this.options.axisLabelFontSize+3)+"px","fill":this.options.axisLabelColor.toRGBString()}; +if(_297<=Math.PI*0.5){ +MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"top","left":_298+"px","top":(_299-this.options.axisLabelFontSize)+"px"}); +MochiKit.Base.update(_301,{"x":_298,"y":(_299-this.options.axisLabelFontSize),"textAnchor":"left"}); +}else{ +if((_297>Math.PI*0.5)&&(_297<=Math.PI)){ +MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"bottom","left":_298+"px","top":_299+"px"}); +MochiKit.Base.update(_301,{"textAnchor":"left","x":_298,"y":_299}); +}else{ +if((_297>Math.PI)&&(_297<=Math.PI*1.5)){ +MochiKit.Base.update(_300,{"textAlign":"right","verticalAlign":"bottom","left":_298+"px","top":_299+"px"}); +MochiKit.Base.update(_301,{"textAnchor":"right","x":_298-_294,"y":_299}); +}else{ +MochiKit.Base.update(_300,{"textAlign":"left","verticalAlign":"bottom","left":_298+"px","top":_299+"px"}); +MochiKit.Base.update(_301,{"textAnchor":"left","x":_298-_294,"y":_299-this.options.axisLabelFontSize}); +} +} +} +if(this.options.axisLabelUseDiv){ +var _302=DIV({"style":_300},this.layout.xticks[i][1]); +this.xlabels.push(_302); +MochiKit.DOM.appendChildNodes(this.container,_302); +}else{ +var _302=this.createSVGElement("text",_301); +_302.appendChild(this.document.createTextNode(this.layout.xticks[i][1])); +this.root.appendChild(_302); +} +} +} +}; +PlotKit.SVGRenderer.prototype._renderBackground=function(){ +var opts={"stroke":"none","fill":this.options.backgroundColor.toRGBString()}; +this._drawRect(0,0,this.width,this.height,opts); +}; +PlotKit.SVGRenderer.prototype._drawRect=function(x,y,w,h,_304){ +var _305={x:x+"px",y:y+"px",width:w+"px",height:h+"px"}; +if(_304){ +MochiKit.Base.update(_305,_304); +} +var elem=this.createSVGElement("rect",_305); +this.root.appendChild(elem); +}; +PlotKit.SVGRenderer.prototype._drawLine=function(x1,y1,x2,y2,_306){ +var _307={x1:x1+"px",y1:y1+"px",x2:x2+"px",y2:y2+"px"}; +if(_306){ +MochiKit.Base.update(_307,_306); +} +var elem=this.createSVGElement("line",_307); +this.root.appendChild(elem); +}; +PlotKit.SVGRenderer.prototype.clear=function(){ +while(this.element.firstChild){ +this.element.removeChild(this.element.firstChild); +} +if(this.options.axisLabelUseDiv){ +for(var i=0;i=6)&&(!_313)){ +var _314=_312["width"]?_312["width"]:"100"; +var _315=_312["height"]?_312["height"]:"100"; +var eid=_312["id"]?_312["id"]:"notunique"; +var html=""; +var _318=document.createElement(html); +var _319=_318.getSVGDocument().createElementNS(PlotKit.SVGRenderer.SVGNS,"svg"); +_319.setAttribute("width",_314); +_319.setAttribute("height",_315); +_318.getSVGDocument().appendChild(_319); +return _318; +}else{ +return PlotKit.SVGRenderer.prototype.createSVGElement("svg",_312); +} +}; +PlotKit.SVGRenderer.isSupported=function(){ +var _320=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1); +var _321=navigator.appVersion.match(/MSIE (\d\.\d)/); +var _322=navigator.userAgent.match(/AppleWebKit\/(\d+)/); +var _323=navigator.userAgent.match(/Opera\/(\d*\.\d*)/); +var _324=navigator.userAgent.match(/rv:(\d*\.\d*).*Gecko/); +var _325="http://www.w3.org/TR/SVG11/feature#SVG"; +if(_321&&(_321[1]>=6)&&!_320){ +return document.implementation.hasFeature(_325,"1.1"); +} +if(_323&&(_323[1]>8.9)){ +return true; +} +if(_324&&(_324>1.7)){ +return true; +} +return false; +}; +PlotKit.SVG={}; +PlotKit.SVG.SVGRenderer=PlotKit.SVGRenderer; +PlotKit.SVG.EXPORT=["SVGRenderer"]; +PlotKit.SVG.EXPORT_OK=["SVGRenderer"]; +PlotKit.SVG.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.SVG.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.SVG); +try{ +if(typeof (PlotKit.CanvasRenderer)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "SweetCanvas depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, Canvas}"; +} +if(typeof (PlotKit.SweetCanvasRenderer)=="undefined"){ +PlotKit.SweetCanvasRenderer={}; +} +PlotKit.SweetCanvasRenderer=function(_326,_327,_328){ +if(arguments.length>0){ +this.__init__(_326,_327,_328); +} +}; +PlotKit.SweetCanvasRenderer.NAME="PlotKit.SweetCanvasRenderer"; +PlotKit.SweetCanvasRenderer.VERSION=PlotKit.VERSION; +PlotKit.SweetCanvasRenderer.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.SweetCanvasRenderer.toString=function(){ +return this.__repr__(); +}; +PlotKit.SweetCanvasRenderer.prototype=new PlotKit.CanvasRenderer(); +PlotKit.SweetCanvasRenderer.prototype.constructor=PlotKit.SweetCanvasRenderer; +PlotKit.SweetCanvasRenderer.__super__=PlotKit.CanvasRenderer.prototype; +PlotKit.SweetCanvasRenderer.prototype.__init__=function(el,_330,opts){ +var _331=PlotKit.Base.officeBlue(); +MochiKit.Base.update(_331,opts); +PlotKit.SweetCanvasRenderer.__super__.__init__.call(this,el,_330,_331); +}; +PlotKit.SweetCanvasRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _332=Color.blackColor().colorWithAlpha(0.1).toRGBString(); +var _333=function(_334,x,y,w,h){ +_334.fillStyle=_332; +_334.fillRect(x-2,y-2,w+4,h+2); +_334.fillStyle=_332; +_334.fillRect(x-1,y-1,w+2,h+1); +}; +var _335=this.options.colorScheme.length; +var _336=this.options.colorScheme; +var _337=PlotKit.Base.keys(this.layout.datasets); +var _338=_337.length; +var _339=function(name){ +for(var i=0;i<_338;i++){ +if(name==_337[i]){ +return _336[i%_335]; +} +} +return _336[0]; +}; +var _340=function(_341,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +if((w<1)||(h<1)){ +return; +} +_341.save(); +_341.shadowBlur=5; +_341.shadowColor=Color.fromHexString("#888888").toRGBString(); +if(this.isIE){ +_341.save(); +_341.fillStyle="#cccccc"; +_341.fillRect(x-2,y-2,w+4,h+2); +_341.restore(); +}else{ +_333(_341,x,y,w,h); +} +if(this.options.shouldFill){ +_341.fillStyle=_339(bar.name).toRGBString(); +_341.fillRect(x,y,w,h); +} +_341.shadowBlur=0; +_341.strokeStyle=Color.whiteColor().toRGBString(); +_341.lineWidth=2; +if(this.options.shouldStroke){ +_341.strokeRect(x,y,w,h); +} +_341.restore(); +}; +this._renderBarChartWrap(this.layout.bars,bind(_340,this)); +}; +PlotKit.SweetCanvasRenderer.prototype._renderLineChart=function(){ +var _342=this.element.getContext("2d"); +var _343=this.options.colorScheme.length; +var _344=this.options.colorScheme; +var _345=PlotKit.Base.keys(this.layout.datasets); +var _346=_345.length; +var bind=MochiKit.Base.bind; +for(var i=0;i<_346;i++){ +var _347=_345[i]; +var _348=_344[i%_343]; +var _349=this.options.strokeColorTransform; +_342.save(); +var _350=function(ctx){ +ctx.beginPath(); +ctx.moveTo(this.area.x,this.area.y+this.area.h); +var _351=function(ctx_,_352){ +if(_352.name==_347){ +ctx_.lineTo(this.area.w*_352.x+this.area.x,this.area.h*_352.y+this.area.y); +} +}; +MochiKit.Iter.forEach(this.layout.points,partial(_351,ctx),this); +ctx.lineTo(this.area.w+this.area.x,this.area.h+this.area.y); +ctx.lineTo(this.area.x,this.area.y+this.area.h); +ctx.closePath(); +}; +if(this.options.shouldFill){ +_342.save(); +if(this.isIE){ +_342.fillStyle="#cccccc"; +}else{ +_342.fillStyle=Color.blackColor().colorWithAlpha(0.2).toRGBString(); +} +_342.translate(-1,-2); +bind(_350,this)(_342); +if(this.options.shouldFill){ +_342.fill(); +} +_342.restore(); +} +_342.shadowBlur=5; +_342.shadowColor=Color.fromHexString("#888888").toRGBString(); +_342.fillStyle=_348.toRGBString(); +_342.lineWidth=2; +_342.strokeStyle=Color.whiteColor().toRGBString(); +if(this.options.shouldFill){ +bind(_350,this)(_342); +_342.fill(); +} +if(this.options.shouldStroke){ +bind(_350,this)(_342); +_342.stroke(); +} +_342.restore(); +} +}; +PlotKit.SweetCanvasRenderer.prototype._renderPieChart=function(){ +var _353=this.element.getContext("2d"); +var _354=this.options.colorScheme.length; +var _355=this.layout.slices; +var _356=this.area.x+this.area.w*0.5; +var _357=this.area.y+this.area.h*0.5; +var _358=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +if(this.isIE){ +_356=parseInt(_356); +_357=parseInt(_357); +_358=parseInt(_358); +} +if(!this.isIE){ +_353.save(); +var _359=Color.blackColor().colorWithAlpha(0.2); +_353.fillStyle=_359.toRGBString(); +_353.shadowBlur=5; +_353.shadowColor=Color.fromHexString("#888888").toRGBString(); +_353.translate(1,1); +_353.beginPath(); +_353.moveTo(_356,_357); +_353.arc(_356,_357,_358+2,0,Math.PI*2,false); +_353.closePath(); +_353.fill(); +_353.restore(); +} +_353.save(); +_353.strokeStyle=Color.whiteColor().toRGBString(); +_353.lineWidth=2; +for(var i=0;i<_355.length;i++){ +var _360=this.options.colorScheme[i%_354]; +_353.fillStyle=_360.toRGBString(); +var _361=function(){ +_353.beginPath(); +_353.moveTo(_356,_357); +_353.arc(_356,_357,_358,_355[i].startAngle-Math.PI/2,_355[i].endAngle-Math.PI/2,false); +_353.lineTo(_356,_357); +_353.closePath(); +}; +if(Math.abs(_355[i].startAngle-_355[i].endAngle)>0.0001){ +if(this.options.shouldFill){ +_361(); +_353.fill(); +} +if(this.options.shouldStroke){ +_361(); +_353.stroke(); +} +} +} +_353.restore(); +}; +PlotKit.SweetCanvasRenderer.prototype._renderBackground=function(){ +var _362=this.element.getContext("2d"); +if(this.layout.style=="bar"||this.layout.style=="line"){ +_362.save(); +_362.fillStyle=this.options.backgroundColor.toRGBString(); +_362.fillRect(this.area.x,this.area.y,this.area.w,this.area.h); +_362.strokeStyle=this.options.axisLineColor.toRGBString(); +_362.lineWidth=1; +var _363=this.layout.yticks; +var _364=false; +if(this.layout.style=="bar"&&this.layout.options.barOrientation=="horizontal"){ +_363=this.layout.xticks; +_364=true; +} +for(var i=0;i<_363.length;i++){ +var x1=0; +var y1=0; +var x2=0; +var y2=0; +if(_364){ +x1=_363[i][0]*this.area.w+this.area.x; +y1=this.area.y; +x2=x1; +y2=y1+this.area.h; +}else{ +x1=this.area.x; +y1=_363[i][0]*this.area.h+this.area.y; +x2=x1+this.area.w; +y2=y1; +} +_362.beginPath(); +_362.moveTo(x1,y1); +_362.lineTo(x2,y2); +_362.closePath(); +_362.stroke(); +} +_362.restore(); +}else{ +PlotKit.SweetCanvasRenderer.__super__._renderBackground.call(this); +} +}; +PlotKit.SweetCanvas={}; +PlotKit.SweetCanvas.SweetCanvasRenderer=PlotKit.SweetCanvasRenderer; +PlotKit.SweetCanvas.EXPORT=["SweetCanvasRenderer"]; +PlotKit.SweetCanvas.EXPORT_OK=["SweetCanvasRenderer"]; +PlotKit.SweetCanvas.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.SweetCanvas.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.SweetCanvas); +try{ +if(typeof (PlotKit.SVGRenderer)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "SweetSVG depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, SVG}"; +} +if(typeof (PlotKit.SweetSVGRenderer)=="undefined"){ +PlotKit.SweetSVGRenderer={}; +} +PlotKit.SweetSVGRenderer=function(_365,_366,_367){ +if(arguments.length>0){ +this.__init__(_365,_366,_367); +} +}; +PlotKit.SweetSVGRenderer.NAME="PlotKit.SweetSVGRenderer"; +PlotKit.SweetSVGRenderer.VERSION=PlotKit.VERSION; +PlotKit.SweetSVGRenderer.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.SweetSVGRenderer.toString=function(){ +return this.__repr__(); +}; +PlotKit.SweetSVGRenderer.prototype=new PlotKit.SVGRenderer(); +PlotKit.SweetSVGRenderer.prototype.constructor=PlotKit.SweetSVGRenderer; +PlotKit.SweetSVGRenderer.__super__=PlotKit.SVGRenderer.prototype; +PlotKit.SweetSVGRenderer.prototype.__init__=function(_368,_369,_370){ +var _371=PlotKit.Base.officeBlue(); +MochiKit.Base.update(_371,_370); +PlotKit.SweetSVGRenderer.__super__.__init__.call(this,_368,_369,_371); +}; +PlotKit.SweetSVGRenderer.prototype._addDropShadowFilter=function(){ +var _372=this.createSVGElement("filter",{x:0,y:0,"id":"dropShadow"}); +var _373=this.createSVGElement("feOffset",{"in":"SourceGraphic","dx":0,"dy":0,"result":"topCopy"}); +var blur=this.createSVGElement("feGaussianBlur",{"in":"SourceAlpha","StdDeviation":2,"result":"shadow"}); +var _375=this.createSVGElement("feOffset",{"in":"shadow","dx":-1,"dy":-2,"result":"movedShadow"}); +var _376=this.createSVGElement("feMerge"); +var _377=this.createSVGElement("feMergeNode",{"in":"topCopy"}); +var _378=this.createSVGElement("feMergeNode",{"in":"movedShadow"}); +_376.appendChild(_377); +_376.appendChild(_378); +_372.appendChild(_373); +_372.appendChild(blur); +_372.appendChild(_375); +_372.appendChild(_376); +this.defs.appendChild(_372); +}; +PlotKit.SweetSVGRenderer.prototype._renderBarChart=function(){ +var bind=MochiKit.Base.bind; +var _379=Color.blackColor().toRGBString(); +var _380="fill:"+_379+";fill-opacity:0.15"; +var _381="stroke-width: 2.0; stroke:"+Color.whiteColor().toRGBString(); +var _382=function(_383,bar){ +var x=this.area.w*bar.x+this.area.x; +var y=this.area.h*bar.y+this.area.y; +var w=this.area.w*bar.w; +var h=this.area.h*bar.h; +if((w<1)||(h<1)){ +return; +} +_383["style"]=_381; +this._drawRect(x-2,y-1,w+4,h+2,{"style":_380}); +this._drawRect(x,y,w,h,_383); +}; +this._renderBarOrLine(this.layout.bars,bind(_382,this)); +}; +PlotKit.SweetSVGRenderer.prototype._renderLineChart=function(){ +var bind=MochiKit.Base.bind; +var _384=Color.blackColor().toRGBString(); +var _385="fill:"+_384+";fill-opacity:0.15"; +var _386="stroke-width: 2.0; stroke:"+Color.whiteColor().toRGBString(); +var _387=function(_388,_389){ +this._tempPointsBuffer+=(this.area.w*_389.x+this.area.x)+","+(this.area.h*_389.y+this.area.y)+" "; +}; +var _390=function(_391){ +this._tempPointsBuffer=""; +this._tempPointsBuffer+=(this.area.x)+","+(this.area.y+this.area.h)+" "; +}; +var _392=function(_393){ +this._tempPointsBuffer+=(this.area.w+this.area.x)+","+(this.area.h+this.area.y); +_393["points"]=this._tempPointsBuffer; +_393["stroke"]="none"; +_393["transform"]="translate(-2, -1)"; +_393["style"]=_385; +var _394=this.createSVGElement("polygon",_393); +this.root.appendChild(_394); +_393["transform"]=""; +_393["style"]=_386; +var elem=this.createSVGElement("polygon",_393); +this.root.appendChild(elem); +}; +this._renderBarOrLine(this.layout.points,bind(_387,this),bind(_390,this),bind(_392,this)); +}; +PlotKit.SweetSVGRenderer.prototype._renderPieChart=function(){ +var _395=this.area.x+this.area.w*0.5; +var _396=this.area.y+this.area.h*0.5; +var _397=Color.blackColor().toRGBString(); +var _398=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius); +var _399="fill:"+_397+";fill-opacity:0.15"; +var _400=this.createSVGElement("circle",{"style":_399,"cx":_395+1,"cy":_396+1,"r":_398+1}); +this.root.appendChild(_400); +PlotKit.SweetSVGRenderer.__super__._renderPieChart.call(this); +}; +PlotKit.SweetSVGRenderer.prototype._renderBackground=function(){ +var _401={"fill":this.options.backgroundColor.toRGBString(),"stroke":"none"}; +if(this.layout.style=="bar"||this.layout.style=="line"){ +this._drawRect(this.area.x,this.area.y,this.area.w,this.area.h,_401); +var _402=this.layout.yticks; +var _403=false; +if(this.layout.style=="bar"&&this.layout.options.barOrientation=="horizontal"){ +_402=this.layout.xticks; +_403=true; +} +for(var i=0;i<_402.length;i++){ +var x=0; +var y=0; +var w=0; +var h=0; +if(_403){ +x=_402[i][0]*this.area.w+this.area.x; +y=this.area.y; +w=1; +h=this.area.w; +}else{ +x=this.area.x; +y=_402[i][0]*this.area.h+this.area.y; +w=this.area.w; +h=1; +} +this._drawRect(x,y,w,h,{"fill":this.options.axisLineColor.toRGBString()}); +} +}else{ +PlotKit.SweetSVGRenderer.__super__._renderBackground.call(this); +} +}; +PlotKit.SweetSVG={}; +PlotKit.SweetSVG.SweetSVGRenderer=PlotKit.SweetSVGRenderer; +PlotKit.SweetSVG.EXPORT=["SweetSVGRenderer"]; +PlotKit.SweetSVG.EXPORT_OK=["SweetSVGRenderer"]; +PlotKit.SweetSVG.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.SweetSVG.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.SweetSVG); +try{ +if(typeof (PlotKit.CanvasRenderer)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "PlotKit.EasyPlot depends on all of PlotKit's components"; +} +if(typeof (PlotKit.EasyPlot)=="undefined"){ +PlotKit.EasyPlot={}; +} +PlotKit.EasyPlot.NAME="PlotKit.EasyPlot"; +PlotKit.EasyPlot.VERSION=PlotKit.VERSION; +PlotKit.EasyPlot.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +PlotKit.EasyPlot.toString=function(){ +return this.__repr__(); +}; +PlotKit.EasyPlot=function(_404,_405,_406,_407){ +this.layout=new Layout(_404,_405); +this.divElem=_406; +this.width=parseInt(_406.getAttribute("width")); +this.height=parseInt(_406.getAttribute("height")); +this.deferredCount=0; +if(this.width<1){ +this.width=this.divElem.width?this.divElem.width:300; +} +if(this.height<1){ +this.height=this.divElem.height?this.divElem.height:300; +} +if(isArrayLike(_407)){ +for(var i=0;i<_407.length;i++){ +if(typeof (_407[i])=="string"){ +this.deferredCount++; +var d=MochiKit.Async.doSimpleXMLHttpRequest(_407[i]); +d.addCallback(MochiKit.Base.bind(PlotKit.EasyPlot.onDataLoaded,this)); +}else{ +if(isArrayLike(_407[i])){ +this.layout.addDataset("data-"+i,_407[i]); +} +} +} +}else{ +if(!isUndefinedOrNull(_407)){ +throw "Passed datasources are not Array like"; +} +} +if(CanvasRenderer.isSupported()){ +this.element=CANVAS({"id":this.divElem.getAttribute("id")+"-canvas","width":this.width,"height":this.height},""); +this.divElem.appendChild(this.element); +this.renderer=new SweetCanvasRenderer(this.element,this.layout,_405); +}else{ +if(SVGRenderer.isSupported()){ +this.element=SVGRenderer.SVG({"id":this.divElem.getAttribute("id")+"-svg","width":this.width,"height":this.height,"version":"1.1","baseProfile":"full"},""); +this.divElem.appendChild(this.element); +this.renderer=new SweetSVGRenderer(this.element,this.layout,_405); +} +} +if((this.deferredCount==0)&&(PlotKit.Base.keys(this.layout.datasets).length>0)){ +this.layout.evaluate(); +this.renderer.clear(); +this.renderer.render(); +} +}; +PlotKit.EasyPlot.onDataLoaded=function(_409){ +var _410=new Array(); +var _411=_409.responseText.split("\n"); +for(var i=0;i<_411.length;i++){ +var _412=MochiKit.Format.strip(_411[i]); +if((_412.length>1)&&(_412.charAt(0)!="#")){ +_410.push(_412.split(",")); +} +} +this.layout.addDataset("data-ajax-"+this.deferredCount,_410); +this.deferredCount--; +if((this.deferredCount==0)&&(PlotKit.Base.keys(this.layout.datasets).length>0)){ +this.layout.evaluate(); +this.renderer.clear(); +this.renderer.render(); +} +}; +PlotKit.EasyPlot.prototype.reload=function(){ +this.layout.evaluate(); +this.renderer.clear(); +this.renderer.render(); +}; +PlotKit.EasyPlotModule={}; +PlotKit.EasyPlotModule.EasyPlot=PlotKit.EasyPlot; +PlotKit.EasyPlotModule.EXPORT=["EasyPlot"]; +PlotKit.EasyPlotModule.EXPORT_OK=[]; +PlotKit.EasyPlotModule.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +PlotKit.EasyPlotModule.__new__(); +MochiKit.Base._exportSymbols(this,PlotKit.EasyPlotModule); + + diff --git a/openwrt/packages/luci/host/www/luci/splash/index.html b/openwrt/packages/luci/host/www/luci/splash/index.html new file mode 100644 index 0000000..486409a --- /dev/null +++ b/openwrt/packages/luci/host/www/luci/splash/index.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/openwrt/packages/luci/i18n/english/Makefile b/openwrt/packages/luci/i18n/english/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/i18n/english/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/i18n/english/ipkg/postinst b/openwrt/packages/luci/i18n/english/ipkg/postinst new file mode 100755 index 0000000..24cf8dd --- /dev/null +++ b/openwrt/packages/luci/i18n/english/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-i18n-english ) && rm -f /etc/uci-defaults/luci-i18n-english +} diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.lua b/openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.lua new file mode 100644 index 0000000..cb2aa4e --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.lua @@ -0,0 +1,329 @@ +uci_applied = 'The following changes have been applied' +uci_reverted = 'The following changes have been reverted' +a_i_ui = 'User Interface' +c_lucidesc = 'LuCI is a collection of free Lua software including an MVC-Webframework and webinterface for embedded devices. LuCI is licensed under the Apache-License.' +c_projecthome = 'Project Homepage' +c_leaddev = 'Lead Development' +c_contributors = 'Contributing Developers' +c_thanksto = 'Thanks To' +a_i_i_hello = 'Hello!' +a_i_i_admin1 = 'This is the administration area of LuCI.' +a_i_i_admin2 = 'LuCI is a free, flexible, and user friendly graphical interface for configuring OpenWrt Kamikaze.' +a_i_i_admin3 = 'On the following pages you can adjust all important settings of your router.' +a_i_i_admin4 = 'Notice: In LuCI changes have to be confirmed by clicking Changes - Save & Apply before being applied.' +a_i_i_admin5 = 'As we always want to improve this interface we are looking forward to your feedback and suggestions.' +a_i_i_admin6 = 'And now have fun with your router!' +a_i_i_team = 'The LuCI Team' +a_i_luci1 = 'Here you can customize the settings and the functionality of LuCI.' +a_i_ucicommit = 'Post-commit actions' +a_i_ucicommit1 = 'These commands will be executed automatically when a given UCI configuration is committed allowing changes to be applied instantly.' +a_i_keepflash = 'Files to be kept when flashing a new firmware' +a_i_keepflash1 = 'When flashing a new firmware with LuCI these files will be added to the new firmware installation.' +a_st_i_status1 = 'Here you can find information about the current system status like CPU clock frequency, memory usage or network interface data.' +a_st_i_status2 = 'Also kernel or service logfiles can be viewed here to get an overview over their current state.' +iwscan = 'WLAN-Scan' +iwscan1 = 'Wifi networks in your local environment' +iwscan_encr = 'Encr.' +iwscan_link = 'Link' +iwscan_signal = 'Signal' +iwscan_noise = 'Noise' +routes = 'Routes' +routes_netmask = 'Netmask' +routes_gateway = 'Gateway' +routes_metric = 'Metric' +a_s_desc = 'Here you can configure the basic aspects of your device like its hostname or the timezone.' +a_s_packages = 'Software' +a_s_changepw = 'Admin Password' +a_s_p_ipkg = 'OPKG-Configuration' +a_s_sshkeys = 'SSH-Keys' +a_s_fstab = 'Mount Points' +a_s_flash = 'Flash Firmware' +a_s_i_system1 = 'Change settings related to the system itself, its identification, installed hard- and software, authentication or mount points.' +a_s_i_system2 = 'These settings define the base of your system.' +a_s_i_system3 = 'Pay attention as any misconfiguration here may prevent your device from booting or may lock yourself out of it.' +a_s_packages_do = 'Perform Actions' +a_s_packages_install = 'Install' +a_s_packages_installurl = 'Download and install package' +a_s_packages_ipkg = 'Edit package lists and installation targets' +a_s_packages_name = 'Package name' +a_s_packages_remove = 'Remove' +a_s_packages_search = 'Find package' +a_s_packages_update = 'Package lists updated' +a_s_packages_updatelist = 'Update package lists' +a_s_packages_upgrade = 'Upgrade installed packages' +a_s_p_ipkg_pkglists = 'Package lists' +a_s_p_ipkg_targets = 'Installation targets' +a_s_changepw1 = 'Change the password of the system administrator (User root)' +a_s_changepw_changed = 'Password successfully changed' +a_s_changepw_nomatch = 'Error: Passwords do not match' +a_s_sshkeys1 = 'Here you can paste public SSH-Keys (one per line) for SSH public-key authentication.' +a_s_fstab_mountpoints = 'Mount Points' +a_s_fstab_mountpoints1 = 'Mount Points define at which point a memory device will be attached to the filesystem' +a_s_fstab_active = 'Mounted file systems' +a_s_fstab_used = 'Used' +a_s_fstab_avail = 'Available' +a_s_fstab_mountpoint = 'Mount Point' +a_s_fstab_device1 = 'The device file of the memory or partition (e.g. /dev/sda1)' +a_s_fstab_fs1 = 'The filesystem that was used to format the memory (e.g. ext3)' +a_s_fstab_swap1 = 'If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable RAM. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the RAM.' +a_s_flash_flashed = 'Firmware successfully flashed. Rebooting device...' +a_s_flash_flasherr = 'Failed to flash' +a_s_flash_fwimage = 'Firmware image' +a_s_flash_received = 'Image received. About to start flashing process. DO NOT POWER OFF THE DEVICE!' +a_s_flash_inprogress = 'Writing firmware...' +a_s_flash_fwupgrade = 'Flash Firmware' +a_s_flash_keepcfg = 'Keep configuration files' +a_s_flash_notimplemented = 'Sorry, this function is not (yet) available for your platform.' +a_s_flash_upgrade1 = 'Replaces the installed firmware with a new one. The firmware format is platform-dependent.' +a_s_reboot1 = 'Reboots the operating system of your device' +a_s_reboot_do = 'Perform reboot' +a_s_reboot_running = 'Please wait: Device rebooting...' +a_s_reboot_u = 'Warning: There are unsaved changes that will be lost while rebooting!' +a_s_applyreboot1 = 'Changes applied.' +a_s_backup = 'Backup / Restore' +a_s_backup_backup = 'Create backup' +a_s_backup_archive = 'Backup Archive' +a_s_backup_reset = 'Reset router to defaults' +a_s_backup_reset1 = 'Proceed reverting all settings and resetting to firmware defaults?' +a_s_backup_restore = 'Restore backup' +a_s_backup1 = 'Here you can backup and restore your router configuration and - if possible - reset the router to the default settings.' +a_srv_http = 'HTTP-Server' +a_srv_ssh = 'SSH-Server' +a_srv_services1 = 'Services and daemons perform certain tasks on your device.' +a_srv_services2 = 'Most of them are network servers, that offer a certain service for your device or network like shell access, serving webpages like LuCI, doing mesh routing, sending e-mails, ...' +a_srv_http1 = 'A small webserver which can be used to serve LuCI.' +a_srv_http_authrealm = 'Authentication Realm' +a_srv_http_authrealm1 = 'The realm which will be displayed at the authentication prompt for protected pages.' +a_srv_http_config1 = 'defaults to /etc/httpd.conf' +a_srv_http_root = 'Document root' +a_srv_dropbear1 = 'Dropbear offers SSH network shell access and an integrated SCP server' +a_srv_d_pwauth = 'Password authentication' +a_srv_d_pwauth1 = 'Allow SSH password authentication' +a_w_channel = 'Channel' +a_w_wifi1 = 'On this pages you can find configuration options for WLAN based wireless networks.' +a_w_wifi2 = 'You can easily integrate your 802.11a/b/g/n-devices into your physical network and use the virtual adapter support to build wireless repeaters or offer several networks with one device.' +a_w_wifi3 = 'There is support for Managed, Client, Ad-Hoc and WDS operating modes as well as WPA and WPA2 encryption for secure communnication.' +a_w_devices1 = 'Here you can configure installed wifi devices.' +a_w_txantenna = 'Transmit Antenna' +a_w_rxantenna = 'Receive Antenna' +a_w_distance1 = 'Distance to furthest station (in meter)' +a_w_diversity = 'Diversity' +a_w_countrycode = 'Country Code' +a_w_connlimit = 'Connection Limit' +a_w_networks1 = 'You can run several wifi networks with one device. Be aware that there are certain hardware and driverspecific restrictions. Normally you can operate 1 Ad-Hoc or up to 3 Master-Mode and 1 Client-Mode network simultaneously.' +a_w_netid = 'Network Name (ESSID)' +a_w_network1 = 'Add the Wifi network to physical network' +a_w_netmanual = ' - Create new Network - ' +a_w_txpwr = 'Transmit Power' +a_w_brcmburst = 'Broadcom Frameburst' +a_w_athburst = 'Atheros Frameburst' +a_w_radiussrv = 'RadiusServer' +a_w_radiusport = 'Radius-Port' +a_w_apisolation = 'AP-Isolation' +a_w_apisolation1 = 'Prevents Client to Client communication' +a_w_hideessid = 'Hide ESSID' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq is a combined DHCP-Server and DNS-Forwarder for NAT firewalls' +dhcp_dnsmasq_domainneeded = 'Domain required' +dhcp_dnsmasq_domainneeded_desc = 'Don't forward DNS-Requests without DNS-Name' +dhcp_dnsmasq_authoritative = 'Authoritative' +dhcp_dnsmasq_authoritative_desc = 'This is the only DHCP in the local network' +dhcp_dnsmasq_boguspriv = 'Filter private' +dhcp_dnsmasq_boguspriv_desc = 'Don't forward reverse lookups for local networks' +dhcp_dnsmasq_filterwin2k = 'Filter useless' +dhcp_dnsmasq_filterwin2k_desc = 'filter useless DNS-queries of Windows-systems' +dhcp_dnsmasq_localisequeries = 'Localise queries' +dhcp_dnsmasq_localisequeries_desc = 'localises the hostname depending on its subnet' +dhcp_dnsmasq_local = 'Local Server' +dhcp_dnsmasq_domain = 'Local Domain' +dhcp_dnsmasq_expandhosts = 'Expand Hosts' +dhcp_dnsmasq_expandhosts_desc = 'adds domain names to hostentries in the resolv file' +dhcp_dnsmasq_nonegcache = 'don't cache unknown' +dhcp_dnsmasq_nonegcache_desc = 'prevents caching of negative DNS-replies' +dhcp_dnsmasq_readethers = 'Use /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Read /etc/ethers to configure the DHCP-Server' +dhcp_dnsmasq_leasefile = 'Leasefile' +dhcp_dnsmasq_leasefile_desc = 'file where given DHCP-leases will be stored' +dhcp_dnsmasq_resolvfile = 'Resolvfile' +dhcp_dnsmasq_resolvfile_desc = 'local DNS file' +dhcp_dnsmasq_nohosts = 'Ignore /etc/hosts' +dhcp_dnsmasq_strictorder = 'Strict order' +dhcp_dnsmasq_strictorder_desc = 'DNS-Server will be queried in the order of the resolvfile' +dhcp_dnsmasq_logqueries = 'Log queries' +dhcp_dnsmasq_noresolv = 'Ignore resolve file' +dhcp_dnsmasq_dnsforwardmax = 'concurrent queries' +dhcp_dnsmasq_port = 'DNS-Port' +dhcp_dnsmasq_ednspacket_max = 'max. EDNS0 paket size' +dhcp_dnsmasq_dhcpleasemax = 'max. DHCP-Leases' +dhcp_dnsmasq_addnhosts = 'additional hostfile' +dhcp_dnsmasq_queryport = 'query port' +dhcp_dnsmasq_enabletftp = 'Enable TFTP-Server' +dhcp_dnsmasq_tftproot = 'TFTP-Server Root' +dhcp_dnsmasq_dhcpboot = 'Network Boot Image' +a_n_switch = 'Switch' +a_n_conntrack = 'Active Connections' +a_n_conntrack_desc = 'This page gives an overview over currently active network connections.' +a_n_routes = 'Routes' +a_n_routes4 = 'IPv4 Routes' +a_n_routes6 = 'IPv6 Routes' +a_network1 = 'In this area you find all network-related settings.' +a_network2 = 'On most routers the network switch can be freely configured and splitted up into several VLANs.' +a_network3 = 'Interfaces and PPPoE / PPTP-Settings allow a custom organisation of the network and connections to other networks like the internet.' +a_network4 = 'With DHCP devices in your local network can be automatically configured for network communication.' +a_network5 = 'Firewall and portforwarding can be used to secure your network while providing services to external networks.' +a_n_switch1 = 'The network ports on your router can be combined to several VLANs in which computers can communicate directly with each other. VLANs are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network.' +network_switch_desc = 'Ports belonging to a VLAN are separated with spaces. The port with the highest number (usually 5) is oftern the connection to the internal network interface of the router. On devices with 5 ports often the one with the lowest number (0) is the predefined Uplink port.' +a_n_ifaces1 = 'On this page you can configure the network interfaces. You can bridge several interfaces by ticking the "bridge interfaces" field and enter the names of several network interfaces separated by spaces. You can also use VLAN notation INTERFACE.VLANNR (e.g.: eth0.1).' +a_n_i_bridge = 'Bridge interfaces' +a_n_i_bridge1 = 'creates a bridge over specified interface(s)' +dhcp_desc = 'With DHCP network members can automatically receive their network settings (IP-address, netmask, DNS-server, ...).' +dhcp_dhcp_leasetime = 'Leasetime' +dhcp_dhcp_dynamicdhcp = 'Dynamic DHCP' +dhcp_dhcp_ignore = 'Ignore interface' +dhcp_dhcp_ignore_desc = 'disable DHCP for this interface' +dhcp_dhcp_force = 'Force' +dhcp_dhcp_start_desc = 'first address (last octet)' +dhcp_dhcp_limit_desc = 'number of leased addresses -1' +dhcp_dhcp_dhcpoption = 'DHCP-Options' +dhcp_dhcp_dhcpoption_desc = 'See "dnsmasq --help dhcp" for a list of available options.' +dhcp_leases = 'Leases' +luci_ethers = 'Static Leases' +dhcp_timeremain = 'Leasetime remaining' +dhcp_leases_active = 'Active Leases' +a_n_ptp = 'Point-to-Point Connections' +a_n_ptp1 = 'Point-to-Point connections with PPPoE or PPTP are often used to connect a device over DSL or similar technologies to an internet access point.' +network_interface_prereq = 'You need to install "comgt" for UMTS/GPRS, "ppp-mod-pppoe" for PPPoE, "ppp-mod-pppoa" for PPPoA or "pptp" for PPtP support' +network_interface_prereq_mini = 'You need to install "ppp-mod-pppoe" for PPPoE or "pptp" for PPtP support' +network_interface_server = 'PPTP-Server' +network_interface_demand = 'Automatic Disconnect' +network_interface_demand_desc = 'Time (in seconds) after which an unused connection will be closed' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'Number of failed connection tests to initiate automatic reconnect' +network_interface_device = 'Modem device' +network_interface_device_desc = 'The device node of your modem, e.g. /dev/ttyUSB0' +network_interface_defaultroute = 'Replace default route' +network_interface_defaultroute_desc = 'Let pppd replace the current default route to use the PPP interface after successful connect' +network_interface_peerdns = 'Use peer DNS' +network_interface_peerdns_desc = 'Configure the local DNS server to use the name servers adverticed by the PPP peer' +network_interface_ipv6 = 'Enable IPv6 on PPP link' +network_interface_connect = 'Connect script' +network_interface_connect_desc = 'Let pppd run this script after establishing the PPP link' +network_interface_disconnect = 'Disconnect script' +network_interface_disconnect_desc = 'Let pppd run this script before tearing down the PPP link' +network_interface_pppd_options = 'Additional pppd options' +network_interface_pppd_options_desc = 'Specify additional command line arguments for pppd here' +network_interface_apn = 'Access point (APN)' +network_interface_pincode = 'PIN code' +network_interface_pincode_desc = 'Make sure that you provide the correct pin code here or you might lock your sim card!' +network_interface_service = 'Service type' +network_interface_maxwait = 'Setup wait time' +network_interface_maxwait_desc = 'Seconds to wait for the modem to become ready before attempting to connect' +network_interface_encaps = 'PPPoA Encapsulation' + +a_n_r_routes1 = 'Routes specify over which interface and gateway a certain host or network can be reached.' +a_n_routes_static = 'Static Routes' +a_n_routes_static4 = 'Static IPv4 Routes' +a_n_routes_static6 = 'Static IPv6 Routes' +a_n_routes_kernel4 = 'Active IPv4-Routes' +a_n_routes_kernel6 = 'Active IPv6-Routes' +a_n_r_target1 = 'Host-IP or Network' +a_n_r_target6 = 'IPv6-Address or Network (CIDR)' +a_n_r_netmask1 = 'if target is a network' +m_n_inet = 'Internet Connection' +m_n_local = 'Local Network' +m_n_route = 'Route' +m_n_brdige = 'Bridge' +m_w_ap = 'Provide (Access Point)' +m_w_adhoc = 'Independent (Ad-Hoc)' +m_w_client = 'Join (Client)' +m_w_wds = 'Distributed (WDS)' +m_w_clientmode = 'Clientmode' +system_system_logsize = 'System log buffer size' +system_system_logip = 'External system log server' +system_system_conloglevel = 'Log output level' +system_system_conloglevel_desc = 'Level of log messages on the console' +m_i_processor = 'Processor' +m_i_memory = 'Memory' +m_i_systemtime = 'Local Time' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'First leased address' +m_n_d_numleases = 'Number of leased addresses' +routingtable = 'Routing table' +wlanscan = 'Wifi scan' +frequency = 'Frequency' +power = 'Power' +noise = 'Noise' +signal = 'Signal' +link = 'Link' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Bitrate' +m_n_keepalive = 'automatically reconnect' +m_n_dialondemand = 'disconnect when idle for' +m_n_pptp_server = 'PPTP-Server' +leds = 'LED Configuration' +leds_desc = 'Customizes the behaviour of the device LEDs if possible.' +system_led_name = 'LED Name' +system_led_sysfs = 'LED Device' +system_led_default = 'Default state' +system_led_default_desc = 'ticked = on' +system_led_trigger = 'Trigger' +system_led_trigger_none = 'None' +system_led_trigger_defaulton = 'Default On' +system_led_trigger_timer = 'Timer' +system_led_trigger_heartbeat = 'Heartbeat (Load Average)' +system_led_trigger_netdev = 'Network Device' +system_led_delayoff = 'Off-State Delay' +system_led_delayoff_desc = 'Time (in ms) the LED is off' +system_led_delayon = 'On-State Delay' +system_led_delayon_desc = 'Time (in ms) the LED is on' +system_led_dev = 'Device' +system_led_mode = 'Trigger Mode' +system_led_mode_link = 'Link On' +system_led_mode_tx = 'Transmit' +system_led_mode_rx = 'Receive' +network_interface_up = 'Active' +network_interface_hwaddr = 'MAC-Address' +network_interface_hwaddr_desc = 'Hardware Address' +network_interface_txrx = 'Traffic' +network_interface_txrx_desc = 'transmitted / received' +network_interface_err = 'Errors' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Create / Assign firewall-zone' +network_interface_fwzone_desc = 'This interface does not belong to any firewall zone yet.' +process_head = 'Processes' +process_descr = 'This list gives an overview over currently running system processes and their status.' +process_pid = 'PID' +process_owner = 'Owner' +process_command = 'Command' +process_cpu = 'CPU usage (%)' +process_mem = 'Memory usage (%)' +process_hup = 'Hang Up' +process_term = 'Terminate' +process_kill = 'Kill' +mem_cached = 'cached' +mem_buffered = 'buffered' +mem_free = 'free' +a_s_crontab = 'Scheduled Tasks' +a_s_crontab1 = 'This is the system crontab in which scheduled tasks can be defined.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Path to CA-Certificate' +a_w_eaptype = 'EAP-Method' +a_w_tlsprivkey = 'Path to Private Key' +a_w_tlsprivkeypwd = 'Password of Private Key' +a_w_peapauth = 'PEAP-Authentication' +a_w_peapidentity = 'PEAP-Identity' +a_w_peappassword = 'PEAP-Password' +a_w_create = 'Create Network' +hostnames = 'Hostnames' +hostnames_entries = 'Host entries' +hostnames_hostname = 'Hostname' +hostnames_address = 'IP address' +luci_components = "LuCI Components" +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.xml b/openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.xml new file mode 100644 index 0000000..23ab06e --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/admin-core.en.xml @@ -0,0 +1,334 @@ + + + + +The following changes have been applied +The following changes have been reverted +User Interface +LuCI is a collection of free Lua software including an MVC-Webframework and webinterface for embedded devices. LuCI is licensed under the Apache-License. +Project Homepage +Lead Development +Contributing Developers +Thanks To +Hello! +This is the administration area of LuCI. +LuCI is a free, flexible, and user friendly graphical interface for configuring OpenWrt Kamikaze. +On the following pages you can adjust all important settings of your router. +Notice: In LuCI changes have to be confirmed by clicking Changes - Save & Apply before being applied. +As we are always want to improve this interface we are looking forward to your feedback and suggestions. +And now have fun with your router! +The LuCI Team +Here you can customize the settings and the functionality of LuCI. +Post-commit actions +These commands will be executed automatically when a given UCI configuration is committed allowing changes to be applied instantly. +Files to be kept when flashing a new firmware +When flashing a new firmware with LuCI these files will be added to the new firmware installation. +Here you can find information about the current system status like CPU clock frequency, memory usage or network interface data. +Also kernel or service logfiles can be viewed here to get an overview over their current state. +WLAN-Scan +Wifi networks in your local environment +Encr. +Link +Signal +Noise +Routes +Netmask +Gateway +Metric +Here you can configure the basic aspects of your device like its hostname or the timezone. +Software +Admin Password +OPKG-Configuration +SSH-Keys +Mount Points +Flash Firmware +Change settings related to the system itself, its identification, installed hard- and software, authentication or mount points. +These settings define the base of your system. +Pay attention as any misconfiguration here may prevent your device from booting or may lock yourself out of it. +Perform Actions +Install +Download and install package +Edit package lists and installation targets +Package name +Remove +Find package +Package lists updated +Update package lists +Upgrade installed packages +Package lists +Installation targets +Change the password of the system administrator (User root) +Password successfully changed +Error: Passwords do not match +Here you can paste public SSH-Keys (one per line) for SSH public-key authentication. +Mount Points +Mount Points define at which point a memory device will be attached to the filesystem +Mounted file systems +Used +Available +Mount Point +The device file of the memory or partition (e.g. /dev/sda1) +The filesystem that was used to format the memory (e.g. ext3) +If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable RAM. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the RAM. +Firmware successfully flashed. Rebooting device... +Failed to flash +Firmware image +Image received. About to start flashing process. DO NOT POWER OFF THE DEVICE! +Writing firmware... +Flash Firmware +Keep configuration files +Sorry, this function is not (yet) available for your platform. +Replaces the installed firmware with a new one. The firmware format is platform-dependent. +Reboots the operating system of your device +Perform reboot +Please wait: Device rebooting... +Warning: There are unsaved changes that will be lost while rebooting! +Changes applied. +Backup / Restore +Create backup +Backup Archive +Reset router to defaults +Proceed reverting all settings and resetting to firmware defaults? +Restore backup +Here you can backup and restore your router configuration and - if possible - reset the router to the default settings. +HTTP-Server +SSH-Server +Services and daemons perform certain tasks on your device. +Most of them are network servers, that offer a certain service for your device or network like shell access, serving webpages like LuCI, doing mesh routing, sending e-mails, ... +A small webserver which can be used to serve LuCI. +Authentication Realm +The realm which will be displayed at the authentication prompt for protected pages. +defaults to /etc/httpd.conf +Document root +Dropbear offers SSH network shell access and an integrated SCP server +Password authentication +Allow SSH password authentication +Channel +On this pages you can find configuration options for WLAN based wireless networks. +You can easily integrate your 802.11a/b/g/n-devices into your physical network and use the virtual adapter support to build wireless repeaters or offer several networks with one device. +There is support for Managed, Client, Ad-Hoc and WDS operating modes as well as WPA and WPA2 encryption for secure communnication. +Here you can configure installed wifi devices. +Transmit Antenna +Receive Antenna +Distance to furthest station (in meter) +Diversity +Country Code +Connection Limit +You can run several wifi networks with one device. Be aware that there are certain hardware and driverspecific restrictions. Normally you can operate 1 Ad-Hoc or up to 3 Master-Mode and 1 Client-Mode network simultaneously. +Network Name (ESSID) +Add the Wifi network to physical network + - Create new Network - +Transmit Power +Broadcom Frameburst +Atheros Frameburst +RadiusServer +Radius-Port +AP-Isolation +Prevents Client to Client communication +Hide ESSID +Access Point +Ad-Hoc +Pseudo Ad-Hoc (ahdemo) +Client +WDS +Monitor +Dnsmasq is a combined DHCP-Server and DNS-Forwarder for NAT firewalls +Domain required +Don't forward DNS-Requests without DNS-Name +Authoritative +This is the only DHCP in the local network +Filter private +Don't forward reverse lookups for local networks +Filter useless +filter useless DNS-queries of Windows-systems +Localise queries +localises the hostname depending on its subnet +Local Server +Local Domain +Expand Hosts +adds domain names to hostentries in the resolv file +don't cache unknown +prevents caching of negative DNS-replies +Use /etc/ethers +Read /etc/ethers to configure the DHCP-Server +Leasefile +file where given DHCP-leases will be stored +Resolvfile +local DNS file +Ignore /etc/hosts +Strict order +DNS-Server will be queried in the order of the resolvfile +Log queries +Ignore resolve file +concurrent queries +DNS-Port +max. EDNS0 paket size +max. DHCP-Leases +additional hostfile +query port +Enable TFTP-Server +TFTP-Server Root +Network Boot Image +Switch +Active Connections +This page gives an overview over currently active network connections. +Routes +IPv4 Routes +IPv6 Routes +In this area you find all network-related settings. +On most routers the network switch can be freely configured and splitted up into several VLANs. +Interfaces and PPPoE / PPTP-Settings allow a custom organisation of the network and connections to other networks like the internet. +With DHCP devices in your local network can be automatically configured for network communication. +Firewall and portforwarding can be used to secure your network while providing services to external networks. +The network ports on your router can be combined to several VLANs in which computers can communicate directly with each other. VLANs are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network. +Ports belonging to a VLAN are separated with spaces. The port with the highest number (usually 5) is oftern the connection to the internal network interface of the router. On devices with 5 ports often the one with the lowest number (0) is the predefined Uplink port. +On this page you can configure the network interfaces. You can bridge several interfaces by ticking the "bridge interfaces" field and enter the names of several network interfaces separated by spaces. You can also use VLAN notation INTERFACE.VLANNR (e.g.: eth0.1). +Bridge interfaces +creates a bridge over specified interface(s) +With DHCP network members can automatically receive their network settings (IP-address, netmask, DNS-server, ...). +Leasetime +Dynamic DHCP +Ignore interface +disable DHCP for this interface +Force +first address (last octet) +number of leased addresses -1 +DHCP-Options +See "dnsmasq --help dhcp" for a list of available options. +Leases +Static Leases +Leasetime remaining +Active Leases +Point-to-Point Connections +Point-to-Point connections with PPPoE or PPTP are often used to connect a device over DSL or similar technologies to an internet access point. +You need to install "comgt" for UMTS/GPRS, "ppp-mod-pppoe" for PPPoE, "ppp-mod-pppoa" for PPPoA or "pptp" for PPtP support +You need to install "ppp-mod-pppoe" for PPPoE or "pptp" for PPtP support +PPTP-Server +Automatic Disconnect +Time (in seconds) after which an unused connection will be closed +Keep-Alive +Number of failed connection tests to initiate automatic reconnect +Modem device +The device node of your modem, e.g. /dev/ttyUSB0 +Replace default route +Let pppd replace the current default route to use the PPP interface after successful connect +Use peer DNS +Configure the local DNS server to use the name servers adverticed by the PPP peer +Enable IPv6 on PPP link +Connect script +Let pppd run this script after establishing the PPP link +Disconnect script +Let pppd run this script before tearing down the PPP link +Additional pppd options +Specify additional command line arguments for pppd here +Access point (APN) +PIN code +Make sure that you provide the correct pin code here or you might lock your sim card! +Service type +Setup wait time +Seconds to wait for the modem to become ready before attempting to connect +PPPoA Encapsulation + + +Routes specify over which interface and gateway a certain host or network can be reached. +Static Routes +Static IPv4 Routes +Static IPv6 Routes +Active IPv4-Routes +Active IPv6-Routes +Host-IP or Network +IPv6-Address or Network (CIDR) +if target is a network +Internet Connection +Local Network +Route +Bridge +Provide (Access Point) +Independent (Ad-Hoc) +Join (Client) +Distributed (WDS) +Clientmode +System log buffer size +External system log server +Log output level +Level of log messages on the console +Processor +Memory +Local Time +Uptime +First leased address +Number of leased addresses +Routing table +Wifi scan +Frequency +Power +Noise +Signal +Link +Frag. +RTS +Bitrate +automatically reconnect +disconnect when idle for +PPTP-Server +LED Configuration +Customizes the behaviour of the device LEDs if possible. +LED Name +LED Device +Default state +ticked = on +Trigger +None +Default On +Timer +Heartbeat (Load Average) +Network Device +Off-State Delay +Time (in ms) the LED is off +On-State Delay +Time (in ms) the LED is on +Device +Trigger Mode +Link On +Transmit +Receive +Active +MAC-Address +Hardware Address +Traffic +transmitted / received +Errors +TX / RX +Create / Assign firewall-zone +This interface does not belong to any firewall zone yet. +Processes +This list gives an overview over currently running system processes and their status. +PID +Owner +Command +CPU usage (%) +Memory usage (%) +Hang Up +Terminate +Kill +cached +buffered +free +Scheduled Tasks +This is the system crontab in which scheduled tasks can be defined. +NAS ID +Path to CA-Certificate +EAP-Method +Path to Private Key +Password of Private Key +PEAP-Authentication +PEAP-Identity +PEAP-Password +Create Network +Hostnames +Host entries +Hostname +IP address +Clamp Segment Size +Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs. + diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.lua b/openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.lua new file mode 100644 index 0000000..7e5ae15 --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.lua @@ -0,0 +1,17 @@ +cbi_add = 'Add entry' +cbi_del = 'Remove entry' +cbi_replace = 'Replace entry' +cbi_invalid = 'Invalid input value' +cbi_invalid_section = 'Validation failed: Please check any input fields for mistakes.' +cbi_missing = 'This field is mandatory' +cbi_deperror = 'Validation failed: At least one mandatory field has no or an invalid value' +cbi_reqerror = 'A requirement for this option was not met' +cbi_addopt = '-- Additional Field --' +cbi_optional = ' (optional)' +cbi_sectempty = 'This section contains no values yet' +cbi_manual = '-- custom --' +cbi_select = '-- Please choose --' +cbi_gorel = 'Go to relevant configuration page' +cbi_applying = 'Applying changes' +cbi_upload = 'Uploaded File' +cbi_browser = 'Search file...' diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.xml b/openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.xml new file mode 100644 index 0000000..40f5f54 --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/cbi.en.xml @@ -0,0 +1,23 @@ + + + + +Add entry +Remove entry +Replace entry +Invalid input value +Validation failed: Please check any input fields for mistakes. +This field is mandatory +Validation failed: At least one mandatory field has no or an invalid value +A requirement for this option was not met +-- Additional Field -- + (optional) +This section contains no values yet +-- custom -- +-- Please choose -- +Go to relevant configuration page +Applying changes +Uploaded File +Search file... + + diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.lua b/openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.lua new file mode 100644 index 0000000..d923a88 --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.lua @@ -0,0 +1,102 @@ +skiplink1 = 'Skip to navigation' +skiplink2 = 'Skip to content' +navigation = 'Navigation' +about = 'About' +add = 'Add' +addresses = 'Addresses' +aliases = 'Aliases' +all = 'all' +back = 'back' +administration = 'Administration' +essentials = 'Essentials' +apply = 'Apply' +basicsettings = 'Basic Settings' +broadcast = 'IPv4-Broadcast' +changes = 'Changes' +channel = 'Channel' +cidr6 = 'CIDR-Notation: address/prefix' +code = 'Code' +config = 'Configuration' +configfile = 'Configuration file' +confirmation = 'Confirmation' +delete = 'Delete' +descr = 'Description' +design = 'Design' +destination = 'Destination' +device = 'Device' +devices = 'Devices' +disable = 'disable' +distance = 'Distance' +dmesg = 'Kernel Log' +dnsserver = 'DNS-Server' +edit = 'Edit' +enable = 'enable' +encryption = 'Encryption' +error = 'Error' +filesystem = 'Filesystem' +filter = 'Filter' +gateway = 'IPv4-Gateway' +gateway6 = 'IPv6-Gateway' +general = 'General' +hostname = 'Hostname' +install = 'Install' +installed = 'installed' +interface = 'Interface' +interfaces = 'Interfaces' +ipaddress = 'IPv4-Address' +ip6address = 'IPv6-Address' +legend = 'Legend' +library = 'Library' +logout = 'Logout' +key = 'Key' +language = 'Language' +limit = 'Limit' +load = 'Load' +login = 'Login' +macaddress = 'MAC-Address' +manpage = 'see '%s' manpage' +metric = 'Metric' +mode = 'Mode' +name = 'Name' +netmask = 'IPv4-Netmask' +network = 'Network' +networks = 'Networks' +none = 'none' +notinstalled = 'not installed' +ok = 'OK' +options = 'Options' +overview = 'Overview' +packagemanager = 'Package Manager' +password = 'Password' +path = 'Path' +port = 'Port' +ports = 'Ports' +protocol = 'Protocol' +reboot = 'Reboot' +reset = 'Reset' +revert = 'Revert' +save = 'Save' +saveapply = 'Save & Apply' +scan = 'Scan' +service = 'Service' +services = 'Services' +settings = 'Settings' +size = 'Size' +source = 'Source' +start = 'Start' +static = 'static' +status = 'Status' +statistics = 'Statistics' +submit = 'Submit' +syslog = 'System Log' +system = 'System' +target = 'Target' +timezone = 'Timezone' +type = 'Type' +unknownerror = 'Unknown Error' +unsavedchanges = 'Unsaved Changes' +username = 'Username' +version = 'Version' +webui = 'Web UI' +wifi = 'Wifi' +zone = 'Zone' diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.xml b/openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.xml new file mode 100644 index 0000000..e499dbb --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/default.en.xml @@ -0,0 +1,109 @@ + + + + +Skip to navigation +Skip to content +Navigation + +About +Add +Addresses +Aliases +all +back +Administration +Essentials +Apply +Basic Settings +IPv4-Broadcast +Changes +Channel +CIDR-Notation: address/prefix +Code +Configuration +Configuration file +Confirmation +Delete +Description +Design +Destination +Device +Devices +disable +Distance +Kernel Log +DNS-Server +Edit +enable +Encryption +Error +Filesystem +Filter +IPv4-Gateway +IPv6-Gateway +General +Hostname +Install +installed +Interface +Interfaces +IPv4-Address +IPv6-Address +Legend +Library +Logout +Key +Language +Limit +Load +Login +MAC-Address +see '%s' manpage +Metric +Mode +Name +IPv4-Netmask +Network +Networks +none +not installed +OK +Options +Overview +Package Manager +Password +Path +Port +Ports +Protocol +Reboot +Reset +Revert +Save +Save & Apply +Scan +Service +Services +Settings +Size +Source +Start +static +Status +Statistics +Submit +System Log +System +Target +Timezone +Type +Unknown Error +Unsaved Changes +Username +Version +Web UI +Wifi +Zone + + diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.lua b/openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.lua new file mode 100644 index 0000000..2a8759f --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Authorization Required' +sysauth_prompt = 'Please enter your username and password.' +sysauth_failed = 'Invalid username and/or password! Please try again.' diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.xml b/openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.xml new file mode 100644 index 0000000..f62eeeb --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/sysauth.en.xml @@ -0,0 +1,9 @@ + + + + +Authorization Required +Please enter your username and password. +Invalid username and/or password! Please try again. + + diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.lua b/openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.lua new file mode 100644 index 0000000..4fb286c --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.lua @@ -0,0 +1,38 @@ +wifi_auto = 'auto' +wifi_fh = 'Frequency Hopping' +wifi_diversity = 'Diversity' +wifi_txantenna = 'Transmitter Antenna' +wifi_rxantenna = 'Receiver Antenna' +wifi_distance = 'Distance Optimization' +wifi_distance_desc = 'Distance to farthest network member in meters.' +wifi_macpolicy = 'MAC-Address Filter' +wifi_whitelist = 'Allow listed only' +wifi_blacklist = 'Allow all except listed' +wifi_maclist = 'MAC-List' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Country Code' +wifi_maxassoc = 'Connection Limit' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Fragmentation Threshold' +wifi_rts = 'RTS/CTS Threshold' +wifi_wds = 'WDS' +wifi_wdssep = 'Separate WDS' +wifi_hidden = 'Hide ESSID' +wifi_isloate = 'Isolate Clients' +wifi_isloate_desc = 'Prevent Client to Client Communication' +wifi_bgscan = 'Background Scan' +wifi_rate = 'Transmission Rate' +wifi_mcast_rate = 'Multicast Rate' +wifi_minrate = 'Minimum Rate' +wifi_maxrate = 'Maximum Rate' +wifi_compression = 'Compression' +wifi_turbo = 'Turbo Mode' +wifi_ff = 'Fast Frames' +wifi_wmm = 'WMM Mode' +wifi_xr = 'XR Support' +wifi_ar = 'AR Support' +wifi_nosbeacon = 'Disable HW-Beacon timer' +wifi_noprobereq = 'Do not send probe responses' +wifi_wpareq = 'WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP and ad-hoc mode) to be installed.' +wifi_keyreq = '40bit/104bit WEP is autodetected based on key length. Use either 5/13 ASCII or 10/26 HEX characters as WEP key. A valid ASCII-based key will be translated into a HEX-based one. WPA(2)-PSK keys should be 64 HEX characters.' diff --git a/openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.xml b/openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.xml new file mode 100644 index 0000000..fd6751f --- /dev/null +++ b/openwrt/packages/luci/i18n/english/luasrc/i18n/wifi.en.xml @@ -0,0 +1,44 @@ + + + + +auto +Frequency Hopping +Diversity +Transmitter Antenna +Receiver Antenna +Distance Optimization +Distance to farthest network member in meters. +MAC-Address Filter +Allow listed only +Allow all except listed +MAC-List +Frame Bursting +Country Code +Connection Limit +ESSID +BSSID +Fragmentation Threshold +RTS/CTS Threshold +WDS +Separate WDS +Hide ESSID +Isolate Clients +Prevent Client to Client Communication +Background Scan +Transmission Rate +Multicast Rate +Minimum Rate +Maximum Rate +Compression +Turbo Mode +Fast Frames +WMM Mode +XR Support +AR Support +Disable HW-Beacon timer +Don not send probe responses + +WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP and ad-hoc mode) to be installed. + + diff --git a/openwrt/packages/luci/i18n/english/root/etc/uci-defaults/luci-i18n-english b/openwrt/packages/luci/i18n/english/root/etc/uci-defaults/luci-i18n-english new file mode 100755 index 0000000..506d6ef --- /dev/null +++ b/openwrt/packages/luci/i18n/english/root/etc/uci-defaults/luci-i18n-english @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.languages.en=English + commit luci +EOF + diff --git a/openwrt/packages/luci/i18n/french/Makefile b/openwrt/packages/luci/i18n/french/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/i18n/french/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/i18n/french/ipkg/postinst b/openwrt/packages/luci/i18n/french/ipkg/postinst new file mode 100755 index 0000000..e220e4d --- /dev/null +++ b/openwrt/packages/luci/i18n/french/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-i18n-french ) && rm -f /etc/uci-defaults/luci-i18n-french +} diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.lua b/openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.lua new file mode 100644 index 0000000..a4789a0 --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.lua @@ -0,0 +1,327 @@ +uci_applied = 'Les changements suivants ont été appliqués' +uci_reverted = 'Les changements suivants ont été annulés' +a_i_ui = 'Interface utilisateur' +c_lucidesc = 'LuCI est une suite logicielle d'applications Lua software incluant un MVC-Webframework et une interface web pour équipements embarqués. Luci est sous license Apache.' +c_projecthome = 'Page d'accueil du projet' +c_leaddev = 'Développeurs principaux' +c_contributors = 'Contributeurs' +c_thanksto = 'Merci à' +a_i_i_hello = 'Bonjour !' +a_i_i_admin1 = 'Voici la page d'administration de LuCI.' +a_i_i_admin2 = 'LuCI est une interface graphique libre, flexible, et user friendly pour configurer OpenWrt Kamikaze.' +a_i_i_admin3 = 'Dans les pages suivantes vous pouvez ajuster tous les réglages importants de votre routeur.' +a_i_i_admin4 = 'Vous trouverez une page de navigation sur le côté gauche permettant d'accèder aux différentes pages de configuration.' +a_i_i_admin5 = 'Nous souhaitons améliorer l'interface de manière permanente, vos retours et suggestions sont primordiaux.' +a_i_i_admin6 = 'Et maintenant que la fête commence !' +a_i_i_team = 'L'équipe LuCI' +a_i_luci1 = 'Ici, vous pouvez personnaliser les réglages et les fonctionnalités de LuCI.' +a_i_ucicommit = 'Actions post-changements' +a_i_ucicommit1 = 'Ces commandes seront executées automatiquement lorsqu'une configuration UCI est appliquée, les changement prenant effet immédiatement.' +a_i_keepflash = 'Fichiers à conserver lors d'une mise à jour du firmware' +a_i_keepflash1 = 'Lors d'une nouvelle installation, ces fichiers seront ajoutés à la nouvelle installation.' +a_st_i_status1 = 'Ici, vous trouverez des informations sur l'état actuel du système comme la fréquence processeur, utilisation mémoire et trafic réseau.' +a_st_i_status2 = 'Les journaux des services ou du noyau peuvent être vus ici afin d'obtenir un aperçu de leur état.' +iwscan = 'Scan WLAN' +iwscan1 = 'Réseaux Wi-Fi dans votre environnement' +iwscan_encr = 'Chiffrement' +iwscan_link = 'Lien' +iwscan_signal = 'Signal' +iwscan_noise = 'Bruit' +routes = 'Routes' +routes_netmask = 'Masque réseau' +routes_gateway = 'Passerelle' +routes_metric = 'Metrique' +a_s_desc = 'Ici, vous pouvez configurer les aspects basiques de votre routeur comme son nom ou son fuseau horaire.' +a_s_packages = 'Logiciels' +a_s_changepw = 'Mot de passe administrateur' +a_s_p_ipkg = 'Configuration OPKG' +a_s_sshkeys = 'Clés SSH' +a_s_fstab = 'Points de montage' +a_s_flash = 'Mise à jour firmware' +a_s_i_system1 = 'Changements en rapport avec le système, son identification le logiciel/matériel installé, l'authentification ou points de montage.' +a_s_i_system2 = 'Ces réglages définissent la base de votre système.' +a_s_i_system3 = 'Soyez vigilent car un mauvais réglage peut empêcher votre équipement de démarrer, ou vous empêcher de vous y connecter.' +a_s_packages_do = 'Accomplir les actions' +a_s_packages_install = 'Installer' +a_s_packages_installurl = 'Télécharge et installe le paquet' +a_s_packages_ipkg = 'Editer la liste des paquets et le répertoire de destination' +a_s_packages_name = 'Nom du paquet' +a_s_packages_remove = 'Désinstaller' +a_s_packages_search = 'Trouver un paquet' +a_s_packages_update = 'Liste des paquets mise à jour' +a_s_packages_updatelist = 'Mettre à jour la liste des paquets' +a_s_packages_upgrade = 'Mettre à jour les paquets installés' +a_s_p_ipkg_pkglists = 'Listes de paquets' +a_s_p_ipkg_targets = 'Répertoires de destination' +a_s_changepw1 = 'Changer le mot de passe du système (Utilisateur "root")' +a_s_changepw_changed = 'Mot de passe changé avec succès' +a_s_changepw_nomatch = 'Erreur: les mots de passe ne correspondent pas' +a_s_sshkeys1 = 'Vous pouvez copier ici des clés SSH publiques (une par ligne) pour une authentification SSH sur clés publiques.' +a_s_fstab_mountpoints = 'Points de montage' +a_s_fstab_mountpoints1 = 'Les points de montage définissent l'attachement d'un périphérique au système de fichier.' +a_s_fstab_active = 'Systèmes de fichiers montés' +a_s_fstab_used = 'Utilisé' +a_s_fstab_avail = 'Disponible' +a_s_fstab_mountpoint = 'Point de montage' +a_s_fstab_device1 = 'Le périphérique de bloc contenant la partition (ex : /dev/sda1)' +a_s_fstab_fs1 = 'Le système de fichiers utilisé pour formatter le support de stockage (ex : ext3)' +a_s_fstab_swap1 = 'Si la mémoire physique n'est pas en quantité suffisante, les données inutilisées peuvent être temporairement transférée sur une partition d'échange, relevant la quantité de RAM disponible. Ce processus est lent car la mémoire d'échange ne peut être accédée aux taux de transfert de la RAM.' +a_s_flash_flashed = 'Firmware installé avec succès. Redémarrage...' +a_s_flash_flasherr = 'Programme lors de la programmation' +a_s_flash_fwimage = 'Image firmware' +a_s_flash_received = 'Image reçue. Début du processus de flashage. NE PAS ETEINDRE L'EQUIPEMENT !' +a_s_flash_inprogress = 'Ecriture du firmware...' +a_s_flash_fwupgrade = 'Mise à jour firmware' +a_s_flash_keepcfg = 'Conserver les fichiers de configuration' +a_s_flash_notimplemented = 'Désolé, cette fonction n'est pas (encore) disponible pour votre plateforme.' +a_s_flash_upgrade1 = 'Remplace les fichiers existants par les nouveaux. Le format du firmware est dépendant de la plateforme.' +a_s_reboot1 = 'Redémarrage du système d'exploitation de votre équipement' +a_s_reboot_do = 'Redémarrer' +a_s_reboot_running = 'Patientez s'il vous plaît: équipement en cours de redémarrage...' +a_s_reboot_u = 'Attention : il reste des changements non appliqués qui seront perdus après redémarrage !' +a_s_applyreboot1 = 'Changements appliqués.' +a_s_backup = 'Sauvegarder / Restaurer' +a_s_backup_backup = 'Créer une archive de sauvegarde' +a_s_backup_archive = 'Sauvegarder l'archive' +a_s_backup_reset = 'Revenir à la configuration par défaut du routeur' +a_s_backup_reset1 = 'Etes-vous sûr de vouloir revenir à la configuration par défaut du firmware ?' +a_s_backup_restore = 'Restaurer une sauvegarde' +a_s_backup1 = 'Ici, vous pouvez sauvegarder et restaurer la configuration de votre routeur et, si possible, restaurer la configuration par défaut du routeur.' +a_srv_http = 'Serveur HTTP' +a_srv_ssh = 'Serveur SSH' +a_srv_services1 = 'Les services et démons accomplissent certaines tâches sur votre équipement.' +a_srv_services2 = 'La plupart d'entre eux sont des serveurs réseaux, qui vous offrent certains services comme un accès shell, accéder à des pages comme LuCI, faire du routage mesh, envoyer des e-mails ...' +a_srv_http1 = 'Un serveur web léger qui peut être utilisé pour LuCI.' +a_srv_http_authrealm = 'Domaine d'authentification' +a_srv_http_authrealm1 = 'Le domaine qui sera affiché lors de la fenêtre d'authentification.' +a_srv_http_config1 = 'fichier de configuration par défaut : /etc/httpd.conf' +a_srv_http_root = 'Page racine' +a_srv_dropbear1 = 'Dropbear est un serveur SSH et intègre un serveur SCP' +a_srv_d_pwauth = 'Authentification par mot de passe' +a_srv_d_pwauth1 = 'Autoriser l'authentification SSH par mot de passe' +a_w_channel = 'Canal' +a_w_wifi1 = 'Dans cette page vous trouverez des options de configuration pour les réseau sans-fils.' +a_w_wifi2 = 'Vous pouvez facilement installer un périphérique 802.11a/b/g/n dans votre réseau physique existant et utiliser la gestion des interfaces virtuelles pour créer des répéteurs sans-fils ou fournir plusieurs réseaux avec un seul équipement.' +a_w_wifi3 = 'Les modes Point d'accès, Station, Ad-Hoc et WDS couplés aux chiffrements WPA et WPA2 sont gérés.' +a_w_devices1 = 'Ici vous pouvez configurer les équipements Wi-Fi installés.' +a_w_txantenna = 'Antenne transmission' +a_w_rxantenna = 'Antenne réception' +a_w_distance1 = 'Distance vers la station la plus éloignée (m)' +a_w_diversity = 'Diversité' +a_w_countrycode = 'Code pays' +a_w_connlimit = 'Limite de connexion' +a_w_networks1 = 'Vous pouvez faire fonctionner plusieurs réseaux Wi-Fi sur un seul équipement. Il existe des limitations matérielles et liées au pilote. En général vous pouvez faire fonctionner simultanément 1 réseau Ad-Hoc et 3 points d'accès simultanément.' +a_w_netid = 'Nom du réseau (ESSID)' +a_w_network1 = 'Ajouter ce réseau Wi-Fi au réseau physique' +a_w_netmanual = ' - Créer un nouveau réseau - ' +a_w_txpwr = 'Puissance d'émission' +a_w_brcmburst = 'Technologie Broadcom Frameburst' +a_w_athburst = 'Technologie Atheros Frameburst' +a_w_radiussrv = 'Serveur Radius' +a_w_radiusport = 'Port Radius' +a_w_apisolation = 'Isolation AP' +a_w_apisolation1 = 'Empêche la communication directe Client à Client' +a_w_hideessid = 'Cacher le ESSID' +a_w_ap = 'Point d'accès' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq est un serveur DHCP combiné à un requêteur DNS pour les pare-feu NAT' +dhcp_dnsmasq_domainneeded = 'Domain requis' +dhcp_dnsmasq_domainneeded_desc = 'Ne pas transmettre de requêtes DNS sans nom DNS' +dhcp_dnsmasq_authoritative = 'Authoritaire' +dhcp_dnsmasq_authoritative_desc = 'C'est le seul serveur DHCP sur le réseau local' +dhcp_dnsmasq_boguspriv = 'Filtrer les requêtes privées' +dhcp_dnsmasq_boguspriv_desc = 'Ne pas transmettre les requêtes de recherche inverse pour les réseaux locaux' +dhcp_dnsmasq_filterwin2k = 'Filtrer les requêtes inutiles' +dhcp_dnsmasq_filterwin2k_desc = 'filtre les requêtes inutiles émises par les systèmes Windows' +dhcp_dnsmasq_localisequeries = 'Localiser les requêtes' +dhcp_dnsmasq_localisequeries_desc = 'localiser la réponse suivant l'émetteur de la requête' +dhcp_dnsmasq_local = 'Serveur local' +dhcp_dnsmasq_domain = 'Domaine local' +dhcp_dnsmasq_expandhosts = 'Etendre le nom d'hôte' +dhcp_dnsmasq_expandhosts_desc = 'concatène le nom de domaine aux noms d'hôtes' +dhcp_dnsmasq_nonegcache = 'Ne pas mettre en cache les requêtes négatives' +dhcp_dnsmasq_nonegcache_desc = 'empêche la mise en cache de requêtes DNS erronnées' +dhcp_dnsmasq_readethers = 'Utiliser /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Lire /etc/ethers pour configurer le serveur DHCP' +dhcp_dnsmasq_leasefile = 'Fichier de baux' +dhcp_dnsmasq_leasefile_desc = 'fichier dans lequel les baux DHCP seront stockés' +dhcp_dnsmasq_resolvfile = 'Fichier de résolution' +dhcp_dnsmasq_resolvfile_desc = 'fichier de résolution local' +dhcp_dnsmasq_nohosts = 'Ignorer /etc/hosts' +dhcp_dnsmasq_strictorder = 'Ordre stricte' +dhcp_dnsmasq_strictorder_desc = 'Les serveurs DNS du fichier de résolution seront interrogés dans l'ordre' +dhcp_dnsmasq_logqueries = 'Journaliser les requêtes' +dhcp_dnsmasq_noresolv = 'Ignorer le fichier de résolution' +dhcp_dnsmasq_dnsforwardmax = 'Requêtes concurrentes maximum' +dhcp_dnsmasq_port = 'Port DNS' +dhcp_dnsmasq_ednspacket_max = 'taille maximum du paquet. EDNS.0 ' +dhcp_dnsmasq_dhcpleasemax = 'baux maximum' +dhcp_dnsmasq_addnhosts = 'fichiers de noms d'hôtes supplémentaires' +dhcp_dnsmasq_queryport = 'port de requête' +dhcp_dnsmasq_enabletftp = 'Activer le serveur TFTP' +dhcp_dnsmasq_tftproot = 'Racine du serveur TFTP' +dhcp_dnsmasq_dhcpboot = 'Image de démarrage réseau' +a_n_switch = 'Switch' +a_n_conntrack = 'Connexions Actives' +a_n_conntrack_desc = 'Cette page donne une vue d'ensemble des connexions réseaux actuellement actives.' +a_n_routes = 'Routes' +a_n_routes4 = 'IPv4 Routes' +a_n_routes6 = 'IPv6 Routes' +a_network1 = 'Dans cette section vous trouverez tous les réglages relatifs au réseau.' +a_network2 = 'Sur la plupart des routeurs, les ports des switchs peuvent être configurés et séparés en plusieurs VLANs.' +a_network3 = 'Les réglages des interfaces et du PPPoE / PPTP vous permettent une configuration personalisée du réseau.' +a_network4 = 'Les équipements utilisant DHCP dans votre réseau local peuvent être configurés automatique pour l'accès au réseau.' +a_network5 = 'Le pare-feu et la redirection de ports peuvent être utilisés pour fournir un service interne à un réseau extérieur.' +a_n_switch1 = 'Les ports de votre routeur peuvent être configurés pour combiner plusieurs VLANs dans lesquels les machines connectées peuvent dialoguer directement l'une avec l'autre. Les VLANs sont souvent utilisés pour séparer différences sous-réseaux. Bien souvent il y a un port d'uplink pour une connexion vers un réseau plus vaste, comme internet et les autres ports sont réservés au réseau local.' +network_switch_desc = 'Les ports appartenant à un VLAN sont séparés par des espaces. Le port ayant le numéro le plus élevé (5 en général) est souvent connecté à l'interface interne du routeur. Les équipements avec 5 ports ont souvent leur port 0 comme port d'uplink par défaut.' +a_n_ifaces1 = 'Dans cette page vous pourrez configurer les interfaces réseaux. Vous pouvez bridger différentes interfaces en cochant le champ "bridger les interfaces" et en saisissant les noms des interfaces réseau séparées par des espaces. Vous pouvez aussi utiliser la notation VLAN, INTERFACE.VLANNB (ex : eth0.1).' +a_n_i_bridge = 'Bridger les interfaces' +a_n_i_bridge1 = 'créer un bridge entre plusieurs interfaces' +dhcp_desc = 'Avec DHCP, les machines connectées au réseau peuvent recevoir leurs réglages réseau directement (adresse IP, masque de réseau, serveur DNS, ...)' +dhcp_dhcp_leasetime = 'Durée du bail' +dhcp_dhcp_dynamicdhcp = 'DHCP dynamique' +dhcp_dhcp_ignore = 'Ignorer l'interface' +dhcp_dhcp_ignore_desc = 'désactiver DHCP sur cette interface' +dhcp_dhcp_force = 'Forcer' +dhcp_dhcp_start_desc = 'première addresse (dernier octet)' +dhcp_dhcp_limit_desc = 'nombre d'adresses disponibles - 1' +dhcp_dhcp_dhcpoption = 'Options DHCP' +dhcp_dhcp_dhcpoption_desc = 'Voir "dnsmasq --help dhcp" pour une liste d'options disponibles.' +dhcp_leases = 'Baux' +luci_ethers = 'Baux Statiques' +dhcp_timeremain = 'Durée de validité' +dhcp_leases_active = 'Baux actifs' +a_n_ptp = 'Connexions Point-à-Point' +a_n_ptp1 = 'Les connexions Point-à-Point en PPPoE ou PPTP sont souvent utilisées pour connecter un équipement à internet sur du DSL ou une technologie similaire.' +network_interface_prereq = 'Vous avez besoin d'installer "comgt" pour le support UMTS/GPRS, "ppp-mod-pppoe" pour le PPPoE, "ppp-mod-pppoa" pour le PPPoA ou "pptp" pour le PPtP' +network_interface_prereq_mini = 'Vous avez besoin d'installer "ppp-mod-pppoe" pour le support PPPoE ou "pptp" pour le PPtP' +network_interface_server = 'Serveur PPTP' +network_interface_demand = 'Déconnexion automatique' +network_interface_demand_desc = 'Délai d'inactivité à partir duquel la connexion est coupée' +network_interface_keepalive = 'Maintenir la connexion' +network_interface_keepalive_desc = 'Reconnexion si la connexion est perdue' +network_interface_device = 'Interface Modem' +network_interface_device_desc = 'Le noeud d'interface de votre modem, e.g. /dev/ttyUSB0' +network_interface_defaultroute = 'Remplacer la route par défaut' +network_interface_defaultroute_desc = 'Laisser pppd remplacer la route par défaut courante pour utiliser l'interface PPP après l'établissement de la connexion' +network_interface_peerdns = 'Utiliser le DNS fourni' +network_interface_peerdns_desc = 'Configurer le serveur DNS local pour utiliser le serveur de nom fourni par le pair PPP' +network_interface_ipv6 = 'Activer l'IPv6 sur le lien PPP' +network_interface_connect = 'Script de Connexion' +network_interface_connect_desc = 'pppd exécutera ce script après l'établissement du lien PPP' +network_interface_disconnect = 'Script de Déconnexion' +network_interface_disconnect_desc = 'pppd exécutera ce script avant de déconnecter le lien PPP' +network_interface_pppd_options = 'Options pppd supplémentaires' +network_interface_pppd_options_desc = 'Spécifiez ici des arguments de ligne de commande supplémentaire pour pppd' +network_interface_apn = 'Point d'accès (APN)' +network_interface_pincode = 'code PIN' +network_interface_pincode_desc = 'Assurez-vous de fournir le bon code PIN ou vous pourriez bloquer votre carte SIM !' +network_interface_service = 'Type de service' +network_interface_maxwait = 'Délai d'initialisation' +network_interface_maxwait_desc = 'Secondes à attendre pour que le modem soit prêt avant d'essayer de se connecter' +a_n_r_routes1 = 'Avec les routes statiques vous pouvez spécifier à travers quelle interface ou passerelle un réseau peut être contacté.' +a_n_routes_static = 'Routes statiques' +a_n_routes_static4 = 'Routes IPv4 statiques' +a_n_routes_static6 = 'Routes IPv6 statiques' +a_n_routes_kernel4 = 'Routes IPv4 actives' +a_n_routes_kernel6 = 'Routes IPv6 actives' +a_n_r_target1 = 'adresse IP ou réseau' +a_n_r_target6 = 'adresse IPv6 ou réseau' +a_n_r_netmask1 = 'si la destination est un réseau' +m_n_inet = 'Connexion Internet' +m_n_local = 'Réseau Local' +m_n_route = 'Route' +m_n_brdige = 'Bridge' +m_w_ap = 'Point d'accès' +m_w_adhoc = 'Ad-Hoc' +m_w_client = 'Client' +m_w_wds = 'WDS' +m_w_clientmode = 'Mode client' +system_system_logsize = 'Taille de buffer du journal système' +system_system_logip = 'Serveur externe pour le journal système' +system_system_conloglevel = 'Niveau de gravité du journal' +system_system_conloglevel_desc = 'Niveau de gravité du journal système affiché sur la console' +m_i_processor = 'Processeur' +m_i_memory = 'Mémoire' +m_i_systemtime = 'Heure Locale' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'Première adresse attribuée' +m_n_d_numleases = 'Nombre d'adresses attribuées' +routingtable = 'Table de routage' +wlanscan = 'Scan Wifi' +frequency = 'Fréquence' +power = 'Puissance' +noise = 'Bruit' +signal = 'Signal' +link = 'Lien' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Débit binaire' +m_n_keepalive = 'reconnecter automatiquement' +m_n_dialondemand = 'déconnecter après une inactivité de' +m_n_pptp_server = 'Serveur PPTP' +leds = 'Configuration des LEDs' +leds_desc = 'Personnaliser le comportement des LEDs si possible.' +system_led_name = 'Nom de la LED' +system_led_sysfs = 'Inteface de la LED' +system_led_default = 'Etat par défaut' +system_led_default_desc = 'ticked = on' +system_led_trigger = 'Clignotant' +system_led_trigger_none = 'Aucun' +system_led_trigger_defaulton = 'Allumé par défaut' +system_led_trigger_timer = 'Timer' +system_led_trigger_heartbeat = 'Heartbeat (Load Average)' +system_led_trigger_netdev = 'Interface Réseau' +system_led_delayoff = 'Délai de l'état Off' +system_led_delayoff_desc = 'Temps (en ms) pendant lequel la LED est éteinte' +system_led_delayon = 'Délai de l'état On' +system_led_delayon_desc = 'Temps (en ms) pendant lequel la LED est allumée' +system_led_dev = 'Interface' +system_led_mode = 'Mode Clignotant' +system_led_mode_link = 'Lien établi' +system_led_mode_tx = 'Transmet' +system_led_mode_rx = 'Reçoit' +network_interface_up = 'Active' +network_interface_hwaddr = 'Addresse MAC' +network_interface_hwaddr_desc = 'Addresse matériel' +network_interface_txrx = 'Trafic' +network_interface_txrx_desc = 'transmis / reçu' +network_interface_err = 'Erreurs' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Créer / Assigner une zone du pare-feu' +network_interface_fwzone_desc = 'Cette interface n'appartient à aucune zone du pare-feu pour le moment.' +process_head = 'Processus' +process_descr = 'Cette liste donne une vue d'ensemble des processus en exécution et leur statut.' +process_pid = 'PID' +process_owner = 'Propriétaire' +process_command = 'Commande' +process_cpu = 'Utilisation CPU (%)' +process_mem = 'Utilisation Mémoire (%)' +process_hup = 'Signal (HUP)' +process_term = 'Terminer' +process_kill = 'Tuer' +mem_cached = 'mis en cache' +mem_buffered = 'bufferisé' +mem_free = 'libre' +a_s_crontab = 'Tâches Régulières' +a_s_crontab1 = 'Ceci est le système crontab avec lequel sont définies les tâches récurrentes.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Chemin de la CA' +a_w_eaptype = 'Méthode EAP' +a_w_tlsprivkey = 'Chemin de la clé privée' +a_w_tlsprivkeypwd = 'Mot de passe de la clé privée' +a_w_peapauth = 'Authentification' +a_w_peapidentity = 'Identité' +a_w_peappassword = 'Mot de passe' +a_w_create = 'Créer un réseau' +hostnames = 'Noms d'hôtes' +hostnames_entries = 'Entrées d'hôtes' +hostnames_hostname = 'Nom d'hôte' +hostnames_address = 'Adresse IP' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.xml b/openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.xml new file mode 100644 index 0000000..5629245 --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/admin-core.fr.xml @@ -0,0 +1,334 @@ + + + + +Les changements suivants ont été appliqués +Les changements suivants ont été annulés +Interface utilisateur +LuCI est une suite logicielle d'applications Lua software incluant un MVC-Webframework et une interface web pour équipements embarqués. Luci est sous license Apache. +Page d'accueil du projet +Développeurs principaux +Contributeurs +Merci à +Bonjour ! +Voici la page d'administration de LuCI. +LuCI est une interface graphique libre, flexible, et user friendly pour configurer OpenWrt Kamikaze. +Dans les pages suivantes vous pouvez ajuster tous les réglages importants de votre routeur. +Vous trouverez une page de navigation sur le côté gauche permettant d'accèder aux différentes pages de configuration. +Nous souhaitons améliorer l'interface de manière permanente, vos retours et suggestions sont primordiaux. +Et maintenant que la fête commence ! +L'équipe LuCI +Ici, vous pouvez personnaliser les réglages et les fonctionnalités de LuCI. +Actions post-changements +Ces commandes seront executées automatiquement lorsqu'une configuration UCI est appliquée, les changement prenant effet immédiatement. +Fichiers à conserver lors d'une mise à jour du firmware +Lors d'une nouvelle installation, ces fichiers seront ajoutés à la nouvelle installation. +Ici, vous trouverez des informations sur l'état actuel du système comme la fréquence processeur, utilisation mémoire et trafic réseau. +Les journaux des services ou du noyau peuvent être vus ici afin d'obtenir un aperçu de leur état. +Scan WLAN +Réseaux Wi-Fi dans votre environnement +Chiffrement +Lien +Signal +Bruit +Routes +Masque réseau +Passerelle +Metrique +Ici, vous pouvez configurer les aspects basiques de votre routeur comme son nom ou son fuseau horaire. +Logiciels +Mot de passe administrateur +Configuration OPKG +Clés SSH +Points de montage +Mise à jour firmware +Changements en rapport avec le système, son identification le logiciel/matériel installé, l'authentification ou points de montage. +Ces réglages définissent la base de votre système. +Soyez vigilent car un mauvais réglage peut empêcher votre équipement de démarrer, ou vous empêcher de vous y connecter. +Accomplir les actions +Installer +Télécharge et installe le paquet +Editer la liste des paquets et le répertoire de destination +Nom du paquet +Désinstaller +Trouver un paquet +Liste des paquets mise à jour +Mettre à jour la liste des paquets +Mettre à jour les paquets installés +Listes de paquets +Répertoires de destination +Changer le mot de passe du système (Utilisateur "root") +Mot de passe changé avec succès +Erreur: les mots de passe ne correspondent pas +Vous pouvez copier ici des clés SSH publiques (une par ligne) pour une authentification SSH sur clés publiques. +Points de montage +Les points de montage définissent l'attachement d'un périphérique au système de fichier. +Systèmes de fichiers montés +Utilisé +Disponible +Point de montage +Le périphérique de bloc contenant la partition (ex : /dev/sda1) +Le système de fichiers utilisé pour formatter le support de stockage (ex : ext3) +Si la mémoire physique n'est pas en quantité suffisante, les données inutilisées peuvent être temporairement transférée sur une partition d'échange, relevant la quantité de RAM disponible. Ce processus est lent car la mémoire d'échange ne peut être accédée aux taux de transfert de la RAM. +Firmware installé avec succès. Redémarrage... +Programme lors de la programmation +Image firmware +Image reçue. Début du processus de flashage. NE PAS ETEINDRE L'EQUIPEMENT ! +Ecriture du firmware... +Mise à jour firmware +Conserver les fichiers de configuration +Désolé, cette fonction n'est pas (encore) disponible pour votre plateforme. +Remplace les fichiers existants par les nouveaux. Le format du firmware est dépendant de la plateforme. +Redémarrage du système d'exploitation de votre équipement +Redémarrer +Patientez s'il vous plaît: équipement en cours de redémarrage... +Attention : il reste des changements non appliqués qui seront perdus après redémarrage ! +Changements appliqués. +Sauvegarder / Restaurer +Créer une archive de sauvegarde +Sauvegarder l'archive +Revenir à la configuration par défaut du routeur +Etes-vous sûr de vouloir revenir à la configuration par défaut du firmware ? +Restaurer une sauvegarde +Ici, vous pouvez sauvegarder et restaurer la configuration de votre routeur et, si possible, restaurer la configuration par défaut du routeur. +Serveur HTTP +Serveur SSH +Les services et démons accomplissent certaines tâches sur votre équipement. +La plupart d'entre eux sont des serveurs réseaux, qui vous offrent certains services comme un accès shell, accéder à des pages comme LuCI, faire du routage mesh, envoyer des e-mails ... +Un serveur web léger qui peut être utilisé pour LuCI. +Domaine d'authentification +Le domaine qui sera affiché lors de la fenêtre d'authentification. +fichier de configuration par défaut : /etc/httpd.conf +Page racine +Dropbear est un serveur SSH et intègre un serveur SCP +Authentification par mot de passe +Autoriser l'authentification SSH par mot de passe +Canal +Dans cette page vous trouverez des options de configuration pour les réseau sans-fils. +Vous pouvez facilement installer un périphérique 802.11a/b/g/n dans votre réseau physique existant et utiliser la gestion des interfaces virtuelles pour créer des répéteurs sans-fils ou fournir plusieurs réseaux avec un seul équipement. +Les modes Point d'accès, Station, Ad-Hoc et WDS couplés aux chiffrements WPA et WPA2 sont gérés. +Ici vous pouvez configurer les équipements Wi-Fi installés. +Antenne transmission +Antenne réception +Distance vers la station la plus éloignée (m) +Diversité +Code pays +Limite de connexion +Vous pouvez faire fonctionner plusieurs réseaux Wi-Fi sur un seul équipement. Il existe des limitations matérielles et liées au pilote. En général vous pouvez faire fonctionner simultanément 1 réseau Ad-Hoc et 3 points d'accès simultanément. +Nom du réseau (ESSID) +Ajouter ce réseau Wi-Fi au réseau physique + - Créer un nouveau réseau - +Puissance d'émission +Technologie Broadcom Frameburst +Technologie Atheros Frameburst +Serveur Radius +Port Radius +Isolation AP +Empêche la communication directe Client à Client +Cacher le ESSID +Point d'accès +Ad-Hoc +Pseudo Ad-Hoc (ahdemo) +Client +WDS +Monitor +Dnsmasq est un serveur DHCP combiné à un requêteur DNS pour les pare-feu NAT +Domain requis +Ne pas transmettre de requêtes DNS sans nom DNS +Authoritaire +C'est le seul serveur DHCP sur le réseau local +Filtrer les requêtes privées +Ne pas transmettre les requêtes de recherche inverse pour les réseaux locaux +Filtrer les requêtes inutiles +filtre les requêtes inutiles émises par les systèmes Windows +Localiser les requêtes +localiser la réponse suivant l'émetteur de la requête +Serveur local +Domaine local +Etendre le nom d'hôte +concatène le nom de domaine aux noms d'hôtes +Ne pas mettre en cache les requêtes négatives +empêche la mise en cache de requêtes DNS erronnées +Utiliser /etc/ethers +Lire /etc/ethers pour configurer le serveur DHCP +Fichier de baux +fichier dans lequel les baux DHCP seront stockés +Fichier de résolution +fichier de résolution local +Ignorer /etc/hosts +Ordre stricte +Les serveurs DNS du fichier de résolution seront interrogés dans l'ordre +Journaliser les requêtes +Ignorer le fichier de résolution +Requêtes concurrentes maximum +Port DNS +taille maximum du paquet. EDNS.0 +baux maximum +fichiers de noms d'hôtes supplémentaires +port de requête +Activer le serveur TFTP +Racine du serveur TFTP +Image de démarrage réseau +Switch +Connexions Actives +Cette page donne une vue d'ensemble des connexions réseaux actuellement actives. +Routes +IPv4 Routes +IPv6 Routes +Dans cette section vous trouverez tous les réglages relatifs au réseau. +Sur la plupart des routeurs, les ports des switchs peuvent être configurés et séparés en plusieurs VLANs. +Les réglages des interfaces et du PPPoE / PPTP vous permettent une configuration personalisée du réseau. +Les équipements utilisant DHCP dans votre réseau local peuvent être configurés automatique pour l'accès au réseau. +Le pare-feu et la redirection de ports peuvent être utilisés pour fournir un service interne à un réseau extérieur. +Les ports de votre routeur peuvent être configurés pour combiner plusieurs VLANs dans lesquels les machines connectées peuvent dialoguer directement l'une avec l'autre. Les VLANs sont souvent utilisés pour séparer différences sous-réseaux. Bien souvent il y a un port d'uplink pour une connexion vers un réseau plus vaste, comme internet et les autres ports sont réservés au réseau local. +Les ports appartenant à un VLAN sont séparés par des espaces. Le port ayant le numéro le plus élevé (5 en général) est souvent connecté à l'interface interne du routeur. Les équipements avec 5 ports ont souvent leur port 0 comme port d'uplink par défaut. +Dans cette page vous pourrez configurer les interfaces réseaux. Vous pouvez bridger différentes interfaces en cochant le champ "bridger les interfaces" et en saisissant les noms des interfaces réseau séparées par des espaces. Vous pouvez aussi utiliser la notation VLAN, INTERFACE.VLANNB (ex : eth0.1). +Bridger les interfaces +créer un bridge entre plusieurs interfaces +Avec DHCP, les machines connectées au réseau peuvent recevoir leurs réglages réseau directement (adresse IP, masque de réseau, serveur DNS, ...) +Durée du bail +DHCP dynamique +Ignorer l'interface +désactiver DHCP sur cette interface +Forcer +première addresse (dernier octet) +nombre d'adresses disponibles - 1 +Options DHCP +Voir "dnsmasq --help dhcp" pour une liste d'options disponibles. +Baux +Baux Statiques +Durée de validité +Baux actifs +Connexions Point-à-Point +Les connexions Point-à-Point en PPPoE ou PPTP sont souvent utilisées pour connecter un équipement à internet sur du DSL ou une technologie similaire. +Vous avez besoin d'installer "comgt" pour le support UMTS/GPRS, "ppp-mod-pppoe" pour le PPPoE, "ppp-mod-pppoa" pour le PPPoA ou "pptp" pour le PPtP +Vous avez besoin d'installer "ppp-mod-pppoe" pour le support PPPoE ou "pptp" pour le PPtP +Serveur PPTP +Déconnexion automatique +Délai d'inactivité à partir duquel la connexion est coupée +Maintenir la connexion +Reconnexion si la connexion est perdue +Interface Modem +Le noeud d'interface de votre modem, e.g. /dev/ttyUSB0 +Remplacer la route par défaut +Laisser pppd remplacer la route par défaut courante pour utiliser l'interface PPP après l'établissement de la connexion +Utiliser le DNS fourni +Configurer le serveur DNS local pour utiliser le serveur de nom fourni par le pair PPP +Activer l'IPv6 sur le lien PPP +Script de Connexion +pppd exécutera ce script après l'établissement du lien PPP +Script de Déconnexion +pppd exécutera ce script avant de déconnecter le lien PPP +Options pppd supplémentaires +Spécifiez ici des arguments de ligne de commande supplémentaire pour pppd +Point d'accès (APN) +code PIN +Assurez-vous de fournir le bon code PIN ou vous pourriez bloquer votre carte SIM ! +Type de service +Délai d'initialisation +Secondes à attendre pour que le modem soit prêt avant d'essayer de se connecter +Avec les routes statiques vous pouvez spécifier à travers quelle interface ou passerelle un réseau peut être contacté. +Routes statiques +Routes IPv4 statiques +Routes IPv6 statiques +Routes IPv4 actives +Routes IPv6 actives +adresse IP ou réseau +adresse IPv6 ou réseau +si la destination est un réseau +Connexion Internet +Réseau Local +Route +Bridge +Point d'accès +Ad-Hoc +Client +WDS +Mode client +Taille de buffer du journal système +Serveur externe pour le journal système +Niveau de gravité du journal +Niveau de gravité du journal système affiché sur la console +Processeur +Mémoire +Heure Locale +Uptime +Première adresse attribuée +Nombre d'adresses attribuées +Table de routage +Scan Wifi +Fréquence +Puissance +Bruit +Signal +Lien +Frag. +RTS +Débit binaire +reconnecter automatiquement +déconnecter après une inactivité de +Serveur PPTP +Configuration des LEDs +Personnaliser le comportement des LEDs si possible. +Nom de la LED +Inteface de la LED +Etat par défaut +ticked = on +Clignotant +Aucun +Allumé par défaut +Timer +Heartbeat (Load Average) +Interface Réseau +Délai de l'état Off +Temps (en ms) pendant lequel la LED est éteinte +Délai de l'état On +Temps (en ms) pendant lequel la LED est allumée +Interface +Mode Clignotant +Lien établi +Transmet +Reçoit +Active +Addresse MAC +Addresse matériel +Trafic +transmis / reçu +Erreurs +TX / RX +Créer / Assigner une zone du pare-feu +Cette interface n'appartient à aucune zone du pare-feu pour le moment. +Processus +Cette liste donne une vue d'ensemble des processus en exécution et leur statut. +PID +Propriétaire +Commande +Utilisation CPU (%) +Utilisation Mémoire (%) +Signal (HUP) +Terminer +Tuer +mis en cache +bufferisé +libre +Tâches Régulières +Ceci est le système crontab avec lequel sont définies les tâches récurrentes. +NAS ID +Chemin de la CA +Méthode EAP +Chemin de la clé privée +Mot de passe de la clé privée +Authentification +Identité +Mot de passe +Créer un réseau +Noms d'hôtes +Entrées d'hôtes +Nom d'hôte +Adresse IP +PPPoA Encapsulation +Clamp Segment Size +Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs. + + + diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.lua b/openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.lua new file mode 100644 index 0000000..a62ccc9 --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.lua @@ -0,0 +1,17 @@ +cbi_add = 'Ajouter une entrée' +cbi_del = 'Supprimer l'entrée' +cbi_replace = 'Remplacer l'entrée' +cbi_invalid = 'Erreur : donnée entrée invalide' +cbi_invalid_section = 'Erreur de validation : merci de vérifier les champs de saisie.' +cbi_missing = 'Ce champ est obligatoire' +cbi_deperror = 'Erreur de validation : au moins un champ est vide ou a une valeur incorrecte' +cbi_reqerror = 'Une spécification pour cette option n'a pu être vérifiée' +cbi_addopt = '-- Champ Supplémentaire --' +cbi_optional = ' (optionnel)' +cbi_sectempty = 'Cette section ne contient pas encore de valeur' +cbi_manual = '-- autre --' +cbi_select = '-- Choisir --' +cbi_gorel = 'Aller à la page de configuration correspondante' +cbi_applying = 'Changements en cours d'application' +cbi_upload = 'Fichier Uploadé' +cbi_browser = 'Chercher un fichier...' diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.xml b/openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.xml new file mode 100644 index 0000000..4d6a8d5 --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/cbi.fr.xml @@ -0,0 +1,23 @@ + + + + +Ajouter une entrée +Supprimer l'entrée +Remplacer l'entrée +Erreur : donnée entrée invalide +Erreur de validation : merci de vérifier les champs de saisie. +Ce champ est obligatoire +Erreur de validation : au moins un champ est vide ou a une valeur incorrecte +Une spécification pour cette option n'a pu être vérifiée +-- Champ Supplémentaire -- + (optionnel) +Cette section ne contient pas encore de valeur +-- autre -- +-- Choisir -- +Aller à la page de configuration correspondante +Changements en cours d'application +Fichier Uploadé +Chercher un fichier... + + diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.lua b/openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.lua new file mode 100644 index 0000000..8d9fa10 --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.lua @@ -0,0 +1,99 @@ +about = 'A propos' +add = 'Ajouter' +all = 'tous' +addresses = 'Adresses' +aliases = 'Alias' +back = 'retour' +administration = 'Administration' +essentials = 'Essentiel' +apply = 'Appliquer' +basicsettings = 'Paramètres de base' +broadcast = 'Broadcast IPv4' +changes = 'Changements' +channel = 'Canal' +cidr6 = 'Notation CIDR : adresse/prefixe' +code = 'Code' +config = 'Configuration' +configfile = 'Fichier de configuration' +confirmation = 'Confirmation' +delete = 'Effacer' +descr = 'Description' +design = 'Apparence' +destination = 'Destination' +device = 'Equipement' +devices = 'Equipements' +disable = 'désactiver' +distance = 'Distance' +dmesg = 'Journal du noyau' +dnsserver = 'Serveur DNS' +edit = 'Editer' +enable = 'activer' +encryption = 'Chiffrement' +error = 'Erreur' +filesystem = 'Système de fichiers' +filter = 'Filtrer' +gateway = 'Passerelle' +gateway6 = 'Passerelle IPv6' +general = 'Général' +hostname = 'Nom d'hôte' +install = 'Installer' +installed = 'installé' +interface = 'Interface' +interfaces = 'Interfaces' +ipaddress = 'Adresse IP' +ip6address = 'Adresse IPv6' +legend = 'Légende' +library = 'Bibliothèque' +logout = 'Déconnexion' +key = 'Clé' +language = 'Langue' +limit = 'Limite' +load = 'Charger' +login = 'Connexion' +macaddress = 'Adresse MAC' +manpage = 'voir la page de man de '%s'' +metric = 'Metrique' +mode = 'Mode' +name = 'Nom' +netmask = 'Masque réseau' +network = 'Réseau' +networks = 'Réseaux' +none = 'aucun' +notinstalled = 'pas installé' +ok = 'OK' +options = 'Options' +overview = 'Vue d'ensemble' +packagemanager = 'Gestionnaire de paquets' +password = 'Mot de passe' +path = 'Chemin' +port = 'Port' +ports = 'Ports' +protocol = 'Protocole' +reboot = 'Redémarrage' +reset = 'Remise à zéro' +revert = 'Revenir' +save = 'Sauvegarder' +saveapply = 'Sauvegarder et Appliquer' +scan = 'Scan' +service = 'Service' +services = 'Services' +settings = 'Réglages' +size = 'Taille' +source = 'Source' +start = 'Démarrer' +static = 'statique' +status = 'Status' +statistics = 'Statistiques' +submit = 'Soumettre' +syslog = 'Journal système' +system = 'Système' +target = 'Cible' +timezone = 'Fuseau horaire' +type = 'Type' +unknownerror = 'Erreur inconnue' +unsavedchanges = 'Changements non appliqués' +username = 'Nom d'utilisateur' +version = 'Version' +webui = 'IU Web' +wifi = 'Wi-Fi' +zone = 'Zone' diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.xml b/openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.xml new file mode 100644 index 0000000..f84b3a9 --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/default.fr.xml @@ -0,0 +1,106 @@ + + + + +A propos +Ajouter +tous + +Adresses +Alias +retour +Administration +Essentiel +Appliquer +Paramètres de base +Broadcast IPv4 +Changements +Canal +Notation CIDR : adresse/prefixe +Code +Configuration +Fichier de configuration +Confirmation +Effacer +Description +Apparence +Destination +Equipement +Equipements +désactiver +Distance +Journal du noyau +Serveur DNS +Editer +activer +Chiffrement +Erreur +Système de fichiers +Filtrer +Passerelle +Passerelle IPv6 +Général +Nom d'hôte +Installer +installé +Interface +Interfaces +Adresse IP +Adresse IPv6 +Légende +Bibliothèque +Déconnexion +Clé +Langue +Limite +Charger +Connexion +Adresse MAC +voir la page de man de '%s' +Metrique +Mode +Nom +Masque réseau +Réseau +Réseaux +aucun +pas installé +OK +Options +Vue d'ensemble +Gestionnaire de paquets +Mot de passe +Chemin +Port +Ports +Protocole +Redémarrage +Remise à zéro +Revenir +Sauvegarder +Sauvegarder et Appliquer +Scan +Service +Services +Réglages +Taille +Source +Démarrer +statique +Status +Statistiques +Soumettre +Journal système +Système +Cible +Fuseau horaire +Type +Erreur inconnue +Changements non appliqués +Nom d'utilisateur +Version +IU Web +Wi-Fi +Zone + + diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.lua b/openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.lua new file mode 100644 index 0000000..341fcfc --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Authorisation requise' +sysauth_prompt = 'Saisissez votre nom d'utilisateur et mot de passe.' +sysauth_failed = 'Nom d'utilisateur et/ou mot de passe erroné ! Réessayez s'il vous plaît.' diff --git a/openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.xml b/openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.xml new file mode 100644 index 0000000..a7934dd --- /dev/null +++ b/openwrt/packages/luci/i18n/french/luasrc/i18n/sysauth.fr.xml @@ -0,0 +1,9 @@ + + + + +Authorisation requise +Saisissez votre nom d'utilisateur et mot de passe. +Nom d'utilisateur et/ou mot de passe erroné ! Réessayez s'il vous plaît. + + diff --git a/openwrt/packages/luci/i18n/french/root/etc/uci-defaults/luci-i18n-french b/openwrt/packages/luci/i18n/french/root/etc/uci-defaults/luci-i18n-french new file mode 100755 index 0000000..e424eaf --- /dev/null +++ b/openwrt/packages/luci/i18n/french/root/etc/uci-defaults/luci-i18n-french @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.languages.fr='Francais' + commit luci +EOF + diff --git a/openwrt/packages/luci/i18n/german/Makefile b/openwrt/packages/luci/i18n/german/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/i18n/german/ipkg/postinst b/openwrt/packages/luci/i18n/german/ipkg/postinst new file mode 100755 index 0000000..c5af662 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-i18n-german ) && rm -f /etc/uci-defaults/luci-i18n-german +} diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.lua b/openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.lua new file mode 100644 index 0000000..ccfdc01 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.lua @@ -0,0 +1,346 @@ +a_i_i_admin1 = 'Dies ist der Administrationsbereich von LuCI.' +a_i_i_admin2 = 'LuCI ist eine freie, flexible und benutzerfreundliche grafische Oberfläche zur Konfiguration von OpenWrt Kamikaze.' +a_i_i_admin3 = 'Auf den folgenden Seiten können alle wichtigen Einstellungen des Routers vorgenommen werden.' +a_i_i_admin4 = 'Hinweis: In LuCI werden getätigte Änderungen erst nach einem Klick auf Änderungen - Speichern & Anwenden angewandt.' +a_i_i_admin5 = 'Wir sind natürlich stets darum bemüht, diese Oberfläche noch besser und intuitiver zu Gestalten und freuen uns über jegliche Art von Feedback oder Verbesserungsvorschlägen.' +a_i_i_admin6 = 'Und nun wünschen wir viel Spaß mit dem Router!' +a_i_i_hello = 'Hallo!' +a_i_i_team = 'Das LuCI-Team' +a_i_keepflash = 'Zu übernehmende Dateien bei Firmwareupgrade' +a_i_keepflash1 = 'Die folgenden Dateien und Verzeichnisse werden beim Aktualisieren der Firmware über die Oberfläche automatisch in die neue Firmware übernommen.' +a_i_luci1 = 'Hier können Eigenschaften und die Funktionalität der Oberfläche angepasst werden.' +a_i_ucicommit = 'UCI-Befehle beim Anwenden' +a_i_ucicommit1 = 'Beim Anwenden der Konfiguration aus der Oberflächliche heraus können automatisch die relevanten Dienste neugestart werden, sodass Änderungen sofort nach dem Anwenden aktiv werden und der Router nicht erst neugestartet werden muss.' +a_i_ui = 'Benutzeroberfläche' +a_n_i_bridge = 'Netzwerkbrücke' +a_n_i_bridge1 = 'überbrückt angegebene Schnittstelle(n)' +a_n_ifaces1 = 'An dieser Stelle können die einzelnen Schnittstellen des Netzwerkes konfiguriert werden. Es können mehrere Schnittstellen zu einer Brücke zusammengefasst werden, indem diese durch Leerzeichen getrennt aufgezählt werden und ein entsprechender Haken im Feld Netzwerkbrücke gesetzt wird. Es können VLANs in der Notation SCHNITTSTELLE.VLANNR (z.B.: eth0.1) verwendet werden.' +a_n_ptp = 'Punkt-zu-Punkt Verbindungen' +a_n_ptp1 = 'Punkt-zu-Punkt Verbindungen über PPPoE oder PPTP werden häufig dazu verwendet, um über DSL o.ä. Techniken eine Verbindung zum Internetgateway eines Internetzugangsanbieters aufzubauen.' +a_n_r_netmask1 = 'falls Ziel ein Netzwerk ist' +a_n_r_target1 = 'Host-IP oder Netzwerk' +a_n_r_target6 = 'IPv6 Host- oder Netzwerk-Addresse (CIDR)' +a_n_routes = 'Routen' +a_n_routes4 = 'IPv4 Routen' +a_n_routes6 = 'IPv6 Routen' +a_n_routes1 = 'Routen geben an, über welche Schnittstelle und welches Gateway ein bestimmter Host oder ein bestimmtes Netzwerk erreicht werden kann.' +a_n_routes_static = 'Statische Routen' +a_n_routes_static4 = 'Statische IPv4 Routen' +a_n_routes_static6 = 'Statische IPv6 Routen' +a_n_routes_kernel4 = 'Aktive IPv4-Routen' +a_n_routes_kernel6 = 'Aktive IPv6-Routen' +a_n_switch = 'Switch' +a_n_switch1 = 'Die Netzwerkschnittstellen am Router können zu verschienden VLANs zusammengefasst werden, in denen Geräte miteinander direkt kommunizieren können. VLANs werden auch häufig dazu genutzt, um Netzwerke voneiander zu trennen. So ist oftmals eine Schnittstelle als Uplink zu einem größerem Netz, wie dem Internet vorkonfiguriert und die anderen Schnittstellen bilden ein VLAN für das lokale Netzwerk.' +a_n_conntrack = 'Aktive Verbindungen' +a_n_conntrack_desc = 'Diese Seite gibt eine Ãœbersicht über aktive Netzwerkverbindungen.' +a_network1 = 'In diesem Bereich finden sich alle netzwerkbezogenen Einstellungen.' +a_network2 = 'Der Netzwerkswitch kann bei den meisten Routern frei konfiguriert und in mehrere VLANs aufgeteilt werden.' +a_network3 = 'Schnittstellen und PPPoE/PPTP-Einstellungen ermöglichen die freie Organisation des Netzwerks und die Anbindung an ein WAN.' +a_network4 = 'DHCP ermöglichst die automatische Netzwerkkonfiguration von Rechnern im (W)LAN.' +a_network5 = 'Portweiterleitung und Firewall erlauben eine effektive Absicherung des Netzes, bei gleichzeitiger Bereitstellung von externen Diensten.' +a_s_changepw = 'Passwort ändern' +a_s_changepw1 = 'Ändert das Passwort des Systemverwalters (Benutzer "root")' +a_s_changepw_changed = 'Passwort erfolgreich geändert' +a_s_changepw_nomatch = 'Passwörter stimmen nicht überein' +a_s_desc = 'An dieser Stelle können Grundeinstellungen des Systems wie Hostname oder Zeitzone vorgenommen werden.' +a_s_flash = 'Upgrade' +a_s_flash_flashed = 'Flashvorgang erfolgreich. Router startet neu...' +a_s_flash_flasherr = 'Flashvorgang fehlgeschlagen' +a_s_flash_fwimage = 'Firmwareimage' +a_s_flash_received = 'Abbild empfangen. Starte Flashvorgang. SCHALTEN SIE DAS GERÄT NICHT AUS!' +a_s_flash_inprogress = 'Schreibe Firmware...' +a_s_flash_fwupgrade = 'Firmware aktualisieren' +a_s_flash_keepcfg = 'Konfigurationsdateien übernehmen' +a_s_flash_notimplemented = 'Diese Funktion steht leider (noch) nicht zur Verfügung.' +a_s_flash_upgrade1 = 'Ersetzt die installierte Firmware (das Betriebssystem des Routers) durch ein neues. Das Format der Firmware ist plattformabhängig.' +a_s_fstab = 'Einhängepunkte' +a_s_fstab_active = 'Eingehängte Dateisysteme' +a_s_fstab_used = 'Benutzt' +a_s_fstab_avail = 'Verfügbar' +a_s_fstab_device1 = 'Die Gerätedatei des Speichers oder der Partition (z.B.: /dev/sda)' +a_s_fstab_fs1 = 'Das Dateisystem mit dem der Speicher formatiert ist (z.B.: ext3)' +a_s_fstab_mountpoint = 'Einhängepunkt' +a_s_fstab_mountpoints = 'Einhängepunkte' +a_s_fstab_mountpoints1 = 'Einhängepunkte bestimmen, an welcher Stelle des Dateisystems bestimmte Laufwerke und Speicher zur Verwendung eingebunden werden.' +a_s_fstab_swap1 = 'Falls der Arbeitsspeicher des Routers nicht ausreicht, kann dieser nicht benutzte Daten zeitweise auf einem SWAP-Laufwerk auslagern um so die effektive Größe des Arbeitsspeichers zu erhöhen. Die Auslagerung der Daten ist natürlich bedeutend langsamer als direkte Arbeitsspeicherzugriffe.' +a_s_i_system1 = 'Hier finden sich Einstellungen, die das System selbst, dessen Kennung, installierte Software und Hardware, Authentifizierung oder eingehängte Speicher betreffen.' +a_s_i_system2 = 'Diese Einstellungen definieren die Grundlage des Systems, auf dem die installierte Software aufbaut.' +a_s_i_system3 = 'Beachte bitte, dass eine fehlerhafte Konfiguration den Start des Routers verhindern oder dich vom Zugriff auf diesen ausschließen kann.' +a_s_p_ipkg = 'OPKG-Konfiguration' +a_s_p_ipkg_pkglists = 'Paketlisten' +a_s_p_ipkg_targets = 'Installationsziele' +a_s_packages = 'Paketverwaltung' +a_s_packages_do = 'Aktionen ausführen' +a_s_packages_install = 'Installation von' +a_s_packages_installurl = 'Paket herunterladen und installieren' +a_s_packages_ipkg = 'Paketlisten und Installationsziele bearbeiten' +a_s_packages_name = 'Paketname' +a_s_packages_remove = 'Deinstallation von' +a_s_packages_search = 'Paket suchen' +a_s_packages_update = 'Paketlisten aktualisieren' +a_s_packages_updatelist = 'Paketlisten aktualisieren' +a_s_packages_upgrade = 'Installierte Pakete aktualisieren' +a_s_reboot1 = 'Startet das Betriebssystem des Routers neu.' +a_s_reboot_do = 'Neustart durchführen' +a_s_reboot_running = 'Bitte warten: Neustart wird durchgeführt...' +a_s_reboot_u = 'Warnung: Es gibt ungespeicherte Änderungen, die beim Neustart verloren gehen!' +a_s_sshkeys = 'SSH-Schlüssel' +a_s_sshkeys1 = 'Hier können öffentliche SSH-Schlüssel (einer pro Zeile) zur Authentifizierung abgelegt werden.' +a_srv_d_pwauth = 'Passwortanmeldung' +a_srv_d_pwauth1 = 'Erlaube Anmeldung per Passwort' +a_srv_dropbear1 = 'Der SSH-Server ermöglicht Shell-Zugriff über das Netzwerk und bietet einen integrierten SCP-Dienst.' +a_srv_http1 = 'Ein kleiner Webserver, der für die Bereitstellung von LuCI genutzt werden kann.' +a_srv_http_authrealm = 'Anmeldeaufforderung' +a_srv_http_authrealm1 = 'Aufforderungstext zum Anmelden im Administrationsbereich' +a_srv_http_config1 = '/etc/httpd.conf wenn leer' +a_srv_http_root = 'Wurzelverzeichnis' +a_srv_http_keepalive = 'Keep-Alive aktivieren' +a_srv_http_timeout = 'Verbindungszeitlimit' +a_srv_http_path = 'Pluginpfad' +a_srv_lucittpd = 'Ein schlanker HTTP/1.1 webserver in C und Lua geschrieben um LuCI zu betreiben.' +a_srv_services1 = 'Dienste und Dämonen stellen bestimmte Funktionalitäten auf dem Router zur Verfügung.' +a_srv_services2 = 'Es handelt sich hierbei meist um Netzwerkserver, die verschiedene Aufgaben auf dem Router erfüllen, beispielsweise Shell-Zugang ermöglichen oder diese Weboberfläche per HTTP anbieten.' +a_st_i_status1 = 'Hier finden sich Informationen über den aktuellen Status des Systems, beispielsweise Prozessortakt, Speicherauslastung und Netzwerkschnittstellen.' +a_st_i_status2 = 'Zusätzlich können hier Protokolldaten, des Kernels und diverser Systemdienste eingesehen werden, um deren Zustand zu kontrollieren.' +a_w_devices1 = 'An dieser Stelle können eingebaute WLAN-Geräte konfiguriert werden.' +a_w_apisolation = 'AP-Isolation' +a_w_apisolation1 = 'Unterbindet Client-Client-Verkehr' +a_w_athburst = 'Atheros-Frameburst' +a_w_brcmburst = 'Broadcom-Frameburst' +a_w_channel = 'Funkkanal' +a_w_connlimit = 'Verbindungslimit' +a_w_countrycode = 'Ländercode' +a_w_distance1 = 'Distanz zum am weitesten entfernten Funkpartner (m)' +a_w_diversity = 'Diversität' +a_w_hideessid = 'ESSID verstecken' +a_w_netid = 'Netzkennung (ESSID)' +a_w_network1 = 'WLAN-Netz zu Netzwerk hinzufügen' +a_w_networks1 = 'Pro WLAN-Gerät können mehrere Netze bereitgestellt werden. Es sollte beachtet werden, dass es hardware- / treiberspezifische Einschränkungen gibt. So kann pro WLAN-Gerät in der Regel entweder 1 Ad-Hoc-Zugang ODER bis zu 3 Access-Point und 1 Client-Zugang gleichzeitig erstellt werden.' +a_w_netmanual = ' - Neues Netzwerk erstellen - ' +a_w_radiusport = 'Radius-Port' +a_w_radiussrv = 'Radius-Server' +a_w_rxantenna = 'Empfangsantenne' +a_w_txantenna = 'Sendeantenne' +a_w_txpwr = 'Sendeleistung' +a_w_wifi1 = 'Hier finden sich Konfiugrationsmöglichkeiten für Drahtlos-Netzwerke nach dem WLAN-Standard.' +a_w_wifi2 = '802.11b/g/a/n-Geräte können so einfach in das bestehende physische Netzwerk integriert werden. Die Unterstützung von virtuellen Adaptern ermöglicht auch den Einsatz als Wireless-Repeater oder von mehreren Netzwerken gleichzeitig auf einem Gerät.' +a_w_wifi3 = 'Es werden Managed, Client, Ad-Hoc und WDS-Modus unterstützt sowie WPA und WPA2-Verschlüsselung zur gesicherten Kommunikation.' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_client = 'Client' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_monitor = 'Monitor' +a_w_wds = 'WDS' +accept = 'Annehmen' +aliases = 'Aliasse' +bitrate = 'Bitrate' +c_contributors = 'Mitwirkende Entwickler' +c_leaddev = 'Leitende Entwicklung' +c_lucidesc = 'LuCI ist eine Sammlung freier Lua-Software einschließlich eines MVC-Webframeworks und einer Weboberfläche für eingebettete Geräte. Luci steht unter der Apache-Lizenz.' +c_projecthome = 'Projekt Homepage' +c_thanksto = 'Dank an' +configure = 'Konfigurieren' +contact = 'Kontakt' +contact1 = 'Diese Daten sind auf der öffentlichen Kontaktseite sichtbar. Bitte gib an, wie man dich am besten kontaktieren kann. Diese Informationen sollten nach der Picopeering Vereinbarung mindestens deine E-Mail-Adresse enthalten. Damit dein Knoten durch Topographieprogramme erfasst werden kann, gib bitte deine Geokoordinaten oder zumindest deine Straße und Hausnummer unter Standort an.' +coord = 'Koordinaten' +coord1 = 'Bitte als Breite;Länge (z.B: 51.5;12.9) angeben' +cpu = 'Prozessor' +decline = 'Ablehnen' +defroutes = 'Standardrouten' +destination = 'Ziel' +dhcp_dhcp_dynamicdhcp = 'Dynamisches DHCP' +dhcp_dhcp_force = 'Start erzwingen' +dhcp_dhcp_ignore = 'Schnittstelle ignorieren' +dhcp_dhcp_ignore_desc = 'DHCP für dieses Netzwerk deaktivieren' +dhcp_dhcp_leasetime = 'Laufzeit' +dhcp_dhcp_dhcpoption = 'DHCP-Optionen' +dhcp_dhcp_dhcpoption_desc = 'Siehe "dnsmasq --help dhcp" für eine Liste verfügbarer Optionen.' +dhcp_dhcp_limit_desc = 'Anzahl zu vergebender Adressen -1' +dhcp_dhcp_start_desc = 'Erste vergebene Adresse (letztes Oktett)' +dhcp_dnsmasq_addnhosts = 'Zusätzliche Hostdatei' +dhcp_dnsmasq_authoritative = 'Authoritativ' +dhcp_dnsmasq_authoritative_desc = 'Dies ist der einzige DHCP im lokalen Netz' +dhcp_dnsmasq_boguspriv = 'Private Anfragen filtern' +dhcp_dnsmasq_boguspriv_desc = 'Reverse DNS-Anfragen für lokale Netze nicht weiterleiten' +dhcp_dnsmasq_dhcpleasemax = 'max. DHCP-Leases' +dhcp_dnsmasq_dnsforwardmax = 'gleichzeitige Abfragen' +dhcp_dnsmasq_domain = 'Lokale Domain' +dhcp_dnsmasq_domainneeded = 'Anfragen nur mit Domain' +dhcp_dnsmasq_domainneeded_desc = 'Anfragen ohne Domainnamen nicht weiterleiten' +dhcp_dnsmasq_ednspacket_max = 'max. EDNS.0 Paketgröße' +dhcp_dnsmasq_expandhosts = 'Erweitere Hosts' +dhcp_dnsmasq_expandhosts_desc = 'Fügt Domainnamen zu einfachen Hosteinträgen in der Resolvdatei hinzu' +dhcp_dnsmasq_filterwin2k = 'Windowsanfragen filtern' +dhcp_dnsmasq_filterwin2k_desc = 'nutzlose DNS-Anfragen aktueller Windowssysteme filtern' +dhcp_dnsmasq_leasefile = 'Leasedatei' +dhcp_dnsmasq_leasefile_desc = 'Speicherort für vergebenen DHCP-Adressen' +dhcp_dnsmasq_local = 'Lokale Server' +dhcp_dnsmasq_localisequeries = 'Lokalisiere Anfragen' +dhcp_dnsmasq_localisequeries_desc = 'Gibt die Adresse eines Hostnamen entsprechend seines Subnetzes zurück' +dhcp_dnsmasq_logqueries = 'Schreibe Abfragelog' +dhcp_dnsmasq_nohosts = 'Ignoriere /etc/hosts' +dhcp_dnsmasq_nonegcache = 'Unbekannte nicht cachen' +dhcp_dnsmasq_nonegcache_desc = 'Negative DNS-Antworten nicht zwischenspeichern' +dhcp_dnsmasq_noresolv = 'Ignoriere Resolvdatei' +dhcp_dnsmasq_port = 'DNS-Port' +dhcp_dnsmasq_queryport = 'Abfrageport' +dhcp_dnsmasq_readethers = 'Verwende /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Lese Informationen aus /etc/ethers um den DHCP-Server zu konfigurieren' +dhcp_dnsmasq_resolvfile = 'Resolvdatei' +dhcp_dnsmasq_resolvfile_desc = 'Lokale DNS-Datei' +dhcp_dnsmasq_strictorder = 'Strikte Reihenfolge' +dhcp_dnsmasq_strictorder_desc = 'DNS-Server werden strikt der Reihenfolge in der Resolvdatei nach abgefragt' +dhcp_dnsmasq_enabletftp = 'TFTP-Server aktivieren' +dhcp_dnsmasq_tftproot = 'TFTP-Server Wurzelverzeichnis' +dhcp_dnsmasq_dhcpboot = 'Netzwerk-Boot Abbild' +file = 'Datei' +frag = 'Frag.' +frequency = 'Frequenz' +iface = 'Schnittstelle' +iwscan = 'WLAN-Scan' +iwscan1 = 'Drahtlosnetzwerke in der lokalen Umgebung des Routers:' +iwscan_encr = 'Vers.' +iwscan_link = 'Verb.' +iwscan_noise = 'Rausch' +iwscan_signal = 'Signal' +link = 'Verb.' +dhcp_leases = 'Zuweisungen' +luci_ethers = 'Statische Einträge' +dhcp_timeremain = 'Verbleibende Gültigkeit' +dhcp_leases_active = 'Aktive Zuweisungen' +network_interface_prereq = 'Für die Unterstützung von UMTS/GPRS muss "comgt", für PPPoE "ppp-mod-pppoe", für PPPoA "ppp-mod-pppoa" und für PPtP "pptp" installiert sein' +network_interface_prereq_mini = 'Für die Unterstützung von PPPoE muss "ppp-mod-pppoe" und für PPtP "pptp" installiert sein' +network_interface_demand = 'Automatische Trennung' +network_interface_demand_desc = 'Zeit (in s) nach der die Verbindung bei Inaktivität getrennt wird' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'Anzahl fehlgeschlagener Verbindungstests nach der automatisch neu verbunden wird' +network_interface_server = 'PPTP-Server' +network_interface_device = 'Modemgerät' +network_interface_device_desc = 'Geräteknoten des Modems, z.B. /dev/ttyUSB0' +network_interface_defaultroute = 'Standardroute ersetzen' +network_interface_defaultroute_desc = 'Lässt pppd die aktuelle Standardroute ersetzen und über die PPP Schnittstelle leiten' +network_interface_peerdns = 'DNS der Gegenstelle nutzen' +network_interface_peerdns_desc = 'Konfiguriert den lokalen DNS-Server so, dass er die von der Gegenstelle angekündigten Nameserver-Adressen nutzt' +network_interface_ipv6 = 'IPv6 für die PPP-Verbindung aktivieren' +network_interface_connect = 'Verbindungs-Script' +network_interface_connect_desc = 'Lässt pppd das angegebene Script nach dem Aufbau der PPP Verbindung abarbeiten' +network_interface_disconnect = 'Trennuns-Script' +network_interface_disconnect_desc = 'Lässt pppd das angegebene Script vor dem Trennen der PPP Verbindung abarbeiten' +network_interface_pppd_options = 'Weitere pppd Optionen' +network_interface_pppd_options_desc = 'Hier können zusätzliche Kommandozeilenargumente für pppd angegeben werden' +network_interface_apn = 'Zugriffspunkt (APN)' +network_interface_pincode = 'PIN-Code' +network_interface_pincode_desc = 'Stellen Sie sicher das die richtige PIN hier eingetragen wird, sonst könnte die SIM-Karte gesperrt werden!' +network_interface_service = 'Dienstart' +network_interface_maxwait = 'Initialisierungszeit' +network_interface_maxwait_desc = 'Zeit in Sekunden um auf die Initialisierung des Modems zu warten bevor ein Verbindungsversuch unternommen wird' +network_switch_desc = 'Die zu einem VLAN gehörenden Schnittstellen werden durch Leerzeichen getrennt. Die Schnittstelle mit der höchsten Nummer (meistens 5) bildet in der Regel die Verbindung zur internen Netzschnittstelle des Routers. Bei Geräten mit 5 Schnittstellen ist in der Regel die Schnittstelle mit der niedrigsten Nummer (0) die standardmäßige Uplinkschnittstelle des Routers.' +network_interface_encaps = 'PPPoA Kapselung' + +noise = 'Rausch' +power = 'Leistung' +routes = 'Routen' +routes_gateway = 'Gateway' +routes_metric = 'Metrik' +routes_netmask = 'Netzmaske' +rts = 'RTS' +signal = 'Signal' +status = 'Status' +system_type = 'Systemtyp' +texteditor = 'Texteditor' +uci_applied = 'Die folgenden Änderungen wurden übernommen' +uci_reverted = 'Die folgenden Änderungen wurden verworfen' +m_n_local = 'Lokales Netz' +m_n_inet = 'Internetverbindung' +m_n_route = 'Weiterleiten' +m_n_bridge = 'Ãœberbrücken' +m_w_ap = 'Anbieten (Access Point)' +m_w_adhoc = 'Unabhängig (Ad-Hoc)' +m_w_client = 'Einklinken (Client)' +m_w_wds = 'Verteilen (WDS)' +m_w_clientmode = 'Verbindungsmodus' +system_system_logsize = 'Größe des Systemprotokollpuffers' +system_system_logip = 'Externer Systemprotokollserver' +system_system_conloglevel = 'Protokollausgabelevel' +system_system_conloglevel_desc = 'Level auf der Konsole ausgegebener Meldungen' +m_i_processor = 'Prozessor' +m_i_memory = 'Hauptspeicher' +m_i_systemtime = 'Lokale Zeit' +m_i_uptime = 'Laufzeit' +m_n_d_firstaddress = 'Erste vergebene Adresse' +m_n_d_numleases = 'Anzahl vergebener Adressen' +routingtable = 'Routingtabelle' +wlanscan = 'WLAN-Scan' +m_n_keepalive = 'automatisch neu verbinden' +m_n_dialondemand = 'trennen bei Inaktivität nach' +m_n_pptp_server = 'PPTP-Server' +a_s_applyreboot1 = 'Änderungen angewandt.' +a_s_backup = 'Sichern / Wiederherstellen' +a_s_backup_backup = 'Sicherung erstellen' +a_s_backup_archive = 'Sicherungsarchiv' +a_s_backup_reset = 'Grundeinstellungen wiederherstellen' +a_s_backup_reset1 = 'Alle aktuellen Einstellungen verwerfen und Grundeinstellungen wiederherstellen?' +a_s_backup_restore = 'Sicherung wiederherstellen' +a_s_backup1 = 'Auf dieser Seite können Sicherungen der Konfiguration erstellt und eingespielt werden und - wenn möglich - die Grundeinstellungen wiederhergestellt werden.' +leds = 'LED Konfiguration' +leds_desc = 'Passt das Verhalten der Geräte-LEDs an - wenn dies möglich ist.' +system_led_name = 'LED Name' +system_led_sysfs = 'LED Gerät' +system_led_default = 'Grundzustand' +system_led_default_desc = 'ausgewählt = an' +system_led_trigger = 'Auslöser' +system_led_trigger_none = 'Keiner' +system_led_trigger_defaulton = 'Immer an' +system_led_trigger_timer = 'Taktgeber' +system_led_trigger_heartbeat = 'Herzschlag (Mittlere Systemlast)' +system_led_trigger_netdev = 'Netzwerkschnittstelle' +system_led_delayoff = 'Einschaltverzögerung' +system_led_delayoff_desc = 'Zeit (in ms) die die LED deaktiviert ist' +system_led_delayon = 'Ausschaltverzögerung' +system_led_delayon_desc = 'Zeit (in ms) die die LED aktiviert ist' +system_led_dev = 'Schnittstelle' +system_led_mode = 'Auslösemodus' +system_led_mode_link = 'Verbindung hergestellt' +system_led_mode_tx = 'Senden' +system_led_mode_rx = 'Empfangen' +network_interface_up = 'Aktiv' +network_interface_hwaddr = 'MAC-Adresse' +network_interface_hwaddr_desc = 'Hardware Adresse' +network_interface_txrx = 'Traffic' +network_interface_txrx_desc = 'gesendet / empfangen' +network_interface_err = 'Fehler' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Firewallzone anlegen / zuweisen' +network_interface_fwzone_desc = 'Diese Schnittstelle gehört bis jetzt zu keiner Firewallzone.' +process_head = 'Prozesse' +process_descr = 'Diese Tabelle gibt eine Ãœbersicht über aktuell laufende Systemprozeese und deren Status.' +process_pid = 'PID' +process_owner = 'Besitzer' +process_command = 'Befehl' +process_cpu = 'CPU-Nutzung (%)' +process_mem = 'Speichernutzung (%)' +process_hup = 'Auflegen' +process_term = 'Beenden' +process_kill = 'Töten' +mem_cached = 'gecached' +mem_buffered = 'gepuffert' +mem_free = 'frei' +a_s_crontab = 'Geplante Aufgaben' +a_s_crontab1 = 'Dies ist die System-Crontab in der geplante Aufgaben definiert werden können.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Pfad zum CA-Zertifikat' +a_w_eaptype = 'EAP-Methode' +a_w_tlsprivkey = 'Pfad zum Privaten Schlüssel' +a_w_tlsprivkeypwd = 'Passwort des Privaten Schlüssels' +a_w_peapauth = 'PEAP-Authentifizierung' +a_w_peapidentity = 'PEAP-Identitäz' +a_w_peappassword = 'PEAP-Passwort' +a_w_create = 'Netzwerk anlegen' +hostnames = 'Rechnernamen' +hostnames_entries = 'Host-Einträge' +hostnames_hostname = 'Rechnername' +hostnames_address = 'IP-Adresse' +luci_components = "LuCI Komponenten" +m_n_mssfix = "Segmentgrößen Clamping" +m_n_mssfix_desc = "Behebt Probleme bei nicht erreichbaren Webseiten, Absenden von Formularen oder anderes unerwartetes Verhalten für einige ISPs." +dhcp_desc = 'Mit DHCP können Netzwerkteilnehmer automatisch Einstellungen wie IP-Adresse, Präfix, DNS-Server, usw. beziehen.' diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.xml b/openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.xml new file mode 100644 index 0000000..15637d6 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/admin-core.de.xml @@ -0,0 +1,372 @@ + + + + +Dies ist der Administrationsbereich von LuCI. +LuCI ist eine freie, flexible und benutzerfreundliche grafische Oberfläche zur Konfiguration von OpenWrt Kamikaze. +Auf den folgenden Seiten können alle wichtigen Einstellungen des Routers vorgenommen werden. +Hinweis: In LuCI werden getätigte Änderungen erst nach einem Klick auf Änderungen - Speichern & Anwenden angewandt. +Wir sind natürlich stets darum bemüht, diese Oberfläche noch besser und intuitiver zu Gestalten und freuen uns über jegliche Art von Feedback oder Verbesserungsvorschlägen. +Und nun wünschen wir viel Spaß mit dem Router! +Hallo! +Das LuCI-Team +Zu übernehmende Dateien bei Firmwareupgrade +Die folgenden Dateien und Verzeichnisse werden beim Aktualisieren der Firmware über die Oberfläche automatisch in die neue Firmware übernommen. +Hier können Eigenschaften und die Funktionalität der Oberfläche angepasst werden. +UCI-Befehle beim Anwenden +Beim Anwenden der Konfiguration aus der Oberflächliche heraus können automatisch die relevanten Dienste neugestart werden, sodass Änderungen sofort nach dem Anwenden aktiv werden und der Router nicht erst neugestartet werden muss. +Benutzeroberfläche +Netzwerkbrücke +überbrückt angegebene Schnittstelle(n) +An dieser Stelle können die einzelnen Schnittstellen des Netzwerkes konfiguriert werden. Es können mehrere Schnittstellen zu einer Brücke zusammengefasst werden, indem diese durch Leerzeichen getrennt aufgezählt werden und ein entsprechender Haken im Feld Netzwerkbrücke gesetzt wird. Es können VLANs in der Notation SCHNITTSTELLE.VLANNR (z.B.: eth0.1) verwendet werden. +Punkt-zu-Punkt Verbindungen +Punkt-zu-Punkt Verbindungen über PPPoE oder PPTP werden häufig dazu verwendet, um über DSL o.ä. Techniken eine Verbindung zum Internetgateway eines Internetzugangsanbieters aufzubauen. +falls Ziel ein Netzwerk ist +Host-IP oder Netzwerk +IPv6 Host- oder Netzwerk-Addresse (CIDR) +Routen +IPv4 Routen +IPv6 Routen +Routen geben an, über welche Schnittstelle und welches Gateway ein bestimmter Host oder ein bestimmtes Netzwerk erreicht werden kann. +Statische Routen +Statische IPv4 Routen +Statische IPv6 Routen +Aktive IPv4-Routen +Aktive IPv6-Routen +Switch +Die Netzwerkschnittstellen am Router können zu verschienden VLANs zusammengefasst werden, in denen Geräte miteinander direkt kommunizieren können. VLANs werden auch häufig dazu genutzt, um Netzwerke voneiander zu trennen. So ist oftmals eine Schnittstelle als Uplink zu einem größerem Netz, wie dem Internet vorkonfiguriert und die anderen Schnittstellen bilden ein VLAN für das lokale Netzwerk. +Aktive Verbindungen +Diese Seite gibt eine Ãœbersicht über aktive Netzwerkverbindungen. +In diesem Bereich finden sich alle netzwerkbezogenen Einstellungen. +Der Netzwerkswitch kann bei den meisten Routern frei konfiguriert und in mehrere VLANs aufgeteilt werden. +Schnittstellen und PPPoE/PPTP-Einstellungen ermöglichen die freie Organisation des Netzwerks und die Anbindung an ein WAN. +DHCP ermöglichst die automatische Netzwerkkonfiguration von Rechnern im (W)LAN. +Portweiterleitung und Firewall erlauben eine effektive Absicherung des Netzes, bei gleichzeitiger Bereitstellung von externen Diensten. +Passwort ändern +Ändert das Passwort des Systemverwalters (Benutzer "root") +Passwort erfolgreich geändert +Passwörter stimmen nicht überein +An dieser Stelle können Grundeinstellungen des Systems wie Hostname oder Zeitzone vorgenommen werden. +Upgrade +Flashvorgang erfolgreich. Router startet neu... +Flashvorgang fehlgeschlagen +Firmwareimage +Abbild empfangen. Starte Flashvorgang. SCHALTEN SIE DAS GERÄT NICHT AUS! +Schreibe Firmware... +Firmware aktualisieren +Konfigurationsdateien übernehmen +Diese Funktion steht leider (noch) nicht zur Verfügung. +Ersetzt die installierte Firmware (das Betriebssystem des Routers) durch ein neues. Das Format der Firmware ist plattformabhängig. +Einhängepunkte +Eingehängte Dateisysteme +Benutzt +Verfügbar +Die Gerätedatei des Speichers oder der Partition (z.B.: /dev/sda) +Das Dateisystem mit dem der Speicher formatiert ist (z.B.: ext3) +Einhängepunkt +Einhängepunkte +Einhängepunkte bestimmen, an welcher Stelle des Dateisystems bestimmte Laufwerke und Speicher zur Verwendung eingebunden werden. +Falls der Arbeitsspeicher des Routers nicht ausreicht, kann dieser nicht benutzte Daten zeitweise auf einem SWAP-Laufwerk auslagern um so die effektive Größe des Arbeitsspeichers zu erhöhen. Die Auslagerung der Daten ist natürlich bedeutend langsamer als direkte Arbeitsspeicherzugriffe. +Hier finden sich Einstellungen, die das System selbst, dessen Kennung, installierte Software und Hardware, Authentifizierung oder eingehängte Speicher betreffen. +Diese Einstellungen definieren die Grundlage des Systems, auf dem die installierte Software aufbaut. +Beachte bitte, dass eine fehlerhafte Konfiguration den Start des Routers verhindern oder dich vom Zugriff auf diesen ausschließen kann. +OPKG-Konfiguration +Paketlisten +Installationsziele +Paketverwaltung +Aktionen ausführen +Installation von +Paket herunterladen und installieren +Paketlisten und Installationsziele bearbeiten +Paketname +Deinstallation von +Paket suchen +Paketlisten aktualisieren +Paketlisten aktualisieren +Installierte Pakete aktualisieren +Startet das Betriebssystem des Routers neu. +Neustart durchführen +Bitte warten: Neustart wird durchgeführt... +Warnung: Es gibt ungespeicherte Änderungen, die beim Neustart verloren gehen! +SSH-Schlüssel +Hier können öffentliche SSH-Schlüssel (einer pro Zeile) zur Authentifizierung abgelegt werden. +Passwortanmeldung +Erlaube Anmeldung per Passwort +Der SSH-Server ermöglicht Shell-Zugriff über das Netzwerk und bietet einen integrierten SCP-Dienst. +Ein kleiner Webserver, der für die Bereitstellung von LuCI genutzt werden kann. +Anmeldeaufforderung +Aufforderungstext zum Anmelden im Administrationsbereich +/etc/httpd.conf wenn leer +Wurzelverzeichnis +Dienste und Dämonen stellen bestimmte Funktionalitäten auf dem Router zur Verfügung. +Es handelt sich hierbei meist um Netzwerkserver, die verschiedene Aufgaben auf dem Router erfüllen, beispielsweise Shell-Zugang ermöglichen oder diese Weboberfläche per HTTP anbieten. +Hier finden sich Informationen über den aktuellen Status des Systems, beispielsweise Prozessortakt, Speicherauslastung und Netzwerkschnittstellen. +Zusätzlich können hier Protokolldaten, des Kernels und diverser Systemdienste eingesehen werden, um deren Zustand zu kontrollieren. +An dieser Stelle können eingebaute WLAN-Geräte konfiguriert werden. +AP-Isolation +Unterbindet Client-Client-Verkehr +Atheros-Frameburst +Broadcom-Frameburst +Funkkanal +Verbindungslimit +Ländercode +Distanz zum am weitesten entfernten Funkpartner (m) +Diversität +ESSID verstecken +Netzkennung (ESSID) +WLAN-Netz zu Netzwerk hinzufügen +Pro WLAN-Gerät können mehrere Netze bereitgestellt werden. Es sollte beachtet werden, dass es hardware- / treiberspezifische Einschränkungen gibt. So kann pro WLAN-Gerät in der Regel entweder 1 Ad-Hoc-Zugang ODER bis zu 3 Access-Point und 1 Client-Zugang gleichzeitig erstellt werden. + - Neues Netzwerk erstellen - +Radius-Port +Radius-Server +Empfangsantenne +Sendeantenne +Sendeleistung +Hier finden sich Konfiugrationsmöglichkeiten für Drahtlos-Netzwerke nach dem WLAN-Standard. +802.11b/g/a/n-Geräte können so einfach in das bestehende physische Netzwerk integriert werden. Die Unterstützung von virtuellen Adaptern ermöglicht auch den Einsatz als Wireless-Repeater oder von mehreren Netzwerken gleichzeitig auf einem Gerät. +Es werden Managed, Client, Ad-Hoc und WDS-Modus unterstützt sowie WPA und WPA2-Verschlüsselung zur gesicherten Kommunikation. +Access Point +Ad-Hoc +Client +Pseudo Ad-Hoc (ahdemo) +Monitor +WDS +Annehmen +Aliasse +Bitrate +Mitwirkende Entwickler +Leitende Entwicklung +LuCI ist eine Sammlung freier Lua-Software einschließlich eines MVC-Webframeworks und einer Weboberfläche für eingebettete Geräte. Luci steht unter der Apache-Lizenz. +Projekt Homepage +Dank an +Konfigurieren +Kontakt +Diese Daten sind auf der öffentlichen Kontaktseite sichtbar. Bitte gib an, wie man dich am besten kontaktieren kann. Diese Informationen sollten nach der Picopeering Vereinbarung mindestens deine E-Mail-Adresse enthalten. Damit dein Knoten durch Topographieprogramme erfasst werden kann, gib bitte deine Geokoordinaten oder zumindest deine Straße und Hausnummer unter Standort an. +Koordinaten +Bitte als Breite;Länge (z.B: 51.5;12.9) angeben +Prozessor +Ablehnen +Standardrouten +Ziel +Dynamisches DHCP +Start erzwingen +Schnittstelle ignorieren +DHCP für dieses Netzwerk deaktivieren +Laufzeit +DHCP-Optionen +Siehe "dnsmasq --help dhcp" für eine Liste verfügbarer Optionen. +Anzahl zu vergebender Adressen -1 +Erste vergebene Adresse (letztes Oktett) +Zusätzliche Hostdatei +Authoritativ +Dies ist der einzige DHCP im lokalen Netz +Private Anfragen filtern +Reverse DNS-Anfragen für lokale Netze nicht weiterleiten +max. DHCP-Leases +gleichzeitige Abfragen +Lokale Domain +Anfragen nur mit Domain +Anfragen ohne Domainnamen nicht weiterleiten +max. EDNS.0 Paketgröße +Erweitere Hosts +Fügt Domainnamen zu einfachen Hosteinträgen in der Resolvdatei hinzu +Windowsanfragen filtern +nutzlose DNS-Anfragen aktueller Windowssysteme filtern +Leasedatei +Speicherort für vergebenen DHCP-Adressen +Lokale Server +Lokalisiere Anfragen +Gibt die Adresse eines Hostnamen entsprechend seines Subnetzes zurück +Schreibe Abfragelog +Ignoriere /etc/hosts +Unbekannte nicht cachen +Negative DNS-Antworten nicht zwischenspeichern +Ignoriere Resolvdatei +DNS-Port +Abfrageport +Verwende /etc/ethers +Lese Informationen aus /etc/ethers um den DHCP-Server zu konfigurieren +Resolvdatei +Lokale DNS-Datei +Strikte Reihenfolge +DNS-Server werden strikt der Reihenfolge in der Resolvdatei nach abgefragt +TFTP-Server aktivieren +TFTP-Server Wurzelverzeichnis +Netzwerk-Boot Abbild +Datei +Frag. +Frequenz + +Schnittstelle +WLAN-Scan +Drahtlosnetzwerke in der lokalen Umgebung des Routers: +Vers. +Verb. +Rausch +Signal +Verb. + +Zuweisungen +Statische Einträge +Verbleibende Gültigkeit +Aktive Zuweisungen + +Für die Unterstützung von UMTS/GPRS muss "comgt", für PPPoE "ppp-mod-pppoe", für PPPoA "ppp-mod-pppoa" und für PPtP "pptp" installiert sein +Für die Unterstützung von PPPoE muss "ppp-mod-pppoe" und für PPtP "pptp" installiert sein +Automatische Trennung +Zeit (in s) nach der die Verbindung bei Inaktivität getrennt wird +Keep-Alive +Anzahl fehlgeschlagener Verbindungstests nach der automatisch neu verbunden wird +PPTP-Server +Modemgerät +Geräteknoten des Modems, z.B. /dev/ttyUSB0 +Standardroute ersetzen +Lässt pppd die aktuelle Standardroute ersetzen und über die PPP Schnittstelle leiten +DNS der Gegenstelle nutzen +Konfiguriert den lokalen DNS-Server so, dass er die von der Gegenstelle angekündigten Nameserver-Adressen nutzt +IPv6 für die PPP-Verbindung aktivieren +Verbindungs-Script +Lässt pppd das angegebene Script nach dem Aufbau der PPP Verbindung abarbeiten +Trennuns-Script +Lässt pppd das angegebene Script vor dem Trennen der PPP Verbindung abarbeiten +Weitere pppd Optionen +Hier können zusätzliche Kommandozeilenargumente für pppd angegeben werden +Zugriffspunkt (APN) +PIN-Code +Stellen Sie sicher das die richtige PIN hier eingetragen wird, sonst könnte die SIM-Karte gesperrt werden! +Dienstart +Initialisierungszeit +Zeit in Sekunden um auf die Initialisierung des Modems zu warten bevor ein Verbindungsversuch unternommen wird +Die zu einem VLAN gehörenden Schnittstellen werden durch Leerzeichen getrennt. Die Schnittstelle mit der höchsten Nummer (meistens 5) bildet in der Regel die Verbindung zur internen Netzschnittstelle des Routers. Bei Geräten mit 5 Schnittstellen ist in der Regel die Schnittstelle mit der niedrigsten Nummer (0) die standardmäßige Uplinkschnittstelle des Routers. +PPPoA Kapselung + +Rausch +Leistung +Routen +Gateway +Metrik +Netzmaske +RTS +Signal +Status +Systemtyp +Texteditor +Die folgenden Änderungen wurden übernommen +Die folgenden Änderungen wurden verworfen + +Lokales Netz +Internetverbindung +Weiterleiten +Ãœberbrücken + +Anbieten (Access Point) +Unabhängig (Ad-Hoc) +Einklinken (Client) +Verteilen (WDS) +Verbindungsmodus + + +Größe des Systemprotokollpuffers +Externer Systemprotokollserver +Protokollausgabelevel +Level auf der Konsole ausgegebener Meldungen + +Prozessor +Hauptspeicher +Lokale Zeit +Laufzeit + +Erste vergebene Adresse +Anzahl vergebener Adressen + +Routingtabelle +WLAN-Scan + + +automatisch neu verbinden +trennen bei Inaktivität nach +PPTP-Server + +Änderungen angewandt. + +Sichern / Wiederherstellen +Sicherung erstellen +Sicherungsarchiv +Grundeinstellungen wiederherstellen +Alle aktuellen Einstellungen verwerfen und Grundeinstellungen wiederherstellen? +Sicherung wiederherstellen +Auf dieser Seite können Sicherungen der Konfiguration erstellt und eingespielt werden und - wenn möglich - die Grundeinstellungen wiederhergestellt werden. + +LED Konfiguration +Passt das Verhalten der Geräte-LEDs an - wenn dies möglich ist. +LED Name +LED Gerät +Grundzustand +ausgewählt = an +Auslöser +Keiner +Immer an +Taktgeber +Herzschlag (Mittlere Systemlast) +Netzwerkschnittstelle +Einschaltverzögerung +Zeit (in ms) die die LED deaktiviert ist +Ausschaltverzögerung +Zeit (in ms) die die LED aktiviert ist +Schnittstelle +Auslösemodus +Verbindung hergestellt +Senden +Empfangen + +Aktiv +MAC-Adresse +Hardware Adresse +Traffic +gesendet / empfangen +Fehler +TX / RX + +Firewallzone anlegen / zuweisen +Diese Schnittstelle gehört bis jetzt zu keiner Firewallzone. + +Prozesse +Diese Tabelle gibt eine Ãœbersicht über aktuell laufende Systemprozeese und deren Status. +PID +Besitzer +Befehl +CPU-Nutzung (%) +Speichernutzung (%) +Auflegen +Beenden +Töten + +gecached +gepuffert +frei + +Geplante Aufgaben +Dies ist die System-Crontab in der geplante Aufgaben definiert werden können. + +NAS ID +Pfad zum CA-Zertifikat +EAP-Methode +Pfad zum Privaten Schlüssel +Passwort des Privaten Schlüssels +PEAP-Authentifizierung +PEAP-Identitäz +PEAP-Passwort + +Netzwerk anlegen + +Rechnernamen +Host-Einträge +Rechnername +IP-Adresse + +Segmentgrößen Clamping +Behebt Probleme bei nicht erreichbaren Webseiten, Absenden von Formularen oder anderes unerwartetes Verhalten für einige ISPs. +Mit DHCP können Netzwerkteilnehmer automatisch Einstellungen wie IP-Adresse, Präfix, DNS-Server, usw. beziehen. + + + diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.lua b/openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.lua new file mode 100644 index 0000000..7f7087b --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.lua @@ -0,0 +1,16 @@ +cbi_add = 'Eintrag hinzufügen' +cbi_del = 'Eintrag entfernen' +cbi_replace = 'Eintrag ersetzen' +cbi_invalid = 'Ungültige Eingabe' +cbi_invalid_section = 'Validierung fehlgeschlagen: Bitte die Eingabefelder auf Fehler überprüfen.' +cbi_missing = 'Dieses Feld muss ausgefüllt werden' +cbi_deperror = 'Validierung fehlgeschlagen: Mindestens ein benötigtes Feld ist leer oder hat einen ungültigen Wert' +cbi_reqerror = 'Nicht erfüllte Abhängigkeit für dieses Feld' +cbi_addopt = '-- Zusätzliches Feld --' +cbi_sectempty = 'Diese Sektion enthält noch keine Einträge' +cbi_manual = '-- benutzerdefiniert --' +cbi_select = '-- Bitte auswählen --' +cbi_gorel = 'Gehe zu relevanter Konfigurationsseite' +cbi_applying = 'Änderungen werden angewandt' +cbi_upload = 'hochgeladene Datei' +cbi_browser = 'Datei suchen...' diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.xml b/openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.xml new file mode 100644 index 0000000..1726cd8 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/cbi.de.xml @@ -0,0 +1,22 @@ + + + + +Eintrag hinzufügen +Eintrag entfernen +Eintrag ersetzen +Ungültige Eingabe +Validierung fehlgeschlagen: Bitte die Eingabefelder auf Fehler überprüfen. +Dieses Feld muss ausgefüllt werden +Validierung fehlgeschlagen: Mindestens ein benötigtes Feld ist leer oder hat einen ungültigen Wert +Nicht erfüllte Abhängigkeit für dieses Feld +-- Zusätzliches Feld -- +Diese Sektion enthält noch keine Einträge +-- benutzerdefiniert -- +-- Bitte auswählen -- +Gehe zu relevanter Konfigurationsseite +Änderungen werden angewandt +hochgeladene Datei +Datei suchen... + + diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.lua b/openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.lua new file mode 100644 index 0000000..238cba5 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.lua @@ -0,0 +1,102 @@ +skiplink1 = 'Zur Navigation springen' +skiplink2 = 'Zum Inhalt springen' +navigation = 'Navigation' +about = 'Ãœber' +add = 'Hinzufügen' +addresses = 'Adressen' +aliases = 'Aliasse' +all = 'alle' +administration = 'Administration' +essentials = 'Vereinfacht' +apply = 'Anwenden' +back = 'zurück' +basicsettings = 'Grundeinstellungen' +broadcast = 'IPv4-Broadcast' +changes = 'Änderungen' +channel = 'Kanal' +cidr6 = 'CIDR-Notation: Adresse/Prefix' +code = 'Code' +config = 'Konfiguration' +configfile = 'Konfigurationsdatei' +confirmation = 'Bestätigung' +delete = 'Löschen' +descr = 'Beschreibung' +design = 'Design' +destination = 'Ziel' +device = 'Gerät' +devices = 'Geräte' +disable = 'deaktivieren' +distance = 'Distanz' +dmesg = 'Kernelprotokoll' +dnsserver = 'DNS-Server' +edit = 'Bearbeiten' +enable = 'aktivieren' +encryption = 'Verschlüsselung' +error = 'Fehler' +filesystem = 'Dateisystem' +filter = 'Filter' +gateway = 'IPv4-Gateway' +gateway6 = 'IPv6-Gateway' +general = 'Allgemeines' +hostname = 'Hostname' +install = 'Installieren' +installed = 'installiert' +interface = 'Schnittstelle' +interfaces = 'Schnittstellen' +ipaddress = 'IPv4-Adresse' +ip6address = 'IPv6-Adresse' +legend = 'Legende' +library = 'Bibliothek' +load = 'Last' +login = 'Anmelden' +logout = 'Abmelden' +key = 'Schlüssel' +language = 'Sprache' +limit = 'Limit' +macaddress = 'MAC-Adresse' +manpage = 'siehe '%s' manpage' +metric = 'Metrik' +mode = 'Modus' +name = 'Name' +netmask = 'IPv4-Netzmaske' +network = 'Netzwerk' +networks = 'Netzwerke' +none = 'keine' +notinstalled = 'nicht installiert' +ok = 'OK' +options = 'Optionen' +overview = 'Ãœbersicht' +packagemanager = 'Packet-Manager' +password = 'Passwort' +path = 'Pfad' +port = 'Port' +ports = 'Ports' +protocol = 'Protokoll' +reboot = 'Neu Starten' +reset = 'Zurücksetzen' +revert = 'Verwerfen' +save = 'Speichern' +saveapply = 'Speichern & Anwenden' +scan = 'Scan' +service = 'Dienst' +services = 'Dienste' +settings = 'Einstellungen' +size = 'Größe' +source = 'Quelle' +start = 'Start' +static = 'statisch' +statistics = 'Statistiken' +status = 'Status' +submit = 'Absenden' +syslog = 'Systemprotokoll' +system = 'System' +target = 'Ziel' +timezone = 'Zeitzone' +type = 'Typ' +unknownerror = 'Unbekannter Fehler' +unsavedchanges = 'Ungespeicherte Änderungen' +username = 'Benutzername' +version = 'Version' +webui = 'Weboberfläche' +wifi = 'Drahtlos' +zone = 'Zone' diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.xml b/openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.xml new file mode 100644 index 0000000..fb1348d --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/default.de.xml @@ -0,0 +1,131 @@ + + + + +Zur Navigation springen +Zum Inhalt springen +Navigation + +Ãœber +Hinzufügen +Adressen +Aliasse +alle +Administration +Vereinfacht + +Anwenden + +zurück +Grundeinstellungen +IPv4-Broadcast + +Änderungen +Kanal +CIDR-Notation: Adresse/Prefix +Code +Konfiguration +Konfigurationsdatei +Bestätigung + +Löschen +Beschreibung +Design +Ziel +Gerät +Geräte +deaktivieren +Distanz +Kernelprotokoll +DNS-Server + +Bearbeiten +aktivieren +Verschlüsselung +Fehler + +Dateisystem +Filter + +IPv4-Gateway +IPv6-Gateway +Allgemeines + +Hostname + +Installieren +installiert +Schnittstelle +Schnittstellen +IPv4-Adresse +IPv6-Adresse + +Legende +Bibliothek +Last +Anmelden +Abmelden + +Schlüssel + +Sprache +Limit + +MAC-Adresse +siehe '%s' manpage +Metrik +Modus + +Name +IPv4-Netzmaske +Netzwerk +Netzwerke +keine +nicht installiert + +OK +Optionen +Ãœbersicht + +Packet-Manager +Passwort +Pfad +Port +Ports +Protokoll + +Neu Starten +Zurücksetzen +Verwerfen + +Speichern +Speichern & Anwenden +Scan +Dienst +Dienste +Einstellungen +Größe +Quelle +Start +statisch +Statistiken +Status +Absenden +Systemprotokoll +System + +Ziel +Zeitzone +Typ + +Unbekannter Fehler +Ungespeicherte Änderungen +Benutzername + +Version + +Weboberfläche +Drahtlos +Zone + + diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.lua b/openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.lua new file mode 100644 index 0000000..164064b --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Autorisation benötigt' +sysauth_prompt = 'Bitte Benutzernamen und Passwort eingeben.' +sysauth_failed = 'Ungültiger Benutzername und/oder ungültiges Passwort! Bitte nocheinmal versuchen.' diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.xml b/openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.xml new file mode 100644 index 0000000..5eec4b8 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/sysauth.de.xml @@ -0,0 +1,9 @@ + + + + +Autorisation benötigt +Bitte Benutzernamen und Passwort eingeben. +Ungültiger Benutzername und/oder ungültiges Passwort! Bitte nocheinmal versuchen. + + diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.lua b/openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.lua new file mode 100644 index 0000000..3e48b35 --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.lua @@ -0,0 +1,37 @@ +wifi_auto = 'auto' +wifi_fh = 'Frequenzsprung' +wifi_diversity = 'Diversität' +wifi_txantenna = 'Sendeantenne' +wifi_rxantenna = 'Empfangsantenne' +wifi_distance = 'Distanzoptimierung' +wifi_distance_desc = 'Distanz zum am weitesten entfernten Funkpartner in Meter.' +wifi_macpolicy = 'MAC-Adressfilter' +wifi_whitelist = 'Nur gelistete erlauben' +wifi_blacklist = 'Alle außer gelistete erlauben' +wifi_maclist = 'MAC-Adressliste' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Ländercode' +wifi_maxassoc = 'Verbindungsbegrenzung' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Fragmentierungsschwelle' +wifi_rts = 'RTS/CTS-Schwelle' +wifi_wds = 'WDS' +wifi_wdssep = 'Separates WDS' +wifi_hidden = 'ESSID verstecken' +wifi_isloate = 'Clients isolieren' +wifi_isloate_desc = 'Verhindert Client zu Client Kommunikation' +wifi_bgscan = 'Hintergrundscan' +wifi_rate = 'Ãœbertragungsrate' +wifi_mcast_rate = 'Multicastrate' +wifi_minrate = 'Mindestübertragungsrate' +wifi_maxrate = 'Höchstübertragungsrate' +wifi_compression = 'Kompression' +wifi_turbo = 'Turbo Modus' +wifi_ff = 'Schnelle Frames' +wifi_wmm = 'WMM Modus' +wifi_xr = 'XR-Unterstützung' +wifi_ar = 'AR-Unterstützung' +wifi_nosbeacon = 'Deaktiviere Hardware-Beacon Zeitgeber' +wifi_noprobereq = 'Scan-Anforderungen nicht beantworten' +wifi_wpareq = 'Für WPA-Verschlüsselung muss wpa_supplicant (für Clientmodus) oder hostapd (für AP und Ad-hoc-Modus) installiert sein.' diff --git a/openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.xml b/openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.xml new file mode 100644 index 0000000..040bffa --- /dev/null +++ b/openwrt/packages/luci/i18n/german/luasrc/i18n/wifi.de.xml @@ -0,0 +1,44 @@ + + + + +auto +Frequenzsprung +Diversität +Sendeantenne +Empfangsantenne +Distanzoptimierung +Distanz zum am weitesten entfernten Funkpartner in Meter. +MAC-Adressfilter +Nur gelistete erlauben +Alle außer gelistete erlauben +MAC-Adressliste +Frame Bursting +Ländercode +Verbindungsbegrenzung +ESSID +BSSID +Fragmentierungsschwelle +RTS/CTS-Schwelle +WDS +Separates WDS +ESSID verstecken +Clients isolieren +Verhindert Client zu Client Kommunikation +Hintergrundscan +Ãœbertragungsrate +Multicastrate +Mindestübertragungsrate +Höchstübertragungsrate +Kompression +Turbo Modus +Schnelle Frames +WMM Modus +XR-Unterstützung +AR-Unterstützung +Deaktiviere Hardware-Beacon Zeitgeber +Scan-Anforderungen nicht beantworten + +Für WPA-Verschlüsselung muss wpa_supplicant (für Clientmodus) oder hostapd (für AP und Ad-hoc-Modus) installiert sein. + + diff --git a/openwrt/packages/luci/i18n/german/root/etc/uci-defaults/luci-i18n-german b/openwrt/packages/luci/i18n/german/root/etc/uci-defaults/luci-i18n-german new file mode 100755 index 0000000..26a928f --- /dev/null +++ b/openwrt/packages/luci/i18n/german/root/etc/uci-defaults/luci-i18n-german @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.languages.de=Deutsch + commit luci +EOF + diff --git a/openwrt/packages/luci/i18n/italian/Makefile b/openwrt/packages/luci/i18n/italian/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/i18n/italian/ipkg/postinst b/openwrt/packages/luci/i18n/italian/ipkg/postinst new file mode 100755 index 0000000..623ef1c --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-i18n-italian ) && rm -f /etc/uci-defaults/luci-i18n-italian +} diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.lua b/openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.lua new file mode 100644 index 0000000..2a62788 --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.lua @@ -0,0 +1,327 @@ +uci_applied = 'Le seguenti modifiche sono state applicate' +uci_reverted = 'Le seguenti modifiche sono state annullate' +a_i_ui = 'Interfaccia utente' +c_lucidesc = 'LuCI è una collezione di software libero scritto in Lua comprendente un Webframework e interfaccia web MVC per dispositivi integrati. LuCI è rilasciato sotto la Apache-License.' +c_projecthome = 'Sito del progetto' +c_leaddev = 'Lead Development' +c_contributors = 'Contributing Developers' +c_thanksto = 'Ringraziamenti' +a_i_i_hello = 'Ciao!' +a_i_i_admin1 = 'Questa è l'area d'amministrazione di LuCI.' +a_i_i_admin2 = 'LuCI è un'interfaccia grafica gratuita, flessibile, e amichevole per configurare OpenWrt Kamikaze.' +a_i_i_admin3 = 'Nelle seguenti pagine puoi impostare tutti i settaggi più importanti del tuo router' +a_i_i_admin4 = 'Nota: Le modifiche devono essere confermate in LuCI cliccando Modifiche - Salva e Applica prima di essere applicate.' +a_i_i_admin5 = 'dal momento che vogliamo migliorare quest'interfaccia accettiamo suggerimenti.' +a_i_i_admin6 = 'Ed ora buon divertimento con il tuo router!' +a_i_i_team = 'Il Team di LuCI' +a_i_luci1 = 'Qui puoi personalizzare i settaggi e le funzionalità di LuCI.' +a_i_ucicommit = 'Azioni post-modifica' +a_i_ucicommit1 = 'Questi comandi verranno eseguiti automaticamente quando un comando di configurazione UCI viene applicato permettendo alle modifiche di essere applicate immediatamente.' +a_i_keepflash = 'Files da conservare quando si aggiorna un nuovo firmware' +a_i_keepflash1 = 'Quando si aggiorna un firmware con LuCI questi files verranno aggiunti al nuovo firmware.' +a_st_i_status1 = 'Qui puoi trovare informazione sullo stato del sistema come frequenza di clock della CPU, uso della memoria o dati della scheda di rete.' +a_st_i_status2 = 'Inoltre i log del kernel o dei servizi sono visualizzabili qui per avere un riassunto dello stato attuale.' +iwscan = 'Scansione WLAN' +iwscan1 = 'Reti Wifi nell'ambiente circostante' +iwscan_encr = 'Encr.' +iwscan_link = 'Collegamento' +iwscan_signal = 'Segnale' +iwscan_noise = 'Disturbo' +routes = 'Route' +routes_netmask = 'Maschera di rete' +routes_gateway = 'Gateway' +routes_metric = 'Metrica' +a_s_desc = 'Qui puoi configurare gli aspetti base del tuo dispositivo come l'hostname o il fuso orario.' +a_s_packages = 'Software' +a_s_changepw = 'Password di Amministratore' +a_s_p_ipkg = 'Configurazione di OPKG' +a_s_sshkeys = 'Chiavi SSHs' +a_s_fstab = 'Punti di mount' +a_s_flash = 'Aggiorna firmware' +a_s_i_system1 = 'Modifica impostazioni relative al sistema, la sua identificazione, installazioni hardware e software, autenticazione o punti di mount.' +a_s_i_system2 = 'Queste impostazioni definiscono la base del tuo sistema.' +a_s_i_system3 = 'Fai attenzione perchè una cattiva configurazione qui può impedire al tuo dispositivo di avviarsi o impedirti di entrarvi.' +a_s_packages_do = 'Esegui azioni' +a_s_packages_install = 'Installa' +a_s_packages_installurl = 'Scarica e installa pacchetto' +a_s_packages_ipkg = 'Modifica lista dei pacchetti e destinazione dell'installazione' +a_s_packages_name = 'Nome pacchetto' +a_s_packages_remove = 'Rimuovi' +a_s_packages_search = 'Cerca pacchetto' +a_s_packages_update = 'Lista pacchetti aggiornata' +a_s_packages_updatelist = 'Aggiorna lista pacchetti' +a_s_packages_upgrade = 'Upgrade installed packages' +a_s_p_ipkg_pkglists = 'Lista pacchetti' +a_s_p_ipkg_targets = 'Destinazione installazione' +a_s_changepw1 = 'Cambia la password dell'amministratore di sistema (Utente root)' +a_s_changepw_changed = 'Password cambiata con successo' +a_s_changepw_nomatch = 'Errore: le password non corrispondono' +a_s_sshkeys1 = 'Qui puoi incollare le tue chiavi SSH (una per linea) per l'autenticazione SSH a chiave pubblica.' +a_s_fstab_mountpoints = 'Punti di mount' +a_s_fstab_mountpoints1 = 'I punti di mount definiscono in quale punto un dispositivo di memoria verrà attaccato al tuo filesystem' +a_s_fstab_active = 'File system montati' +a_s_fstab_used = 'Usati' +a_s_fstab_avail = 'Disponibili' +a_s_fstab_mountpoint = 'Punto di mount' +a_s_fstab_device1 = 'Il file del dispositivo di memoria o della partizione (e.s. /dev/sda1)' +a_s_fstab_fs1 = 'Il filesystem usato per formattare la memoria (e.s. ext3)' +a_s_fstab_swap1 = 'Se la tua memoria è insufficiente i dati non usati possono venire temporaneamente spostati in un'area di swap risultando in un più grande quantitativo di RAM usabile. Sappi che spostare dati in swap è un processo molto lento e che il dispositivo di swap non può essere acceduto alle alte velocità della RAM.' +a_s_flash_flashed = 'Firmware aggiornato con successo. Riavvio il dispositivo...' +a_s_flash_flasherr = 'Aggiornamento fallito' +a_s_flash_fwimage = 'Firmware image' +a_s_flash_received = 'Firmware ricevuto. Mi preparo ad aggiornare il dispositivo. NON SPEGNERE IL DISPOSITIVO!' +a_s_flash_inprogress = 'Scrivendo il firmware...' +a_s_flash_fwupgrade = 'Aggiorna firmware' +a_s_flash_keepcfg = 'Mantieni files di configurazione' +a_s_flash_notimplemented = 'Spiacente, questa funzione non è (ancora) disponibile per la tua piattaforma.' +a_s_flash_upgrade1 = 'Sostituisce il firmware installato con uno nuovo. Il firmware è dipendente dalla piattaforma.' +a_s_reboot1 = 'Riavvia il sistema operativo del tuo dispositivo' +a_s_reboot_do = 'Esegui un riavvio' +a_s_reboot_running = 'Per favore attendi: Riavvio del dispositivo...' +a_s_reboot_u = 'Attenzione: Ci sono modifiche non salvate che verranno persi riavviando!' +a_s_applyreboot1 = 'Modifiche applicate.' +a_s_backup = 'Backup / Ripristina' +a_s_backup_backup = 'Crea un backup' +a_s_backup_archive = 'Archivio di backup' +a_s_backup_reset = 'Ripristina il router come predefinito' +a_s_backup_reset1 = 'Procedi annullando tutte le modifiche e resettando ai predefiniti del firmware?' +a_s_backup_restore = 'Ripristina backup' +a_s_backup1 = 'Qui puoi salvare e ripristinare la configurazione del tuo router e - se possibile - resettare il router con le impostazioni predefinite.' +a_srv_http = 'Server HTTP' +a_srv_ssh = 'Server SSH' +a_srv_services1 = 'Servizi e demoni svolgono alcune azioni sul tuo dispositivo.' +a_srv_services2 = 'Molti di loro sono servers, che offrono un determinato servizio al tuo dispositivo o alla tua rete come accesso shell, servire pagine web come LuCI, fare mesh routing, inviare e-mails, ...' +a_srv_http1 = 'Un piccolo webserver che può essere usato per servire LuCI.' +a_srv_http_authrealm = 'Authentication Realm' +a_srv_http_authrealm1 = 'Il realm che verrà visualizzato al prompt di autenticazione per le pagine protette.' +a_srv_http_config1 = 'predefinito /etc/httpd.conf' +a_srv_http_root = 'Radice dei documenti' +a_srv_dropbear1 = 'Dropbear offre accesso SSH e integra un server SCP' +a_srv_d_pwauth = 'Password di authenticazione' +a_srv_d_pwauth1 = 'Permetti autenticazione SSH tramite password' +a_w_channel = 'Canale' +a_w_wifi1 = 'In questa pagina puoi trovare impostazioni di configurazione per reti WLAN.' +a_w_wifi2 = 'Puoi facilmente integrare i tuoi dispositivi 802.11a/b/g/n-devices nella tua rete fisica e usare la scheda di rete virtuale per costruire ripetitori wireless o offrire più di una rete con un solo dispositivo.' +a_w_wifi3 = 'Sono supportate le modalità operative Managed, Client, Ad-Hoc and WDS come per la crittografia WPA e WPA2 per comunicazioni sicure.' +a_w_devices1 = 'Qui puoi configurare i tuoi dispositivi wireless installati.' +a_w_txantenna = 'Antenna trasmittente' +a_w_rxantenna = 'Antenna ricevente' +a_w_distance1 = 'Distanza della stazione più lontana (in metri)' +a_w_diversity = 'Diversity' +a_w_countrycode = 'Codice nazione' +a_w_connlimit = 'Limite connessioni' +a_w_networks1 = 'Puoi avere più reti wifi con un solo dispositivo. Sappi ceh ci sono alcune restrizioni relative all'hardware ed al driver.Normalmente puoi avere 1 rete Ad-Hoc o fino a 3 reti Master e uan rete in modalità Client contemporaneamente.' +a_w_netid = 'Nome rete (ESSID)' +a_w_network1 = 'Aggiungi la rete Wifi alla rete fisica' +a_w_netmanual = ' - Crea nuova rete - ' +a_w_txpwr = 'Potenza di trasmissione' +a_w_brcmburst = 'Frameburst Broadcom' +a_w_athburst = 'Frameburst Atheros' +a_w_radiussrv = 'Server Radius' +a_w_radiusport = 'Porta Radius' +a_w_apisolation = 'Isolazione AP' +a_w_apisolation1 = 'Impedisci la comunicazione fra Client' +a_w_hideessid = 'Nascondi ESSID' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq è un server DHCP e forwarder DNS per firewall NAT' +dhcp_dnsmasq_domainneeded = 'Dominio richiesto' +dhcp_dnsmasq_domainneeded_desc = 'Non inoltrare le richieste DNS senza nome DNS' +dhcp_dnsmasq_authoritative = 'Autoritativo' +dhcp_dnsmasq_authoritative_desc = 'Questo è l'unico server DHCP nella tua rete locale' +dhcp_dnsmasq_boguspriv = 'Filtra privati' +dhcp_dnsmasq_boguspriv_desc = 'Non inoltrare richieste per le reti locali' +dhcp_dnsmasq_filterwin2k = 'Filtra inutili' +dhcp_dnsmasq_filterwin2k_desc = 'Filtra richieste DNS inutili di sistemi windows' +dhcp_dnsmasq_localisequeries = 'Localizza richieste' +dhcp_dnsmasq_localisequeries_desc = 'localizza l'hostname a seconda delle sue sottoreti' +dhcp_dnsmasq_local = 'Server locale' +dhcp_dnsmasq_domain = 'Dominio locale' +dhcp_dnsmasq_expandhosts = 'Espandi host' +dhcp_dnsmasq_expandhosts_desc = 'aggiungi nomi di dominio nel file resolv' +dhcp_dnsmasq_nonegcache = 'non tenere sconosciuti in cache' +dhcp_dnsmasq_nonegcache_desc = 'impedisci la cache di risposte DNS negative' +dhcp_dnsmasq_readethers = 'Usa /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Leggi /etc/ethers per configurare il server DHCP' +dhcp_dnsmasq_leasefile = 'File di lease' +dhcp_dnsmasq_leasefile_desc = 'file dove vengono salvati i lease DHCP assegnati' +dhcp_dnsmasq_resolvfile = 'File resolv' +dhcp_dnsmasq_resolvfile_desc = 'File DNS locale' +dhcp_dnsmasq_nohosts = 'Ignora /etc/hosts' +dhcp_dnsmasq_strictorder = 'Ordine severo' +dhcp_dnsmasq_strictorder_desc = 'I server DNS verranno contattati nell'ordine del file resolv' +dhcp_dnsmasq_logqueries = 'Logga richieste' +dhcp_dnsmasq_noresolv = 'Ignora file resolv' +dhcp_dnsmasq_dnsforwardmax = 'richieste contemporanee' +dhcp_dnsmasq_port = 'Porta DNS' +dhcp_dnsmasq_ednspacket_max = 'Dimensione massima pacchetto EDNS0' +dhcp_dnsmasq_dhcpleasemax = 'Numero massimo di lease DHCP' +dhcp_dnsmasq_addnhosts = 'file hosts aggiuntivo' +dhcp_dnsmasq_queryport = 'porta per le richieste' +dhcp_dnsmasq_enabletftp = 'Abilita server TFTP' +dhcp_dnsmasq_tftproot = 'Radice del server TFTP' +dhcp_dnsmasq_dhcpboot = 'Immagine boot da rete' +a_n_switch = 'Switch' +a_n_conntrack = 'Connessioni attive' +a_n_conntrack_desc = 'Questa pagina ti da una riassunto delle connessioni adesso attive.' +a_n_routes = 'Route' +a_n_routes4 = 'Route IPv4' +a_n_routes6 = 'Route IPv6' +a_network1 = 'In quest'area puoi trovare tutte le impostazioni relative alla rete.' +a_network2 = 'Su molti router lo switch può essere suddiviso liberamente in molte VLANs.' +a_network3 = 'Le impostazioni delle interfacce e di PPPoE / PPTP permettono una configurazione personalizzata della rete e delle connessioni ad altre reti come Internet.' +a_network4 = 'Con DHCP i dispositivi nella tua rete locale possono venire automaticamente configurati per la comunicazione in rete.' +a_network5 = 'Firewall e portforwarding possono essere usati per proteggere la tua rete offrendo servizi alle reti esterne.' +a_n_switch1 = 'Le porte di rete del tuo router possono essere combinate in molte VLAN nelle quali i computer possono comunicare direttamente fra di loro. Le VLAN sono spesso usate per separare segmenti di rete differenti. Spesso c'è come predefinita una porta per la connessione alla prossiam rete più grande come Internet e altre porte per le reti locali.' +network_switch_desc = 'Le porte che appartengono ad una VLAN sono separate con spazi. La porta con priorità più alta (di solito 5) è spesso la connessione all'interfaccia di rete più interna del router. Su dispositivi con 5 porte spesso la porta più bassa (0) è quella di Uplink.' +a_n_ifaces1 = 'In questa pagina puoi configurare le interfacce di rete.Puoi unire più interfacce spuntando la voce "unisci interfacce" e inserendo i nomi di più interfacce di rete separate da spazi. Puoi anche usare la notazione VLAN INTERFACCIA.VLANNUM (e.s.: eth0.1).' +a_n_i_bridge = 'Unisci interfacce' +a_n_i_bridge1 = 'Crea un bridge sulle interfacce selezionate' +dhcp_desc = 'Con DHCP i membri della rete possono ricevere automaticamente le loro impostazioni di rete (indirizzi IP, maschere di rete, server DNS, ...).' +dhcp_dhcp_leasetime = 'Tempo di lease' +dhcp_dhcp_dynamicdhcp = 'DHCP dinamico' +dhcp_dhcp_ignore = 'Ignora interfaccia' +dhcp_dhcp_ignore_desc = 'disabilita DHCP per queste interfacce' +dhcp_dhcp_force = 'Forza' +dhcp_dhcp_start_desc = 'primo indirizzo (ultimo ottetto)' +dhcp_dhcp_limit_desc = 'numero di indirizzi serviti -1' +dhcp_dhcp_dhcpoption = 'Opzioni DHCP' +dhcp_dhcp_dhcpoption_desc = 'Vedi "dnsmasq --help dhcp" per una lista di opzioni disponibile.' +dhcp_leases = 'Lease' +luci_ethers = 'Leases statici' +dhcp_timeremain = 'Tempo lease residuo' +dhcp_leases_active = 'Lease attivi' +a_n_ptp = 'Connessioni Point-to-Point' +a_n_ptp1 = 'Connessioni Point-to-Point con PPPoE o PPTP sono spesso usate per connettere un dispositivo su DSL o tecnologie simili ad un an access point internet.' +network_interface_prereq = 'Devi installare "comgt" per il supporto UMTS/GPRS, "ppp-mod-pppoe" per PPPoE, "ppp-mod-pppoa" per PPPoA e "pptp" per PPtP' +network_interface_prereq_mini = 'Devi installare "ppp-mod-pppoe" per il supporto PPPoE e "pptp" per PPtP' +network_interface_server = 'Server PPTP' +network_interface_demand = 'Disconnetti automaticamente' +network_interface_demand_desc = 'Tempo (in secondi) dopo il quale una connessione inattiva verrà chiusa' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'Numero di test di connettività falliti prima di una riconnessione' +network_interface_device = 'Dispositivo modem' +network_interface_device_desc = 'Il device node del tuo modem, e.s. /dev/ttyUSB0' +network_interface_defaultroute = 'Sostituisci route di default' +network_interface_defaultroute_desc = 'Consenti a pppd di sostituire la route di default con la route corrente per usare l'interfaccia PPP dopo una connessione riuscita' +network_interface_peerdns = 'Usa DNS ottenuti' +network_interface_peerdns_desc = 'Configura il server DNS locale per usare i server DNSnegoziati da PPP' +network_interface_ipv6 = 'Attiva IPv6 sul collegamento PPP' +network_interface_connect = 'Script connessione' +network_interface_connect_desc = 'Permette a pppd di avviare questo script dopo l'avvenuta connessione PPP' +network_interface_disconnect = 'Script disconnessione' +network_interface_disconnect_desc = 'Permette a pppd di avviare questo script prima della disconnessione PPP' +network_interface_pppd_options = 'Opzioni pppd aggiuntive' +network_interface_pppd_options_desc = 'Specifica opzioni linea di comando aggiuntive per pppd qui' +network_interface_apn = 'Access point (APN)' +network_interface_pincode = 'Codice PIN' +network_interface_pincode_desc = 'Fai attenzione di inserire il codice PIN corretto qui o potresti bloccare la tua sim card!' +network_interface_service = 'Tipo di servizio' +network_interface_maxwait = 'Tempo di attesa inizializzazione' +network_interface_maxwait_desc = 'Secondi da attendere prima che il modem diventi pronto prima di provare a connettersi' +a_n_r_routes1 = 'Le route specificano attraverso quale interfaccia e gateway un certo host o rete può essere raggiunto.' +a_n_routes_static = 'Route statiche' +a_n_routes_static4 = 'Route statiche IPv4' +a_n_routes_static6 = 'Route statiche IPv6' +a_n_routes_kernel4 = 'Route IPv4 attive' +a_n_routes_kernel6 = 'Route IPv6 attive' +a_n_r_target1 = 'IP dell'host o rete' +a_n_r_target6 = 'Indirizzo IPv6 o rete (CIDR)' +a_n_r_netmask1 = 'se la destinazione è una rete' +m_n_inet = 'Connessione Internet' +m_n_local = 'Rete locale' +m_n_route = 'Route' +m_n_brdige = 'Bridge' +m_w_ap = 'Offri (Access Point)' +m_w_adhoc = 'Independente (Ad-Hoc)' +m_w_client = 'Partecipa (Client)' +m_w_wds = 'Distribuita (WDS)' +m_w_clientmode = 'Modalità client' +system_system_logsize = 'Dimensione buffer log di sistema' +system_system_logip = 'Server log di sistema esterno' +system_system_conloglevel = 'Livello output di log' +system_system_conloglevel_desc = 'Livello output di log sulla console' +m_i_processor = 'Processore' +m_i_memory = 'Memoria' +m_i_systemtime = 'Ora locale' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'Primo indirizzo offerto' +m_n_d_numleases = 'Numero di indirizzi offerti' +routingtable = 'Tabella di routing' +wlanscan = 'Scansione Wifi' +frequency = 'Frequenza' +power = 'Potenza' +noise = 'Rumore' +signal = 'Segnale' +link = 'Collegamento' +frag = 'Framm.' +rts = 'RTS' +bitrate = 'Bitrate' +m_n_keepalive = 'riconnetti automaticamente' +m_n_dialondemand = 'disconnetti quando non usata per' +m_n_pptp_server = 'Server PPTP' +leds = 'Configurazione LED' +leds_desc = 'Personalizza la configurazione dei LED del sistema se possibile.' +system_led_name = 'Nome LED' +system_led_sysfs = 'Dispositivo LED' +system_led_default = 'Stato predefinito' +system_led_default_desc = 'spuntato = on' +system_led_trigger = 'Causa' +system_led_trigger_none = 'Nessuna' +system_led_trigger_defaulton = 'Predefinito on' +system_led_trigger_timer = 'Timer' +system_led_trigger_heartbeat = 'Battito (Carico medio)' +system_led_trigger_netdev = 'Dispositivo di rete' +system_led_delayoff = 'Tempo dello stato off' +system_led_delayoff_desc = 'Per quanto tempo (in ms) il LED è off' +system_led_delayon = 'Tempo dello stato on' +system_led_delayon_desc = 'Per quanto tempo (in ms) il LED è on' +system_led_dev = 'Dispositivo' +system_led_mode = 'Modalità causa' +system_led_mode_link = 'Collegamento on' +system_led_mode_tx = 'Trasmissione' +system_led_mode_rx = 'Ricezione' +network_interface_up = 'Attiva' +network_interface_hwaddr = 'Indirizzo MAC' +network_interface_hwaddr_desc = 'Hardware Address' +network_interface_txrx = 'Traffico' +network_interface_txrx_desc = 'transmessi / ricevuti' +network_interface_err = 'Errori' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Crea / Assegna zona firewall' +network_interface_fwzone_desc = 'Questa interfaccia non appartiene a nessuna zona del firewall ancora.' +process_head = 'Processi' +process_descr = 'Questa lista da un riassunto dei processi correntemente attivi e del loro stato.' +process_pid = 'PID' +process_owner = 'Proprietario' +process_command = 'Comando' +process_cpu = 'Uso CPU (%)' +process_mem = 'Uso Memory (%)' +process_hup = 'Hangup' +process_term = 'Termina' +process_kill = 'Uccidi' +mem_cached = 'in cache' +mem_buffered = 'in buffer' +mem_free = 'libera' +a_s_crontab = 'Operazioni programmate' +a_s_crontab1 = 'Questa è la crontab del sistema nella quale possono essere definiti le operazioni da programmare.' +a_w_nasid = 'ID della NAS' +a_w_cacert = 'Percorso al certificato CA' +a_w_eaptype = 'Metodo EAP' +a_w_tlsprivkey = 'Percorso alla chiave privata' +a_w_tlsprivkeypwd = 'Password della chiave privata' +a_w_peapauth = 'Autenticazione PEAP' +a_w_peapidentity = 'Identità PEAP' +a_w_peappassword = 'Password PEAP' +a_w_create = 'Crea rete' +hostnames = 'Hostname' +hostnames_entries = 'Campi host' +hostnames_hostname = 'Hostname' +hostnames_address = 'Indirizzo IP' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.xml b/openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.xml new file mode 100644 index 0000000..51f149b --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/admin-core.it.xml @@ -0,0 +1,333 @@ + + + + +Le seguenti modifiche sono state applicate +Le seguenti modifiche sono state annullate +Interfaccia utente +LuCI è una collezione di software libero scritto in Lua comprendente un Webframework e interfaccia web MVC per dispositivi integrati. LuCI è rilasciato sotto la Apache-License. +Sito del progetto +Lead Development +Contributing Developers +Ringraziamenti +Ciao! +Questa è l'area d'amministrazione di LuCI. +LuCI è un'interfaccia grafica gratuita, flessibile, e amichevole per configurare OpenWrt Kamikaze. +Nelle seguenti pagine puoi impostare tutti i settaggi più importanti del tuo router +Nota: Le modifiche devono essere confermate in LuCI cliccando Modifiche - Salva e Applica prima di essere applicate. +dal momento che vogliamo migliorare quest'interfaccia accettiamo suggerimenti. +Ed ora buon divertimento con il tuo router! +Il Team di LuCI +Qui puoi personalizzare i settaggi e le funzionalità di LuCI. +Azioni post-modifica +Questi comandi verranno eseguiti automaticamente quando un comando di configurazione UCI viene applicato permettendo alle modifiche di essere applicate immediatamente. +Files da conservare quando si aggiorna un nuovo firmware +Quando si aggiorna un firmware con LuCI questi files verranno aggiunti al nuovo firmware. +Qui puoi trovare informazione sullo stato del sistema come frequenza di clock della CPU, uso della memoria o dati della scheda di rete. +Inoltre i log del kernel o dei servizi sono visualizzabili qui per avere un riassunto dello stato attuale. +Scansione WLAN +Reti Wifi nell'ambiente circostante +Encr. +Collegamento +Segnale +Disturbo +Route +Maschera di rete +Gateway +Metrica +Qui puoi configurare gli aspetti base del tuo dispositivo come l'hostname o il fuso orario. +Software +Password di Amministratore +Configurazione di OPKG +Chiavi SSHs +Punti di mount +Aggiorna firmware +Modifica impostazioni relative al sistema, la sua identificazione, installazioni hardware e software, autenticazione o punti di mount. +Queste impostazioni definiscono la base del tuo sistema. +Fai attenzione perchè una cattiva configurazione qui può impedire al tuo dispositivo di avviarsi o impedirti di entrarvi. +Esegui azioni +Installa +Scarica e installa pacchetto +Modifica lista dei pacchetti e destinazione dell'installazione +Nome pacchetto +Rimuovi +Cerca pacchetto +Lista pacchetti aggiornata +Aggiorna lista pacchetti +Upgrade installed packages +Lista pacchetti +Destinazione installazione +Cambia la password dell'amministratore di sistema (Utente root) +Password cambiata con successo +Errore: le password non corrispondono +Qui puoi incollare le tue chiavi SSH (una per linea) per l'autenticazione SSH a chiave pubblica. +Punti di mount +I punti di mount definiscono in quale punto un dispositivo di memoria verrà attaccato al tuo filesystem +File system montati +Usati +Disponibili +Punto di mount +Il file del dispositivo di memoria o della partizione (e.s. /dev/sda1) +Il filesystem usato per formattare la memoria (e.s. ext3) +Se la tua memoria è insufficiente i dati non usati possono venire temporaneamente spostati in un'area di swap risultando in un più grande quantitativo di RAM usabile. Sappi che spostare dati in swap è un processo molto lento e che il dispositivo di swap non può essere acceduto alle alte velocità della RAM. +Firmware aggiornato con successo. Riavvio il dispositivo... +Aggiornamento fallito +Firmware image +Firmware ricevuto. Mi preparo ad aggiornare il dispositivo. NON SPEGNERE IL DISPOSITIVO! +Scrivendo il firmware... +Aggiorna firmware +Mantieni files di configurazione +Spiacente, questa funzione non è (ancora) disponibile per la tua piattaforma. +Sostituisce il firmware installato con uno nuovo. Il firmware è dipendente dalla piattaforma. +Riavvia il sistema operativo del tuo dispositivo +Esegui un riavvio +Per favore attendi: Riavvio del dispositivo... +Attenzione: Ci sono modifiche non salvate che verranno persi riavviando! +Modifiche applicate. +Backup / Ripristina +Crea un backup +Archivio di backup +Ripristina il router come predefinito +Procedi annullando tutte le modifiche e resettando ai predefiniti del firmware? +Ripristina backup +Qui puoi salvare e ripristinare la configurazione del tuo router e - se possibile - resettare il router con le impostazioni predefinite. +Server HTTP +Server SSH +Servizi e demoni svolgono alcune azioni sul tuo dispositivo. +Molti di loro sono servers, che offrono un determinato servizio al tuo dispositivo o alla tua rete come accesso shell, servire pagine web come LuCI, fare mesh routing, inviare e-mails, ... +Un piccolo webserver che può essere usato per servire LuCI. +Authentication Realm +Il realm che verrà visualizzato al prompt di autenticazione per le pagine protette. +predefinito /etc/httpd.conf +Radice dei documenti +Dropbear offre accesso SSH e integra un server SCP +Password di authenticazione +Permetti autenticazione SSH tramite password +Canale +In questa pagina puoi trovare impostazioni di configurazione per reti WLAN. +Puoi facilmente integrare i tuoi dispositivi 802.11a/b/g/n-devices nella tua rete fisica e usare la scheda di rete virtuale per costruire ripetitori wireless o offrire più di una rete con un solo dispositivo. +Sono supportate le modalità operative Managed, Client, Ad-Hoc and WDS come per la crittografia WPA e WPA2 per comunicazioni sicure. +Qui puoi configurare i tuoi dispositivi wireless installati. +Antenna trasmittente +Antenna ricevente +Distanza della stazione più lontana (in metri) +Diversity +Codice nazione +Limite connessioni +Puoi avere più reti wifi con un solo dispositivo. Sappi ceh ci sono alcune restrizioni relative all'hardware ed al driver.Normalmente puoi avere 1 rete Ad-Hoc o fino a 3 reti Master e uan rete in modalità Client contemporaneamente. +Nome rete (ESSID) +Aggiungi la rete Wifi alla rete fisica + - Crea nuova rete - +Potenza di trasmissione +Frameburst Broadcom +Frameburst Atheros +Server Radius +Porta Radius +Isolazione AP +Impedisci la comunicazione fra Client +Nascondi ESSID +Access Point +Ad-Hoc +Pseudo Ad-Hoc (ahdemo) +Client +WDS +Monitor +Dnsmasq è un server DHCP e forwarder DNS per firewall NAT +Dominio richiesto +Non inoltrare le richieste DNS senza nome DNS +Autoritativo +Questo è l'unico server DHCP nella tua rete locale +Filtra privati +Non inoltrare richieste per le reti locali +Filtra inutili +Filtra richieste DNS inutili di sistemi windows +Localizza richieste +localizza l'hostname a seconda delle sue sottoreti +Server locale +Dominio locale +Espandi host +aggiungi nomi di dominio nel file resolv +non tenere sconosciuti in cache +impedisci la cache di risposte DNS negative +Usa /etc/ethers +Leggi /etc/ethers per configurare il server DHCP +File di lease +file dove vengono salvati i lease DHCP assegnati +File resolv +File DNS locale +Ignora /etc/hosts +Ordine severo +I server DNS verranno contattati nell'ordine del file resolv +Logga richieste +Ignora file resolv +richieste contemporanee +Porta DNS +Dimensione massima pacchetto EDNS0 +Numero massimo di lease DHCP +file hosts aggiuntivo +porta per le richieste +Abilita server TFTP +Radice del server TFTP +Immagine boot da rete +Switch +Connessioni attive +Questa pagina ti da una riassunto delle connessioni adesso attive. +Route +Route IPv4 +Route IPv6 +In quest'area puoi trovare tutte le impostazioni relative alla rete. +Su molti router lo switch può essere suddiviso liberamente in molte VLANs. +Le impostazioni delle interfacce e di PPPoE / PPTP permettono una configurazione personalizzata della rete e delle connessioni ad altre reti come Internet. +Con DHCP i dispositivi nella tua rete locale possono venire automaticamente configurati per la comunicazione in rete. +Firewall e portforwarding possono essere usati per proteggere la tua rete offrendo servizi alle reti esterne. +Le porte di rete del tuo router possono essere combinate in molte VLAN nelle quali i computer possono comunicare direttamente fra di loro. Le VLAN sono spesso usate per separare segmenti di rete differenti. Spesso c'è come predefinita una porta per la connessione alla prossiam rete più grande come Internet e altre porte per le reti locali. +Le porte che appartengono ad una VLAN sono separate con spazi. La porta con priorità più alta (di solito 5) è spesso la connessione all'interfaccia di rete più interna del router. Su dispositivi con 5 porte spesso la porta più bassa (0) è quella di Uplink. +In questa pagina puoi configurare le interfacce di rete.Puoi unire più interfacce spuntando la voce "unisci interfacce" e inserendo i nomi di più interfacce di rete separate da spazi. Puoi anche usare la notazione VLAN INTERFACCIA.VLANNUM (e.s.: eth0.1). +Unisci interfacce +Crea un bridge sulle interfacce selezionate +Con DHCP i membri della rete possono ricevere automaticamente le loro impostazioni di rete (indirizzi IP, maschere di rete, server DNS, ...). +Tempo di lease +DHCP dinamico +Ignora interfaccia +disabilita DHCP per queste interfacce +Forza +primo indirizzo (ultimo ottetto) +numero di indirizzi serviti -1 +Opzioni DHCP +Vedi "dnsmasq --help dhcp" per una lista di opzioni disponibile. +Lease +Leases statici +Tempo lease residuo +Lease attivi +Connessioni Point-to-Point +Connessioni Point-to-Point con PPPoE o PPTP sono spesso usate per connettere un dispositivo su DSL o tecnologie simili ad un an access point internet. +Devi installare "comgt" per il supporto UMTS/GPRS, "ppp-mod-pppoe" per PPPoE, "ppp-mod-pppoa" per PPPoA e "pptp" per PPtP +Devi installare "ppp-mod-pppoe" per il supporto PPPoE e "pptp" per PPtP +Server PPTP +Disconnetti automaticamente +Tempo (in secondi) dopo il quale una connessione inattiva verrà chiusa +Keep-Alive +Numero di test di connettività falliti prima di una riconnessione +Dispositivo modem +Il device node del tuo modem, e.s. /dev/ttyUSB0 +Sostituisci route di default +Consenti a pppd di sostituire la route di default con la route corrente per usare l'interfaccia PPP dopo una connessione riuscita +Usa DNS ottenuti +Configura il server DNS locale per usare i server DNSnegoziati da PPP +Attiva IPv6 sul collegamento PPP +Script connessione +Permette a pppd di avviare questo script dopo l'avvenuta connessione PPP +Script disconnessione +Permette a pppd di avviare questo script prima della disconnessione PPP +Opzioni pppd aggiuntive +Specifica opzioni linea di comando aggiuntive per pppd qui +Access point (APN) +Codice PIN +Fai attenzione di inserire il codice PIN corretto qui o potresti bloccare la tua sim card! +Tipo di servizio +Tempo di attesa inizializzazione +Secondi da attendere prima che il modem diventi pronto prima di provare a connettersi +Le route specificano attraverso quale interfaccia e gateway un certo host o rete può essere raggiunto. +Route statiche +Route statiche IPv4 +Route statiche IPv6 +Route IPv4 attive +Route IPv6 attive +IP dell'host o rete +Indirizzo IPv6 o rete (CIDR) +se la destinazione è una rete +Connessione Internet +Rete locale +Route +Bridge +Offri (Access Point) +Independente (Ad-Hoc) +Partecipa (Client) +Distribuita (WDS) +Modalità client +Dimensione buffer log di sistema +Server log di sistema esterno +Livello output di log +Livello output di log sulla console +Processore +Memoria +Ora locale +Uptime +Primo indirizzo offerto +Numero di indirizzi offerti +Tabella di routing +Scansione Wifi +Frequenza +Potenza +Rumore +Segnale +Collegamento +Framm. +RTS +Bitrate +riconnetti automaticamente +disconnetti quando non usata per +Server PPTP +Configurazione LED +Personalizza la configurazione dei LED del sistema se possibile. +Nome LED +Dispositivo LED +Stato predefinito +spuntato = on +Causa +Nessuna +Predefinito on +Timer +Battito (Carico medio) +Dispositivo di rete +Tempo dello stato off +Per quanto tempo (in ms) il LED è off +Tempo dello stato on +Per quanto tempo (in ms) il LED è on +Dispositivo +Modalità causa +Collegamento on +Trasmissione +Ricezione +Attiva +Indirizzo MAC +Hardware Address +Traffico +transmessi / ricevuti +Errori +TX / RX +Crea / Assegna zona firewall +Questa interfaccia non appartiene a nessuna zona del firewall ancora. +Processi +Questa lista da un riassunto dei processi correntemente attivi e del loro stato. +PID +Proprietario +Comando +Uso CPU (%) +Uso Memory (%) +Hangup +Termina +Uccidi +in cache +in buffer +libera +Operazioni programmate +Questa è la crontab del sistema nella quale possono essere definiti le operazioni da programmare. +ID della NAS +Percorso al certificato CA +Metodo EAP +Percorso alla chiave privata +Password della chiave privata +Autenticazione PEAP +Identità PEAP +Password PEAP +Crea rete +Hostname +Campi host +Hostname +Indirizzo IP +PPPoA Encapsulation +Clamp Segment Size +Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs. + + diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.lua b/openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.lua new file mode 100644 index 0000000..13174ae --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.lua @@ -0,0 +1,17 @@ +cbi_add = 'Aggiungi campo' +cbi_del = 'Rimuovi campo' +cbi_replace = 'Sostituisci campo' +cbi_invalid = 'Valore immesso non valido' +cbi_invalid_section = 'Validazione fallita: Per favore controlla i campi immessi.' +cbi_missing = 'Questo campo è obbligatorio' +cbi_deperror = 'Validazione fallita: Almeno un campo obbligatorio manca o è invalido' +cbi_reqerror = 'Un requisito per questa opzione non è stato soddisfatto' +cbi_addopt = '-- Campo aggiuntivo --' +cbi_optional = ' (opzionale)' +cbi_sectempty = 'Questa sezione non contiene ancora valori' +cbi_manual = '-- personalizzato --' +cbi_select = '-- Per favore scegli --' +cbi_gorel = 'Vai alla pagina di configurazione relativa' +cbi_applying = 'Applica modifiche' +cbi_upload = 'Invia file' +cbi_browser = 'Cerca file...' diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.xml b/openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.xml new file mode 100644 index 0000000..cdc34b1 --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/cbi.it.xml @@ -0,0 +1,23 @@ + + + + +Aggiungi campo +Rimuovi campo +Sostituisci campo +Valore immesso non valido +Validazione fallita: Per favore controlla i campi immessi. +Questo campo è obbligatorio +Validazione fallita: Almeno un campo obbligatorio manca o è invalido +Un requisito per questa opzione non è stato soddisfatto +-- Campo aggiuntivo -- + (opzionale) +Questa sezione non contiene ancora valori +-- personalizzato -- +-- Per favore scegli -- +Vai alla pagina di configurazione relativa +Applica modifiche +Invia file +Cerca file... + + diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.lua b/openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.lua new file mode 100644 index 0000000..7ffc729 --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.lua @@ -0,0 +1,102 @@ +skiplink1 = 'Salta a navigazione' +skiplink2 = 'Salta a contenuto' +navigation = 'Navigazione' +about = 'Informazioni su' +add = 'Aggiungi' +addresses = 'Indirizzi' +aliases = 'Alias' +all = 'tutti' +back = 'indietro' +administration = 'Amministrazione' +essentials = 'Essenziali' +apply = 'Applica' +basicsettings = 'Impostazioni di base' +broadcast = 'Broadcast IPv4' +changes = 'Modifiche' +channel = 'Canale' +cidr6 = 'Notazione CIDR: indirizzo/prefisso' +code = 'Codice' +config = 'Configurazione' +configfile = 'File di configurazione' +confirmation = 'Conferma' +delete = 'Cancella' +descr = 'Descrizione' +design = 'Design' +destination = 'Destinazione' +device = 'Dispositivo' +devices = 'Dispositivi' +disable = 'disabilita' +distance = 'Distanza' +dmesg = 'Log del kernel' +dnsserver = 'Server DNS' +edit = 'Modifica' +enable = 'abilita' +encryption = 'Crittografia' +error = 'Errore' +filesystem = 'Filesystem' +filter = 'Filtro' +gateway = 'Gateway IPv4' +gateway6 = 'Gateway IPv6' +general = 'Generale' +hostname = 'Hostname' +install = 'Installa' +installed = 'installato' +interface = 'Interfaccia' +interfaces = 'Interfacce' +ipaddress = 'Indirizzo IPv4' +ip6address = 'Indirizzo IPv6' +legend = 'Legenda' +library = 'Libreria' +logout = 'Logout' +key = 'Chiave' +language = 'Lingua' +limit = 'Limite' +load = 'Carico' +login = 'Login' +macaddress = 'Indirizzo MAC' +manpage = 'leggi il manuale di '%s'' +metric = 'Metrica' +mode = 'Modalità' +name = 'Nome' +netmask = 'Maschera di rete IPv4' +network = 'Rete' +networks = 'Reti' +none = 'nessuna' +notinstalled = 'non installato' +ok = 'OK' +options = 'Opzioni' +overview = 'Riassunto' +packagemanager = 'Gestore pacchetti' +password = 'Password' +path = 'Percorso' +port = 'Porta' +ports = 'Porte' +protocol = 'Protocollo' +reboot = 'Riavvia' +reset = 'Reset' +revert = 'Ripristina' +save = 'Salva' +saveapply = 'Salva & applica' +scan = 'Scan' +service = 'Servizio' +services = 'Servizi' +settings = 'Impostazioni' +size = 'Dimensione' +source = 'Origine' +start = 'Inizio' +static = 'statico' +status = 'Stato' +statistics = 'Statistiche' +submit = 'Invia' +syslog = 'Log di sistema' +system = 'Sistema' +target = 'Destinazione' +timezone = 'Fuso orario' +type = 'Tipo' +unknownerror = 'Errore sconosciuto' +unsavedchanges = 'Modifiche non salvate' +username = 'Username' +version = 'Versione' +webui = 'UI web' +wifi = 'Wifi' +zone = 'Zona' diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.xml b/openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.xml new file mode 100644 index 0000000..a6ac75d --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/default.it.xml @@ -0,0 +1,109 @@ + + + + +Salta a navigazione +Salta a contenuto +Navigazione + +Informazioni su +Aggiungi +Indirizzi +Alias +tutti +indietro +Amministrazione +Essenziali +Applica +Impostazioni di base +Broadcast IPv4 +Modifiche +Canale +Notazione CIDR: indirizzo/prefisso +Codice +Configurazione +File di configurazione +Conferma +Cancella +Descrizione +Design +Destinazione +Dispositivo +Dispositivi +disabilita +Distanza +Log del kernel +Server DNS +Modifica +abilita +Crittografia +Errore +Filesystem +Filtro +Gateway IPv4 +Gateway IPv6 +Generale +Hostname +Installa +installato +Interfaccia +Interfacce +Indirizzo IPv4 +Indirizzo IPv6 +Legenda +Libreria +Logout +Chiave +Lingua +Limite +Carico +Login +Indirizzo MAC +leggi il manuale di '%s' +Metrica +Modalità +Nome +Maschera di rete IPv4 +Rete +Reti +nessuna +non installato +OK +Opzioni +Riassunto +Gestore pacchetti +Password +Percorso +Porta +Porte +Protocollo +Riavvia +Reset +Ripristina +Salva +Salva & applica +Scan +Servizio +Servizi +Impostazioni +Dimensione +Origine +Inizio +statico +Stato +Statistiche +Invia +Log di sistema +Sistema +Destinazione +Fuso orario +Tipo +Errore sconosciuto +Modifiche non salvate +Username +Versione +UI web +Wifi +Zona + + diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.lua b/openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.lua new file mode 100644 index 0000000..41200a7 --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Autorizzazione richiesta' +sysauth_prompt = 'Per favore inserisci i tuoi username e password.' +sysauth_failed = 'Username o password non validi! Per favore riprova.' diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.xml b/openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.xml new file mode 100644 index 0000000..a83925e --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/sysauth.it.xml @@ -0,0 +1,9 @@ + + + + +Autorizzazione richiesta +Per favore inserisci i tuoi username e password. +Username o password non validi! Per favore riprova. + + diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.lua b/openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.lua new file mode 100644 index 0000000..223ef27 --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.lua @@ -0,0 +1,37 @@ +wifi_auto = 'auto' +wifi_fh = 'Frequency Hopping' +wifi_diversity = 'Diversity' +wifi_txantenna = 'Antenna trasmettente' +wifi_rxantenna = 'Antenna ricevente' +wifi_distance = 'Ottimizzazione distanza' +wifi_distance_desc = 'Distanza del membro più lontano della rete in metri.' +wifi_macpolicy = 'Filtro dei MAC-Addres' +wifi_whitelist = 'Consenti solo quelli in lista' +wifi_blacklist = 'Consenti tutti tranne quelli in lista' +wifi_maclist = 'Lista MAC' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Codice nazione' +wifi_maxassoc = 'Limite connessioni' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Soglia di frammentazione' +wifi_rts = 'Soglia RTS/CTS' +wifi_wds = 'WDS' +wifi_wdssep = 'WDS separati' +wifi_hidden = 'Nascondi ESSID' +wifi_isloate = 'Isola utenti' +wifi_isloate_desc = 'Impedisci comunicazione fra utenti' +wifi_bgscan = 'Scansione in background' +wifi_rate = 'Velocità di transmissione' +wifi_mcast_rate = 'Velocità multicast' +wifi_minrate = 'Velocità minima' +wifi_maxrate = 'Velocità massima' +wifi_compression = 'Compressione' +wifi_turbo = 'Modalità turbo' +wifi_ff = 'Frame veloci' +wifi_wmm = 'Modalità WMM' +wifi_xr = 'Supporto XR' +wifi_ar = 'Supporto AR' +wifi_nosbeacon = 'Disabilita Timer Beacon HW' +wifi_noprobereq = 'Disabilita Probe-Responses' +wifi_wpareq = 'La crittografia WPA richiede l'installazione di wpa_supplicant (per la modalità client) o hostapd (per la modalità AP o ad-hoc).' diff --git a/openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.xml b/openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.xml new file mode 100644 index 0000000..a09339f --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/luasrc/i18n/wifi.it.xml @@ -0,0 +1,44 @@ + + + + +auto +Frequency Hopping +Diversity +Antenna trasmettente +Antenna ricevente +Ottimizzazione distanza +Distanza del membro più lontano della rete in metri. +Filtro dei MAC-Addres +Consenti solo quelli in lista +Consenti tutti tranne quelli in lista +Lista MAC +Frame Bursting +Codice nazione +Limite connessioni +ESSID +BSSID +Soglia di frammentazione +Soglia RTS/CTS +WDS +WDS separati +Nascondi ESSID +Isola utenti +Impedisci comunicazione fra utenti +Scansione in background +Velocità di transmissione +Velocità multicast +Velocità minima +Velocità massima +Compressione +Modalità turbo +Frame veloci +Modalità WMM +Supporto XR +Supporto AR +Disabilita Timer Beacon HW +Disabilita Probe-Responses + +La crittografia WPA richiede l'installazione di wpa_supplicant (per la modalità client) o hostapd (per la modalità AP o ad-hoc). + + diff --git a/openwrt/packages/luci/i18n/italian/root/etc/uci-defaults/luci-i18n-italian b/openwrt/packages/luci/i18n/italian/root/etc/uci-defaults/luci-i18n-italian new file mode 100755 index 0000000..e64b955 --- /dev/null +++ b/openwrt/packages/luci/i18n/italian/root/etc/uci-defaults/luci-i18n-italian @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.languages.it=Italian + commit luci +EOF + diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/Makefile b/openwrt/packages/luci/i18n/portuguese_brazilian/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/ipkg/postinst b/openwrt/packages/luci/i18n/portuguese_brazilian/ipkg/postinst new file mode 100755 index 0000000..fc33156 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-i18n-portuguese_brazilian ) && rm -f /etc/uci-defaults/luci-i18n-portuguese_brazilian +} diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.lua b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.lua new file mode 100644 index 0000000..585ba86 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.lua @@ -0,0 +1,327 @@ +uci_applied = 'As seguintes alterações foram aplicadas' +uci_reverted = 'As seguintes alterações foram recuperadas' +a_i_ui = 'Interface do Usuário' +c_lucidesc = 'LuCI é uma coleção gratuita de softwares Lua incluindo um Framework Web MVC e uma Interface Web para equipamentos embarcados. LuCI é licenciado sob a Licença Apache.' +c_projecthome = 'Página do Projeto' +c_leaddev = 'Líder(es) do Desenvolvimento' +c_contributors = 'Desenvolvedores que Crontribuíram' +c_thanksto = 'Obrigado à' +a_i_i_hello = 'Olá!' +a_i_i_admin1 = 'Esta é a área de administração LuCI.' +a_i_i_admin2 = 'LuCI é gratuito, flexível e uma interface gráfica fácil de utilizar para configurar OpenWrt Kamikaze.' +a_i_i_admin3 = 'Nas próximas páginas você pode ajustar todas as definições importantes do seu roteador.' +a_i_i_admin4 = 'Aviso: No LuCI as alterações devem ser confirmadas clicando em Alterações - Salvar & Aplicar antes de serem aplicadas.' +a_i_i_admin5 = 'Como nós sempre queremos melhorar essa interface, estamos ansiosos para seus comentários e sugestões.' +a_i_i_admin6 = 'E agora divirta-se com o seu roteador!' +a_i_i_team = 'O Time do LuCI' +a_i_luci1 = 'Aqui você pode customizar as configurações e funcionalidades do LuCI.' +a_i_ucicommit = 'Ações pós-gravação' +a_i_ucicommit1 = 'Estes comandos são executados automaticamente quando uma determinada configuração da UCI está gravada, permitindo mudanças a serem aplicadas instantaneamente.' +a_i_keepflash = 'Arquivos que devem ser mantidos quando gravar um novo firmware.' +a_i_keepflash1 = 'Quando gravar um novo firmware com o LuCI estes arquivos serão adicionados ao novo firmware instalado.' +a_st_i_status1 = 'Aqui você pode encontrar informações sobre o estado atual do sistema, como CPU, frequência do relógio, uso de memória ou da interface de rede de dados.' +a_st_i_status2 = 'Também os arquivos de logs do kernel ou dos serviços podem serem vistos aqui para obter uma visão geral sobre o seu estado atual.' +iwscan = 'WLAN-Scan' +iwscan1 = 'Redes Wifi no seu ambiente local' +iwscan_encr = 'Encr.' +iwscan_link = 'Link' +iwscan_signal = 'Sinal' +iwscan_noise = 'Ruído' +routes = 'Rotas' +routes_netmask = 'Netmask' +routes_gateway = 'Gateway' +routes_metric = 'Métrica' +a_s_desc = 'Aqui você pode configurar os aspectos básicos do seu equipamento como o nome do host ou o fuso horário.' +a_s_packages = 'Software' +a_s_changepw = 'Senha do Admin' +a_s_p_ipkg = 'Configuração-OPKG' +a_s_sshkeys = 'Chaves-SSH' +a_s_fstab = 'Pontos de Montagem' +a_s_flash = 'Atualizar Firmware' +a_s_i_system1 = 'Altera as configurações relacionadas com o sistema em si, sua identificação, hardware e software instalados, autenticação ou pontos de montagem.' +a_s_i_system2 = 'Essas configurações definem a base do seu sistema.' +a_s_i_system3 = 'Preste atenção de que qualquer configuração errada aqui pode impedir o seu equipamento de inicilizar ou talvez bloquear seu acesso de fora à ele.' +a_s_packages_do = 'Executar Ações' +a_s_packages_install = 'Instalar' +a_s_packages_installurl = 'Fazer download e instalar pacote' +a_s_packages_ipkg = 'Editar listas de pacotes e destinos de instalação' +a_s_packages_name = 'Nome do Pacote' +a_s_packages_remove = 'Remover' +a_s_packages_search = 'Procurar pacote' +a_s_packages_update = 'Listas de pacotes atualizadas' +a_s_packages_updatelist = 'Atualizar listas de pacotes' +a_s_packages_upgrade = 'Atualizar os pacotes instalados' +a_s_p_ipkg_pkglists = 'Listas de pacotes' +a_s_p_ipkg_targets = 'Destino de Instalação' +a_s_changepw1 = 'Altera a senha do administrador do sistema (Usuário root)' +a_s_changepw_changed = 'Senha alterada com sucesso' +a_s_changepw_nomatch = 'Erro: As senhas estão diferentes' +a_s_sshkeys1 = 'Aqui você pode colar suas Chaves-SSH públicas (uma por linha) para a autenticação SSH por chave-pública.' +a_s_fstab_mountpoints = 'Pontos de Montagem' +a_s_fstab_mountpoints1 = 'Pontos de montagem definem em que ponto um dispositivo de memória será anexado ao sistema de arquivos' +a_s_fstab_active = 'Sistemas de arquivos montados' +a_s_fstab_used = 'Usado' +a_s_fstab_avail = 'Disponível' +a_s_fstab_mountpoint = 'Ponto de Montagem' +a_s_fstab_device1 = 'O arquivo do dispositivo de memória ou a partição (ex. /dev/sda1)' +a_s_fstab_fs1 = 'O sistema que foi usado para formatar a memória (ex. ext3)' +a_s_fstab_swap1 = 'Se a sua memória física for insuficiente, os dados poderão ser trocados temporariamente para um dispositivo swap, resultando em uma maior quantidade de memória utilizável RAM. Esteja ciente de que a troca de dados (swap) é um processo muito lento pois o dispositivo swap não pode ser acessado com um nível elevado de memória RAM.' +a_s_flash_flashed = 'Firmware gravado com sucesso. Reiniciando o equipamento...' +a_s_flash_flasherr = 'Falha na gravação' +a_s_flash_fwimage = 'Imagem do firmware' +a_s_flash_received = 'Imagem recebida. Durante o processo de gravação, NÃO DESLIGUE O EQUIPAMENTO!' +a_s_flash_inprogress = 'Gravando firmware...' +a_s_flash_fwupgrade = 'Atualizar Firmware' +a_s_flash_keepcfg = 'Manter arquivos de configuração' +a_s_flash_notimplemented = 'Desculpe, esta função não está (ainda) disponível para sua plataforma.' +a_s_flash_upgrade1 = 'Substitui o firmware instalado por um mais novo. O formato do firmware depende da plataforma.' +a_s_reboot1 = 'Reinicia o seu equipamento' +a_s_reboot_do = 'Executar reinicialização' +a_s_reboot_running = 'Por favor aguarde: Equipamento reiniciando...' +a_s_reboot_u = 'Aviso: Existem alterações não salvas que serão perdidas durante a reinicialização!' +a_s_applyreboot1 = 'Alterações aplicadas.' +a_s_backup = 'Backup / Restauração' +a_s_backup_backup = 'Criar backup' +a_s_backup_archive = 'Arquivo de backup' +a_s_backup_reset = 'Restaurar as configurações padrão do roteador' +a_s_backup_reset1 = 'Proceder com a restauração de as configurações padrões?' +a_s_backup_restore = 'Restaurar backup' +a_s_backup1 = 'Aqui você pode fazer o backup e restaurar as configurações do seu roteador e - se possível - restaurar seu roteador para as configurações padrão.' +a_srv_http = 'Servidor-HTTP' +a_srv_ssh = 'Servidor-SSH' +a_srv_services1 = 'Serviços e daemons executando diversas tarefas no seu equipamento.' +a_srv_services2 = 'A maioria deles são servidores de rede, que oferecem um determinado serviço para seu equipamento ou rede como acesso shell, servindo páginas web como o LuCI, fazendo roteamento, enviando e-mails, ...' +a_srv_http1 = 'Um pequeno servidor web que pode ser utilizado para servir a interface LuCI.' +a_srv_http_authrealm = 'Autenticação Realm' +a_srv_http_authrealm1 = 'O realm que será mostrado no prompt de autenticação das páginas protegidas.' +a_srv_http_config1 = 'padrão é /etc/httpd.conf' +a_srv_http_root = 'Diretório raiz' +a_srv_dropbear1 = 'Dropbear oferece um acesso shell seguro à rede (SSH) e um servidor SCP integrado' +a_srv_d_pwauth = 'Autenticação por senha' +a_srv_d_pwauth1 = 'Permitir autenticação SSH por senha' +a_w_channel = 'Canal' +a_w_wifi1 = 'Nesta página você encontrará opções de configuração WLAN baseada em redes sem fio.' +a_w_wifi2 = 'Você pode facilmente integrar seus equipamentos 802.11a/b/g/n com sua rede física e usar o adaptador virtual para construir repetidoras wireless ou oferecer várias redes com um equipamento.' +a_w_wifi3 = 'Há suporte para os modos Managed, Client, Ad-Hoc e WDS bem como encriptação WPA e WPA2 proteger a comunicação.' +a_w_devices1 = 'Aqui você pode configurar dispositivos wifi instalados wifi. ' +a_w_txantenna = 'Antena de Transmissão' +a_w_rxantenna = 'Antena para Recebimento' +a_w_distance1 = 'Distãncia para a estação mais distante (em metros)' +a_w_diversity = 'Diversidade' +a_w_countrycode = 'Código do País' +a_w_connlimit = 'Limite de Conexão' +a_w_networks1 = 'Você pode executar várias redes wifi com um dispositivo. Esteja ciente de que existem certas restrições de hardware e de driver específico. Normalmente você pode operar 1 rede Ad-Hoc ou até 3 redes Master-Mode e 1 Client-Mode simultaneamente.' +a_w_netid = 'Nome da Rede (ESSID)' +a_w_network1 = 'Adicione a rede Wifi à rede física' +a_w_netmanual = ' - Criar nova Rede - ' +a_w_txpwr = 'Potência de Transmissão' +a_w_brcmburst = 'Broadcom Frame Burst' +a_w_athburst = 'Atheros Frame Burst' +a_w_radiussrv = 'Servidor Radius' +a_w_radiusport = 'Porta-Radius' +a_w_apisolation = 'Isolamento do AP' +a_w_apisolation1 = 'Impede a comunicação de Cliente para Cliente' +a_w_hideessid = 'Ocultar ESSID' +a_w_ap = 'Access Point' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'Pseudo Ad-Hoc (ahdemo)' +a_w_client = 'Client' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq é um combinado Servidor-DHCP e Encaminhador-DNS para firewalls NAT' +dhcp_dnsmasq_domainneeded = 'Domínio requerido' +dhcp_dnsmasq_domainneeded_desc = 'Não encaminhar Requisições-DNS sem o Nome do DNS' +dhcp_dnsmasq_authoritative = 'Autoritário' +dhcp_dnsmasq_authoritative_desc = 'Este é o único DHCP na rede local' +dhcp_dnsmasq_boguspriv = 'Filtro privado' +dhcp_dnsmasq_boguspriv_desc = 'Não encaminhar as pesquisas reversas para redes locais' +dhcp_dnsmasq_filterwin2k = 'Filtro de inutilidade' +dhcp_dnsmasq_filterwin2k_desc = 'Filtro de initulidades de consultas-DNS de sistemas windows' +dhcp_dnsmasq_localisequeries = 'Locallizar consultas' +dhcp_dnsmasq_localisequeries_desc = 'Localizar o hostname dependendo de sua sub-rede' +dhcp_dnsmasq_local = 'Servidor Local' +dhcp_dnsmasq_domain = 'Domínio Local' +dhcp_dnsmasq_expandhosts = 'Expandir Hosts' +dhcp_dnsmasq_expandhosts_desc = 'Adiciona os nomes dos domínios às entradas de hosts no arquivo resolv' +dhcp_dnsmasq_nonegcache = 'Não fazer cache desconhecido' +dhcp_dnsmasq_nonegcache_desc = 'Impede o cache de respostas-DNS negativas' +dhcp_dnsmasq_readethers = 'Usar /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Ler /etc/ethers para configurar o Servidor-DHCP' +dhcp_dnsmasq_leasefile = 'Arquivo Lease' +dhcp_dnsmasq_leasefile_desc = 'Arquivo onde os Leases-DHCP serão armazenados' +dhcp_dnsmasq_resolvfile = 'Arquivo Resolv' +dhcp_dnsmasq_resolvfile_desc = 'Arquivo local de DNS' +dhcp_dnsmasq_nohosts = 'Ignorar /etc/hosts' +dhcp_dnsmasq_strictorder = 'Ordem Exata' +dhcp_dnsmasq_strictorder_desc = 'Servidor-DNS será consultado na ordem do arquivo resolv' +dhcp_dnsmasq_logqueries = 'Log das consultas' +dhcp_dnsmasq_noresolv = 'Ignorar arquivo resolv' +dhcp_dnsmasq_dnsforwardmax = 'Consultas simultâneas' +dhcp_dnsmasq_port = 'Porta do DNS' +dhcp_dnsmasq_ednspacket_max = 'tamanho max. do pacote EDNS0' +dhcp_dnsmasq_dhcpleasemax = 'max. de DHCP-Leases' +dhcp_dnsmasq_addnhosts = 'arquivo host adicional' +dhcp_dnsmasq_queryport = 'porta para consulta' +dhcp_dnsmasq_enabletftp = 'Ativar servidor TFTP' +dhcp_dnsmasq_tftproot = 'Diretório raiz do servidor TFTP' +dhcp_dnsmasq_dhcpboot = 'Imagem para o boot remoto' +a_n_switch = 'Switch' +a_n_conntrack = 'Conexões Ativas' +a_n_conntrack_desc = 'Esta página fornece informações sobre as conexões de rede ativas.' +a_n_routes = 'Rotas' +a_n_routes4 = 'Rotas IPv4' +a_n_routes6 = 'Rotas IPv6' +a_network1 = 'Neste espaço você encontrará todas as configurações relacionadas à rede.' +a_network2 = 'Na maioria dos roteadores o switch de rede pode ser configurado livremente e dividos em diversas VLANs.' +a_network3 = 'Interfaces e Configurações-PPPoE / PPTP permite uma organização customizada da rede e conexões com outras redes, como a Internet.' +a_network4 = 'Com o DHCP dispositivos na sua rede local podem ser automaticamente configurados para a comunicação da rede.' +a_network5 = 'Firewall e redirecionamento de portas podem ser usados para proteger sua rede ao mesmo tempo que prestam serviços às redes externas.' +a_n_switch1 = 'As portas de rede do seu roteador podem ser combinadas com diversas VLANs em que os computadores podem se comunicar diretamente entre si. VLANs são frequentemente usadas para separar segmentos de redes diferentes. Muitas vezes é padrão uma porta Uplink para a conexão com a próxima maior rede, como a Internet e outras portas para uma rede local.' +network_switch_desc = 'Portas que pertencem a uma VLAN são separadas com espaços. A porta com o maior número (geralmente 5) é muitas vezes a conexão com a interface de rede interna do roteador. Em dispositivos com 5 portas muitas vezes a porta com o número mais baixo (0) é a porta predefinida como Uplink.' +a_n_ifaces1 = 'Nesta página você pode configurar as interfaces de rede. Você pode ter várias interfaces do tipo bridge, assinalando o campo "interfaces bridge" e entrar com os nomes de várias interfaces de rede separadas por espaços. Você pode também usar a notação para VLAN INTERFACE.VLANNR (ex.: eth0.1).' +a_n_i_bridge = 'Interfaces bridge' +a_n_i_bridge1 = 'cria uma bridge sobre determinada(s) interface(s)' +dhcp_desc = 'Com o DHCP membros da rede podem automaticamente receber suas configurações de rede (endereço-IP, netmask, servidor-DNS, ...).' +dhcp_dhcp_leasetime = 'Tempo de Lease' +dhcp_dhcp_dynamicdhcp = 'DHCP Dinâmico' +dhcp_dhcp_ignore = 'Ignorar Interface' +dhcp_dhcp_ignore_desc = 'desabilitar DHCP para esta interface' +dhcp_dhcp_force = 'Forçar' +dhcp_dhcp_start_desc = 'primeiro endereço (último octeto)' +dhcp_dhcp_limit_desc = 'número de endereços para lease -1' +dhcp_dhcp_dhcpoption = 'Opções-DHCP' +dhcp_dhcp_dhcpoption_desc = 'Veja "dnsmasq --help dhcp" para a lista disponível de opções.' +dhcp_leases = 'Leases' +luci_ethers = 'Leases Estáticos' +dhcp_timeremain = 'Tempo de lease restante' +dhcp_leases_active = 'Leases Ativos' +a_n_ptp = 'Conexões Ponto-a-Ponto' +a_n_ptp1 = 'Conexões Ponto-a-Ponto com PPPoE ou PPTP muitas vezes são usados para conectar um dispositivo sobre DSL ou tecnologia similar para um ponto de acesso à internet.' +network_interface_prereq = 'Você precisa instalar os pacotes "comgt" para UMTS/GPRS, "ppp-mod-pppoe" para PPPoE, "ppp-mod-pppoa" para PPPoA ou "pptp" para o suporte PPtP' +network_interface_prereq_mini = 'Você precisa instalar os pacotes "ppp-mod-pppoe" para PPPoE ou "pptp" para o suporte PPtP' +network_interface_server = 'Servidor-PPTP' +network_interface_demand = 'Desconexão Automática' +network_interface_demand_desc = 'Tempo (em segundos) para desconexão de uma conexão não mais utilizada' +network_interface_keepalive = 'Manter em Atividade' +network_interface_keepalive_desc = 'Número de falhas do teste de conexão para incializar uma reconexão automática' +network_interface_device = 'Dispositivo do Modem' +network_interface_device_desc = 'O caminho do dispostivo do seu modem, ex. /dev/ttyUSB0' +network_interface_defaultroute = 'Susbtituir a rota padrão' +network_interface_defaultroute_desc = 'Permitir o pppd substituir a rota padrão atual e usar a interface PPP como padrão após a conexão ser efetuada com sucesso' +network_interface_peerdns = 'Utilizar DNS do ponto' +network_interface_peerdns_desc = 'Configurar o servidor DNS local para usar o servidores de nomes fornecidos pelo ponto PPP' +network_interface_ipv6 = 'Ativar IPv6 no link PPP' +network_interface_connect = 'Script de conexão' +network_interface_connect_desc = 'Deixar o pppd executar este script após o estabelecimento do link PPP' +network_interface_disconnect = 'Script de desconexão' +network_interface_disconnect_desc = 'Deixar o pppd executar esse script antes de derrubar o link PPP' +network_interface_pppd_options = 'Opções adicionais do pppd' +network_interface_pppd_options_desc = 'Especificar argumentos adicionais por linha de comando para o pppd aqui' +network_interface_apn = 'Ponto de acesso (APN)' +network_interface_pincode = 'Código PIN' +network_interface_pincode_desc = 'Certifique-se de que você forneceu o código PIN correto aqui, ou você pode bloquear o seu cartão SIM!' +network_interface_service = 'Tipo do serviço' +network_interface_maxwait = 'Configurar tempo de espera' +network_interface_maxwait_desc = 'Segundos de espera para o modem ficar pronto antes de tentar se conectar' +a_n_r_routes1 = 'Rotas específicas sobre qual interface e gateway um determinado host ou rede pode ser alcançado.' +a_n_routes_static = 'Rotas Estáticas' +a_n_routes_static4 = 'Rotas Estáticas IPv4' +a_n_routes_static6 = 'Rotas Estáticas IPv6' +a_n_routes_kernel4 = 'Rotas-IPv4 ativas' +a_n_routes_kernel6 = 'Rotas-IPv6 ativas' +a_n_r_target1 = 'IP do host ou rede' +a_n_r_target6 = 'IPv6 do host ou rede' +a_n_r_netmask1 = 'se o destino for uma rede' +m_n_inet = 'Conexão com a Internet' +m_n_local = 'Rede Local' +m_n_route = 'Rota' +m_n_brdige = 'Bridge' +m_w_ap = 'Provedor (Access Point)' +m_w_adhoc = 'Independente (Ad-Hoc)' +m_w_client = 'Cliente (Client)' +m_w_wds = 'Distribuído (WDS)' +m_w_clientmode = 'Modo CLient' +system_system_logsize = 'Tamanho do buffer do sistema de log' +system_system_logip = 'Servidor externo do sistema de log' +system_system_conloglevel = 'Nível de saída do log' +system_system_conloglevel_desc = 'Nível das mensagens de log no console' +m_i_processor = 'Processador' +m_i_memory = 'Memória' +m_i_systemtime = 'Hora Local' +m_i_uptime = 'Uptime' +m_n_d_firstaddress = 'Primeiro endereço de lease' +m_n_d_numleases = 'Número de endereços de lease' +routingtable = 'Tebela de roteamento' +wlanscan = 'Procurar redes Wifi' +frequency = 'Frequência' +power = 'Potência' +noise = 'Ruído' +signal = 'Sinal' +link = 'Link' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Bitrate' +m_n_keepalive = 'reconectar automaticamente' +m_n_dialondemand = 'desconectar quando ocioso por' +m_n_pptp_server = 'Servidor-PPTP' +leds = 'Configuração do LED' +leds_desc = 'Customiza o comportamento do dispositivo de LEDs se possível.' +system_led_name = 'Nome do LED' +system_led_sysfs = 'Dispositivo do LED' +system_led_default = 'Estado padrão' +system_led_default_desc = 'selecionado como = ligado' +system_led_trigger = 'Evento' +system_led_trigger_none = 'Nenhum' +system_led_trigger_defaulton = 'Padrão Ligado' +system_led_trigger_timer = 'Contador' +system_led_trigger_heartbeat = 'Carga Média' +system_led_trigger_netdev = 'Dispositivo de Rede' +system_led_delayoff = 'Tempo no Estado Desligado' +system_led_delayoff_desc = 'Tempo (em ms) do LED desligado' +system_led_delayon = 'Tempo no Estado Ligado' +system_led_delayon_desc = 'Tempo (em ms) do LED ligado' +system_led_dev = 'Dispositivo' +system_led_mode = 'Modo do Evento' +system_led_mode_link = 'Link Ativo' +system_led_mode_tx = 'Transmitir' +system_led_mode_rx = 'Receber' +network_interface_up = 'Ativo' +network_interface_hwaddr = 'Endereço-MAC' +network_interface_hwaddr_desc = 'Endereço do Hardware' +network_interface_txrx = 'Tráfego' +network_interface_txrx_desc = 'transmitido / recebido' +network_interface_err = 'Erros' +network_interface_err_desc = 'TX / RX' +network_interface_fwzone = 'Criar / Atribuir à uma zona de firewall' +network_interface_fwzone_desc = 'Esta interface não pertence a nenhuma zona de firewall ainda.' +process_head = 'Processos' +process_descr = 'Esta lista fornece uma visão geral sobre os processos atualmente sendo executados no sistema.' +process_pid = 'PID' +process_owner = 'Dono' +process_command = 'Comando' +process_cpu = 'Uso da CPU (%)' +process_mem = 'Uso de memória (%)' +process_hup = 'Hang Up' +process_term = 'Terminar' +process_kill = 'Matar' +mem_cached = 'em cache' +mem_buffered = 'em buffer' +mem_free = 'livre' +a_s_crontab = 'Tarefas Agendadas' +a_s_crontab1 = 'Este é o sistema de agendamento de tarefas.' +a_w_nasid = 'NAS ID' +a_w_cacert = 'Caminho do Certificado CA' +a_w_eaptype = 'Método EAP' +a_w_tlsprivkey = 'Caminho da Chave Privada' +a_w_tlsprivkeypwd = 'Senha da Chave Privada' +a_w_peapauth = 'Autenticação PEAP' +a_w_peapidentity = 'Identidate-PEAP' +a_w_peappassword = 'Senha-PEAP' +a_w_create = 'Criar Rede' +hostnames = 'Hostnames' +hostnames_entries = 'Entrada do Host' +hostnames_hostname = 'Hostname' +hostnames_address = 'Endereço de IP' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.xml b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.xml new file mode 100644 index 0000000..35d30d5 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/admin-core.pt-br.xml @@ -0,0 +1,333 @@ + + + + +As seguintes alterações foram aplicadas +As seguintes alterações foram recuperadas +Interface do Usuário +LuCI é uma coleção gratuita de softwares Lua incluindo um Framework Web MVC e uma Interface Web para equipamentos embarcados. LuCI é licenciado sob a Licença Apache. +Página do Projeto +Líder(es) do Desenvolvimento +Desenvolvedores que Crontribuíram +Obrigado à +Olá! +Esta é a área de administração LuCI. +LuCI é gratuito, flexível e uma interface gráfica fácil de utilizar para configurar OpenWrt Kamikaze. +Nas próximas páginas você pode ajustar todas as definições importantes do seu roteador. +Aviso: No LuCI as alterações devem ser confirmadas clicando em Alterações - Salvar & Aplicar antes de serem aplicadas. +Como nós sempre queremos melhorar essa interface, estamos ansiosos para seus comentários e sugestões. +E agora divirta-se com o seu roteador! +O Time do LuCI +Aqui você pode customizar as configurações e funcionalidades do LuCI. +Ações pós-gravação +Estes comandos são executados automaticamente quando uma determinada configuração da UCI está gravada, permitindo mudanças a serem aplicadas instantaneamente. +Arquivos que devem ser mantidos quando gravar um novo firmware. +Quando gravar um novo firmware com o LuCI estes arquivos serão adicionados ao novo firmware instalado. +Aqui você pode encontrar informações sobre o estado atual do sistema, como CPU, frequência do relógio, uso de memória ou da interface de rede de dados. +Também os arquivos de logs do kernel ou dos serviços podem serem vistos aqui para obter uma visão geral sobre o seu estado atual. +WLAN-Scan +Redes Wifi no seu ambiente local +Encr. +Link +Sinal +Ruído +Rotas +Netmask +Gateway +Métrica +Aqui você pode configurar os aspectos básicos do seu equipamento como o nome do host ou o fuso horário. +Software +Senha do Admin +Configuração-OPKG +Chaves-SSH +Pontos de Montagem +Atualizar Firmware +Altera as configurações relacionadas com o sistema em si, sua identificação, hardware e software instalados, autenticação ou pontos de montagem. +Essas configurações definem a base do seu sistema. +Preste atenção de que qualquer configuração errada aqui pode impedir o seu equipamento de inicilizar ou talvez bloquear seu acesso de fora à ele. +Executar Ações +Instalar +Fazer download e instalar pacote +Editar listas de pacotes e destinos de instalação +Nome do Pacote +Remover +Procurar pacote +Listas de pacotes atualizadas +Atualizar listas de pacotes +Atualizar os pacotes instalados +Listas de pacotes +Destino de Instalação +Altera a senha do administrador do sistema (Usuário root) +Senha alterada com sucesso +Erro: As senhas estão diferentes +Aqui você pode colar suas Chaves-SSH públicas (uma por linha) para a autenticação SSH por chave-pública. +Pontos de Montagem +Pontos de montagem definem em que ponto um dispositivo de memória será anexado ao sistema de arquivos +Sistemas de arquivos montados +Usado +Disponível +Ponto de Montagem +O arquivo do dispositivo de memória ou a partição (ex. /dev/sda1) +O sistema que foi usado para formatar a memória (ex. ext3) +Se a sua memória física for insuficiente, os dados poderão ser trocados temporariamente para um dispositivo swap, resultando em uma maior quantidade de memória utilizável RAM. Esteja ciente de que a troca de dados (swap) é um processo muito lento pois o dispositivo swap não pode ser acessado com um nível elevado de memória RAM. +Firmware gravado com sucesso. Reiniciando o equipamento... +Falha na gravação +Imagem do firmware +Imagem recebida. Durante o processo de gravação, NÃO DESLIGUE O EQUIPAMENTO! +Gravando firmware... +Atualizar Firmware +Manter arquivos de configuração +Desculpe, esta função não está (ainda) disponível para sua plataforma. +Substitui o firmware instalado por um mais novo. O formato do firmware depende da plataforma. +Reinicia o seu equipamento +Executar reinicialização +Por favor aguarde: Equipamento reiniciando... +Aviso: Existem alterações não salvas que serão perdidas durante a reinicialização! +Alterações aplicadas. +Backup / Restauração +Criar backup +Arquivo de backup +Restaurar as configurações padrão do roteador +Proceder com a restauração de as configurações padrões? +Restaurar backup +Aqui você pode fazer o backup e restaurar as configurações do seu roteador e - se possível - restaurar seu roteador para as configurações padrão. +Servidor-HTTP +Servidor-SSH +Serviços e daemons executando diversas tarefas no seu equipamento. +A maioria deles são servidores de rede, que oferecem um determinado serviço para seu equipamento ou rede como acesso shell, servindo páginas web como o LuCI, fazendo roteamento, enviando e-mails, ... +Um pequeno servidor web que pode ser utilizado para servir a interface LuCI. +Autenticação Realm +O realm que será mostrado no prompt de autenticação das páginas protegidas. +padrão é /etc/httpd.conf +Diretório raiz +Dropbear oferece um acesso shell seguro à rede (SSH) e um servidor SCP integrado +Autenticação por senha +Permitir autenticação SSH por senha +Canal +Nesta página você encontrará opções de configuração WLAN baseada em redes sem fio. +Você pode facilmente integrar seus equipamentos 802.11a/b/g/n com sua rede física e usar o adaptador virtual para construir repetidoras wireless ou oferecer várias redes com um equipamento. +Há suporte para os modos Managed, Client, Ad-Hoc e WDS bem como encriptação WPA e WPA2 proteger a comunicação. +Aqui você pode configurar dispositivos wifi instalados wifi. +Antena de Transmissão +Antena para Recebimento +Distãncia para a estação mais distante (em metros) +Diversidade +Código do País +Limite de Conexão +Você pode executar várias redes wifi com um dispositivo. Esteja ciente de que existem certas restrições de hardware e de driver específico. Normalmente você pode operar 1 rede Ad-Hoc ou até 3 redes Master-Mode e 1 Client-Mode simultaneamente. +Nome da Rede (ESSID) +Adicione a rede Wifi à rede física + - Criar nova Rede - +Potência de Transmissão +Broadcom Frame Burst +Atheros Frame Burst +Servidor Radius +Porta-Radius +Isolamento do AP +Impede a comunicação de Cliente para Cliente +Ocultar ESSID +Access Point +Ad-Hoc +Pseudo Ad-Hoc (ahdemo) +Client +WDS +Monitor +Dnsmasq é um combinado Servidor-DHCP e Encaminhador-DNS para firewalls NAT +Domínio requerido +Não encaminhar Requisições-DNS sem o Nome do DNS +Autoritário +Este é o único DHCP na rede local +Filtro privado +Não encaminhar as pesquisas reversas para redes locais +Filtro de inutilidade +Filtro de initulidades de consultas-DNS de sistemas windows +Locallizar consultas +Localizar o hostname dependendo de sua sub-rede +Servidor Local +Domínio Local +Expandir Hosts +Adiciona os nomes dos domínios às entradas de hosts no arquivo resolv +Não fazer cache desconhecido +Impede o cache de respostas-DNS negativas +Usar /etc/ethers +Ler /etc/ethers para configurar o Servidor-DHCP +Arquivo Lease +Arquivo onde os Leases-DHCP serão armazenados +Arquivo Resolv +Arquivo local de DNS +Ignorar /etc/hosts +Ordem Exata +Servidor-DNS será consultado na ordem do arquivo resolv +Log das consultas +Ignorar arquivo resolv +Consultas simultâneas +Porta do DNS +tamanho max. do pacote EDNS0 +max. de DHCP-Leases +arquivo host adicional +porta para consulta +Ativar servidor TFTP +Diretório raiz do servidor TFTP +Imagem para o boot remoto +Switch +Conexões Ativas +Esta página fornece informações sobre as conexões de rede ativas. +Rotas +Rotas IPv4 +Rotas IPv6 +Neste espaço você encontrará todas as configurações relacionadas à rede. +Na maioria dos roteadores o switch de rede pode ser configurado livremente e dividos em diversas VLANs. +Interfaces e Configurações-PPPoE / PPTP permite uma organização customizada da rede e conexões com outras redes, como a Internet. +Com o DHCP dispositivos na sua rede local podem ser automaticamente configurados para a comunicação da rede. +Firewall e redirecionamento de portas podem ser usados para proteger sua rede ao mesmo tempo que prestam serviços às redes externas. +As portas de rede do seu roteador podem ser combinadas com diversas VLANs em que os computadores podem se comunicar diretamente entre si. VLANs são frequentemente usadas para separar segmentos de redes diferentes. Muitas vezes é padrão uma porta Uplink para a conexão com a próxima maior rede, como a Internet e outras portas para uma rede local. +Portas que pertencem a uma VLAN são separadas com espaços. A porta com o maior número (geralmente 5) é muitas vezes a conexão com a interface de rede interna do roteador. Em dispositivos com 5 portas muitas vezes a porta com o número mais baixo (0) é a porta predefinida como Uplink. +Nesta página você pode configurar as interfaces de rede. Você pode ter várias interfaces do tipo bridge, assinalando o campo "interfaces bridge" e entrar com os nomes de várias interfaces de rede separadas por espaços. Você pode também usar a notação para VLAN INTERFACE.VLANNR (ex.: eth0.1). +Interfaces bridge +cria uma bridge sobre determinada(s) interface(s) +Com o DHCP membros da rede podem automaticamente receber suas configurações de rede (endereço-IP, netmask, servidor-DNS, ...). +Tempo de Lease +DHCP Dinâmico +Ignorar Interface +desabilitar DHCP para esta interface +Forçar +primeiro endereço (último octeto) +número de endereços para lease -1 +Opções-DHCP +Veja "dnsmasq --help dhcp" para a lista disponível de opções. +Leases +Leases Estáticos +Tempo de lease restante +Leases Ativos +Conexões Ponto-a-Ponto +Conexões Ponto-a-Ponto com PPPoE ou PPTP muitas vezes são usados para conectar um dispositivo sobre DSL ou tecnologia similar para um ponto de acesso à internet. +Você precisa instalar os pacotes "comgt" para UMTS/GPRS, "ppp-mod-pppoe" para PPPoE, "ppp-mod-pppoa" para PPPoA ou "pptp" para o suporte PPtP +Você precisa instalar os pacotes "ppp-mod-pppoe" para PPPoE ou "pptp" para o suporte PPtP +Servidor-PPTP +Desconexão Automática +Tempo (em segundos) para desconexão de uma conexão não mais utilizada +Manter em Atividade +Número de falhas do teste de conexão para incializar uma reconexão automática +Dispositivo do Modem +O caminho do dispostivo do seu modem, ex. /dev/ttyUSB0 +Susbtituir a rota padrão +Permitir o pppd substituir a rota padrão atual e usar a interface PPP como padrão após a conexão ser efetuada com sucesso +Utilizar DNS do ponto +Configurar o servidor DNS local para usar o servidores de nomes fornecidos pelo ponto PPP +Ativar IPv6 no link PPP +Script de conexão +Deixar o pppd executar este script após o estabelecimento do link PPP +Script de desconexão +Deixar o pppd executar esse script antes de derrubar o link PPP +Opções adicionais do pppd +Especificar argumentos adicionais por linha de comando para o pppd aqui +Ponto de acesso (APN) +Código PIN +Certifique-se de que você forneceu o código PIN correto aqui, ou você pode bloquear o seu cartão SIM! +Tipo do serviço +Configurar tempo de espera +Segundos de espera para o modem ficar pronto antes de tentar se conectar +Rotas específicas sobre qual interface e gateway um determinado host ou rede pode ser alcançado. +Rotas Estáticas +Rotas Estáticas IPv4 +Rotas Estáticas IPv6 +Rotas-IPv4 ativas +Rotas-IPv6 ativas +IP do host ou rede +IPv6 do host ou rede +se o destino for uma rede +Conexão com a Internet +Rede Local +Rota +Bridge +Provedor (Access Point) +Independente (Ad-Hoc) +Cliente (Client) +Distribuído (WDS) +Modo CLient +Tamanho do buffer do sistema de log +Servidor externo do sistema de log +Nível de saída do log +Nível das mensagens de log no console +Processador +Memória +Hora Local +Uptime +Primeiro endereço de lease +Número de endereços de lease +Tebela de roteamento +Procurar redes Wifi +Frequência +Potência +Ruído +Sinal +Link +Frag. +RTS +Bitrate +reconectar automaticamente +desconectar quando ocioso por +Servidor-PPTP +Configuração do LED +Customiza o comportamento do dispositivo de LEDs se possível. +Nome do LED +Dispositivo do LED +Estado padrão +selecionado como = ligado +Evento +Nenhum +Padrão Ligado +Contador +Carga Média +Dispositivo de Rede +Tempo no Estado Desligado +Tempo (em ms) do LED desligado +Tempo no Estado Ligado +Tempo (em ms) do LED ligado +Dispositivo +Modo do Evento +Link Ativo +Transmitir +Receber +Ativo +Endereço-MAC +Endereço do Hardware +Tráfego +transmitido / recebido +Erros +TX / RX +Criar / Atribuir à uma zona de firewall +Esta interface não pertence a nenhuma zona de firewall ainda. +Processos +Esta lista fornece uma visão geral sobre os processos atualmente sendo executados no sistema. +PID +Dono +Comando +Uso da CPU (%) +Uso de memória (%) +Hang Up +Terminar +Matar +em cache +em buffer +livre +Tarefas Agendadas +Este é o sistema de agendamento de tarefas. +NAS ID +Caminho do Certificado CA +Método EAP +Caminho da Chave Privada +Senha da Chave Privada +Autenticação PEAP +Identidate-PEAP +Senha-PEAP +Criar Rede +Hostnames +Entrada do Host +Hostname +Endereço de IP +PPPoA Encapsulation +Clamp Segment Size +Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs. + + diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.lua b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.lua new file mode 100644 index 0000000..2ac6ddf --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.lua @@ -0,0 +1,17 @@ +cbi_add = 'Adicionar entrada' +cbi_del = 'Remover entrada' +cbi_replace = 'Substituir entrada' +cbi_invalid = 'Valor inválido' +cbi_invalid_section = 'A validação falhou: Por favor, verifique por erros em algum dos campos de entrada.' +cbi_missing = 'Este campo é obrigatório' +cbi_deperror = 'A validação falhou: É obrigatório pelo menos um campo com o valor correto.' +cbi_reqerror = 'Um requisito para esta opção não foi cumprido' +cbi_addopt = '-- Campo Adicional --' +cbi_optional = ' (opcional)' +cbi_sectempty = 'Esta seção não contêm valores ainda' +cbi_manual = '-- customizado --' +cbi_select = '-- Por favor escolha --' +cbi_gorel = 'Ir para a página relacionada à configuração' +cbi_applying = 'Aplicando mudanças' +cbi_upload = 'Fazer upload do arquivo' +cbi_browser = 'Procurar arquivo...' diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.xml b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.xml new file mode 100644 index 0000000..59b2ee4 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/cbi.pt-br.xml @@ -0,0 +1,23 @@ + + + + +Adicionar entrada +Remover entrada +Substituir entrada +Valor inválido +A validação falhou: Por favor, verifique por erros em algum dos campos de entrada. +Este campo é obrigatório +A validação falhou: É obrigatório pelo menos um campo com o valor correto. +Um requisito para esta opção não foi cumprido +-- Campo Adicional -- + (opcional) +Esta seção não contêm valores ainda +-- customizado -- +-- Por favor escolha -- +Ir para a página relacionada à configuração +Aplicando mudanças +Fazer upload do arquivo +Procurar arquivo... + + diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.lua b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.lua new file mode 100644 index 0000000..26672bd --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.lua @@ -0,0 +1,103 @@ +skiplink1 = 'Ir para a navegação' +skiplink2 = 'Ir para o conteúdo' +navigation = 'Navegação' +about = 'Sobre' +add = 'Adicionar' +addresses = 'Endereços' +aliases = 'Aliases' +all = 'todos' +allf = 'todas' +back = 'voltar' +administration = 'Administração' +essentials = 'Básico' +apply = 'Aplicar' +basicsettings = 'Configurações Básicas' +broadcast = 'Broadcast-IPv4' +changes = 'Alterações' +channel = 'Canal' +cidr6 = 'Notação-CIDR: endereço/prefixo' +code = 'Código' +config = 'Configuração' +configfile = 'Arquivo de configuração' +confirmation = 'Confirmação' +delete = 'Apagar' +descr = 'Descrição' +design = 'Tema' +destination = 'Destino' +device = 'Dispositivo' +devices = 'Dispositivos' +disable = 'desativar' +distance = 'Distância' +dmesg = 'Log do Kernel' +dnsserver = 'Servidor-DNS' +edit = 'Editar' +enable = 'ativar' +encryption = 'Criptografia' +error = 'Erro' +filesystem = 'Sistema de arquivo' +filter = 'Filtro' +gateway = 'Gateway-IPv4' +gateway6 = 'Gateway-IPv6' +general = 'Geral' +hostname = 'Hostname' +install = 'Instalar' +installed = 'instalado' +interface = 'Interface' +interfaces = 'Interfaces' +ipaddress = 'Endereço-IPv4' +ip6address = 'Endereço-IPv6' +legend = 'Legenda' +library = 'Biblioteca' +logout = 'Logout' +key = 'Chave' +language = 'Idioma' +limit = 'Limite' +load = 'Carga' +login = 'Login' +macaddress = 'Endereço-MAC' +manpage = 'veja sobre '%s' no manual' +metric = 'Métrica' +mode = 'Modo' +name = 'Nome' +netmask = 'Netmask-IPv4' +network = 'Rede' +networks = 'Redes' +none = 'nenhum' +notinstalled = 'não instalado' +ok = 'OK' +options = 'Opções' +overview = 'Visão geral' +packagemanager = 'Gerenciador de Pacotes' +password = 'Senha' +path = 'Caminho' +port = 'Porta' +ports = 'Portas' +protocol = 'Protocolo' +reboot = 'Reboot' +reset = 'Restaurar' +revert = 'Recuperar' +save = 'Salvar' +saveapply = 'Salvar & Aplicar' +scan = 'Scanear' +service = 'Serviço' +services = 'Serviços' +settings = 'Configurações' +size = 'Tamanho' +source = 'Origem' +start = 'Início' +static = 'estático' +status = 'Status' +statistics = 'Estatísticas' +submit = 'Enviar' +syslog = 'Log do Sistema' +system = 'Sistema' +target = 'Destino' +timezone = 'Fuso Horário' +type = 'Tipo' +unknownerror = 'Erro Desconhecido' +unsavedchanges = 'Alterações não Salvas' +username = 'Nome do usuário' +version = 'Versão' +webui = 'Web UI' +wifi = 'Wifi' +zone = 'Zona' diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.xml b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.xml new file mode 100644 index 0000000..ac90be3 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/default.pt-br.xml @@ -0,0 +1,110 @@ + + + + +Ir para a navegação +Ir para o conteúdo +Navegação + +Sobre +Adicionar +Endereços +Aliases +todos +todas +voltar +Administração +Básico +Aplicar +Configurações Básicas +Broadcast-IPv4 +Alterações +Canal +Notação-CIDR: endereço/prefixo +Código +Configuração +Arquivo de configuração +Confirmação +Apagar +Descrição +Tema +Destino +Dispositivo +Dispositivos +desativar +Distância +Log do Kernel +Servidor-DNS +Editar +ativar +Criptografia +Erro +Sistema de arquivo +Filtro +Gateway-IPv4 +Gateway-IPv6 +Geral +Hostname +Instalar +instalado +Interface +Interfaces +Endereço-IPv4 +Endereço-IPv6 +Legenda +Biblioteca +Logout +Chave +Idioma +Limite +Carga +Login +Endereço-MAC +veja sobre '%s' no manual +Métrica +Modo +Nome +Netmask-IPv4 +Rede +Redes +nenhum +não instalado +OK +Opções +Visão geral +Gerenciador de Pacotes +Senha +Caminho +Porta +Portas +Protocolo +Reboot +Restaurar +Recuperar +Salvar +Salvar & Aplicar +Scanear +Serviço +Serviços +Configurações +Tamanho +Origem +Início +estático +Status +Estatísticas +Enviar +Log do Sistema +Sistema +Destino +Fuso Horário +Tipo +Erro Desconhecido +Alterações não Salvas +Nome do usuário +Versão +Web UI +Wifi +Zona + + diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.lua b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.lua new file mode 100644 index 0000000..9df9c6a --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.lua @@ -0,0 +1,3 @@ +sysauth_head = 'Autorização Requerida' +sysauth_prompt = 'Digite seu nome de usuário e senha.' +sysauth_failed = 'Nome de usuário inválido e/ou a senha! Por favor, tente novamente.' diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.xml b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.xml new file mode 100644 index 0000000..d63433e --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/sysauth.pt-br.xml @@ -0,0 +1,9 @@ + + + + +Autorização Requerida +Digite seu nome de usuário e senha. +Nome de usuário inválido e/ou a senha! Por favor, tente novamente. + + diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.lua b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.lua new file mode 100644 index 0000000..52a37b7 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.lua @@ -0,0 +1,37 @@ +wifi_auto = 'automático' +wifi_fh = 'Salto de Frequência' +wifi_diversity = 'Diversidade' +wifi_txantenna = 'Antena de Transmissão' +wifi_rxantenna = 'Antena de Recepção' +wifi_distance = 'Otimização de Distância' +wifi_distance_desc = 'Distância para o último host da rede (em metros).' +wifi_macpolicy = 'Filtro de Endereço-MAC' +wifi_whitelist = 'Permitir somente os listados' +wifi_blacklist = 'Permitir todos, exceto os listados' +wifi_maclist = 'Lista de MAC' +wifi_bursting = 'Frame Bursting' +wifi_country = 'Código do País' +wifi_maxassoc = 'Limite de Conexão' +wifi_essid = 'ESSID' +wifi_bssid = 'BSSID' +wifi_frag = 'Fragmentation Threshold' +wifi_rts = 'RTS/CTS Threshold' +wifi_wds = 'WDS' +wifi_wdssep = 'Separar WDS' +wifi_hidden = 'Ocultar ESSID' +wifi_isloate = 'Isolar Clientes' +wifi_isloate_desc = 'Previnir Comunicação de Cliente para Cliente' +wifi_bgscan = 'Scanear em Segundo Plano' +wifi_rate = 'Taxa de Transmissão' +wifi_mcast_rate = 'Taxa de Multicast' +wifi_minrate = 'Taxa Mínima' +wifi_maxrate = 'Taxa Máxima' +wifi_compression = 'Compressão' +wifi_turbo = 'Modo Turbo' +wifi_ff = 'Fast Frames' +wifi_wmm = 'Modo WMM' +wifi_xr = 'Suporte XR' +wifi_ar = 'Suporte AR' +wifi_nosbeacon = 'Disable HW-Beacon timer' +wifi_noprobereq = 'Don not send probe responses' +wifi_wpareq = 'Criptografia-WPA requer wpa_supplicant (para o modo cliente) ou hostapd (para o modo AP e ad-hoc) instalados.' diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.xml b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.xml new file mode 100644 index 0000000..6953be0 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/luasrc/i18n/wifi.pt-br.xml @@ -0,0 +1,44 @@ + + + + +automático +Salto de Frequência +Diversidade +Antena de Transmissão +Antena de Recepção +Otimização de Distância +Distância para o último host da rede (em metros). +Filtro de Endereço-MAC +Permitir somente os listados +Permitir todos, exceto os listados +Lista de MAC +Frame Bursting +Código do País +Limite de Conexão +ESSID +BSSID +Fragmentation Threshold +RTS/CTS Threshold +WDS +Separar WDS +Ocultar ESSID +Isolar Clientes +Previnir Comunicação de Cliente para Cliente +Scanear em Segundo Plano +Taxa de Transmissão +Taxa de Multicast +Taxa Mínima +Taxa Máxima +Compressão +Modo Turbo +Fast Frames +Modo WMM +Suporte XR +Suporte AR +Disable HW-Beacon timer +Don not send probe responses + +Criptografia-WPA requer wpa_supplicant (para o modo cliente) ou hostapd (para o modo AP e ad-hoc) instalados. + + diff --git a/openwrt/packages/luci/i18n/portuguese_brazilian/root/etc/uci-defaults/luci-i18n-portuguese_brazilian b/openwrt/packages/luci/i18n/portuguese_brazilian/root/etc/uci-defaults/luci-i18n-portuguese_brazilian new file mode 100755 index 0000000..a4b0635 --- /dev/null +++ b/openwrt/packages/luci/i18n/portuguese_brazilian/root/etc/uci-defaults/luci-i18n-portuguese_brazilian @@ -0,0 +1,5 @@ +#!/bin/sh +uci batch <<-EOF + set luci.languages.pt_br="Portuguese (Brazilian)" + commit luci +EOF diff --git a/openwrt/packages/luci/i18n/russian/Makefile b/openwrt/packages/luci/i18n/russian/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/i18n/russian/ipkg/postinst b/openwrt/packages/luci/i18n/russian/ipkg/postinst new file mode 100755 index 0000000..7ace482 --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-i18n-russian ) && rm -f /etc/uci-defaults/luci-i18n-russian +} diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.lua b/openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.lua new file mode 100644 index 0000000..4961495 --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.lua @@ -0,0 +1,269 @@ +uci_applied = 'Данные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ принÑÑ‚Ñ‹' +uci_reverted = 'Данные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ отвергнуты' +a_i_ui = 'ПользовательÑкий интерфейÑ' +c_lucidesc = 'LuCI Ñто Ñвободное Lua програмное обеÑпечение Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ MVC-Вебфреймворк и веб Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð²Ñтраиваемый в уÑтройÑтва. LuCI раÑпроÑтранÑетÑÑ Ð¿Ð¾Ð´ лицензией Apache-License.' +c_projecthome = 'ДомашнÑÑ Ñтраница проекта' +c_leaddev = 'Ведущие разработчики' +c_contributors = 'Помогавшие в разработке' +c_thanksto = 'БлагодарÑ' +a_i_i_hello = 'Добро пожаловать.' +a_i_i_admin1 = 'Это зона ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ LuCI.' +a_i_i_admin2 = 'LuCI Ñвободный, гибкий и дружелюбный грфичеÑкий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ Ð½Ð°Ñтройки OpenWrt Kamikaze.' +a_i_i_admin3 = 'С помощью Ñтих Ñтраниц вы можете изменить оÑновные наÑтройки вашего роутера.' +a_i_i_admin4 = 'Внимание: Ð’ LuCI Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð½Ð¸Ð¼Ð°ÑŽÑ‚ÑÑ Ð¿Ð¾Ñле Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ - ПринÑÑ‚ÑŒ.' +a_i_i_admin5 = 'Так же мы вÑегда желаем улучшить Ñтот интерфейÑ, мы вÑегда обратим внимание на ваши вопроÑÑ‹ и предложениÑ.' +a_i_i_admin6 = 'Ртеперь повеÑелитеÑÑŒ Ñо Ñвоим роутером!' +a_i_i_team = 'Команда LuCI' +a_i_luci1 = 'ЗдеÑÑŒ вы можете изменить наÑтройки и функциональноÑÑ‚ÑŒ LuCI.' +a_i_ucicommit = 'ЗапуÑк команд' +a_i_ucicommit1 = 'Эти команды будут запущенны автоматичеÑки когда Ð´Ð°Ð½Ð½Ð°Ñ UCI ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð° и Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ принÑÑ‚Ñ‹.' +a_i_keepflash = 'Файлы которые необходимо Ñохранить при перепрошивании' +a_i_keepflash1 = 'ПоÑле перепрошивки LuCI Ñти файлы будут добавлены в обновлённую ÑиÑтему .' +a_st_i_status1 = 'ЗдеÑÑŒ вы можете найти информацию о текущей ÑтатиÑтики ÑиÑтемы вроде чаÑтоты процеÑÑора, иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ð¼Ñти или Ñетевого интерфейÑа.' +a_st_i_status2 = 'Ртак же Ñдра или ÑервиÑов, ÑиÑтемный журнал может быть так же проÑмотрен здеÑÑŒ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ что бы получить полный обзор текущего ÑоÑтоÑÐ½Ð¸Ñ ÑиÑтемы.' +iwscan = 'WLAN-Сканирование' +iwscan1 = 'Обзор ÑущеÑтвующих Wi-Fi Ñетей' +iwscan_encr = 'Шифрование' +iwscan_link = 'СвÑзь' +iwscan_signal = 'Сигнал' +iwscan_noise = 'Шум' +routes = 'Маршруты' +routes_netmask = 'Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ Ð¼Ð°Ñка' +routes_gateway = 'Шлюз' +routes_metric = 'Метрика' +a_s_desc = 'ЗдеÑÑŒ вы можете наÑтроить оÑновные параметры вашего уÑтройÑтва такие как Ð¸Ð¼Ñ Ñ…Ð¾Ñта или чаÑовой поÑÑ.' +a_s_packages = 'Программное обеÑпечение' +a_s_changepw = 'Пароль админиÑтратора' +a_s_p_ipkg = 'OPKG-ÐаÑтройка' +a_s_sshkeys = 'SSH-Ключи' +a_s_fstab = 'ДиÑковые разделы' +a_s_flash = 'Обновление прошивки' +a_s_i_system1 = 'Изменение наÑтроек ÑиÑтемы ÑвÑзанных Ñ Ñамоидентификацией, уÑÑ‚Ñтанвкой аппаратно и/или програмного обеÑпечениÑ, идентификацией или диÑковыми разделами.' +a_s_i_system2 = 'Эти наÑтройки определÑÑŽÑ‚ оÑнову вашей ÑиÑтемы.' +a_s_i_system3 = 'Ðеобходимо тчательно отнеÑтиÑÑŒ к нижеÑледующим наÑтройкам, в результате неправильной конфигурации которых вы можете потерÑÑ‚ÑŒ управление над ÑиÑтемой или уÑтройÑто может не загружатьÑÑ.' +a_s_packages_do = 'ПринÑÑ‚ÑŒ изменениÑ' +a_s_packages_install = 'УÑтановка' +a_s_packages_installurl = 'Загрузить и уÑтановить пакеты' +a_s_packages_ipkg = 'Изменить лиÑтинг пакетов и путей уÑтановки' +a_s_packages_name = 'Ð˜Ð¼Ñ Ð¿Ð°ÐºÐµÑ‚Ð°' +a_s_packages_remove = 'Удалить' +a_s_packages_search = 'Ðайти пакет' +a_s_packages_update = 'ЛиÑтинг пакетов обновлён' +a_s_packages_updatelist = 'Обновить лиÑтинг пакетов' +a_s_packages_upgrade = 'Заменить уÑтановленные пакеты' +a_s_p_ipkg_pkglists = 'ЛиÑтинг пакетов' +a_s_p_ipkg_targets = 'Путь уÑтановки' +a_s_changepw1 = 'Изменение Ð¿Ð°Ñ€Ð¾Ð»Ñ ÑиÑтемного админиÑтратора (Пользователь root)' +a_s_changepw_changed = 'Пароль уÑпешно изменён' +a_s_changepw_nomatch = 'Ошибка: Пароли не Ñовпадают' +a_s_sshkeys1 = 'ЗдеÑÑŒ вы можете вÑтавить публичный SSH-Ключ Ð´Ð»Ñ SSH публичной-ключевой аутентификации.' +a_s_fstab_mountpoints = 'Точки монтированиÑ' +a_s_fstab_mountpoints1 = 'Точки Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÑÑŽÑ‚ к каком запоминающему уÑтройÑтву будет приÑоединена Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема' +a_s_fstab_active = 'Монтированные файловые ÑиÑтемы"' +a_s_fstab_used = 'ИÑпользованно"' +a_s_fstab_avail = 'ДоÑтупно"' +a_s_fstab_mountpoint = 'Точка приÑоединениÑ' +a_s_fstab_device1 = 'УÑтройÑтво или раздел (пример /dev/sda1)' +a_s_fstab_fs1 = 'Формат файловой ÑиÑтемы (пример ext3)' +a_s_fstab_swap1 = 'ЕÑли физичеÑкой RAM не хватает можно воÑпользоватьÑÑ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ð¼ хранением данных в файле-подкачке. Ð’ результате RAM памÑти будет доÑтупно в большем количеÑтве. Ðо помните, файл подкачки работает гораздо медленнее RAM так что не ждите обработки информации на ÑкороÑÑ‚ÑÑ… Ñравнимых Ñ RAM.' +a_s_flash_flashed = 'Прошивка уÑпешно обновленна. Перезагрузка уÑтройÑтва...' +a_s_flash_flasherr = 'Прошивка невозможна' +a_s_flash_fwimage = 'Файл прошивки' +a_s_flash_fwupgrade = 'Прошить' +a_s_flash_keepcfg = 'Сохранить конфигурационные файлы' +a_s_flash_notimplemented = 'Извините, Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¿Ð¾ÐºÐ° не доÑтупна на вашей платформе.' +a_s_flash_upgrade1 = 'ЗаменÑет уÑтановленную прошивку на новую. Формат прошивки платформо-завиÑимый.' +a_s_reboot1 = 'Сразу произойдёт перезагрузка вашей ÑиÑтемы' +a_s_reboot_do = 'Выполнить перезагрузку' +a_s_reboot_running = 'ПозалуйÑта подождите: УÑтройÑтво перезагружаетÑÑ...' +a_s_reboot_u = 'Внимание: ЕÑÑ‚ÑŒ неÑохранённые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ðµ потерÑÑŽÑ‚ÑÑ Ð¿Ð¾Ñле перезагрузки!' +a_s_applyreboot1 = 'Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð½ÑÑ‚Ñ‹.' +a_s_backup = 'Резервирование / ВоÑÑтановление' +a_s_backup_backup = 'Создать резервную копию' +a_s_backup_archive = 'Ðрхив воÑÑтановлениÑ' +a_s_backup_reset = 'СброÑить роутер к наÑтройкам по умолчанию' +a_s_backup_reset1 = 'Перейти к возврашению вÑех наÑтроек и уÑтановить наÑтройки по умолчанию?' +a_s_backup_restore = 'ВоÑÑтановить резервную копию' +a_s_backup1 = 'ЗдеÑÑŒ вы можете Ñделать резевную копию и воÑÑановить конфигурацию вашего роутера, еÑли Ñто возможно, или уÑтановить наÑтройки по умолчанию.' +a_srv_http = 'HTTP-Сервер' +a_srv_ssh = 'SSH-Сервер' +a_srv_services1 = 'СервиÑÑ‹ и демоны выполнÑющие определённые задачи на уÑтройÑтвах.' +a_srv_services2 = 'БольшинÑтво из них Ñетевые Ñерверы, которые выполнÑÑŽÑ‚ определённые задачи Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… уÑтройÑтв или Ñетей наподобие shell-доÑтупа, web-Ñтраниц таких как LuCI, выполнÑÑŽÑ‚ mesh-маршрутизацию, отправлÑÑŽÑ‚ пиÑьма , ...' +a_srv_http1 = 'Маленький веб-Ñервер, Ñлужащий Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ LuCI.' +a_srv_http_authrealm = 'ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑ‚ÑŒ' +a_srv_http_authrealm1 = 'Что будет показано при авторизации на защищённых Ñтраницах.' +a_srv_http_config1 = 'по умолчанию /etc/httpd.conf' +a_srv_http_root = 'ÐšÐ¾Ñ€Ð½ÐµÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°' +a_srv_dropbear1 = 'Dropbear Ñто SSH-Ñервер Ñо вÑтроенным SCP' +a_srv_d_pwauth = 'ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ паролю' +a_srv_d_pwauth1 = 'Разрешить SSH аутентификацию по паролю' +a_w_channel = 'Канал' +a_w_wifi1 = 'Ðа Ñтой Ñтраничке можно наÑтроить WLAN оÑнованную на беÑпроводных ÑетÑÑ….' +a_w_wifi2 = 'Ð’Ñ‹ можете легко интегрировать ваши 802.11a/b/g/n-уÑтройÑтва в вашу физичеÑкую Ñеть и иÑпользовать виртуальные ÑтройÑтва Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð±ÐµÑпроводных повторителей или ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… Ñетевых топологий на одном физичеÑком уÑтройÑтве.' +a_w_wifi3 = 'Поддерживаемые режимы: Точка, Клиент, Ad-Hoc и WDS, а так же WPA и WPA2 шифрование Ð´Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐµÐ¹ безопаÑноÑти.' +a_w_devices1 = 'ЗдеÑÑŒ вы можете наÑтроить уÑтановленные Wi-Fi уÑтройÑтва.' +a_w_txantenna = 'ÐŸÐµÑ€ÐµÐ´Ð°ÑŽÑ‰Ð°Ñ Ð°Ð½Ñ‚ÐµÐ½Ð½Ð°' +a_w_rxantenna = 'ÐŸÑ€Ð¸Ð½Ð¸Ð¼Ð°ÑŽÑ‰Ð°Ñ Ð°Ð½Ñ‚ÐµÐ½Ð½Ð°' +a_w_distance1 = 'ДиÑÑ‚Ð°Ð½Ñ†Ð¸Ñ Ð´Ð¾ Ñамой дальней Ñтанции (в метрах)' +a_w_diversity = 'РазновидноÑÑ‚ÑŒ антенн' +a_w_countrycode = 'Код Ñтраны' +a_w_connlimit = 'Ограничение Ñоединений' +a_w_networks1 = 'Ð’Ñ‹ можете наÑтраивать различные wifi Ñети на одном уÑтройÑтве. Помните что еÑÑ‚ÑŒ определённые програмные и аппаратные ограничениÑ. Ðормально вы можете иÑпользовать например 1 Ad-Hoc или до 3 Точек и Ñимулированных 1 Клиента.' +a_w_netid = 'Ðазвание Ñети (ESSID)' +a_w_network1 = 'Добавить Wifi Ñеть в физичеÑкую Ñеть' +a_w_txpwr = 'МощьноÑÑ‚ÑŒ передатчика' +a_w_brcmburst = 'Broadcom Frameburst' +a_w_athburst = 'Atheros Frameburst' +a_w_radiussrv = 'RadiusServer' +a_w_radiusport = 'Radius-Port' +a_w_apisolation = 'AP-Isolation' +a_w_apisolation1 = 'Ðе позволÑет клиентам обмениватьÑÑ Ð´Ñ€ÑƒÐ³ Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¼ информацией' +a_w_hideessid = 'Скрыть ESSID' +a_w_ap = 'Точка доÑтупа' +a_w_adhoc = 'Ad-Hoc' +a_w_ahdemo = 'ПÑевдо Ad-Hoc (ahdemo)' +a_w_client = 'Клиент' +a_w_wds = 'WDS' +a_w_monitor = 'Monitor' +dhcp_dnsmasq_desc = 'Dnsmasq Ñодержит в Ñебе DHCP-Сервер и DNS-Forwarder Ð´Ð»Ñ NAT' +dhcp_dnsmasq_domainneeded = 'Domain required' +dhcp_dnsmasq_domainneeded_desc = 'Ðе форвардить DNS-запроÑÑ‹ без DNS-имени' +dhcp_dnsmasq_authoritative = 'Authoritative' +dhcp_dnsmasq_authoritative_desc = 'Только DHCP в локальной Ñети' +dhcp_dnsmasq_boguspriv = 'Filter private' +dhcp_dnsmasq_boguspriv_desc = 'не форвардить реверÑные-Ð´Ð½Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑÑ‹ Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð¹ Ñети' +dhcp_dnsmasq_filterwin2k = 'Filter useless' +dhcp_dnsmasq_filterwin2k_desc = 'фильтровать ненужные DNS-запроÑÑ‹ Windows-ÑиÑтем' +dhcp_dnsmasq_localisequeries = 'Localise queries' +dhcp_dnsmasq_localisequeries_desc = 'локализировать Ð¸Ð¼Ñ Ñ…Ð¾Ñта отноÑÑщегоÑÑ Ðº данной подÑети' +dhcp_dnsmasq_local = 'Локальный Ñервер' +dhcp_dnsmasq_domain = 'Локальный домен' +dhcp_dnsmasq_expandhosts = 'Expand Hosts' +dhcp_dnsmasq_expandhosts_desc = 'ДобавлÑÑ‚ÑŒ доменные имена в хоÑÑ‚Ñ‹' +dhcp_dnsmasq_nonegcache = 'Don't cache unknown' +dhcp_dnsmasq_nonegcache_desc = 'Запрещать кешировать негативные DNS-ответы' +dhcp_dnsmasq_readethers = 'Use /etc/ethers' +dhcp_dnsmasq_readethers_desc = 'Читать /etc/ethers Ð´Ð»Ñ Ð½Ð°Ñтройки DHCP-Сервера' +dhcp_dnsmasq_leasefile = 'Leasefile' +dhcp_dnsmasq_leasefile_desc = 'файл где выданные DHCP-leases хранÑÑ‚ÑÑ' +dhcp_dnsmasq_resolvfile = 'Resolvfile' +dhcp_dnsmasq_resolvfile_desc = 'Локальный DNS файл' +dhcp_dnsmasq_nohosts = 'Ignore /etc/hosts' +dhcp_dnsmasq_strictorder = 'Strict order' +dhcp_dnsmasq_strictorder_desc = 'DNS-Сервер будет обращатьÑÑ Ðº resolvfile' +dhcp_dnsmasq_logqueries = 'Log queries' +dhcp_dnsmasq_noresolv = 'Ignore resolvfile' +dhcp_dnsmasq_dnsforwardmax = 'concurrent queries' +dhcp_dnsmasq_port = 'DNS-Port' +dhcp_dnsmasq_ednspacket_max = 'max. EDNS0 размер пакета' +dhcp_dnsmasq_dhcpleasemax = 'max. DHCP-Leases' +dhcp_dnsmasq_addnhosts = 'дополнительный hostfile' +dhcp_dnsmasq_queryport = 'порт запроÑов' +a_n_switch = 'Свитч' +a_n_routes = 'МаршрутизациÑ' +a_n_routes4 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv4' +a_n_routes6 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv6' +a_n_routes1 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñлужит Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· какой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¸ шлюз можно пройти к определённому хоÑту или Ñегменту Ñети.' +a_network1 = 'Ð’ Ñтом разделе вы Ñможете найти вÑÑ‘ что каÑаетÑÑ Ð½Ð°Ñтроек Ñети.' +a_network2 = 'Ð’ большенÑтве роутеров Ñетевой Ñвитч может быть Ñвободно наÑтроен и добавлен в различные VLAN'Ñ‹.' +a_network3 = 'ÐаÑтройка PPPoE / PPTP позволÑет Ñети и Ñетевые ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº поÑтавщику уÑлуг Интернет.' +a_network4 = 'C DHCP уÑтройÑтва находÑщиеÑÑ Ð² вашей Ñети могут автоматичеÑки IP-адреÑа и вÑе необходимые наÑтройки.' +a_network5 = 'Файрволл и Ð¿Ñ€Ð¾Ð±Ñ€Ð¾Ñ Ð¿Ð¾Ñ€Ñ‚Ð¾Ð² иÑпользуетÑÑ Ð´Ð»Ñ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð°Ð´Ñ‘Ð¶Ð½Ð¾ÑÑ‚ÑŒ и гибкоÑти вашей Ñети.' +a_n_switch1 = 'Сетевые порты на вашем роутере могут маршрутизироватьÑÑ Ð² различные VLAN'Ñ‹ и ÑоединÑÑ‚ÑŒ компютеры напрÑмую. VLAN'Ñ‹ обычно иÑпользуют Ð´Ð»Ñ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкого Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñетей.' +network_switch_desc = 'Порты принадлежашие VLAN'ам разделÑÑŽÑ‚ÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð°Ð¼Ð¸. Порт Ñ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð¼ значением (обычно 5) обычно иÑпользуют Ð´Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½Ð¸Ñ… Ñетей. Ðа уÑтройÑтвах Ñ 5 портами, порт Ñ Ð½Ð°Ð¸Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ значением (0) предназначен Ð´Ð»Ñ Uplink.' +a_n_ifaces1 = 'Ðа Ñтой Ñтраничке вы можете Ñконфигурировать Ñетевые интерфейÑÑ‹. Ð’Ñ‹ можете ÑоединÑÑ‚ÑŒ различные интерфейÑÑ‹ в "моÑÑ‚" Ð¿Ð¾Ð¼ÐµÑ‡Ð°Ñ Ð¸Ñ… как "МоÑÑ‚" и добавлÑÑ‚ÑŒ имена различных Ñетей принадлежащих Ñетевым интерфейÑам разделённые пробелом. Также вы можете иÑпользовать Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ VLAN'ов например INTERFACE.VLANNR (ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ ÐºÐ°Ðº: eth0.1).' +a_n_i_bridge = 'МоÑÑ‚' +a_n_i_bridge1 = 'Ñоздаёт моÑÑ‚ Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… Ñетевых интерфейÑов' +dhcp_desc = 'С помощью DHCP члены Ñетей могут автоматичеÑки получить такие наÑтройки как (IP-ÐдреÑ, Ñетевую маÑку, DNS-имÑ, ...).' +dhcp_dhcp_leasetime = 'Leasetime' +dhcp_dhcp_dynamicdhcp = 'Dynamic DHCP' +dhcp_dhcp_ignore = 'Ignore interface' +dhcp_dhcp_ignore_desc = 'отключить DHCP Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ интерфейÑа' +dhcp_dhcp_force = 'Force' +dhcp_dhcp_start_desc = 'первый Ð°Ð´Ñ€ÐµÑ (поÑледний октет)' +dhcp_dhcp_limit_desc = 'количеÑтво арендованных адреÑов -1' +dhcp_leases = 'Leases' +luci_ethers = 'Static Leases' +dhcp_timeremain = 'Leasetime remaining' +dhcp_leases_active = 'Active Leases' +a_n_ptp = 'Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ°-точка' +a_n_ptp1 = 'Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° PPPoE или PPTP обычно иÑпользуютÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· DSL или подобные технологии Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº поÑтавщику уÑлуг Интернет.' +network_interface_server = 'PPTP-Сервер' +network_interface_demand = 'Automatic Disconnect' +network_interface_demand_desc = 'Ð’Ñ€ÐµÐ¼Ñ (в Ñек.) поÑле которого неиÑпользованное Ñоединение будет закрыто' +network_interface_keepalive = 'Keep-Alive' +network_interface_keepalive_desc = 'КоличеÑтво неудачных Ñоединений Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ переподÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº Ñерверу' +a_n_r_routes1 = 'ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñлужит Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· какой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¸ шлюз можно пройти к определённому хоÑту или Ñегменту Ñети.' +a_n_routes_static = 'СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ' +a_n_routes_static4 = 'СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv4' +a_n_routes_static6 = 'СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv6' +a_n_routes_kernel4 = 'Включение IPv4-Маршрутизации' +a_n_routes_kernel6 = 'Включение IPv6-Маршрутизации' +a_n_r_target1 = 'ХоÑÑ‚-IP или Ñеть' +a_n_r_target6 = 'ХоÑÑ‚-IPv6 или Ñеть' +a_n_r_netmask1 = 'еÑли Ñеть' +m_n_inet = 'Интернет Ñоединение' +m_n_local = 'Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ñеть' +m_n_route = 'Маршрут' +m_n_brdige = 'МоÑÑ‚' +m_w_ap = 'ОбеÑпечивает (AP)' +m_w_adhoc = 'ÐезаыиÑÐ¸Ð¼Ð°Ñ (Ad-Hoc)' +m_w_client = 'ПриÑоединитьÑÑ (Client)' +m_w_wds = 'РаÑÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ð°Ñ (WDS)' +m_w_clientmode = 'Режим клиента' +system_system_logsize = 'Размер буфера ÑиÑтемного журнала' +system_system_logip = 'Внешний Ñервер ÑиÑтемного журналированиÑ' +system_system_conloglevel = 'Уровень ÑиÑтемного логгированиÑ' +system_system_conloglevel_desc = 'Уровень ÑиÑтемного Ð»Ð¾Ð³Ð³Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½Ñоли' +m_i_processor = 'ПроцеÑÑор' +m_i_memory = 'ПамÑÑ‚ÑŒ' +m_i_systemtime = 'Локальное времÑ' +m_i_uptime = 'Ð’Ñ€ÐµÐ¼Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹' +m_n_d_firstaddress = 'Первый арендованный адреÑ' +m_n_d_numleases = 'КоличеÑтво арендованных адреÑов' +routingtable = 'Таблица маршрутизации' +wlanscan = 'ПоиÑк Wi-Fi Ñетей' +frequency = 'ЧаÑтота' +power = 'МощьноÑÑ‚ÑŒ' +noise = 'Шум' +signal = 'Сигнал' +link = 'СвÑзь' +frag = 'Frag.' +rts = 'RTS' +bitrate = 'Битрейт' +m_n_keepalive = 'автоматичеÑки переподÑоединÑÑ‚ÑÑ' +m_n_dialondemand = 'отÑоединитьÑÑ ÐºÐ¾Ð³Ð´Ð° проÑтой длÑ' +m_n_pptp_server = 'PPTP-Сервер' +leds = 'ÐаÑтройка LED' +leds_desc = 'ÐаÑтройка Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ LED'ов еÑли Ñто возможно.' +system_led_name = 'LED ИмÑ' +system_led_sysfs = 'LED УÑтройÑтво' +system_led_default = 'СоÑтоÑние по умолчанию' +system_led_default_desc = 'мигание = включено' +system_led_trigger = 'Триггер' +system_led_trigger_none = 'нет' +system_led_trigger_defaulton = 'По умолчанию включено' +system_led_trigger_timer = 'Таймер' +system_led_trigger_heartbeat = 'Стук (СреднÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°)' +system_led_trigger_netdev = 'Сетевое уÑтройÑтво' +system_led_delayoff = 'Задержка выключена' +system_led_delayoff_desc = 'Ð²Ñ€ÐµÐ¼Ñ (в мÑ) LED выключен' +system_led_delayon = 'Задержка включена' +system_led_delayon_desc = 'Ð²Ñ€ÐµÐ¼Ñ (в мÑ) LED включен' +system_led_dev = 'УÑтройÑтво' +system_led_mode = 'Триггерный режим' +system_led_mode_link = 'СвÑзь включена' +system_led_mode_tx = 'Передача' +system_led_mode_rx = 'Приём' +network_interface_up = 'Ðктивен' +network_interface_hwaddr = 'MAC-ÐдреÑ' +network_interface_hwaddr_desc = 'ÐÐ´Ñ€ÐµÑ ÑƒÑтройÑтва' +network_interface_txrx = 'Трафик' +network_interface_txrx_desc = 'передано / получено' +network_interface_err = 'Ошибок' +network_interface_err_desc = 'Перед. / Получ.' +network_interface_fwzone = 'Создать / Добавить Файрвол-зону' +network_interface_fwzone_desc = 'Этот Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð½Ðµ принадлежит ни к одной Файрвол-зоне.' +network_interface_encaps = 'PPPoA Encapsulation' +m_n_mssfix = "Clamp Segment Size" +m_n_mssfix_desc = "Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs." diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.xml b/openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.xml new file mode 100644 index 0000000..1de8bef --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/admin-core.ru.xml @@ -0,0 +1,276 @@ + + + + +Данные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ принÑÑ‚Ñ‹ +Данные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ отвергнуты +ПользовательÑкий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ +LuCI Ñто Ñвободное Lua програмное обеÑпечение Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ MVC-Вебфреймворк и веб Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð²Ñтраиваемый в уÑтройÑтва. LuCI раÑпроÑтранÑетÑÑ Ð¿Ð¾Ð´ лицензией Apache-License. +ДомашнÑÑ Ñтраница проекта +Ведущие разработчики +Помогавшие в разработке +Ð‘Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ñ +Добро пожаловать. +Это зона ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ LuCI. +LuCI Ñвободный, гибкий и дружелюбный грфичеÑкий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ Ð½Ð°Ñтройки OpenWrt Kamikaze. +С помощью Ñтих Ñтраниц вы можете изменить оÑновные наÑтройки вашего роутера. +Внимание: Ð’ LuCI Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð½Ð¸Ð¼Ð°ÑŽÑ‚ÑÑ Ð¿Ð¾Ñле Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ - ПринÑÑ‚ÑŒ. +Так же мы вÑегда желаем улучшить Ñтот интерфейÑ, мы вÑегда обратим внимание на ваши вопроÑÑ‹ и предложениÑ. +Ртеперь повеÑелитеÑÑŒ Ñо Ñвоим роутером! +Команда LuCI +ЗдеÑÑŒ вы можете изменить наÑтройки и функциональноÑÑ‚ÑŒ LuCI. +ЗапуÑк команд +Эти команды будут запущенны автоматичеÑки когда Ð´Ð°Ð½Ð½Ð°Ñ UCI ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð° и Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ принÑÑ‚Ñ‹. +Файлы которые необходимо Ñохранить при перепрошивании +ПоÑле перепрошивки LuCI Ñти файлы будут добавлены в обновлённую ÑиÑтему . +ЗдеÑÑŒ вы можете найти информацию о текущей ÑтатиÑтики ÑиÑтемы вроде чаÑтоты процеÑÑора, иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð°Ð¼Ñти или Ñетевого интерфейÑа. +Ртак же Ñдра или ÑервиÑов, ÑиÑтемный журнал может быть так же проÑмотрен здеÑÑŒ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ что бы получить полный обзор текущего ÑоÑтоÑÐ½Ð¸Ñ ÑиÑтемы. +WLAN-Сканирование +Обзор ÑущеÑтвующих Wi-Fi Ñетей +Шифрование +СвÑзь +Сигнал +Шум +Маршруты +Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ Ð¼Ð°Ñка +Шлюз +Метрика +ЗдеÑÑŒ вы можете наÑтроить оÑновные параметры вашего уÑтройÑтва такие как Ð¸Ð¼Ñ Ñ…Ð¾Ñта или чаÑовой поÑÑ. +Программное обеÑпечение +Пароль админиÑтратора +OPKG-ÐаÑтройка +SSH-Ключи +ДиÑковые разделы +Обновление прошивки +Изменение наÑтроек ÑиÑтемы ÑвÑзанных Ñ Ñамоидентификацией, уÑÑ‚Ñтанвкой аппаратно и/или програмного обеÑпечениÑ, идентификацией или диÑковыми разделами. +Эти наÑтройки определÑÑŽÑ‚ оÑнову вашей ÑиÑтемы. +Ðеобходимо тчательно отнеÑтиÑÑŒ к нижеÑледующим наÑтройкам, в результате неправильной конфигурации которых вы можете потерÑÑ‚ÑŒ управление над ÑиÑтемой или уÑтройÑто может не загружатьÑÑ. +ПринÑÑ‚ÑŒ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ +УÑтановка +Загрузить и уÑтановить пакеты +Изменить лиÑтинг пакетов и путей уÑтановки +Ð˜Ð¼Ñ Ð¿Ð°ÐºÐµÑ‚Ð° +Удалить +Ðайти пакет +ЛиÑтинг пакетов обновлён +Обновить лиÑтинг пакетов +Заменить уÑтановленные пакеты +ЛиÑтинг пакетов +Путь уÑтановки +Изменение Ð¿Ð°Ñ€Ð¾Ð»Ñ ÑиÑтемного админиÑтратора (Пользователь root) +Пароль уÑпешно изменён +Ошибка: Пароли не Ñовпадают +ЗдеÑÑŒ вы можете вÑтавить публичный SSH-Ключ Ð´Ð»Ñ SSH публичной-ключевой аутентификации. +Точки Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ +Точки Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÑÑŽÑ‚ к каком запоминающему уÑтройÑтву будет приÑоединена Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема +Монтированные файловые ÑиÑтемы" +ИÑпользованно" +ДоÑтупно" +Точка приÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ +УÑтройÑтво или раздел (пример /dev/sda1) +Формат файловой ÑиÑтемы (пример ext3) +ЕÑли физичеÑкой RAM не хватает можно воÑпользоватьÑÑ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ð¼ хранением данных в файле-подкачке. Ð’ результате RAM памÑти будет доÑтупно в большем количеÑтве. Ðо помните, файл подкачки работает гораздо медленнее RAM так что не ждите обработки информации на ÑкороÑÑ‚ÑÑ… Ñравнимых Ñ RAM. +Прошивка уÑпешно обновленна. Перезагрузка уÑтройÑтва... +Прошивка невозможна +Файл прошивки +Прошить +Сохранить конфигурационные файлы +Извините, Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¿Ð¾ÐºÐ° не доÑтупна на вашей платформе. +ЗаменÑет уÑтановленную прошивку на новую. Формат прошивки платформо-завиÑимый. +Сразу произойдёт перезагрузка вашей ÑиÑтемы +Выполнить перезагрузку +ПозалуйÑта подождите: УÑтройÑтво перезагружаетÑÑ... +Внимание: ЕÑÑ‚ÑŒ неÑохранённые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ðµ потерÑÑŽÑ‚ÑÑ Ð¿Ð¾Ñле перезагрузки! +Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð½ÑÑ‚Ñ‹. +Резервирование / ВоÑÑтановление +Создать резервную копию +Ðрхив воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ +СброÑить роутер к наÑтройкам по умолчанию +Перейти к возврашению вÑех наÑтроек и уÑтановить наÑтройки по умолчанию? +ВоÑÑтановить резервную копию +ЗдеÑÑŒ вы можете Ñделать резевную копию и воÑÑановить конфигурацию вашего роутера, еÑли Ñто возможно, или уÑтановить наÑтройки по умолчанию. +HTTP-Сервер +SSH-Сервер +СервиÑÑ‹ и демоны выполнÑющие определённые задачи на уÑтройÑтвах. +БольшинÑтво из них Ñетевые Ñерверы, которые выполнÑÑŽÑ‚ определённые задачи Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… уÑтройÑтв или Ñетей наподобие shell-доÑтупа, web-Ñтраниц таких как LuCI, выполнÑÑŽÑ‚ mesh-маршрутизацию, отправлÑÑŽÑ‚ пиÑьма , ... +Маленький веб-Ñервер, Ñлужащий Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ LuCI. +ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑ‚ÑŒ +Что будет показано при авторизации на защищённых Ñтраницах. +по умолчанию /etc/httpd.conf +ÐšÐ¾Ñ€Ð½ÐµÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° +Dropbear Ñто SSH-Ñервер Ñо вÑтроенным SCP +ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾ паролю +Разрешить SSH аутентификацию по паролю +Канал +Ðа Ñтой Ñтраничке можно наÑтроить WLAN оÑнованную на беÑпроводных ÑетÑÑ…. +Ð’Ñ‹ можете легко интегрировать ваши 802.11a/b/g/n-уÑтройÑтва в вашу физичеÑкую Ñеть и иÑпользовать виртуальные ÑтройÑтва Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ Ð±ÐµÑпроводных повторителей или ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð½Ñ‹Ñ… Ñетевых топологий на одном физичеÑком уÑтройÑтве. +Поддерживаемые режимы: Точка, Клиент, Ad-Hoc и WDS, а так же WPA и WPA2 шифрование Ð´Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐµÐ¹ безопаÑноÑти. +ЗдеÑÑŒ вы можете наÑтроить уÑтановленные Wi-Fi уÑтройÑтва. +ÐŸÐµÑ€ÐµÐ´Ð°ÑŽÑ‰Ð°Ñ Ð°Ð½Ñ‚ÐµÐ½Ð½Ð° +ÐŸÑ€Ð¸Ð½Ð¸Ð¼Ð°ÑŽÑ‰Ð°Ñ Ð°Ð½Ñ‚ÐµÐ½Ð½Ð° +ДиÑÑ‚Ð°Ð½Ñ†Ð¸Ñ Ð´Ð¾ Ñамой дальней Ñтанции (в метрах) +РазновидноÑÑ‚ÑŒ антенн +Код Ñтраны +Ограничение Ñоединений +Ð’Ñ‹ можете наÑтраивать различные wifi Ñети на одном уÑтройÑтве. Помните что еÑÑ‚ÑŒ определённые програмные и аппаратные ограничениÑ. Ðормально вы можете иÑпользовать например 1 Ad-Hoc или до 3 Точек и Ñимулированных 1 Клиента. +Ðазвание Ñети (ESSID) +Добавить Wifi Ñеть в физичеÑкую Ñеть +МощьноÑÑ‚ÑŒ передатчика +Broadcom Frameburst +Atheros Frameburst +RadiusServer +Radius-Port +AP-Isolation +Ðе позволÑет клиентам обмениватьÑÑ Ð´Ñ€ÑƒÐ³ Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¼ информацией +Скрыть ESSID +Точка доÑтупа +Ad-Hoc +ПÑевдо Ad-Hoc (ahdemo) +Клиент +WDS +Monitor +Dnsmasq Ñодержит в Ñебе DHCP-Сервер и DNS-Forwarder Ð´Ð»Ñ NAT +Domain required +Ðе форвардить DNS-запроÑÑ‹ без DNS-имени +Authoritative +Только DHCP в локальной Ñети +Filter private +не форвардить реверÑные-Ð´Ð½Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑÑ‹ Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð¹ Ñети +Filter useless +фильтровать ненужные DNS-запроÑÑ‹ Windows-ÑиÑтем +Localise queries +локализировать Ð¸Ð¼Ñ Ñ…Ð¾Ñта отноÑÑщегоÑÑ Ðº данной подÑети +Локальный Ñервер +Локальный домен +Expand Hosts +ДобавлÑÑ‚ÑŒ доменные имена в хоÑÑ‚Ñ‹ +Don't cache unknown +Запрещать кешировать негативные DNS-ответы +Use /etc/ethers +Читать /etc/ethers Ð´Ð»Ñ Ð½Ð°Ñтройки DHCP-Сервера +Leasefile +файл где выданные DHCP-leases хранÑÑ‚ÑÑ +Resolvfile +Локальный DNS файл +Ignore /etc/hosts +Strict order +DNS-Сервер будет обращатьÑÑ Ðº resolvfile +Log queries +Ignore resolvfile +concurrent queries +DNS-Port +max. EDNS0 размер пакета +max. DHCP-Leases +дополнительный hostfile +порт запроÑов +Свитч +ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ +ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv4 +ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv6 +ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñлужит Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· какой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¸ шлюз можно пройти к определённому хоÑту или Ñегменту Ñети. + +Ð’ Ñтом разделе вы Ñможете найти вÑÑ‘ что каÑаетÑÑ Ð½Ð°Ñтроек Ñети. +Ð’ большенÑтве роутеров Ñетевой Ñвитч может быть Ñвободно наÑтроен и добавлен в различные VLAN'Ñ‹. +ÐаÑтройка PPPoE / PPTP позволÑет Ñети и Ñетевые ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº поÑтавщику уÑлуг Интернет. +C DHCP уÑтройÑтва находÑщиеÑÑ Ð² вашей Ñети могут автоматичеÑки IP-адреÑа и вÑе необходимые наÑтройки. +Файрволл и Ð¿Ñ€Ð¾Ð±Ñ€Ð¾Ñ Ð¿Ð¾Ñ€Ñ‚Ð¾Ð² иÑпользуетÑÑ Ð´Ð»Ñ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð°Ð´Ñ‘Ð¶Ð½Ð¾ÑÑ‚ÑŒ и гибкоÑти вашей Ñети. +Сетевые порты на вашем роутере могут маршрутизироватьÑÑ Ð² различные VLAN'Ñ‹ и ÑоединÑÑ‚ÑŒ компютеры напрÑмую. VLAN'Ñ‹ обычно иÑпользуют Ð´Ð»Ñ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкого Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñетей. +Порты принадлежашие VLAN'ам разделÑÑŽÑ‚ÑÑ Ð¿Ñ€Ð¾Ð±ÐµÐ»Ð°Ð¼Ð¸. Порт Ñ Ð½Ð°Ð¸Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð¼ значением (обычно 5) обычно иÑпользуют Ð´Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½Ð¸Ñ… Ñетей. Ðа уÑтройÑтвах Ñ 5 портами, порт Ñ Ð½Ð°Ð¸Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ значением (0) предназначен Ð´Ð»Ñ Uplink. +Ðа Ñтой Ñтраничке вы можете Ñконфигурировать Ñетевые интерфейÑÑ‹. Ð’Ñ‹ можете ÑоединÑÑ‚ÑŒ различные интерфейÑÑ‹ в "моÑÑ‚" Ð¿Ð¾Ð¼ÐµÑ‡Ð°Ñ Ð¸Ñ… как "МоÑÑ‚" и добавлÑÑ‚ÑŒ имена различных Ñетей принадлежащих Ñетевым интерфейÑам разделённые пробелом. Также вы можете иÑпользовать Ð¾Ð±Ð¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ VLAN'ов например INTERFACE.VLANNR (ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ ÐºÐ°Ðº: eth0.1). +МоÑÑ‚ +Ñоздаёт моÑÑ‚ Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ñ… Ñетевых интерфейÑов +С помощью DHCP члены Ñетей могут автоматичеÑки получить такие наÑтройки как (IP-ÐдреÑ, Ñетевую маÑку, DNS-имÑ, ...). +Leasetime +Dynamic DHCP +Ignore interface +отключить DHCP Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ интерфейÑа +Force +первый Ð°Ð´Ñ€ÐµÑ (поÑледний октет) +количеÑтво арендованных адреÑов -1 +Leases +Static Leases +Leasetime remaining +Active Leases +Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ°-точка +Ð¡Ð¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° PPPoE или PPTP обычно иÑпользуютÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· DSL или подобные технологии Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº поÑтавщику уÑлуг Интернет. +PPTP-Сервер +Automatic Disconnect +Ð’Ñ€ÐµÐ¼Ñ (в Ñек.) поÑле которого неиÑпользованное Ñоединение будет закрыто +Keep-Alive +КоличеÑтво неудачных Ñоединений Ð´Ð»Ñ Ð¸Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ переподÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ðº Ñерверу +ÐœÐ°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñлужит Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· какой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð¸ шлюз можно пройти к определённому хоÑту или Ñегменту Ñети. +СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ +СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv4 +СтатичеÑÐºÐ°Ñ Ð¼Ð°Ñ€ÑˆÑ€ÑƒÑ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ IPv6 +Включение IPv4-Маршрутизации +Включение IPv6-Маршрутизации +ХоÑÑ‚-IP или Ñеть +ХоÑÑ‚-IPv6 или Ñеть +еÑли Ñеть +Интернет Ñоединение +Ð›Ð¾ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ñеть +Маршрут +МоÑÑ‚ +ОбеÑпечивает (AP) +ÐезаыиÑÐ¸Ð¼Ð°Ñ (Ad-Hoc) +ПриÑоединитьÑÑ (Client) +РаÑÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ð°Ñ (WDS) +Режим клиента +Размер буфера ÑиÑтемного журнала +Внешний Ñервер ÑиÑтемного Ð¶ÑƒÑ€Ð½Ð°Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ +Уровень ÑиÑтемного Ð»Ð¾Ð³Ð³Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ +Уровень ÑиÑтемного Ð»Ð¾Ð³Ð³Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½Ñоли +ПроцеÑÑор +ПамÑÑ‚ÑŒ +Локальное Ð²Ñ€ÐµÐ¼Ñ +Ð’Ñ€ÐµÐ¼Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ +Первый арендованный Ð°Ð´Ñ€ÐµÑ +КоличеÑтво арендованных адреÑов +Таблица маршрутизации +ПоиÑк Wi-Fi Ñетей +ЧаÑтота +МощьноÑÑ‚ÑŒ +Шум +Сигнал +СвÑзь +Frag. +RTS +Битрейт +автоматичеÑки переподÑоединÑÑ‚ÑÑ +отÑоединитьÑÑ ÐºÐ¾Ð³Ð´Ð° проÑтой Ð´Ð»Ñ +PPTP-Сервер +ÐаÑтройка LED +ÐаÑтройка Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ LED'ов еÑли Ñто возможно. +LED Ð˜Ð¼Ñ +LED УÑтройÑтво +СоÑтоÑние по умолчанию +мигание = включено +Триггер +нет +По умолчанию включено +Таймер +Стук (СреднÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°) +Сетевое уÑтройÑтво +Задержка выключена +Ð²Ñ€ÐµÐ¼Ñ (в мÑ) LED выключен +Задержка включена +Ð²Ñ€ÐµÐ¼Ñ (в мÑ) LED включен +УÑтройÑтво +Триггерный режим +СвÑзь включена +Передача +Приём +Ðктивен +MAC-ÐÐ´Ñ€ÐµÑ +ÐÐ´Ñ€ÐµÑ ÑƒÑтройÑтва +Трафик +передано / получено +Ошибок +Перед. / Получ. +Создать / Добавить Файрвол-зону +Этот Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð½Ðµ принадлежит ни к одной Файрвол-зоне. +PPPoA Encapsulation +Clamp Segment Size +Fixes problems with unreachable websites, submitting forms or other unexpected behaviour for some ISPs. + + diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.lua b/openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.lua new file mode 100644 index 0000000..805699b --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.lua @@ -0,0 +1,10 @@ +cbi_add = 'Добавить' +cbi_del = 'Удалить' +cbi_invalid = 'Ошибка: Введёное значение не верно' +cbi_missing = 'Ошибка: Это поле обÑзательно к заполнению' +cbi_addopt = '-- Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° --' +cbi_optional = ' (дополнительно)' +cbi_sectempty = 'Эта ÑÐµÐºÑ†Ð¸Ñ Ð¿Ð¾ÐºÐ° не Ñодержит значений' +cbi_manual = '-- выборочный --' +cbi_select = '-- ПожалуйÑта выберете --' +cbi_gorel = 'Перейти к Ñтранице конфигурации' diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.xml b/openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.xml new file mode 100644 index 0000000..31974ef --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/cbi.ru.xml @@ -0,0 +1,16 @@ + + + + +Добавить +Удалить +Ошибка: Введёное значение не верно +Ошибка: Это поле обÑзательно к заполнению +-- Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° -- + (дополнительно) +Эта ÑÐµÐºÑ†Ð¸Ñ Ð¿Ð¾ÐºÐ° не Ñодержит значений +-- выборочный -- +-- ПожалуйÑта выберете -- +Перейти к Ñтранице конфигурации + + diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.lua b/openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.lua new file mode 100644 index 0000000..fe59e45 --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.lua @@ -0,0 +1,95 @@ +about = 'О программе' +add = 'Добавить' +addresses = 'ÐдреÑ' +aliases = 'СÑылка' +all = 'Ð’Ñе' +administration = 'Управление' +essentials = 'Essentials' +apply = 'ПринÑÑ‚ÑŒ' +basicsettings = 'Ðачальные УÑтановки' +broadcast = 'IPv4-Широковещательный' +changes = 'ИзменениÑ' +channel = 'Канал' +cidr6 = 'CIDR-Обозначение: адреÑ/префикÑ' +code = 'Код' +config = 'КонфигурациÑ' +configfile = 'Файл конфигурации' +confirmation = 'Подтверждение' +delete = 'Удалить' +descr = 'ОпиÑание' +design = 'Создание' +device = 'УÑтройÑтво' +devices = 'УÑтройÑтва' +disable = 'выключено' +distance = 'РаÑÑтоÑние' +dmesg = 'Kernel log' +dnsserver = 'DNS-Сервер' +edit = 'Редактировать' +enable = 'включено' +encryption = 'Шифрование' +error = 'Ошибка' +filesystem = 'Ð¤Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема' +filter = 'Фильтр' +gateway = 'IPv4-Шлюз' +gateway6 = 'IPv6-Шлюз' +general = 'ОÑновной' +hostname = 'Ð˜Ð¼Ñ Ñ…Ð¾Ñта' +install = 'УÑтановка' +installed = 'уÑтановленные' +interface = 'ИнтерфейÑ' +interfaces = 'ИнтерфейÑÑ‹' +ipaddress = 'IPv4-ÐдреÑ' +ip6address = 'IPv6-ÐдреÑ' +legend = 'ÐадпиÑÑŒ' +library = 'Библиотека' +logout = 'Выход' +key = 'Ключ' +language = 'Язык' +limit = 'Предел' +load = 'Загрузка' +login = 'Вход' +macaddress = 'MAC-ÐдреÑ' +manpage = 'Ñмотрите '%s' руководÑтво' +metric = 'Метрика' +mode = 'Режим' +name = 'ИмÑ' +netmask = 'IPv4-МаÑка' +network = 'Сеть' +networks = 'Сети' +none = 'ничего' +notinstalled = 'не уÑтановленно' +ok = 'OK' +options = 'Опции' +overview = 'Обзор' +packagemanager = 'Менеджер пакетов' +password = 'Пароль' +path = 'Путь' +port = 'Порт' +ports = 'Порты' +protocol = 'Протокол' +reboot = 'Перезагрузка' +reset = 'СброÑ' +revert = 'Вернуть' +save = 'Сохранить' +saveapply = 'Сохранить & ПринÑÑ‚ÑŒ' +service = 'СервиÑ' +services = 'СервиÑÑ‹' +settings = 'ÐаÑтройки' +size = 'Размер' +start = 'Старт' +static = 'ÑтатичеÑкий' +status = 'СтатуÑ' +statistics = 'СтатиÑтика' +submit = 'Отправить' +syslog = 'СиÑтемный журнал' +system = 'СиÑтема' +target = 'Цель' +timezone = 'Ð’Ñ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð·Ð¾Ð½Ð°' +type = 'Тип' +unknownerror = 'ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°' +unsavedchanges = 'ÐепринÑтые изменениÑ' +username = 'Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ' +version = 'ВерÑиÑ' +webui = 'Web UI' +wifi = 'Wi-Fi' +zone = 'Зона' diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.xml b/openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.xml new file mode 100644 index 0000000..69f092a --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/default.ru.xml @@ -0,0 +1,101 @@ + + + + +О программе +Добавить +ÐÐ´Ñ€ÐµÑ +СÑылка +Ð’Ñе +Управление +Essentials +ПринÑÑ‚ÑŒ +Ðачальные УÑтановки +IPv4-Широковещательный +Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ +Канал +CIDR-Обозначение: адреÑ/Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ +Код +ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ +Файл конфигурации +Подтверждение +Удалить +ОпиÑание +Создание +УÑтройÑтво +УÑтройÑтва +выключено +РаÑÑтоÑние +Kernel log +DNS-Сервер +Редактировать +включено +Шифрование +Ошибка +Ð¤Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема +Фильтр +IPv4-Шлюз +IPv6-Шлюз +ОÑновной +Ð˜Ð¼Ñ Ñ…Ð¾Ñта +УÑтановка +уÑтановленные +Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ +ИнтерфейÑÑ‹ +IPv4-ÐÐ´Ñ€ÐµÑ +IPv6-ÐÐ´Ñ€ÐµÑ +ÐадпиÑÑŒ +Библиотека +Выход +Ключ +Язык +Предел +Загрузка +Вход +MAC-ÐÐ´Ñ€ÐµÑ +Ñмотрите '%s' руководÑтво +Метрика +Режим +Ð˜Ð¼Ñ +IPv4-МаÑка +Сеть +Сети +ничего +не уÑтановленно +OK +Опции +Обзор +Менеджер пакетов +Пароль +Путь +Порт +Порты +Протокол +Перезагрузка +Ð¡Ð±Ñ€Ð¾Ñ +Вернуть +Сохранить +Сохранить & ПринÑÑ‚ÑŒ +Ð¡ÐµÑ€Ð²Ð¸Ñ +СервиÑÑ‹ +ÐаÑтройки +Размер +Старт +ÑтатичеÑкий +Ð¡Ñ‚Ð°Ñ‚ÑƒÑ +СтатиÑтика +Отправить +СиÑтемный журнал +СиÑтема +Цель +Ð’Ñ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð·Ð¾Ð½Ð° +Тип +ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° +ÐепринÑтые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ +Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ +ВерÑÐ¸Ñ +Web UI +Wi-Fi +Зона + + diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.lua b/openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.lua new file mode 100644 index 0000000..a0d3e1f --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.lua @@ -0,0 +1,3 @@ +sysauth_head = 'ТребуетÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ' +sysauth_prompt = 'ПожалуйÑта, введите логин и пароль.' +sysauth_failed = 'Ðеверный логин и/или пароль! ПожалуйÑта попробуйте Ñнова.' diff --git a/openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.xml b/openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.xml new file mode 100644 index 0000000..3a0d2dc --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/luasrc/i18n/sysauth.ru.xml @@ -0,0 +1,9 @@ + + + + +ТребуетÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ +ПожалуйÑта, введите логин и пароль. +Ðеверный логин и/или пароль! ПожалуйÑта попробуйте Ñнова. + + diff --git a/openwrt/packages/luci/i18n/russian/root/etc/uci-defaults/luci-i18n-russian b/openwrt/packages/luci/i18n/russian/root/etc/uci-defaults/luci-i18n-russian new file mode 100755 index 0000000..6966c59 --- /dev/null +++ b/openwrt/packages/luci/i18n/russian/root/etc/uci-defaults/luci-i18n-russian @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.languages.ru=Russian + commit luci +EOF + diff --git a/openwrt/packages/luci/libs/cbi/Makefile b/openwrt/packages/luci/libs/cbi/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi.js b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi.js new file mode 100644 index 0000000..77c59e5 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi.js @@ -0,0 +1,221 @@ +/* + LuCI - Lua Configuration Interface + + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + + 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$ +*/ + +var cbi_d = []; + +function cbi_d_add(field, dep, next) { + var obj = document.getElementById(field); + if (obj) { + var entry + for (var i=0; iRNr-FN=3zVdt9tv~<4fPor7@h1x-1A_*G z4#+T&pBUJtADCR=A+xAY{q)Mqma1&c{a=cmxa4~mroT4KS#`QgUof=)~+&T;I{j*sYXaTd%6BpddF%U0!DD^qC5h za!gM1`zFkilw?>wPi9)j8Wt9I))h*%tJiLm*{Loqq9hZ|aDstdhKpl`^aUv?Mn)zk OR#uKC*E=qb4Aua>fQ#$^ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/apply.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/apply.gif new file mode 100644 index 0000000000000000000000000000000000000000..82ae7ed821f7524c0356e40f79a0379fc634d535 GIT binary patch literal 268 zcmV+n0rUPxNk%w1VGsZi0K^{vM3g9B!ajxBR(;h{C|4L|#z9W1FZTQNam`88@5?V| z96pC8chOCN)>Mw(T#DRUiQ8Fv(@#mEENRI^ZOca`PZo5~OEz>Nz2>iuw1BeWp~dOA zBTNzi%BC{z2#%%nWDQ(& zkP#APQYdIRbsbb52orn(e?S)g~J1 z%8r<(-QeVRgO&gP{{R30A^8LW000gEEC2ui01E&M06+vZ(8)=q0AK`A2tAn4V1q?& p9d!Z1mQ}E{1V<7C3PltEGGGP@1A|xv9lPESaCFRSx11yb06WwgHGu#C literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/download.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/download.gif new file mode 100644 index 0000000000000000000000000000000000000000..f99a5383b23fc4270a45048cea54b7d84e4c632b GIT binary patch literal 189 zcmZ?wbhEHb6krfw*v!umwaLqI!OQM5F>k&+Z^fq|bvhXDvcW-zd1eeis_YHo#<8bh&USm7b|HfiTo^1C<- zB2&*9?YY;WqkfgAr7?@)##fnMrp5vd5e9?B>jf-W))_Q3ne(cwV{E9XUS-Jmz%6-U ohKzU%--1K~l{<@Algzi@uNL9X;o>Z>(Bsa^YtS>66lAal0Is`BfB*mh literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/edit.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b02b6e72a8d3b7f8add18f94fdd25e6d705ddac GIT binary patch literal 280 zcmV+z0q6clNk%w1VGsZi0K@>ugJjP{dk$Tr~sLS5q=$-yaxZ#SE11S zRIB!<(fT-LmH+?$A^8LV00000EC2ui01yBW000G*;3tk`DMpS%Nm39Du;)pl6A@EB z5xm!Np4!AfBnlcnph84J6a~km2eJG}oCYZJ=Ydc~*KCvvDSSTxgcd_Cm=B`#5u?d; z3!M!C{uwM9bQu_Bd3p~bei3zpcpDoG6^DHb2?~}900Ru06&HvI2?=-w0|2G~3!WbU e5ePdx1QoIi4i<=*mj?$A4;L2}RVKnBApko)oOWvf literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/fieldadd.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/fieldadd.gif new file mode 100644 index 0000000000000000000000000000000000000000..431ff64d1f07ea8368ff38ac49941794a3fdd849 GIT binary patch literal 379 zcmZ?wbhEHb6krfwxXQrr|GeMpEk^&ppZIqp{q-#2*GpypKk@m0DeV7?)PKK@zCNA$ z`dro2lOEGfdA01Zo^;&3Zkzdpqptt|eeXPA|NqbH{v$3`n~kTR_U=C5@c+lT*LU_b z?6CO%>(2l8{r~^I{r|G{^@*_mA7}snwCwdU*P=DL|Gypj|E%Km1>^spH~#;&>;M1% z43q)IpDbVlbU-A?PYi4`9Htg{=x~{833+Y}XmD73G1F_0L0j|T!~?dRp1tm=n^ZC5We%>aw-FvmvIpt(dOEPIJ XU%@iXKOm5ik(HI@w%c77M+R#EbrzH@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/find.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/find.gif new file mode 100644 index 0000000000000000000000000000000000000000..9ae5e3489bb888d198eb923bb095b48b04403705 GIT binary patch literal 273 zcmV+s0q*`sNk%w1VGsZi0K^{vc9*og-TcMk{nhCBh_A@i+vHYljktnV?e+bOcW6yp zbLH*z_4)kq_4;Q^Gl{$GpO1s<@%ZNQ{aZUCuG8g1OkMl^{;_vPn!whm%ie)&TXr4L_o{y)q5EzYtB;xTCWf;e!643y9FwiJ6z-cH%*eE2C&?LHF520~{Ks*+N*(+Kf z6ATMOGH`g(00>C|cno`e9u*=05rZ2M2z-c&9*lzt8600y!Ov?p4qk8 z_sQn}X|3gLf|Hfa{4HFBMq+vzJXv+X|6!-#{r&xKvgu!?-l)&;*zNvYc8feuU~I4F zQ<~I5R%ieJ|NsC0A^8LW0018VEC2ui01yBW000Gt;3s}wX?kNyLPFa#5UP3^wk(CC zKe9+;gdm|(VMuts4zO}DT@VOK1m)={2pi9Zf$&VC9jdjm*+RV&K$v9RFu0|I!2+1F z6;Q;%BcIpB1z!^u289U*e{2p3gL?-F2^@(e8U&FXn3w5$p!k!8k%2*+K?fuc zvXg-|`GIQRqSUCAs4#&;3tm~By~MCQ%rwwORo7gy-yy?BWny%m`4$Z=kEQF}JtY=+ zUfLA?(#?Ar^XBeQKBmcC4v)^p`DK_cQ206RTqffIk;3UrB1Hyj7R*hC%3_Rs)g7Jc Jeaeaq)&Qp@T0Z~) literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/link.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/link.gif new file mode 100644 index 0000000000000000000000000000000000000000..f0bb78da6b1e2cb17aa1a0e21c80e02979f6321a GIT binary patch literal 279 zcmV+y0qFimNk%w1VGsZi0K^{vm&^Qekgn|U_T}yMiLlDm+vLaN{=MG)S8$O@RcrG0 z`m5CYWS!x)+5Dr>`-!{kQek_q(&TBN;zLVZ)#vbFn&Fzj)~L(g-skTrF+)B@RpROJ ze4)L|%+de<|NsC0A^8LW0018VEC2ui01yBW000G)peK&x_?;dVMVDm}1jhw|hep&O z==8z~GHrORSgnM6@HQ4;4*@!6xGR+fIw4vg zByI*g?ikQL90EyhXA2I80}~>FNeyv^hX5Oj9sz=0a*zN37#bo03T1_nn*yF52n7l~ d8?74{0v#Ej2(=Ip2?-Mu8X6f_CBY>j06X7qcdP&a literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/reload.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/reload.gif new file mode 100644 index 0000000000000000000000000000000000000000..8268958a19e016741fffb8309b1174e548f5ce19 GIT binary patch literal 248 zcmV51h?dP)!|<#Vc>gJ1)O z9Y&Xm98YHe08|T}nE5Daq{Qc(Rx3cM5 zjz9kQ*3j_j+pnL#{d)WH+j&{p|6ssC8=&};g^__li9rWsJjhQBZ1WCGDDaT!>RZ^( zEEK83!O|Nd>|`Z3*C*`uOEs;l0!ub)PUp?=f27@0VfU<`vGKzV%|l1oS?<>Z^@_<= zC~_&t)O6G|iMKeh$aQzhi;0Q%F-^$to;pK9LUxv-l;q?Z@dd)N%uel7=1K?)Gp=1y z$56M4m6eCxNh-frev|MX$^D9=LUJ*T=NWksPtC-3SYNk)IzaCG{5wQd4hOTmQRpBi`QrZFzZjOw5(w z;B+Ua|6ri_lZBCiL7qW}0SG{LGO*S^P_K*2tV;HB^Xpa+Tva9QCeXgnd6P%76fc9p zOamsHcy;@YDln|Vuw<0nl$s8=rCxw48uw_56lMa6}$ zEFa1XibC1A+uFH>WUA~WrMhG$PUPgWRp}FBoy96PRn(YYfNQZp@O&*5b=4JX)+#bs F0{{l~XioqD literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/save.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/save.gif new file mode 100644 index 0000000000000000000000000000000000000000..35e949963e4b7a5f04fd1c8932a980901e3d4385 GIT binary patch literal 263 zcmV+i0r>t$Nk%w1VGsZi0K^{vcEd+Ya4xgmmXXkDk(iA6{P)e~xr@?RgUwTMzeLpS z#Wqhu{H$s5p4O4v<)^3=A2^0_EulhRp%QGjIf`R%Ru$RUj;1k~O1%3=|$g0$`b{ z1p`T8E1%cF0ssJ7eF+Hu(2Z{06R}5X@39! literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/user.gif b/openwrt/packages/luci/libs/cbi/htdocs/luci-static/resources/cbi/user.gif new file mode 100644 index 0000000000000000000000000000000000000000..dcb5c2a899c84ee0be36e6b92222cdde6fbb8ad3 GIT binary patch literal 246 zcmV5VArX{>gpqy}ZQ3xBIb z?{>Ooo8TtXQxO=NV3P1sT@;64^wK0*F2c + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.cbi", package.seeall) + +require("luci.template") +local util = require("luci.util") +require("luci.http") +require("luci.uvl") +require("luci.fs") + +--local event = require "luci.sys.event" +local uci = require("luci.model.uci") +local class = util.class +local instanceof = util.instanceof + +FORM_NODATA = 0 +FORM_PROCEED = 0 +FORM_VALID = 1 +FORM_INVALID = -1 +FORM_CHANGED = 2 + +AUTO = true + +CREATE_PREFIX = "cbi.cts." +REMOVE_PREFIX = "cbi.rts." + +-- Loads a CBI map from given file, creating an environment and returns it +function load(cbimap, ...) + require("luci.fs") + local i18n = require "luci.i18n" + require("luci.config") + require("luci.util") + + local upldir = "/lib/uci/upload/" + local cbidir = luci.util.libpath() .. "/model/cbi/" + + assert(luci.fs.stat(cbimap) or luci.fs.stat(cbidir..cbimap..".lua"), + "Model not found!") + + local func, err = loadfile(cbimap) + if not func then + func, err = loadfile(cbidir..cbimap..".lua") + end + assert(func, err) + + luci.i18n.loadc("cbi") + luci.i18n.loadc("uvl") + + local env = { + translate=i18n.translate, + translatef=i18n.translatef, + arg={...} + } + + setfenv(func, setmetatable(env, {__index = + function(tbl, key) + return rawget(tbl, key) or _M[key] or _G[key] + end})) + + local maps = { func() } + local uploads = { } + local has_upload = false + + for i, map in ipairs(maps) do + if not instanceof(map, Node) then + error("CBI map returns no valid map object!") + return nil + else + map:prepare() + if map.upload_fields then + has_upload = true + for _, field in ipairs(map.upload_fields) do + uploads[ + field.config .. '.' .. + field.section.sectiontype .. '.' .. + field.option + ] = true + end + end + end + end + + if has_upload then + local uci = luci.model.uci.cursor() + local prm = luci.http.context.request.message.params + local fd, cbid + + luci.http.setfilehandler( + function( field, chunk, eof ) + if not field then return end + if field.name and not cbid then + local c, s, o = field.name:gmatch( + "cbid%.([^%.]+)%.([^%.]+)%.([^%.]+)" + )() + + if c and s and o then + local t = uci:get( c, s ) + if t and uploads[c.."."..t.."."..o] then + local path = upldir .. field.name + fd = io.open(path, "w") + if fd then + cbid = field.name + prm[cbid] = path + end + end + end + end + + if field.name == cbid and fd then + fd:write(chunk) + end + + if eof and fd then + fd:close() + fd = nil + cbid = nil + end + end + ) + end + + return maps +end + +local function _uvl_validate_section(node, name) + local co = node.map:get() + + luci.uvl.STRICT_UNKNOWN_OPTIONS = false + luci.uvl.STRICT_UNKNOWN_SECTIONS = false + + local function tag_fields(e) + if e.option and node.fields[e.option] then + if node.fields[e.option].error then + node.fields[e.option].error[name] = e + else + node.fields[e.option].error = { [name] = e } + end + elseif e.childs then + for _, c in ipairs(e.childs) do tag_fields(c) end + end + end + + local function tag_section(e) + local s = { } + for _, c in ipairs(e.childs) do + if c.childs and not c:is(luci.uvl.errors.ERR_DEPENDENCY) then + table.insert( s, c.childs[1]:string() ) + else + table.insert( s, c:string() ) + end + end + if #s > 0 then + if node.error then + node.error[name] = s + else + node.error = { [name] = s } + end + end + end + + local stat, err = node.map.validator:validate_section(node.config, name, co) + if err then + node.map.save = false + tag_fields(err) + tag_section(err) + end + +end + +local function _uvl_strip_remote_dependencies(deps) + local clean = {} + + for k, v in pairs(deps) do + k = k:gsub("%$config%.%$section%.", "") + if k:match("^[%w_]+$") and type(v) == "string" then + clean[k] = v + end + end + + return clean +end + + +-- Node pseudo abstract class +Node = class() + +function Node.__init__(self, title, description) + self.children = {} + self.title = title or "" + self.description = description or "" + self.template = "cbi/node" +end + +-- i18n helper +function Node._i18n(self, config, section, option, title, description) + + -- i18n loaded? + if type(luci.i18n) == "table" then + + local key = config and config:gsub("[^%w]+", "") or "" + + if section then key = key .. "_" .. section:lower():gsub("[^%w]+", "") end + if option then key = key .. "_" .. tostring(option):lower():gsub("[^%w]+", "") end + + self.title = title or luci.i18n.translate( key, option or section or config ) + self.description = description or luci.i18n.translate( key .. "_desc", "" ) + end +end + +-- Prepare nodes +function Node.prepare(self, ...) + for k, child in ipairs(self.children) do + child:prepare(...) + end +end + +-- Append child nodes +function Node.append(self, obj) + table.insert(self.children, obj) +end + +-- Parse this node and its children +function Node.parse(self, ...) + for k, child in ipairs(self.children) do + child:parse(...) + end +end + +-- Render this node +function Node.render(self, scope) + scope = scope or {} + scope.self = self + + luci.template.render(self.template, scope) +end + +-- Render the children +function Node.render_children(self, ...) + for k, node in ipairs(self.children) do + node:render(...) + end +end + + +--[[ +A simple template element +]]-- +Template = class(Node) + +function Template.__init__(self, template) + Node.__init__(self) + self.template = template +end + +function Template.render(self) + luci.template.render(self.template, {self=self}) +end + + +--[[ +Map - A map describing a configuration file +]]-- +Map = class(Node) + +function Map.__init__(self, config, ...) + Node.__init__(self, ...) + Node._i18n(self, config, nil, nil, ...) + + self.config = config + self.parsechain = {self.config} + self.template = "cbi/map" + self.apply_on_parse = nil + self.readinput = true + + self.uci = uci.cursor() + self.save = true + + self.changed = false + + if not self.uci:load(self.config) then + error("Unable to read UCI data: " .. self.config) + end + + self.validator = luci.uvl.UVL() + self.scheme = self.validator:get_scheme(self.config) + +end + +function Map.formvalue(self, key) + return self.readinput and luci.http.formvalue(key) +end + +function Map.formvaluetable(self, key) + return self.readinput and luci.http.formvaluetable(key) +end + +function Map.get_scheme(self, sectiontype, option) + if not option then + return self.scheme and self.scheme.sections[sectiontype] + else + return self.scheme and self.scheme.variables[sectiontype] + and self.scheme.variables[sectiontype][option] + end +end + +function Map.submitstate(self) + return self:formvalue("cbi.submit") +end + +-- Chain foreign config +function Map.chain(self, config) + table.insert(self.parsechain, config) +end + +function Map.state_handler(self, state) + return state +end + +-- Use optimized UCI writing +function Map.parse(self, readinput, ...) + self.readinput = (readinput ~= false) + Node.parse(self, ...) + + if self.save then + for i, config in ipairs(self.parsechain) do + self.uci:save(config) + end + if self:submitstate() and (self.autoapply or luci.http.formvalue("cbi.apply")) then + for i, config in ipairs(self.parsechain) do + self.uci:commit(config) + + -- Refresh data because commit changes section names + self.uci:load(config) + end + if self.apply_on_parse then + self.uci:apply(self.parsechain) + else + self._apply = function() + local cmd = self.uci:apply(self.parsechain, true) + return io.popen(cmd) + end + end + + -- Reparse sections + Node.parse(self, true) + + end + for i, config in ipairs(self.parsechain) do + self.uci:unload(config) + end + if type(self.commit_handler) == "function" then + self:commit_handler(self:submitstate()) + end + end + + if self:submitstate() then + if self.save then + self.state = self.changed and FORM_CHANGED or FORM_VALID + else + self.state = FORM_INVALID + end + else + self.state = FORM_NODATA + end + + return self:state_handler(self.state) +end + +function Map.render(self, ...) + Node.render(self, ...) + if self._apply then + local fp = self._apply() + fp:read("*a") + fp:close() + end +end + +-- Creates a child section +function Map.section(self, class, ...) + if instanceof(class, AbstractSection) then + local obj = class(self, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractSection") + end +end + +-- UCI add +function Map.add(self, sectiontype) + return self.uci:add(self.config, sectiontype) +end + +-- UCI set +function Map.set(self, section, option, value) + if option then + return self.uci:set(self.config, section, option, value) + else + return self.uci:set(self.config, section, value) + end +end + +-- UCI del +function Map.del(self, section, option) + if option then + return self.uci:delete(self.config, section, option) + else + return self.uci:delete(self.config, section) + end +end + +-- UCI get +function Map.get(self, section, option) + if not section then + return self.uci:get_all(self.config) + elseif option then + return self.uci:get(self.config, section, option) + else + return self.uci:get_all(self.config, section) + end +end + +--[[ +Compound - Container +]]-- +Compound = class(Node) + +function Compound.__init__(self, ...) + Node.__init__(self) + self.children = {...} +end + +function Compound.parse(self, ...) + local cstate, state = 0, 0 + + for k, child in ipairs(self.children) do + cstate = child:parse(...) + state = (not state or cstate < state) and cstate or state + end + + return state +end + + +--[[ +Delegator - Node controller +]]-- +Delegator = class(Node) +function Delegator.__init__(self, ...) + Node.__init__(self, ...) + self.nodes = {} + self.template = "cbi/delegator" +end + +function Delegator.state(self, name, node, transitor) + transitor = transitor or self.transistor_linear + local state = {node=node, name=name, transitor=transitor} + + assert(instanceof(node, Node), "Invalid node") + assert(not self.nodes[name], "Duplicate entry") + + self.nodes[name] = state + self:append(state) + + return state +end + +function Delegator.get(self, name) + return self.nodes[name] +end + +function Delegator.transistor_linear(self, state, cstate) + if cstate > 0 then + for i, child in ipairs(self.children) do + if state == child then + return self.children[i+1] + end + end + else + return state + end +end + +function Delegator.parse(self, ...) + local active = self:getactive() + assert(active, "Invalid state") + + local cstate = active.node:parse() + self.active = active.transistor(self, active.node, cstate) + + if not self.active then + return FORM_DONE + else + self.active:parse(false) + return FROM_PROCEED + end +end + +function Delegator.render(self, ...) + self.active.node:render(...) +end + +function Delegator.getactive(self) + return self:get(Map.formvalue(self, "cbi.delegated") + or (self.children[1] and self.children[1].name)) +end + +--[[ +Page - A simple node +]]-- + +Page = class(Node) +Page.__init__ = Node.__init__ +Page.parse = function() end + + +--[[ +SimpleForm - A Simple non-UCI form +]]-- +SimpleForm = class(Node) + +function SimpleForm.__init__(self, config, title, description, data) + Node.__init__(self, title, description) + self.config = config + self.data = data or {} + self.template = "cbi/simpleform" + self.dorender = true + self.pageaction = false + self.readinput = true +end + +SimpleForm.formvalue = Map.formvalue +SimpleForm.formvaluetable = Map.formvaluetable + +function SimpleForm.parse(self, readinput, ...) + self.readinput = (readinput ~= false) + if self:submitstate() then + Node.parse(self, 1, ...) + end + + local valid = true + for k, j in ipairs(self.children) do + for i, v in ipairs(j.children) do + valid = valid + and (not v.tag_missing or not v.tag_missing[1]) + and (not v.tag_invalid or not v.tag_invalid[1]) + and (not v.error) + end + end + + local state = + not self:submitstate() and FORM_NODATA + or valid and FORM_VALID + or FORM_INVALID + + self.dorender = not self.handle or self:handle(state, self.data) ~= false + return state +end + +function SimpleForm.render(self, ...) + if self.dorender then + Node.render(self, ...) + end +end + +function SimpleForm.submitstate(self) + return self:formvalue("cbi.submit") +end + +function SimpleForm.section(self, class, ...) + if instanceof(class, AbstractSection) then + local obj = class(self, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractSection") + end +end + +-- Creates a child field +function SimpleForm.field(self, class, ...) + local section + for k, v in ipairs(self.children) do + if instanceof(v, SimpleSection) then + section = v + break + end + end + if not section then + section = self:section(SimpleSection) + end + + if instanceof(class, AbstractValue) then + local obj = class(self, section, ...) + obj.track_missing = true + section:append(obj) + return obj + else + error("class must be a descendent of AbstractValue") + end +end + +function SimpleForm.set(self, section, option, value) + self.data[option] = value +end + + +function SimpleForm.del(self, section, option) + self.data[option] = nil +end + + +function SimpleForm.get(self, section, option) + return self.data[option] +end + + +function SimpleForm.get_scheme() + return nil +end + + + +--[[ +AbstractSection +]]-- +AbstractSection = class(Node) + +function AbstractSection.__init__(self, map, sectiontype, ...) + Node.__init__(self, ...) + self.sectiontype = sectiontype + self.map = map + self.config = map.config + self.optionals = {} + self.defaults = {} + self.fields = {} + self.tag_error = {} + self.tag_invalid = {} + self.tag_deperror = {} + self.changed = false + + self.optional = true + self.addremove = false + self.dynamic = false +end + +-- Appends a new option +function AbstractSection.option(self, class, option, ...) + -- Autodetect from UVL + if class == true and self.map:get_scheme(self.sectiontype, option) then + local vs = self.map:get_scheme(self.sectiontype, option) + if vs.type == "boolean" then + class = Flag + elseif vs.type == "list" then + class = DynamicList + elseif vs.type == "enum" or vs.type == "reference" then + class = ListValue + else + class = Value + end + end + + if instanceof(class, AbstractValue) then + local obj = class(self.map, self, option, ...) + + Node._i18n(obj, self.config, self.section or self.sectiontype, option, ...) + + self:append(obj) + self.fields[option] = obj + return obj + elseif class == true then + error("No valid class was given and autodetection failed.") + else + error("class must be a descendant of AbstractValue") + end +end + +-- Parse optional options +function AbstractSection.parse_optionals(self, section) + if not self.optional then + return + end + + self.optionals[section] = {} + + local field = self.map:formvalue("cbi.opt."..self.config.."."..section) + for k,v in ipairs(self.children) do + if v.optional and not v:cfgvalue(section) then + if field == v.option then + field = nil + else + table.insert(self.optionals[section], v) + end + end + end + + if field and #field > 0 and self.dynamic then + self:add_dynamic(field) + end +end + +-- Add a dynamic option +function AbstractSection.add_dynamic(self, field, optional) + local o = self:option(Value, field, field) + o.optional = optional +end + +-- Parse all dynamic options +function AbstractSection.parse_dynamic(self, section) + if not self.dynamic then + return + end + + local arr = luci.util.clone(self:cfgvalue(section)) + local form = self.map:formvaluetable("cbid."..self.config.."."..section) + for k, v in pairs(form) do + arr[k] = v + end + + for key,val in pairs(arr) do + local create = true + + for i,c in ipairs(self.children) do + if c.option == key then + create = false + end + end + + if create and key:sub(1, 1) ~= "." then + self:add_dynamic(key, true) + end + end +end + +-- Returns the section's UCI table +function AbstractSection.cfgvalue(self, section) + return self.map:get(section) +end + +-- Push events +function AbstractSection.push_events(self) + --luci.util.append(self.map.events, self.events) + self.map.changed = true +end + +-- Removes the section +function AbstractSection.remove(self, section) + self.map.autoapply = false + return self.map:del(section) +end + +-- Creates the section +function AbstractSection.create(self, section) + local stat + + if section then + stat = section:match("^%w+$") and self.map:set(section, nil, self.sectiontype) + else + section = self.map:add(self.sectiontype) + stat = section + end + + if stat then + for k,v in pairs(self.children) do + if v.default then + self.map:set(section, v.option, v.default) + end + end + + for k,v in pairs(self.defaults) do + self.map:set(section, k, v) + end + end + + self.map.autoapply = false + + return stat +end + + +SimpleSection = class(AbstractSection) + +function SimpleSection.__init__(self, form, ...) + AbstractSection.__init__(self, form, nil, ...) + self.template = "cbi/nullsection" +end + + +Table = class(AbstractSection) + +function Table.__init__(self, form, data, ...) + local datasource = {} + datasource.config = "table" + self.data = data + + datasource.formvalue = Map.formvalue + datasource.formvaluetable = Map.formvaluetable + datasource.readinput = true + + function datasource.get(self, section, option) + return data[section] and data[section][option] + end + + function datasource.submitstate(self) + return Map.formvalue(self, "cbi.submit") + end + + function datasource.del(...) + return true + end + + function datasource.get_scheme() + return nil + end + + AbstractSection.__init__(self, datasource, "table", ...) + self.template = "cbi/tblsection" + self.rowcolors = true + self.anonymous = true +end + +function Table.parse(self, readinput) + self.map.readinput = (readinput ~= false) + for i, k in ipairs(self:cfgsections()) do + if self.map:submitstate() then + Node.parse(self, k) + end + end +end + +function Table.cfgsections(self) + local sections = {} + + for i, v in luci.util.kspairs(self.data) do + table.insert(sections, i) + end + + return sections +end + + + +--[[ +NamedSection - A fixed configuration section defined by its name +]]-- +NamedSection = class(AbstractSection) + +function NamedSection.__init__(self, map, section, stype, ...) + AbstractSection.__init__(self, map, stype, ...) + Node._i18n(self, map.config, section, nil, ...) + + -- Defaults + self.addremove = false + + -- Use defaults from UVL + if not self.override_scheme and self.map:get_scheme(self.sectiontype) then + local vs = self.map:get_scheme(self.sectiontype) + self.addremove = not vs.unique and not vs.required + self.dynamic = vs.dynamic + self.title = self.title or vs.title + self.description = self.description or vs.descr + end + + self.template = "cbi/nsection" + self.section = section +end + +function NamedSection.parse(self, novld) + local s = self.section + local active = self:cfgvalue(s) + + if self.addremove then + local path = self.config.."."..s + if active then -- Remove the section + if self.map:formvalue("cbi.rns."..path) and self:remove(s) then + self:push_events() + return + end + else -- Create and apply default values + if self.map:formvalue("cbi.cns."..path) then + self:create(s) + return + end + end + end + + if active then + AbstractSection.parse_dynamic(self, s) + if self.map:submitstate() then + Node.parse(self, s) + + if not novld and not self.override_scheme and self.map.scheme then + _uvl_validate_section(self, s) + end + end + AbstractSection.parse_optionals(self, s) + + if self.changed then + self:push_events() + end + end +end + + +--[[ +TypedSection - A (set of) configuration section(s) defined by the type + addremove: Defines whether the user can add/remove sections of this type + anonymous: Allow creating anonymous sections + validate: a validation function returning nil if the section is invalid +]]-- +TypedSection = class(AbstractSection) + +function TypedSection.__init__(self, map, type, ...) + AbstractSection.__init__(self, map, type, ...) + Node._i18n(self, map.config, type, nil, ...) + + self.template = "cbi/tsection" + self.deps = {} + self.anonymous = false + + -- Use defaults from UVL + if not self.override_scheme and self.map:get_scheme(self.sectiontype) then + local vs = self.map:get_scheme(self.sectiontype) + self.addremove = not vs.unique and not vs.required + self.dynamic = vs.dynamic + self.anonymous = not vs.named + self.title = self.title or vs.title + self.description = self.description or vs.descr + end +end + +-- Return all matching UCI sections for this TypedSection +function TypedSection.cfgsections(self) + local sections = {} + self.map.uci:foreach(self.map.config, self.sectiontype, + function (section) + if self:checkscope(section[".name"]) then + table.insert(sections, section[".name"]) + end + end) + + return sections +end + +-- Limits scope to sections that have certain option => value pairs +function TypedSection.depends(self, option, value) + table.insert(self.deps, {option=option, value=value}) +end + +function TypedSection.parse(self, novld) + if self.addremove then + -- Remove + local crval = REMOVE_PREFIX .. self.config + local name = self.map:formvaluetable(crval) + for k,v in pairs(name) do + if k:sub(-2) == ".x" then + k = k:sub(1, #k - 2) + end + if self:cfgvalue(k) and self:checkscope(k) then + self:remove(k) + end + end + end + + local co + for i, k in ipairs(self:cfgsections()) do + AbstractSection.parse_dynamic(self, k) + if self.map:submitstate() then + Node.parse(self, k, novld) + + if not novld and not self.override_scheme and self.map.scheme then + _uvl_validate_section(self, k) + end + end + AbstractSection.parse_optionals(self, k) + end + + if self.addremove then + -- Create + local created + local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype + local name = self.map:formvalue(crval) + if self.anonymous then + if name then + created = self:create() + end + else + if name then + -- Ignore if it already exists + if self:cfgvalue(name) then + name = nil; + end + + name = self:checkscope(name) + + if not name then + self.err_invalid = true + end + + if name and #name > 0 then + created = self:create(name) and name + if not created then + self.invalid_cts = true + end + end + end + end + + if created then + AbstractSection.parse_optionals(self, created) + end + end + + if created or self.changed then + self:push_events() + end +end + +-- Verifies scope of sections +function TypedSection.checkscope(self, section) + -- Check if we are not excluded + if self.filter and not self:filter(section) then + return nil + end + + -- Check if at least one dependency is met + if #self.deps > 0 and self:cfgvalue(section) then + local stat = false + + for k, v in ipairs(self.deps) do + if self:cfgvalue(section)[v.option] == v.value then + stat = true + end + end + + if not stat then + return nil + end + end + + return self:validate(section) +end + + +-- Dummy validate function +function TypedSection.validate(self, section) + return section +end + + +--[[ +AbstractValue - An abstract Value Type + null: Value can be empty + valid: A function returning the value if it is valid otherwise nil + depends: A table of option => value pairs of which one must be true + default: The default value + size: The size of the input fields + rmempty: Unset value if empty + optional: This value is optional (see AbstractSection.optionals) +]]-- +AbstractValue = class(Node) + +function AbstractValue.__init__(self, map, section, option, ...) + Node.__init__(self, ...) + self.section = section + self.option = option + self.map = map + self.config = map.config + self.tag_invalid = {} + self.tag_missing = {} + self.tag_reqerror = {} + self.tag_error = {} + self.deps = {} + --self.cast = "string" + + self.track_missing = false + self.rmempty = true + self.default = nil + self.size = nil + self.optional = false +end + +function AbstractValue.prepare(self) + -- Use defaults from UVL + if not self.override_scheme + and self.map:get_scheme(self.section.sectiontype, self.option) then + local vs = self.map:get_scheme(self.section.sectiontype, self.option) + if self.cast == nil then + self.cast = (vs.type == "list") and "list" or "string" + end + self.title = self.title or vs.title + self.description = self.description or vs.descr + if self.default == nil then + self.default = vs.default + end + + if vs.depends and not self.override_dependencies then + for i, deps in ipairs(vs.depends) do + deps = _uvl_strip_remote_dependencies(deps) + if next(deps) then + self:depends(deps) + end + end + end + end + + self.cast = self.cast or "string" +end + +-- Add a dependencie to another section field +function AbstractValue.depends(self, field, value) + local deps + if type(field) == "string" then + deps = {} + deps[field] = value + else + deps = field + end + + table.insert(self.deps, {deps=deps, add=""}) +end + +-- Generates the unique CBID +function AbstractValue.cbid(self, section) + return "cbid."..self.map.config.."."..section.."."..self.option +end + +-- Return whether this object should be created +function AbstractValue.formcreated(self, section) + local key = "cbi.opt."..self.config.."."..section + return (self.map:formvalue(key) == self.option) +end + +-- Returns the formvalue for this object +function AbstractValue.formvalue(self, section) + return self.map:formvalue(self:cbid(section)) +end + +function AbstractValue.additional(self, value) + self.optional = value +end + +function AbstractValue.mandatory(self, value) + self.rmempty = not value +end + +function AbstractValue.parse(self, section, novld) + local fvalue = self:formvalue(section) + local cvalue = self:cfgvalue(section) + + if fvalue and #fvalue > 0 then -- If we have a form value, write it to UCI + fvalue = self:transform(self:validate(fvalue, section)) + if not fvalue and not novld then + if self.error then + self.error[section] = "invalid" + else + self.error = { [section] = "invalid" } + end + self.map.save = false + end + if fvalue and not (fvalue == cvalue) then + if self:write(section, fvalue) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end + end + else -- Unset the UCI or error + if self.rmempty or self.optional then + if self:remove(section) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end + elseif cvalue ~= fvalue and not novld then + self:write(section, fvalue or "") + if self.error then + self.error[section] = "missing" + else + self.error = { [section] = "missing" } + end + self.map.save = false + end + end +end + +-- Render if this value exists or if it is mandatory +function AbstractValue.render(self, s, scope) + if not self.optional or self:cfgvalue(s) or self:formcreated(s) then + scope = scope or {} + scope.section = s + scope.cbid = self:cbid(s) + scope.striptags = luci.util.striptags + + scope.ifattr = function(cond,key,val) + if cond then + return string.format( + ' %s="%s"', tostring(key), + luci.util.pcdata(tostring( val + or scope[key] + or (type(self[key]) ~= "function" and self[key]) + or "" )) + ) + else + return '' + end + end + + scope.attr = function(...) + return scope.ifattr( true, ... ) + end + + Node.render(self, scope) + end +end + +-- Return the UCI value of this object +function AbstractValue.cfgvalue(self, section) + local value = self.map:get(section, self.option) + if not value then + return nil + elseif not self.cast or self.cast == type(value) then + return value + elseif self.cast == "string" then + if type(value) == "table" then + return value[1] + end + elseif self.cast == "table" then + return luci.util.split(value, "%s+", nil, true) + end +end + +-- Validate the form value +function AbstractValue.validate(self, value) + return value +end + +AbstractValue.transform = AbstractValue.validate + + +-- Write to UCI +function AbstractValue.write(self, section, value) + return self.map:set(section, self.option, value) +end + +-- Remove from UCI +function AbstractValue.remove(self, section) + return self.map:del(section, self.option) +end + + + + +--[[ +Value - A one-line value + maxlength: The maximum length +]]-- +Value = class(AbstractValue) + +function Value.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/value" + self.keylist = {} + self.vallist = {} +end + +function Value.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + + +-- DummyValue - This does nothing except being there +DummyValue = class(AbstractValue) + +function DummyValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/dvalue" + self.value = nil +end + +function DummyValue.cfgvalue(self, section) + local value + if self.value then + if type(self.value) == "function" then + value = self:value(section) + else + value = self.value + end + else + value = AbstractValue.cfgvalue(self, section) + end + return value +end + +function DummyValue.parse(self) + +end + + +--[[ +Flag - A flag being enabled or disabled +]]-- +Flag = class(AbstractValue) + +function Flag.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/fvalue" + + self.enabled = "1" + self.disabled = "0" +end + +-- A flag can only have two states: set or unset +function Flag.parse(self, section) + local fvalue = self:formvalue(section) + + if fvalue then + fvalue = self.enabled + else + fvalue = self.disabled + end + + if fvalue == self.enabled or (not self.optional and not self.rmempty) then + if not(fvalue == self:cfgvalue(section)) then + self:write(section, fvalue) + end + else + self:remove(section) + end +end + + + +--[[ +ListValue - A one-line value predefined in a list + widget: The widget that will be used (select, radio) +]]-- +ListValue = class(AbstractValue) + +function ListValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/lvalue" + + self.keylist = {} + self.vallist = {} + self.size = 1 + self.widget = "select" +end + +function ListValue.prepare(self, ...) + AbstractValue.prepare(self, ...) + if not self.override_scheme + and self.map:get_scheme(self.section.sectiontype, self.option) then + local vs = self.map:get_scheme(self.section.sectiontype, self.option) + if self.value and vs.valuelist and not self.override_values then + for k, v in ipairs(vs.valuelist) do + local deps = {} + if not self.override_dependencies + and vs.enum_depends and vs.enum_depends[v.value] then + for i, dep in ipairs(vs.enum_depends[v.value]) do + table.insert(deps, _uvl_strip_remote_dependencies(dep)) + end + end + self:value(v.value, v.title or v.value, unpack(deps)) + end + end + end +end + +function ListValue.value(self, key, val, ...) + if luci.util.contains(self.keylist, key) then + return + end + + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) + + for i, deps in ipairs({...}) do + table.insert(self.deps, {add = "-"..key, deps=deps}) + end +end + +function ListValue.validate(self, val) + if luci.util.contains(self.keylist, val) then + return val + else + return nil + end +end + + + +--[[ +MultiValue - Multiple delimited values + widget: The widget that will be used (select, checkbox) + delimiter: The delimiter that will separate the values (default: " ") +]]-- +MultiValue = class(AbstractValue) + +function MultiValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/mvalue" + + self.keylist = {} + self.vallist = {} + + self.widget = "checkbox" + self.delimiter = " " +end + +function MultiValue.render(self, ...) + if self.widget == "select" and not self.size then + self.size = #self.vallist + end + + AbstractValue.render(self, ...) +end + +function MultiValue.value(self, key, val) + if luci.util.contains(self.keylist, key) then + return + end + + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function MultiValue.valuelist(self, section) + local val = self:cfgvalue(section) + + if not(type(val) == "string") then + return {} + end + + return luci.util.split(val, self.delimiter) +end + +function MultiValue.validate(self, val) + val = (type(val) == "table") and val or {val} + + local result + + for i, value in ipairs(val) do + if luci.util.contains(self.keylist, value) then + result = result and (result .. self.delimiter .. value) or value + end + end + + return result +end + + +StaticList = class(MultiValue) + +function StaticList.__init__(self, ...) + MultiValue.__init__(self, ...) + self.cast = "table" + self.valuelist = self.cfgvalue + + if not self.override_scheme + and self.map:get_scheme(self.section.sectiontype, self.option) then + local vs = self.map:get_scheme(self.section.sectiontype, self.option) + if self.value and vs.values and not self.override_values then + for k, v in pairs(vs.values) do + self:value(k, v) + end + end + end +end + +function StaticList.validate(self, value) + value = (type(value) == "table") and value or {value} + + local valid = {} + for i, v in ipairs(value) do + if luci.util.contains(self.keylist, v) then + table.insert(valid, v) + end + end + return valid +end + + +DynamicList = class(AbstractValue) + +function DynamicList.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/dynlist" + self.cast = "table" + self.keylist = {} + self.vallist = {} +end + +function DynamicList.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function DynamicList.formvalue(self, section) + local value = AbstractValue.formvalue(self, section) + value = (type(value) == "table") and value or {value} + + local valid = {} + for i, v in ipairs(value) do + if v and #v > 0 + and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i) + and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i..".x") then + table.insert(valid, v) + end + end + + return valid +end + + +--[[ +TextValue - A multi-line value + rows: Rows +]]-- +TextValue = class(AbstractValue) + +function TextValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/tvalue" +end + +--[[ +Button +]]-- +Button = class(AbstractValue) + +function Button.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/button" + self.inputstyle = nil + self.rmempty = true +end + + +FileUpload = class(AbstractValue) + +function FileUpload.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/upload" + if not self.map.upload_fields then + self.map.upload_fields = { self } + else + self.map.upload_fields[#self.map.upload_fields+1] = self + end +end + +function FileUpload.formcreated(self, section) + return AbstractValue.formcreated(self, section) or + self.map:formvalue("cbi.rlf."..section.."."..self.option) or + self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") +end + +function FileUpload.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val and luci.fs.access(val) then + return val + end + return nil +end + +function FileUpload.formvalue(self, section) + local val = AbstractValue.formvalue(self, section) + if val then + if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and + not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") + then + return val + end + luci.fs.unlink(val) + self.value = nil + end + return nil +end + +function FileUpload.remove(self, section) + local val = AbstractValue.formvalue(self, section) + if val and luci.fs.access(val) then luci.fs.unlink(val) end + return AbstractValue.remove(self, section) +end + + +FileBrowser = class(AbstractValue) + +function FileBrowser.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/browser" +end diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/browser.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/browser.htm new file mode 100644 index 0000000..224da0e --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/browser.htm @@ -0,0 +1,23 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: browser.htm 3555 2008-10-10 21:52:22Z jow $ + +-%> + +<% + local t = require("luci.tools.webadmin") + local v = self:cfgvalue(section) +-%> +<%+cbi/valueheader%> + /> + '<%=self.default_path and ", '"..self.default_path.."'"%>);return false" alt="<%:cbi_browser%>" title="<%:cbi_browser%>" src="<%=resource%>/cbi/folder.png" style="vertical-align:bottom" /> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/button.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/button.htm new file mode 100644 index 0000000..99c3ba6 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/button.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: button.htm 3652 2008-10-29 19:41:33Z jow $ + +-%> +<%+cbi/valueheader%> + <% if self:cfgvalue(section) ~= false then %> + " type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.title)%> /> + <% else %> + - + <% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valuefooter.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valuefooter.htm new file mode 100644 index 0000000..43ce1c3 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/cell_valuefooter.htm @@ -0,0 +1,34 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: cell_valuefooter.htm 3340 2008-09-16 15:51:35Z Cyrus $ + +-%> +
+ +<% if #self.deps > 0 then -%> + +<%- end %> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valueheader.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valueheader.htm new file mode 100644 index 0000000..dd2eb8e --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/full_valueheader.htm @@ -0,0 +1,24 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: full_valueheader.htm 3171 2008-09-06 22:42:55Z jow $ + +-%> + +
"> + <%- if self.title and #self.title > 0 then -%> + +
+ <%- end -%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/fvalue.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/fvalue.htm new file mode 100644 index 0000000..5aade0c --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/fvalue.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: fvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> + value="1" /> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/header.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/header.htm new file mode 100644 index 0000000..bc40e19 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/header.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> + +<%+header%> +
+
+ + + +
diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/lvalue.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/lvalue.htm new file mode 100644 index 0000000..90a5ca4 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/lvalue.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: lvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + +<% elseif self.widget == "radio" then + local c = 0 + for i, key in pairs(self.keylist) do + c = c + 1 +%> + /> + ><%=self.vallist[i]%>
+<% if c == self.size then c = 0 %>
+<% end end %> +<% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/map.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/map.htm new file mode 100644 index 0000000..23d09a2 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/map.htm @@ -0,0 +1,36 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: map.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> + +
+

<%=self.title%>

+
<%=self.description%>
+ <%- if self._apply then -%> +
+ <%:cbi_applying%> +
    <%- + local fp = self._apply() + self._apply = nil + local line = fp:read() + while line do + write("
  • " .. luci.util.pcdata(line) .. "
  • \n") + line = fp:read() + end + fp:close() + -%>
+
+ <%- end -%> + <%- self:render_children() %> +
+
diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/mvalue.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/mvalue.htm new file mode 100644 index 0000000..9f1a8f3 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/mvalue.htm @@ -0,0 +1,35 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: mvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<% +local v = self:valuelist(section) or {} +%> +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + +<% elseif self.widget == "checkbox" then + local c = 0; + for i, key in pairs(self.keylist) do + c = c + 1 +%> + /> + ><%=self.vallist[i]%>
+<% if c == self.size then c = 0 %>
+<% end end %> +<% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nsection.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nsection.htm new file mode 100644 index 0000000..5042a37 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nsection.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: nsection.htm 3652 2008-10-29 19:41:33Z jow $ + +-%> + +<% if self:cfgvalue(self.section) then section = self.section %> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> + <% if self.description and #self.description > 0 then -%> +
<%=self.description%>
+ <%- end %> + <% if self.addremove then -%> +
+ +
+ <%- end %> +
+ <%+cbi/ucisection%> +
+
+
+<% elseif self.addremove then %> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+ +
+ <%- end %> +<% end %> + diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nullsection.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nullsection.htm new file mode 100644 index 0000000..9b2882a --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/nullsection.htm @@ -0,0 +1,23 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: nullsection.htm 3340 2008-09-16 15:51:35Z Cyrus $ + +-%> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
+ <% self:render_children(1, scope or {}) %> +
+
+
\ No newline at end of file diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/simpleform.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/simpleform.htm new file mode 100644 index 0000000..0e9d535 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/simpleform.htm @@ -0,0 +1,46 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: simpleform.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> + + +
+ + +
+
+

<%=self.title%>

+
<%=self.description%>
+ <% self:render_children() %> +
+
+<%- if self.message then %> +
<%=self.message%>
+<%- end %> +<%- if self.errmessage then %> +
<%=self.errmessage%>
+<%- end %> +
+<%- if self.submit ~= false then %> + +<% end %> +<%- if self.reset ~= false then %> + +<% end %> + +
+ diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tblsection.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tblsection.htm new file mode 100644 index 0000000..fb00ed3 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tblsection.htm @@ -0,0 +1,135 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tblsection.htm 4051 2009-01-16 20:29:47Z Cyrus $ + +-%> +<%- +local rowcnt = 1 +function rowstyle() + rowcnt = rowcnt + 1 + return (rowcnt % 2) + 1 +end +-%> + + +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+
+ <%- local count = 0 -%> + + + <%- if not self.anonymous then -%> + <%- if self.sectionhead then -%> + + <%- else -%> + + <%- end -%> + <%- end -%> + <%- for i, k in pairs(self.children) do if not k.optional then -%> + + <%- count = count + 1; end; end; if self.extedit or self.addremove then -%> + + <%- count = count + 1; end -%> + + + <%- if not self.anonymous then -%> + <%- if self.sectiondesc then -%> + + <%- else -%> + + <%- end -%> + <%- end -%> + <%- for i, k in pairs(self.children) do if not k.optional then -%> + + <%- end; end; if self.extedit or self.addremove then -%> + + <%- end -%> + + <%- local isempty = true + for i, k in ipairs(self:cfgsections()) do + section = k + isempty = false + scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" } + -%> + + <% if not self.anonymous then -%> + + <%- end %> + + + <%- + for k, node in ipairs(self.children) do + if not node.optional then + node:render(section, scope or {}) + end + end + -%> + + <%- if self.extedit or self.addremove then -%> + + <%- end -%> + + <%- end -%> + + <%- if isempty then -%> + + + + <%- end -%> +
<%=self.sectionhead%>  + <%- if k.titleref then -%><%- end -%> + <%-=k.title-%> + <%- if k.titleref then -%><%- end -%> +  
<%=self.sectiondesc%><%=k.description%>

<%=k%>

+ <%- if self.extedit then -%> + + <%=self.extedit:format(section)%> + <%- elseif type(self.extedit) == "function" then -%> + <%=self:extedit(section)%> + <%- end -%> + " title="<%:edit%>"><%:edit%> + <%- end; if self.addremove then %> + + <%- end -%> +

<%:cbi_sectempty%>
+ + <% if self.error then %> +
+
    <% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%> +
  • <%=luci.util.pcdata(e):gsub("\n","
    ")%>
  • + <%- end end %>
+
+ <% end %> + + <%- if self.addremove then -%> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.anonymous then %> + + <% else %> + <% if self.invalid_cts then -%>
<% end %> + + + <% if self.invalid_cts then -%> +
<%:cbi_invalid%>
+ <%- end %> + <% end %> +
+ <%- end %> + <%- end -%> +
+
+ diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tsection.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tsection.htm new file mode 100644 index 0000000..56a9b4e --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tsection.htm @@ -0,0 +1,59 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tsection.htm 3652 2008-10-29 19:41:33Z jow $ + +-%> + +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+ <% local isempty = true for i, k in ipairs(self:cfgsections()) do -%> + <% if self.addremove then -%> +
+ +
+ <%- end %> + <% section = k; isempty = false %> + + <% if not self.anonymous then -%> +

<%=k:upper()%>

+ <%- end %> + +
+ <%+cbi/ucisection%> +
+
+ <%- end %> + + <% if isempty then -%> + <%:cbi_sectempty%>

+ <%- end %> + + <% if self.addremove then -%> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.anonymous then -%> + + <%- else -%> + <% if self.invalid_cts then -%>
<% end %> + + + <% if self.invalid_cts then -%> +
<%:cbi_invalid%>
+ <%- end %> + <%- end %> +
+ <%- end %> + <%- end %> +
diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tvalue.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tvalue.htm new file mode 100644 index 0000000..0cd3766 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/tvalue.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: tvalue.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> + +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/ucisection.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/ucisection.htm new file mode 100644 index 0000000..f4c82a9 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/ucisection.htm @@ -0,0 +1,66 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ucisection.htm 3475 2008-09-30 21:13:33Z Cyrus $ + +-%> + +<% self:render_children(section, scope or {}) %> + +<% if self.error and self.error[section] then -%> +
+
    <% for _, e in ipairs(self.error[section]) do %>
  • <%=luci.util.pcdata(e):gsub("\n","
    ")%>
  • <% end %>
+
+<%- end %> + +<% if self.optionals[section] and #self.optionals[section] > 0 or self.dynamic then %> +
+ <% if self.dynamic then %> + + <% if self.optionals[section] and #self.optionals[section] > 0 then %> + + <% end %> + <% else %> + + + <% end %> + +
+<% end %> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/upload.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/upload.htm new file mode 100644 index 0000000..b56b84b --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/upload.htm @@ -0,0 +1,28 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upload.htm 3530 2008-10-07 15:41:15Z jow $ + +-%> + +<% + local t = require("luci.tools.webadmin") + local v = self:cfgvalue(section) +-%> +<%+cbi/valueheader%> + <% if v then %> + <%:cbi_upload Uploaded File%> (<%=t.byte_format(luci.fs.stat(v).size or 0)%>) + /> + " alt="<%:cbi_replace%>" title="<%:cbi_replace%>" src="<%=resource%>/cbi/reload.gif" /> + <% else %> + /> + <% end %> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/value.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/value.htm new file mode 100644 index 0000000..e6e9948 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/value.htm @@ -0,0 +1,38 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: value.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+cbi/valueheader%> + /> + <% if #self.keylist > 0 then -%> + + <% end -%> +<%+cbi/valuefooter%> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valuefooter.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valuefooter.htm new file mode 100644 index 0000000..fd8f97c --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valuefooter.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: valuefooter.htm 2639 2008-07-20 15:16:13Z jow $ + +-%> + +<% include( valuefooter or "cbi/full_valuefooter" ) %> diff --git a/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valueheader.htm b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valueheader.htm new file mode 100644 index 0000000..4aa9f07 --- /dev/null +++ b/openwrt/packages/luci/libs/cbi/luasrc/view/cbi/valueheader.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: valueheader.htm 2639 2008-07-20 15:16:13Z jow $ + +-%> + +<% include( valueheader or "cbi/full_valueheader" ) %> diff --git a/openwrt/packages/luci/libs/core/Makefile b/openwrt/packages/luci/libs/core/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/core/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/core/luasrc/ccache.lua b/openwrt/packages/luci/libs/core/luasrc/ccache.lua new file mode 100644 index 0000000..4db3b39 --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/ccache.lua @@ -0,0 +1,86 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ccache.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local io = require "io" +local util = require "luci.util" +local posix = require "posix" +local debug = require "debug" +local string = require "string" +local package = require "package" + +local type, loadfile = type, loadfile + + +module "luci.ccache" + +function cache_ondemand(...) + if debug.getinfo(1, 'S').source ~= "=?" then + cache_enable(...) + end +end + +function cache_enable(cachepath, mode) + cachepath = cachepath or "/tmp/luci-modulecache" + mode = mode or "r--r--r--" + + local loader = package.loaders[2] + local uid = posix.getpid("uid") + + if not posix.stat(cachepath) then + posix.mkdir(cachepath) + end + + local function _encode_filename(name) + local encoded = "" + for i=1, #name do + encoded = encoded .. ("%2X" % string.byte(name, i)) + end + return encoded + end + + local function _load_sane(file) + local stat = posix.stat(file) + if stat and stat.uid == uid and stat.mode == mode then + return loadfile(file) + end + end + + local function _write_sane(file, func) + if posix.getpid("uid") == uid then + local fp = io.open(file, "w") + if fp then + fp:write(util.get_bytecode(func)) + fp:close() + posix.chmod(file, mode) + end + end + end + + package.loaders[2] = function(mod) + local encoded = cachepath .. "/" .. _encode_filename(mod) + local modcons = _load_sane(encoded) + + if modcons then + return modcons + end + + -- No cachefile + modcons = loader(mod) + if type(modcons) == "function" then + _write_sane(encoded, modcons) + end + return modcons + end +end diff --git a/openwrt/packages/luci/libs/core/luasrc/debug.lua b/openwrt/packages/luci/libs/core/luasrc/debug.lua new file mode 100644 index 0000000..f991ab8 --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/debug.lua @@ -0,0 +1,25 @@ +local debug = require "debug" +local io = require "io" +local collectgarbage = collectgarbage + +module "luci.debug" +__file__ = debug.getinfo(1, 'S').source:sub(2) + +-- Enables the memory tracer with given flags and returns a function to disable the tracer again +function trap_memtrace(flags) + flags = flags or "l" + local tracefile = io.open("/tmp/memtrace", "w") + + local function trap(what, line) + local info = debug.getinfo(2, "Sn") + tracefile:write(info.source..":"..line.."\t"..(info.namewhat or "").."\t"..(info.name or "").."\t"..collectgarbage("count").."\n") + end + + debug.sethook(trap, flags) + + return function() + debug.sethook() + tracefile:close() + end +end + diff --git a/openwrt/packages/luci/libs/core/luasrc/fs.lua b/openwrt/packages/luci/libs/core/luasrc/fs.lua new file mode 100644 index 0000000..c574e3d --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/fs.lua @@ -0,0 +1,270 @@ +--[[ +LuCI - Filesystem tools + +Description: +A module offering often needed filesystem manipulation functions + +FileId: +$Id: fs.lua 4104 2009-01-20 10:19:22Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local io = require "io" +local os = require "os" +local ltn12 = require "luci.ltn12" +local posix = require "posix" + +local type = type + +--- LuCI filesystem library. +module "luci.fs" + +--- Test for file access permission on given path. +-- @class function +-- @name access +-- @param str String value containing the path +-- @return Number containing the return code, 0 on sucess or nil on error +-- @return String containing the error description (if any) +-- @return Number containing the os specific errno (if any) +access = posix.access + +--- Evaluate given shell glob pattern and return a table containing all matching +-- file and directory entries. +-- @class function +-- @name glob +-- @param filename String containing the path of the file to read +-- @return Table containing file and directory entries or nil if no matches +-- @return String containing the error description (if no matches) +-- @return Number containing the os specific errno (if no matches) +glob = posix.glob + +--- Checks wheather the given path exists and points to a regular file. +-- @param filename String containing the path of the file to test +-- @return Boolean indicating wheather given path points to regular file +function isfile(filename) + return posix.stat(filename, "type") == "regular" +end + +--- Checks wheather the given path exists and points to a directory. +-- @param dirname String containing the path of the directory to test +-- @return Boolean indicating wheather given path points to directory +function isdirectory(dirname) + return posix.stat(dirname, "type") == "directory" +end + +--- Read the whole content of the given file into memory. +-- @param filename String containing the path of the file to read +-- @return String containing the file contents or nil on error +-- @return String containing the error message on error +function readfile(filename) + local fp, err = io.open(filename) + + if fp == nil then + return nil, err + end + + local data = fp:read("*a") + fp:close() + return data +end + +--- Write the contents of given string to given file. +-- @param filename String containing the path of the file to read +-- @param data String containing the data to write +-- @return Boolean containing true on success or nil on error +-- @return String containing the error message on error +function writefile(filename, data) + local fp, err = io.open(filename, "w") + + if fp == nil then + return nil, err + end + + fp:write(data) + fp:close() + + return true +end + +--- Copies a file. +-- @param source Source file +-- @param dest Destination +-- @return Boolean containing true on success or nil on error +function copy(source, dest) + return ltn12.pump.all( + ltn12.source.file(io.open(source)), + ltn12.sink.file(io.open(dest, "w")) + ) +end + +--- Renames a file. +-- @param source Source file +-- @param dest Destination +-- @return Boolean containing true on success or nil on error +function rename(source, dest) + local stat, err, code = os.rename(source, dest) + if code == 18 then + stat, err, code = copy(source, dest) + if stat then + stat, err, code = unlink(source) + end + end + return stat, err, code +end + +--- Get the last modification time of given file path in Unix epoch format. +-- @param path String containing the path of the file or directory to read +-- @return Number containing the epoch time or nil on error +-- @return String containing the error description (if any) +-- @return Number containing the os specific errno (if any) +function mtime(path) + return posix.stat(path, "mtime") +end + +--- Set the last modification time of given file path in Unix epoch format. +-- @param path String containing the path of the file or directory to read +-- @param mtime Last modification timestamp +-- @param atime Last accessed timestamp +-- @return 0 in case of success nil on error +-- @return String containing the error description (if any) +-- @return Number containing the os specific errno (if any) +utime = posix.utime + +--- Return the last element - usually the filename - from the given path with +-- the directory component stripped. +-- @class function +-- @name basename +-- @param path String containing the path to strip +-- @return String containing the base name of given path +-- @see dirname +basename = posix.basename + +--- Return the directory component of the given path with the last element +-- stripped of. +-- @class function +-- @name dirname +-- @param path String containing the path to strip +-- @return String containing the directory component of given path +-- @see basename +dirname = posix.dirname + +--- Return a table containing all entries of the specified directory. +-- @class function +-- @name dir +-- @param path String containing the path of the directory to scan +-- @return Table containing file and directory entries or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +dir = posix.dir + +--- Create a new directory, recursively on demand. +-- @param path String with the name or path of the directory to create +-- @param recursive Create multiple directory levels (optional, default is true) +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +function mkdir(path, recursive) + if recursive then + local base = "." + + if path:sub(1,1) == "/" then + base = "" + path = path:gsub("^/+","") + end + + for elem in path:gmatch("([^/]+)/*") do + base = base .. "/" .. elem + + local stat = posix.stat( base ) + + if not stat then + local stat, errmsg, errno = posix.mkdir( base ) + + if type(stat) ~= "number" or stat ~= 0 then + return stat, errmsg, errno + end + else + if stat.type ~= "directory" then + return nil, base .. ": File exists", 17 + end + end + end + + return 0 + else + return posix.mkdir( path ) + end +end + +--- Remove the given empty directory. +-- @class function +-- @name rmdir +-- @param path String containing the path of the directory to remove +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +rmdir = posix.rmdir + +--- Get information about given file or directory. +-- @class function +-- @name stat +-- @param path String containing the path of the directory to query +-- @return Table containing file or directory properties or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +stat = posix.stat + +--- Set permissions on given file or directory. +-- @class function +-- @name chmod +-- @param path String containing the path of the directory +-- @param perm String containing the permissions to set ([ugoa][+-][rwx]) +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +chmod = posix.chmod + +--- Create a hard- or symlink from given file (or directory) to specified target +-- file (or directory) path. +-- @class function +-- @name link +-- @param path1 String containing the source path to link +-- @param path2 String containing the destination path for the link +-- @param symlink Boolean indicating wheather to create a symlink (optional) +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +link = posix.link + +--- Remove the given file. +-- @class function +-- @name unlink +-- @param path String containing the path of the file to remove +-- @return Number with the return code, 0 on sucess or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +unlink = posix.unlink + +--- Retrieve target of given symlink. +-- @class function +-- @name readlink +-- @param path String containing the path of the symlink to read +-- @return String containing the link target or nil on error +-- @return String containing the error description on error +-- @return Number containing the os specific errno on error +readlink = posix.readlink diff --git a/openwrt/packages/luci/libs/core/luasrc/init.lua b/openwrt/packages/luci/libs/core/luasrc/init.lua new file mode 100644 index 0000000..e500b71 --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/init.lua @@ -0,0 +1,34 @@ +--[[ +LuCI - Lua Configuration Interface + +Description: +Main class + +FileId: +$Id: init.lua 4079 2009-01-17 17:59:11Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local require = require + +module "luci" + +local v = require "luci.version" + +__version__ = v.luciversion or "0.9" +__appname__ = v.luciname or "LuCI" diff --git a/openwrt/packages/luci/libs/core/luasrc/ip.lua b/openwrt/packages/luci/libs/core/luasrc/ip.lua new file mode 100644 index 0000000..4e858b6 --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/ip.lua @@ -0,0 +1,632 @@ +--[[ + +LuCI ip calculation libarary +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: ip.lua 3835 2008-11-29 21:37:29Z jow $ + +]]-- + +--- LuCI IP calculation library. +module( "luci.ip", package.seeall ) + +require("bit") +require("luci.util") + +--- Boolean; true if system is little endian +LITTLE_ENDIAN = not luci.util.bigendian() + +--- Boolean; true if system is big endian +BIG_ENDIAN = not LITTLE_ENDIAN + +--- Specifier for IPv4 address family +FAMILY_INET4 = 0x04 + +--- Specifier for IPv6 address family +FAMILY_INET6 = 0x06 + + +local function __bless(x) + return setmetatable( x, { + __index = luci.ip.cidr, + __add = luci.ip.cidr.add, + __sub = luci.ip.cidr.sub, + __lt = luci.ip.cidr.lower, + __eq = luci.ip.cidr.equal, + __le = + function(...) + return luci.ip.cidr.equal(...) or luci.ip.cidr.lower(...) + end + } ) +end + +local function __array16( x, family ) + local list + + if type(x) == "number" then + list = { bit.rshift(x, 16), bit.band(x, 0xFFFF) } + + elseif type(x) == "string" then + if x:find(":") then x = IPv6(x) else x = IPv4(x) end + if x then + assert( x[1] == family, "Can't mix IPv4 and IPv6 addresses" ) + list = { unpack(x[2]) } + end + + elseif type(x) == "table" and type(x[2]) == "table" then + assert( x[1] == family, "Can't mix IPv4 and IPv6 addresses" ) + list = { unpack(x[2]) } + + elseif type(x) == "table" then + list = x + end + + assert( list, "Invalid operand" ) + + return list +end + +local function __mask16(bits) + return bit.lshift( bit.rshift( 0xFFFF, 16 - bits % 16 ), 16 - bits % 16 ) +end + +local function __not16(bits) + return bit.band( bit.bnot( __mask16(bits) ), 0xFFFF ) +end + +local function __maxlen(family) + return ( family == FAMILY_INET4 ) and 32 or 128 +end + +local function __sublen(family) + return ( family == FAMILY_INET4 ) and 30 or 127 +end + + +--- Convert given short value to network byte order on little endian hosts +-- @param x Unsigned integer value between 0x0000 and 0xFFFF +-- @return Byte-swapped value +-- @see htonl +-- @see ntohs +function htons(x) + if LITTLE_ENDIAN then + return bit.bor( + bit.rshift( x, 8 ), + bit.band( bit.lshift( x, 8 ), 0xFF00 ) + ) + else + return x + end +end + +--- Convert given long value to network byte order on little endian hosts +-- @param x Unsigned integer value between 0x00000000 and 0xFFFFFFFF +-- @return Byte-swapped value +-- @see htons +-- @see ntohl +function htonl(x) + if LITTLE_ENDIAN then + return bit.bor( + bit.lshift( htons( bit.band( x, 0xFFFF ) ), 16 ), + htons( bit.rshift( x, 16 ) ) + ) + else + return x + end +end + +--- Convert given short value to host byte order on little endian hosts +-- @class function +-- @name ntohs +-- @param x Unsigned integer value between 0x0000 and 0xFFFF +-- @return Byte-swapped value +-- @see htonl +-- @see ntohs +ntohs = htons + +--- Convert given short value to host byte order on little endian hosts +-- @class function +-- @name ntohl +-- @param x Unsigned integer value between 0x00000000 and 0xFFFFFFFF +-- @return Byte-swapped value +-- @see htons +-- @see ntohl +ntohl = htonl + + +--- Parse given IPv4 address in dotted quad or CIDR notation. If an optional +-- netmask is given as second argument and the IP address is encoded in CIDR +-- notation then the netmask parameter takes precedence. If neither a CIDR +-- encoded prefix nor a netmask parameter is given, then a prefix length of +-- 32 bit is assumed. +-- @param address IPv4 address in dotted quad or CIDR notation +-- @param netmask IPv4 netmask in dotted quad notation (optional) +-- @return luci.ip.cidr instance or nil if given address was invalid +-- @see IPv6 +-- @see Hex +function IPv4(address, netmask) + address = address or "0.0.0.0/0" + + local obj = __bless({ FAMILY_INET4 }) + + local data = {} + local prefix = address:match("/(.+)") + address = address:gsub("/.+","") + + if netmask then + prefix = obj:prefix(netmask) + elseif prefix then + prefix = tonumber(prefix) + if not prefix or prefix < 0 or prefix > 32 then return nil end + else + prefix = 32 + end + + local b1, b2, b3, b4 = address:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$") + + b1 = tonumber(b1) + b2 = tonumber(b2) + b3 = tonumber(b3) + b4 = tonumber(b4) + + if b1 and b1 <= 255 and + b2 and b2 <= 255 and + b3 and b3 <= 255 and + b4 and b4 <= 255 and + prefix + then + table.insert(obj, { b1 * 256 + b2, b3 * 256 + b4 }) + table.insert(obj, prefix) + return obj + end +end + +--- Parse given IPv6 address in full, compressed, mixed or CIDR notation. +-- If an optional netmask is given as second argument and the IP address is +-- encoded in CIDR notation then the netmask parameter takes precedence. +-- If neither a CIDR encoded prefix nor a netmask parameter is given, then a +-- prefix length of 128 bit is assumed. +-- @param address IPv6 address in full/compressed/mixed or CIDR notation +-- @param netmask IPv6 netmask in full/compressed/mixed notation (optional) +-- @return luci.ip.cidr instance or nil if given address was invalid +-- @see IPv4 +-- @see Hex +function IPv6(address, netmask) + address = address or "::/0" + + local obj = __bless({ FAMILY_INET6 }) + + local data = {} + local prefix = address:match("/(.+)") + address = address:gsub("/.+","") + + if netmask then + prefix = obj:prefix(netmask) + elseif prefix then + prefix = tonumber(prefix) + if not prefix or prefix < 0 or prefix > 128 then return nil end + else + prefix = 128 + end + + local borderl = address:sub(1, 1) == ":" and 2 or 1 + local borderh, zeroh, chunk, block + + if #address > 45 then return nil end + + repeat + borderh = address:find(":", borderl, true) + if not borderh then break end + + block = tonumber(address:sub(borderl, borderh - 1), 16) + if block and block <= 0xFFFF then + data[#data+1] = block + else + if zeroh or borderh - borderl > 1 then return nil end + zeroh = #data + 1 + end + + borderl = borderh + 1 + until #data == 7 + + chunk = address:sub(borderl) + if #chunk > 0 and #chunk <= 4 then + block = tonumber(chunk, 16) + if not block or block > 0xFFFF then return nil end + + data[#data+1] = block + elseif #chunk > 4 then + if #data == 7 or #chunk > 15 then return nil end + borderl = 1 + for i=1, 4 do + borderh = chunk:find(".", borderl, true) + if not borderh and i < 4 then return nil end + borderh = borderh and borderh - 1 + + block = tonumber(chunk:sub(borderl, borderh)) + if not block or block > 255 then return nil end + + if i == 1 or i == 3 then + data[#data+1] = block * 256 + else + data[#data] = data[#data] + block + end + + borderl = borderh and borderh + 2 + end + end + + if zeroh then + if #data == 8 then return nil end + while #data < 8 do + table.insert(data, zeroh, 0) + end + end + + if #data == 8 and prefix then + table.insert(obj, data) + table.insert(obj, prefix) + return obj + end +end + +--- Transform given hex-encoded value to luci.ip.cidr instance of specified +-- address family. +-- @param hex String containing hex encoded value +-- @param prefix Prefix length of CIDR instance (optional, default is 32/128) +-- @param family Address family, either luci.ip.FAMILY_INET4 or FAMILY_INET6 +-- @param swap Bool indicating whether to swap byteorder on low endian host +-- @return luci.ip.cidr instance or nil if given value was invalid +-- @see IPv4 +-- @see IPv6 +function Hex( hex, prefix, family, swap ) + family = ( family ~= nil ) and family or FAMILY_INET4 + swap = ( swap == nil ) and true or swap + prefix = prefix or __maxlen(family) + + local len = __maxlen(family) + local tmp = "" + local data = { } + + for i = 1, (len/4) - #hex do tmp = tmp .. '0' end + + if swap and LITTLE_ENDIAN then + for i = #hex, 1, -2 do tmp = tmp .. hex:sub( i - 1, i ) end + else + tmp = tmp .. hex + end + + hex = tmp + + for i = 1, ( len / 4 ), 4 do + local n = tonumber( hex:sub( i, i+3 ), 16 ) + if n then + data[#data+1] = n + else + return nil + end + end + + return __bless({ family, data, prefix }) +end + + +--- LuCI IP Library / CIDR instances +-- @class module +-- @cstyle instance +-- @name luci.ip.cidr +cidr = luci.util.class() + +--- Test whether the instance is a IPv4 address. +-- @return Boolean indicating a IPv4 address type +-- @see cidr.is6 +function cidr.is4( self ) + return self[1] == FAMILY_INET4 +end + +--- Test whether the instance is a IPv6 address. +-- @return Boolean indicating a IPv6 address type +-- @see cidr.is4 +function cidr.is6( self ) + return self[1] == FAMILY_INET6 +end + +--- Return a corresponding string representation of the instance. +-- If the prefix length is lower then the maximum possible prefix length for the +-- corresponding address type then the address is returned in CIDR notation, +-- otherwise the prefix will be left out. +function cidr.string( self ) + local str + if self:is4() then + str = string.format( + "%d.%d.%d.%d", + bit.rshift(self[2][1], 8), bit.band(self[2][1], 0xFF), + bit.rshift(self[2][2], 8), bit.band(self[2][2], 0xFF) + ) + if self[3] < 32 then + str = str .. "/" .. self[3] + end + elseif self:is6() then + str = string.format( "%X:%X:%X:%X:%X:%X:%X:%X", unpack(self[2]) ) + if self[3] < 128 then + str = str .. "/" .. self[3] + end + end + return str +end + +--- Test whether the value of the instance is lower then the given address. +-- This function will throw an exception if the given address has a different +-- family than this instance. +-- @param addr A luci.ip.cidr instance to compare against +-- @return Boolean indicating whether this instance is lower +-- @see cidr.higher +-- @see cidr.equal +function cidr.lower( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + for i = 1, #self[2] do + if self[2][i] ~= addr[2][i] then + return self[2][i] < addr[2][i] + end + end + return false +end + +--- Test whether the value of the instance is higher then the given address. +-- This function will throw an exception if the given address has a different +-- family than this instance. +-- @param addr A luci.ip.cidr instance to compare against +-- @return Boolean indicating whether this instance is higher +-- @see cidr.lower +-- @see cidr.equal +function cidr.higher( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + for i = 1, #self[2] do + if self[2][i] ~= addr[2][i] then + return self[2][i] > addr[2][i] + end + end + return false +end + +--- Test whether the value of the instance is equal to the given address. +-- This function will throw an exception if the given address is a different +-- family than this instance. +-- @param addr A luci.ip.cidr instance to compare against +-- @return Boolean indicating whether this instance is equal +-- @see cidr.lower +-- @see cidr.higher +function cidr.equal( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + for i = 1, #self[2] do + if self[2][i] ~= addr[2][i] then + return false + end + end + return true +end + +--- Return the prefix length of this CIDR instance. +-- @param mask Override instance prefix with given netmask (optional) +-- @return Prefix length in bit +function cidr.prefix( self, mask ) + local prefix = self[3] + + if mask then + prefix = 0 + + local stop = false + local obj = type(mask) ~= "table" + and ( self:is4() and IPv4(mask) or IPv6(mask) ) or mask + + if not obj then return nil end + + for _, word in ipairs(obj[2]) do + if word == 0xFFFF then + prefix = prefix + 16 + else + local bitmask = bit.lshift(1, 15) + while bit.band(word, bitmask) == bitmask do + prefix = prefix + 1 + bitmask = bit.lshift(1, 15 - (prefix % 16)) + end + + break + end + end + end + + return prefix +end + +--- Return a corresponding CIDR representing the network address of this +-- instance. +-- @param bits Override prefix length of this instance (optional) +-- @return CIDR instance containing the network address +-- @see cidr.host +-- @see cidr.broadcast +-- @see cidr.mask +function cidr.network( self, bits ) + local data = { } + bits = bits or self[3] + + for i = 1, math.floor( bits / 16 ) do + data[#data+1] = self[2][i] + end + + if #data < #self[2] then + data[#data+1] = bit.band( self[2][1+#data], __mask16(bits) ) + + for i = #data + 1, #self[2] do + data[#data+1] = 0 + end + end + + return __bless({ self[1], data, __maxlen(self[1]) }) +end + +--- Return a corresponding CIDR representing the host address of this +-- instance. This is intended to extract the host address from larger subnet. +-- @return CIDR instance containing the network address +-- @see cidr.network +-- @see cidr.broadcast +-- @see cidr.mask +function cidr.host( self ) + return __bless({ self[1], self[2], __maxlen(self[1]) }) +end + +--- Return a corresponding CIDR representing the netmask of this instance. +-- @param bits Override prefix length of this instance (optional) +-- @return CIDR instance containing the netmask +-- @see cidr.network +-- @see cidr.host +-- @see cidr.broadcast +function cidr.mask( self, bits ) + local data = { } + bits = bits or self[3] + + for i = 1, math.floor( bits / 16 ) do + data[#data+1] = 0xFFFF + end + + if #data < #self[2] then + data[#data+1] = __mask16(bits) + + for i = #data + 1, #self[2] do + data[#data+1] = 0 + end + end + + return __bless({ self[1], data, __maxlen(self[1]) }) +end + +--- Return CIDR containing the broadcast address of this instance. +-- @return CIDR instance containing the netmask, always nil for IPv6 +-- @see cidr.network +-- @see cidr.host +-- @see cidr.mask +function cidr.broadcast( self ) + -- IPv6 has no broadcast addresses (XXX: assert() instead?) + if self[1] == FAMILY_INET4 then + local data = { unpack(self[2]) } + local offset = math.floor( self[3] / 16 ) + 1 + + if offset <= #data then + data[offset] = bit.bor( data[offset], __not16(self[3]) ) + for i = offset + 1, #data do data[i] = 0xFFFF end + + return __bless({ self[1], data, __maxlen(self[1]) }) + end + end +end + +--- Test whether this instance fully contains the given CIDR instance. +-- @param addr CIDR instance to test against +-- @return Boolean indicating whether this instance contains the given CIDR +function cidr.contains( self, addr ) + assert( self[1] == addr[1], "Can't compare IPv4 and IPv6 addresses" ) + + if self:prefix() <= addr:prefix() then + return self:network() == addr:network(self:prefix()) + end + + return false +end + +--- Add specified amount of hosts to this instance. +-- @param amount Number of hosts to add to this instance +-- @param inplace Boolen indicating whether to alter values inplace (optional) +-- @return CIDR representing the new address or nil on overflow error +-- @see cidr.sub +function cidr.add( self, amount, inplace ) + local data = { unpack(self[2]) } + local shorts = __array16( amount, self[1] ) + + for pos = #data, 1, -1 do + local add = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0 + if ( data[pos] + add ) > 0xFFFF then + data[pos] = ( data[pos] + add ) % 0xFFFF + if pos > 1 then + data[pos-1] = data[pos-1] + ( add - data[pos] ) + else + return nil + end + else + data[pos] = data[pos] + add + end + end + + if inplace then + self[2] = data + return self + else + return __bless({ self[1], data, self[3] }) + end +end + +--- Substract specified amount of hosts from this instance. +-- @param amount Number of hosts to substract from this instance +-- @param inplace Boolen indicating whether to alter values inplace (optional) +-- @return CIDR representing the new address or nil on underflow error +-- @see cidr.add +function cidr.sub( self, amount, inplace ) + local data = { unpack(self[2]) } + local shorts = __array16( amount, self[1] ) + + for pos = #data, 1, -1 do + local sub = ( #shorts > 0 ) and table.remove( shorts, #shorts ) or 0 + if ( data[pos] - sub ) < 0 then + data[pos] = ( sub - data[pos] ) % 0xFFFF + if pos > 1 then + data[pos-1] = data[pos-1] - ( sub + data[pos] ) + else + return nil + end + else + data[pos] = data[pos] - sub + end + end + + if inplace then + self[2] = data + return self + else + return __bless({ self[1], data, self[3] }) + end +end + +--- Return CIDR containing the lowest available host address within this subnet. +-- @return CIDR containing the host address, nil if subnet is too small +-- @see cidr.maxhost +function cidr.minhost( self ) + if self[3] <= __sublen(self[1]) then + -- 1st is Network Address in IPv4 and Subnet-Router Anycast Adresse in IPv6 + return self:network():add(1, true) + end +end + +--- Return CIDR containing the highest available host address within the subnet. +-- @return CIDR containing the host address, nil if subnet is too small +-- @see cidr.minhost +function cidr.maxhost( self ) + if self[3] <= __sublen(self[1]) then + local data = { unpack(self[2]) } + local offset = math.floor( self[3] / 16 ) + 1 + + data[offset] = bit.bor( data[offset], __not16(self[3]) ) + for i = offset + 1, #data do data[i] = 0xFFFF end + data = __bless({ self[1], data, __maxlen(self[1]) }) + + -- Last address in reserved for Broadcast Address in IPv4 + if data[1] == FAMILY_INET4 then data:sub(1, true) end + + return data + end +end diff --git a/openwrt/packages/luci/libs/core/luasrc/ltn12.lua b/openwrt/packages/luci/libs/core/luasrc/ltn12.lua new file mode 100644 index 0000000..f258cef --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/ltn12.lua @@ -0,0 +1,391 @@ +--[[ +LuaSocket 2.0.2 license +Copyright � 2004-2007 Diego Nehab + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +]]-- +--[[ + Changes made by LuCI project: + * Renamed to luci.ltn12 to avoid collisions with luasocket + * Added inline documentation +]]-- +----------------------------------------------------------------------------- +-- LTN12 - Filters, sources, sinks and pumps. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- RCS ID: $Id: ltn12.lua 3246 2008-09-12 07:48:36Z Cyrus $ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Declare module +----------------------------------------------------------------------------- +local string = require("string") +local table = require("table") +local base = _G + +--- Diego Nehab's LTN12 - Filters, sources, sinks and pumps. +-- See http://lua-users.org/wiki/FiltersSourcesAndSinks for design concepts +module("luci.ltn12") + +filter = {} +source = {} +sink = {} +pump = {} + +-- 2048 seems to be better in windows... +BLOCKSIZE = 2048 +_VERSION = "LTN12 1.0.1" + +----------------------------------------------------------------------------- +-- Filter stuff +----------------------------------------------------------------------------- + +--- LTN12 Filter constructors +-- @class module +-- @name luci.ltn12.filter + +--- Return a high level filter that cycles a low-level filter +-- by passing it each chunk and updating a context between calls. +-- @param low Low-level filter +-- @param ctx Context +-- @param extra Extra argument passed to the low-level filter +-- @return LTN12 filter +function filter.cycle(low, ctx, extra) + base.assert(low) + return function(chunk) + local ret + ret, ctx = low(ctx, chunk, extra) + return ret + end +end + +--- Chain a bunch of filters together. +-- (thanks to Wim Couwenberg) +-- @param ... filters to be chained +-- @return LTN12 filter +function filter.chain(...) + local n = table.getn(arg) + local top, index = 1, 1 + local retry = "" + return function(chunk) + retry = chunk and retry + while true do + if index == top then + chunk = arg[index](chunk) + if chunk == "" or top == n then return chunk + elseif chunk then index = index + 1 + else + top = top+1 + index = top + end + else + chunk = arg[index](chunk or "") + if chunk == "" then + index = index - 1 + chunk = retry + elseif chunk then + if index == n then return chunk + else index = index + 1 end + else base.error("filter returned inappropriate nil") end + end + end + end +end + +----------------------------------------------------------------------------- +-- Source stuff +----------------------------------------------------------------------------- + +--- LTN12 Source constructors +-- @class module +-- @name luci.ltn12.source + +-- create an empty source +local function empty() + return nil +end + +--- Create an empty source. +-- @return LTN12 source +function source.empty() + return empty +end + +--- Return a source that just outputs an error. +-- @param err Error object +-- @return LTN12 source +function source.error(err) + return function() + return nil, err + end +end + +--- Create a file source. +-- @param handle File handle ready for reading +-- @param io_err IO error object +-- @return LTN12 source +function source.file(handle, io_err) + if handle then + return function() + local chunk = handle:read(BLOCKSIZE) + if not chunk then handle:close() end + return chunk + end + else return source.error(io_err or "unable to open file") end +end + +--- Turn a fancy source into a simple source. +-- @param src fancy source +-- @return LTN12 source +function source.simplify(src) + base.assert(src) + return function() + local chunk, err_or_new = src() + src = err_or_new or src + if not chunk then return nil, err_or_new + else return chunk end + end +end + +--- Create a string source. +-- @param s Data +-- @return LTN12 source +function source.string(s) + if s then + local i = 1 + return function() + local chunk = string.sub(s, i, i+BLOCKSIZE-1) + i = i + BLOCKSIZE + if chunk ~= "" then return chunk + else return nil end + end + else return source.empty() end +end + +--- Creates rewindable source. +-- @param src LTN12 source to be made rewindable +-- @return LTN12 source +function source.rewind(src) + base.assert(src) + local t = {} + return function(chunk) + if not chunk then + chunk = table.remove(t) + if not chunk then return src() + else return chunk end + else + t[#t+1] = chunk + end + end +end + +--- Chain a source and a filter together. +-- @param src LTN12 source +-- @param f LTN12 filter +-- @return LTN12 source +function source.chain(src, f) + base.assert(src and f) + local last_in, last_out = "", "" + local state = "feeding" + local err + return function() + if not last_out then + base.error('source is empty!', 2) + end + while true do + if state == "feeding" then + last_in, err = src() + if err then return nil, err end + last_out = f(last_in) + if not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + elseif last_out ~= "" then + state = "eating" + if last_in then last_in = "" end + return last_out + end + else + last_out = f(last_in) + if last_out == "" then + if last_in == "" then + state = "feeding" + else + base.error('filter returned ""') + end + elseif not last_out then + if last_in then + base.error('filter returned inappropriate nil') + else + return nil + end + else + return last_out + end + end + end + end +end + +--- Create a source that produces contents of several sources. +-- Sources will be used one after the other, as if they were concatenated +-- (thanks to Wim Couwenberg) +-- @param ... LTN12 sources +-- @return LTN12 source +function source.cat(...) + local src = table.remove(arg, 1) + return function() + while src do + local chunk, err = src() + if chunk then return chunk end + if err then return nil, err end + src = table.remove(arg, 1) + end + end +end + +----------------------------------------------------------------------------- +-- Sink stuff +----------------------------------------------------------------------------- + +--- LTN12 sink constructors +-- @class module +-- @name luci.ltn12.sink + +--- Create a sink that stores into a table. +-- @param t output table to store into +-- @return LTN12 sink +function sink.table(t) + t = t or {} + local f = function(chunk, err) + if chunk then t[#t+1] = chunk end + return 1 + end + return f, t +end + +--- Turn a fancy sink into a simple sink. +-- @param snk fancy sink +-- @return LTN12 sink +function sink.simplify(snk) + base.assert(snk) + return function(chunk, err) + local ret, err_or_new = snk(chunk, err) + if not ret then return nil, err_or_new end + snk = err_or_new or snk + return 1 + end +end + +--- Create a file sink. +-- @param handle file handle to write to +-- @param io_err IO error +-- @return LTN12 sink +function sink.file(handle, io_err) + if handle then + return function(chunk, err) + if not chunk then + handle:close() + return 1 + else return handle:write(chunk) end + end + else return sink.error(io_err or "unable to open file") end +end + +-- creates a sink that discards data +local function null() + return 1 +end + +--- Create a sink that discards data. +-- @return LTN12 sink +function sink.null() + return null +end + +--- Create a sink that just returns an error. +-- @param err Error object +-- @return LTN12 sink +function sink.error(err) + return function() + return nil, err + end +end + +--- Chain a sink with a filter. +-- @param f LTN12 filter +-- @param snk LTN12 sink +-- @return LTN12 sink +function sink.chain(f, snk) + base.assert(f and snk) + return function(chunk, err) + if chunk ~= "" then + local filtered = f(chunk) + local done = chunk and "" + while true do + local ret, snkerr = snk(filtered, err) + if not ret then return nil, snkerr end + if filtered == done then return 1 end + filtered = f(done) + end + else return 1 end + end +end + +----------------------------------------------------------------------------- +-- Pump stuff +----------------------------------------------------------------------------- + +--- LTN12 pump functions +-- @class module +-- @name luci.ltn12.pump + +--- Pump one chunk from the source to the sink. +-- @param src LTN12 source +-- @param snk LTN12 sink +-- @return Chunk of data or nil if an error occured +-- @return Error object +function pump.step(src, snk) + local chunk, src_err = src() + local ret, snk_err = snk(chunk, src_err) + if chunk and ret then return 1 + else return nil, src_err or snk_err end +end + +--- Pump all data from a source to a sink, using a step function. +-- @param src LTN12 source +-- @param snk LTN12 sink +-- @param step step function (optional) +-- @return 1 if the operation succeeded otherwise nil +-- @return Error object +function pump.all(src, snk, step) + base.assert(src and snk) + step = step or pump.step + while true do + local ret, err = step(src, snk) + if not ret then + if err then return nil, err + else return 1 end + end + end +end + diff --git a/openwrt/packages/luci/libs/core/luasrc/util.lua b/openwrt/packages/luci/libs/core/luasrc/util.lua new file mode 100644 index 0000000..5815942 --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/util.lua @@ -0,0 +1,787 @@ +--[[ +LuCI - Utility library + +Description: +Several common useful Lua functions + +FileId: +$Id: util.lua 4119 2009-01-25 13:14:29Z jow $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local io = require "io" +local math = require "math" +local table = require "table" +local debug = require "debug" +local ldebug = require "luci.debug" +local string = require "string" +local coroutine = require "coroutine" + +local getmetatable, setmetatable = getmetatable, setmetatable +local rawget, rawset, unpack = rawget, rawset, unpack +local tostring, type, assert = tostring, type, assert +local ipairs, pairs, loadstring = ipairs, pairs, loadstring +local require, pcall, xpcall = require, pcall, xpcall + +--- LuCI utility functions. +module "luci.util" + +-- +-- Pythonic string formatting extension +-- +getmetatable("").__mod = function(a, b) + if not b then + return a + elseif type(b) == "table" then + return a:format(unpack(b)) + else + return a:format(b) + end +end + + +-- +-- Class helper routines +-- + +-- Instantiates a class +local function _instantiate(class, ...) + local inst = setmetatable({}, {__index = class}) + + if inst.__init__ then + inst:__init__(...) + end + + return inst +end + +--- Create a Class object (Python-style object model). +-- The class object can be instantiated by calling itself. +-- Any class functions or shared parameters can be attached to this object. +-- Attaching a table to the class object makes this table shared between +-- all instances of this class. For object parameters use the __init__ function. +-- Classes can inherit member functions and values from a base class. +-- Class can be instantiated by calling them. All parameters will be passed +-- to the __init__ function of this class - if such a function exists. +-- The __init__ function must be used to set any object parameters that are not shared +-- with other objects of this class. Any return values will be ignored. +-- @param base The base class to inherit from (optional) +-- @return A class object +-- @see instanceof +-- @see clone +function class(base) + return setmetatable({}, { + __call = _instantiate, + __index = base + }) +end + +--- Test whether the given object is an instance of the given class. +-- @param object Object instance +-- @param class Class object to test against +-- @return Boolean indicating whether the object is an instance +-- @see class +-- @see clone +function instanceof(object, class) + local meta = getmetatable(object) + while meta and meta.__index do + if meta.__index == class then + return true + end + meta = getmetatable(meta.__index) + end + return false +end + + +-- +-- Scope manipulation routines +-- + +--- Create a new or get an already existing thread local store associated with +-- the current active coroutine. A thread local store is private a table object +-- whose values can't be accessed from outside of the running coroutine. +-- @return Table value representing the corresponding thread local store +function threadlocal() + local tbl = {} + + local function get(self, key) + local c = coroutine.running() + local thread = coxpt[c] or c or 0 + if not rawget(self, thread) then + return nil + end + return rawget(self, thread)[key] + end + + local function set(self, key, value) + local c = coroutine.running() + local thread = coxpt[c] or c or 0 + if not rawget(self, thread) then + rawset(self, thread, {}) + end + rawget(self, thread)[key] = value + end + + setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"}) + + return tbl +end + + +-- +-- Debugging routines +-- + +--- Write given object to stderr. +-- @param obj Value to write to stderr +-- @return Boolean indicating whether the write operation was successful +function perror(obj) + return io.stderr:write(tostring(obj) .. "\n") +end + +--- Recursively dumps a table to stdout, useful for testing and debugging. +-- @param t Table value to dump +-- @param maxdepth Maximum depth +-- @return Always nil +function dumptable(t, maxdepth, i, seen) + i = i or 0 + seen = seen or setmetatable({}, {__mode="k"}) + + for k,v in pairs(t) do + perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v)) + if type(v) == "table" and (not maxdepth or i < maxdepth) then + if not seen[v] then + seen[v] = true + dumptable(v, maxdepth, i+1, seen) + else + perror(string.rep("\t", i) .. "*** RECURSION ***") + end + end + end +end + + +-- +-- String and data manipulation routines +-- + +--- Escapes all occurrences of the given character in given string. +-- @param s String value containing unescaped characters +-- @param c String value with character to escape (optional, defaults to "\") +-- @return String value with each occurrence of character escaped with "\" +function escape(s, c) + c = c or "\\" + return s:gsub(c, "\\" .. c) +end + +--- Create valid XML PCDATA from given string. +-- @param value String value containing the data to escape +-- @return String value containing the escaped data +local function _pcdata_repl(c) + local i = string.byte(c) + + if ( i >= 0x00 and i <= 0x08 ) or ( i >= 0x0B and i <= 0x0C ) or + ( i >= 0x0E and i <= 0x1F ) or ( i == 0x7F ) + then + return "" + + elseif ( i == 0x26 ) or ( i == 0x27 ) or ( i == 0x22 ) or + ( i == 0x3C ) or ( i == 0x3E ) + then + return string.format("&#%i;", i) + end + + return c +end + +function pcdata(value) + return value and tostring(value):gsub("[&\"'<>%c]", _pcdata_repl) +end + +--- Strip HTML tags from given string. +-- @param value String containing the HTML text +-- @return String with HTML tags stripped of +function striptags(s) + return pcdata(s:gsub("]*>", " "):gsub("%s+", " ")) +end + +--- Splits given string on a defined separator sequence and return a table +-- containing the resulting substrings. The optional max parameter specifies +-- the number of bytes to process, regardless of the actual length of the given +-- string. The optional last parameter, regex, specifies whether the separator +-- sequence is interpreted as regular expression. +-- @param str String value containing the data to split up +-- @param pat String with separator pattern (optional, defaults to "\n") +-- @param max Maximum times to split (optional) +-- @param regex Boolean indicating whether to interpret the separator +-- pattern as regular expression (optional, default is false) +-- @return Table containing the resulting substrings +function split(str, pat, max, regex) + pat = pat or "\n" + max = max or #str + + local t = {} + local c = 1 + + if #str == 0 then + return {""} + end + + if #pat == 0 then + return nil + end + + if max == 0 then + return str + end + + repeat + local s, e = str:find(pat, c, not regex) + max = max - 1 + if s and max < 0 then + t[#t+1] = str:sub(c) + else + t[#t+1] = str:sub(c, s and s - 1) + end + c = e and e + 1 or #str + 1 + until not s or max < 0 + + return t +end + +--- Remove leading and trailing whitespace from given string value. +-- @param str String value containing whitespace padded data +-- @return String value with leading and trailing space removed +function trim(str) + return (str:gsub("^%s*(.-)%s*$", "%1")) +end + +--- Count the occurences of given substring in given string. +-- @param str String to search in +-- @param pattern String containing pattern to find +-- @return Number of found occurences +function cmatch(str, pat) + local count = 0 + for _ in str:gmatch(pat) do count = count + 1 end + return count +end + +--- Parse certain units from the given string and return the canonical integer +-- value or 0 if the unit is unknown. Upper- or lower case is irrelevant. +-- Recognized units are: +-- o "y" - one year (60*60*24*366) +-- o "m" - one month (60*60*24*31) +-- o "w" - one week (60*60*24*7) +-- o "d" - one day (60*60*24) +-- o "h" - one hour (60*60) +-- o "min" - one minute (60) +-- o "kb" - one kilobyte (1024) +-- o "mb" - one megabyte (1024*1024) +-- o "gb" - one gigabyte (1024*1024*1024) +-- o "kib" - one si kilobyte (1000) +-- o "mib" - one si megabyte (1000*1000) +-- o "gib" - one si gigabyte (1000*1000*1000) +-- @param ustr String containing a numerical value with trailing unit +-- @return Number containing the canonical value +function parse_units(ustr) + + local val = 0 + + -- unit map + local map = { + -- date stuff + y = 60 * 60 * 24 * 366, + m = 60 * 60 * 24 * 31, + w = 60 * 60 * 24 * 7, + d = 60 * 60 * 24, + h = 60 * 60, + min = 60, + + -- storage sizes + kb = 1024, + mb = 1024 * 1024, + gb = 1024 * 1024 * 1024, + + -- storage sizes (si) + kib = 1000, + mib = 1000 * 1000, + gib = 1000 * 1000 * 1000 + } + + -- parse input string + for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do + + local num = spec:gsub("[^0-9%.]+$","") + local spn = spec:gsub("^[0-9%.]+", "") + + if map[spn] or map[spn:sub(1,1)] then + val = val + num * ( map[spn] or map[spn:sub(1,1)] ) + else + val = val + num + end + end + + + return val +end + +-- also register functions above in the central string class for convenience +string.escape = escape +string.pcdata = pcdata +string.striptags = striptags +string.split = split +string.trim = trim +string.cmatch = cmatch +string.parse_units = parse_units + + +--- Appends numerically indexed tables or single objects to a given table. +-- @param src Target table +-- @param ... Objects to insert +-- @return Target table +function append(src, ...) + for i, a in ipairs({...}) do + if type(a) == "table" then + for j, v in ipairs(a) do + src[#src+1] = v + end + else + src[#src+1] = a + end + end + return src +end + +--- Combines two or more numerically indexed tables and single objects into one table. +-- @param tbl1 Table value to combine +-- @param tbl2 Table value to combine +-- @param ... More tables to combine +-- @return Table value containing all values of given tables +function combine(...) + return append({}, ...) +end + +--- Checks whether the given table contains the given value. +-- @param table Table value +-- @param value Value to search within the given table +-- @return Boolean indicating whether the given value occurs within table +function contains(table, value) + for k, v in pairs(table) do + if value == v then + return k + end + end + return false +end + +--- Update values in given table with the values from the second given table. +-- Both table are - in fact - merged together. +-- @param t Table which should be updated +-- @param updates Table containing the values to update +-- @return Always nil +function update(t, updates) + for k, v in pairs(updates) do + t[k] = v + end +end + +--- Retrieve all keys of given associative table. +-- @param t Table to extract keys from +-- @return Sorted table containing the keys +function keys(t) + local keys = { } + if t then + for k, _ in kspairs(t) do + keys[#keys+1] = k + end + end + return keys +end + +--- Clones the given object and return it's copy. +-- @param object Table value to clone +-- @param deep Boolean indicating whether to do recursive cloning +-- @return Cloned table value +function clone(object, deep) + local copy = {} + + for k, v in pairs(object) do + if deep and type(v) == "table" then + v = clone(v, deep) + end + copy[k] = v + end + + return setmetatable(copy, getmetatable(object)) +end + + +--- Create a dynamic table which automatically creates subtables. +-- @return Dynamic Table +function dtable() + return setmetatable({}, { __index = + function(tbl, key) + return rawget(tbl, key) + or rawget(rawset(tbl, key, dtable()), key) + end + }) +end + + +-- Serialize the contents of a table value. +function _serialize_table(t, seen) + assert(not seen[t], "Recursion detected.") + seen[t] = true + + local data = "" + local idata = "" + local ilen = 0 + + for k, v in pairs(t) do + if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then + k = serialize_data(k, seen) + v = serialize_data(v, seen) + data = data .. ( #data > 0 and ", " or "" ) .. + '[' .. k .. '] = ' .. v + elseif k > ilen then + ilen = k + end + end + + for i = 1, ilen do + local v = serialize_data(t[i], seen) + idata = idata .. ( #idata > 0 and ", " or "" ) .. v + end + + return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data +end + +--- Recursively serialize given data to lua code, suitable for restoring +-- with loadstring(). +-- @param val Value containing the data to serialize +-- @return String value containing the serialized code +-- @see restore_data +-- @see get_bytecode +function serialize_data(val, seen) + seen = seen or setmetatable({}, {__mode="k"}) + + if val == nil then + return "nil" + elseif type(val) == "number" then + return val + elseif type(val) == "string" then + return "%q" % val + elseif type(val) == "boolean" then + return val and "true" or "false" + elseif type(val) == "function" then + return "loadstring(%q)" % get_bytecode(val) + elseif type(val) == "table" then + return "{ " .. _serialize_table(val, seen) .. " }" + else + return '"[unhandled data type:' .. type(val) .. ']"' + end +end + +--- Restore data previously serialized with serialize_data(). +-- @param str String containing the data to restore +-- @return Value containing the restored data structure +-- @see serialize_data +-- @see get_bytecode +function restore_data(str) + return loadstring("return " .. str)() +end + + +-- +-- Byte code manipulation routines +-- + +--- Return the current runtime bytecode of the given data. The byte code +-- will be stripped before it is returned. +-- @param val Value to return as bytecode +-- @return String value containing the bytecode of the given data +function get_bytecode(val) + local code + + if type(val) == "function" then + code = string.dump(val) + else + code = string.dump( loadstring( "return " .. serialize_data(val) ) ) + end + + return code and strip_bytecode(code) +end + +--- Strips unnescessary lua bytecode from given string. Information like line +-- numbers and debugging numbers will be discarded. Original version by +-- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) +-- @param code String value containing the original lua byte code +-- @return String value containing the stripped lua byte code +function strip_bytecode(code) + local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12) + local subint + if endian == 1 then + subint = function(code, i, l) + local val = 0 + for n = l, 1, -1 do + val = val * 256 + code:byte(i + n - 1) + end + return val, i + l + end + else + subint = function(code, i, l) + local val = 0 + for n = 1, l, 1 do + val = val * 256 + code:byte(i + n - 1) + end + return val, i + l + end + end + + local strip_function + strip_function = function(code) + local count, offset = subint(code, 1, size) + local stripped, dirty = string.rep("\0", size), offset + count + offset = offset + count + int * 2 + 4 + offset = offset + int + subint(code, offset, int) * ins + count, offset = subint(code, offset, int) + for n = 1, count do + local t + t, offset = subint(code, offset, 1) + if t == 1 then + offset = offset + 1 + elseif t == 4 then + offset = offset + size + subint(code, offset, size) + elseif t == 3 then + offset = offset + num + elseif t == 254 or t == 9 then + offset = offset + lnum + end + end + count, offset = subint(code, offset, int) + stripped = stripped .. code:sub(dirty, offset - 1) + for n = 1, count do + local proto, off = strip_function(code:sub(offset, -1)) + stripped, offset = stripped .. proto, offset + off - 1 + end + offset = offset + subint(code, offset, int) * int + int + count, offset = subint(code, offset, int) + for n = 1, count do + offset = offset + subint(code, offset, size) + size + int * 2 + end + count, offset = subint(code, offset, int) + for n = 1, count do + offset = offset + subint(code, offset, size) + size + end + stripped = stripped .. string.rep("\0", int * 3) + return stripped, offset + end + + return code:sub(1,12) .. strip_function(code:sub(13,-1)) +end + + +-- +-- Sorting iterator functions +-- + +function _sortiter( t, f ) + local keys = { } + + for k, v in pairs(t) do + keys[#keys+1] = k + end + + local _pos = 0 + + table.sort( keys, f ) + + return function() + _pos = _pos + 1 + if _pos <= #keys then + return keys[_pos], t[keys[_pos]] + end + end +end + +--- Return a key, value iterator which returns the values sorted according to +-- the provided callback function. +-- @param t The table to iterate +-- @param f A callback function to decide the order of elements +-- @return Function value containing the corresponding iterator +function spairs(t,f) + return _sortiter( t, f ) +end + +--- Return a key, value iterator for the given table. +-- The table pairs are sorted by key. +-- @param t The table to iterate +-- @return Function value containing the corresponding iterator +function kspairs(t) + return _sortiter( t ) +end + +--- Return a key, value iterator for the given table. +-- The table pairs are sorted by value. +-- @param t The table to iterate +-- @return Function value containing the corresponding iterator +function vspairs(t) + return _sortiter( t, function (a,b) return t[a] < t[b] end ) +end + + +-- +-- System utility functions +-- + +--- Test whether the current system is operating in big endian mode. +-- @return Boolean value indicating whether system is big endian +function bigendian() + return string.byte(string.dump(function() end), 7) == 0 +end + +--- Execute given commandline and gather stdout. +-- @param command String containing command to execute +-- @return String containing the command's stdout +function exec(command) + local pp = io.popen(command) + local data = pp:read("*a") + pp:close() + + return data +end + +--- Return a line-buffered iterator over the output of given command. +-- @param command String containing the command to execute +-- @return Iterator +function execi(command) + local pp = io.popen(command) + + return pp and function() + local line = pp:read() + + if not line then + pp:close() + end + + return line + end +end + +-- Deprecated +function execl(command) + local pp = io.popen(command) + local line = "" + local data = {} + + while true do + line = pp:read() + if (line == nil) then break end + data[#data+1] = line + end + pp:close() + + return data +end + +--- Returns the absolute path to LuCI base directory. +-- @return String containing the directory path +function libpath() + return require "luci.fs".dirname(ldebug.__file__) +end + + +-- +-- Coroutine safe xpcall and pcall versions modified for Luci +-- original version: +-- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org) +-- +-- Copyright © 2005 Kepler Project. +-- Permission is hereby granted, free of charge, to any person obtaining a +-- copy of this software and associated documentation files (the "Software"), +-- to deal in the Software without restriction, including without limitation +-- the rights to use, copy, modify, merge, publish, distribute, sublicense, +-- and/or sell copies of the Software, and to permit persons to whom the +-- Software is furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be +-- included in all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +-- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +-- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +local performResume, handleReturnValue +local oldpcall, oldxpcall = pcall, xpcall +coxpt = {} +setmetatable(coxpt, {__mode = "kv"}) + +-- Identity function for copcall +local function copcall_id(trace, ...) + return ... +end + +--- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function +-- @param f Lua function to be called protected +-- @param err Custom error handler +-- @param ... Parameters passed to the function +-- @return A boolean whether the function call succeeded and the return +-- values of either the function or the error handler +function coxpcall(f, err, ...) + local res, co = oldpcall(coroutine.create, f) + if not res then + local params = {...} + local newf = function() return f(unpack(params)) end + co = coroutine.create(newf) + end + local c = coroutine.running() + coxpt[co] = coxpt[c] or c or 0 + + return performResume(err, co, ...) +end + +--- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function +-- @param f Lua function to be called protected +-- @param ... Parameters passed to the function +-- @return A boolean whether the function call succeeded and the returns +-- values of the function or the error object +function copcall(f, ...) + return coxpcall(f, copcall_id, ...) +end + +-- Handle return value of protected call +function handleReturnValue(err, co, status, ...) + if not status then + return false, err(debug.traceback(co, (...)), ...) + end + if coroutine.status(co) == 'suspended' then + return performResume(err, co, coroutine.yield(...)) + else + return true, ... + end +end + +-- Resume execution of protected function call +function performResume(err, co, ...) + return handleReturnValue(err, co, coroutine.resume(co, ...)) +end diff --git a/openwrt/packages/luci/libs/core/luasrc/version.lua b/openwrt/packages/luci/libs/core/luasrc/version.lua new file mode 100644 index 0000000..9e5cb71 --- /dev/null +++ b/openwrt/packages/luci/libs/core/luasrc/version.lua @@ -0,0 +1,12 @@ +--[[ +LuCI - Lua Configuration Interface +Version definition - do not edit this file +]]-- + +module "luci.version" + +distname = "Host System" +distversion = "SDK" + +luciname = "LuCI" +luciversion = "SVN" diff --git a/openwrt/packages/luci/libs/fastindex/Makefile b/openwrt/packages/luci/libs/fastindex/Makefile new file mode 100644 index 0000000..ee1a40e --- /dev/null +++ b/openwrt/packages/luci/libs/fastindex/Makefile @@ -0,0 +1,13 @@ +include ../../build/module.mk +include ../../build/config.mk +include ../../build/gccconfig.mk + +%.o: %.c + $(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $< + +compile: src/fastindex.o + mkdir -p dist$(LUCI_LIBRARYDIR) + $(LINK) $(SHLIB_FLAGS) -o dist$(LUCI_LIBRARYDIR)/fastindex.so src/fastindex.o $(LUA_SHLIBS) + +clean: + rm -f src/*.o diff --git a/openwrt/packages/luci/libs/fastindex/src/fastindex.c b/openwrt/packages/luci/libs/fastindex/src/fastindex.c new file mode 100644 index 0000000..c9c64bf --- /dev/null +++ b/openwrt/packages/luci/libs/fastindex/src/fastindex.c @@ -0,0 +1,379 @@ +/* + * fastindex - fast lua module indexing plugin + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE /* XXX: portability hack for timestamp */ +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "list.h" + +#define MODNAME "luci.fastindex" +#define DEFAULT_BUFLEN 1024 + +//#define DEBUG 1 + +#ifdef DEBUG +#define DPRINTF(...) fprintf(stderr, __VA_ARGS__) +#else +#define DPRINTF(...) do {} while (0) +#endif + +/** + * list_for_each_offset - iterate over a list, start with the provided pointer + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_offset(pos, head, offset) \ + for (pos = (offset)->next; pos != (offset); \ + pos = ((pos->next == (head)) && ((offset) != (head)) ? (head)->next : pos->next)) + +static char *namespace = NULL; + +struct fastindex_entry { + struct list_head list; + time_t timestamp; + int checked; + char *name; +}; + +struct fastindex_pattern { + struct list_head list; + char pattern[]; +}; + +struct fastindex { + lua_State *L; + int checked; + char *func; + struct list_head patterns; + struct list_head *last; + struct list_head entries; + int ofs; + char *buf; + int buflen; +}; + +static inline struct fastindex * +to_fastindex(struct lua_State *L) +{ + struct fastindex *f; + lua_getfield(L, lua_upvalueindex(1), "__data"); + f = lua_touserdata(L, -1); + lua_pop(L, 1); + return f; +} + +static int +fastindex_module(lua_State *L) +{ + const char *s; + s = luaL_checkstring(L, 1); + + if (s) { + if (namespace) + free(namespace); + namespace = strdup(s); + } + + return 0; +} + +static struct fastindex_entry * +find_entry(struct fastindex *f, char *name) +{ + struct list_head *p; + + if (!f->last) + f->last = &f->entries; + + list_for_each_offset(p, &f->entries, f->last) { + struct fastindex_entry *e; + e = container_of(p, struct fastindex_entry, list); + if (!strcmp(e->name, name)) + return e; + } + return NULL; +} + +static struct fastindex_entry * +new_entry(struct fastindex *f, char *name) +{ + struct fastindex_entry *e; + + e = malloc(sizeof(struct fastindex_entry)); + if (!e) + goto error; + + memset(e, 0, sizeof(struct fastindex_entry)); + e->name = strdup(name); + if (!e->name) { + free(e); + goto error; + } + INIT_LIST_HEAD(&e->list); + + return e; + +error: + return NULL; +} + +static void free_entry(struct fastindex_entry *e) +{ + list_del(&e->list); + free(e->name); + free(e); +} + +int bufferwriter(lua_State *L, const void *p, size_t sz, void *ud) +{ + struct fastindex *f = ud; + + while (f->ofs + sz > f->buflen) { + char *b = f->buf; + f->buflen *= 2; + f->buf = realloc(f->buf, f->buflen); + if (!f->buf) { + free(b); + return 1; + } + } + memcpy(f->buf + f->ofs, p, sz); + f->ofs += sz; + return 0; +} + +static void +load_index(struct fastindex *f, struct fastindex_entry *e) +{ + lua_State *L; + + DPRINTF("Loading module: %s\n", e->name); + + if (!f->buf) + f->buf = malloc(f->buflen); + + if (!f->buf) + luaL_error(f->L, "Out of memory!\n"); + + f->ofs = 0; + L = luaL_newstate(); + if (!L) + return; + + namespace = NULL; + luaL_openlibs(L); + lua_pushcfunction(L, fastindex_module); + lua_setfield(L, LUA_GLOBALSINDEX, "module"); + + do { + if (luaL_dofile(L, e->name)) { + DPRINTF("Warning: unable to open module '%s'\n", e->name); + break; + } + + lua_getglobal(L, f->func); + lua_dump(L, bufferwriter, f); + DPRINTF("Got %d bytes\n", f->ofs); + if (f->ofs == 0) + break; + lua_createtable(f->L, (namespace ? 2 : 1), 0); + luaL_loadbuffer(f->L, f->buf, f->ofs, "tmp"); + lua_rawseti(f->L, -2, 1); + if (namespace) { + DPRINTF("Module has namespace '%s'\n", namespace); + lua_pushstring(f->L, namespace); + lua_rawseti(f->L, -2, 2); + free(namespace); + namespace = NULL; + } + lua_setfield(f->L, -2, e->name); + } while (0); + + lua_close(L); +} + + +static int +fastindex_scan(lua_State *L) +{ + struct list_head *tmp, *p; + struct fastindex *f; + glob_t gl; + int i; + int gl_flags = GLOB_NOESCAPE | GLOB_NOSORT | GLOB_MARK; + + f = to_fastindex(L); + f->checked++; + + + if (list_empty(&f->patterns)) + return 0; + + lua_getfield(L, lua_upvalueindex(1), "indexes"); + list_for_each(p, &f->patterns) { + struct fastindex_pattern *pt = container_of(p, struct fastindex_pattern, list); + glob(pt->pattern, gl_flags, NULL, &gl); + gl_flags |= GLOB_APPEND; + } + for (i = 0; i < gl.gl_pathc; i++) { + struct fastindex_entry *e; + struct stat st; + + if (stat(gl.gl_pathv[i], &st)) + continue; + + if ((st.st_mode & S_IFMT) != S_IFREG) + continue; + + e = find_entry(f, gl.gl_pathv[i]); + if (!e) { + e = new_entry(f, gl.gl_pathv[i]); + list_add_tail(&e->list, &f->entries); + } + + e->checked = f->checked; + if ((e->timestamp < st.st_mtime)) { + load_index(f, e); + e->timestamp = st.st_mtime; + } + } + globfree(&gl); + list_for_each_safe(p, tmp, &f->entries) { + struct fastindex_entry *e = container_of(p, struct fastindex_entry, list); + if (e->checked < f->checked) { + lua_pushnil(f->L); + lua_setfield(f->L, -2, e->name); + free_entry(e); + } + } + lua_pop(L, 1); + + return 0; +} + +static int +fastindex_free(lua_State *L) +{ + struct fastindex *f; + struct list_head *p, *tmp; + + f = lua_touserdata(L, -1); + list_for_each_safe(p, tmp, &f->patterns) { + struct fastindex_pattern *pt; + pt = container_of(p, struct fastindex_pattern, list); + list_del(p); + free(pt); + } + list_for_each_safe(p, tmp, &f->entries) { + struct fastindex_entry *e; + e = container_of(p, struct fastindex_entry, list); + free_entry(e); + } + return 0; +} + +static int +fastindex_add(lua_State *L) +{ + struct fastindex_pattern *pt; + struct fastindex *f; + const char *str; + + f = to_fastindex(L); + str = luaL_checkstring(L, 1); + if (!str) + luaL_error(L, "Invalid argument"); + + pt = malloc(sizeof(struct fastindex_pattern) + strlen(str) + 1); + if (!pt) + luaL_error(L, "Out of memory"); + + INIT_LIST_HEAD(&pt->list); + strcpy(pt->pattern, str); + list_add(&pt->list, &f->patterns); + + return 0; +} + +static const luaL_Reg fastindex_m[] = { + { "add", fastindex_add }, + { "scan", fastindex_scan }, + { NULL, NULL } +}; + +static int +fastindex_new(lua_State *L) +{ + struct fastindex *f; + const char *func; + + func = luaL_checkstring(L, 1); + + f = lua_newuserdata(L, sizeof(struct fastindex)); + lua_createtable(L, 0, 2); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, fastindex_free); + lua_setfield(L, -2, "__gc"); + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); + lua_pushvalue(L, -2); + lua_setfield(L, -2, "__data"); + lua_createtable(L, 0, 1); + lua_setfield(L, -2, "indexes"); + lua_pushvalue(L, -2); + luaI_openlib(L, NULL, fastindex_m, 1); + + memset(f, 0, sizeof(struct fastindex)); + f->L = L; + f->buflen = DEFAULT_BUFLEN; + INIT_LIST_HEAD(&f->entries); + INIT_LIST_HEAD(&f->patterns); + + f->func = strdup(func); + if (!f->func) { + if (f->func) + free(f->func); + luaL_error(L, "Out of memory\n"); + } + + return 1; +} + +static const luaL_Reg fastindex[] = { + { "new", fastindex_new }, + { NULL, NULL }, +}; + +int +luaopen_luci_fastindex(lua_State *L) +{ + luaL_register(L, MODNAME, fastindex); + return 0; +} diff --git a/openwrt/packages/luci/libs/fastindex/src/list.h b/openwrt/packages/luci/libs/fastindex/src/list.h new file mode 100644 index 0000000..2959a06 --- /dev/null +++ b/openwrt/packages/luci/libs/fastindex/src/list.h @@ -0,0 +1,601 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#include +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#ifndef container_of +#define container_of(ptr, type, member) ( \ + (type *)( (char *)ptr - offsetof(type,member) )) +#endif + + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = NULL; + entry->prev = NULL; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = NULL; + n->pprev = NULL; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos; pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after current point + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from current point + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +#endif diff --git a/openwrt/packages/luci/libs/http/Makefile b/openwrt/packages/luci/libs/http/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/http/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/http/luasrc/http/protocol.lua b/openwrt/packages/luci/libs/http/luasrc/http/protocol.lua new file mode 100644 index 0000000..ba365d2 --- /dev/null +++ b/openwrt/packages/luci/libs/http/luasrc/http/protocol.lua @@ -0,0 +1,690 @@ +--[[ + +HTTP protocol implementation for LuCI +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: protocol.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +--- LuCI http protocol class. +-- This class contains several functions useful for http message- and content +-- decoding and to retrive form data from raw http messages. +module("luci.http.protocol", package.seeall) + +local ltn12 = require("luci.ltn12") + +HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size + +--- Decode an urlencoded string - optionally without decoding +-- the "+" sign to " " - and return the decoded string. +-- @param str Input string in x-www-urlencoded format +-- @param no_plus Don't decode "+" signs to spaces +-- @return The decoded string +-- @see urlencode +function urldecode( str, no_plus ) + + local function __chrdec( hex ) + return string.char( tonumber( hex, 16 ) ) + end + + if type(str) == "string" then + if not no_plus then + str = str:gsub( "+", " " ) + end + + str = str:gsub( "%%([a-fA-F0-9][a-fA-F0-9])", __chrdec ) + end + + return str +end + +--- Extract and split urlencoded data pairs, separated bei either "&" or ";" +-- from given url or string. Returns a table with urldecoded values. +-- Simple parameters are stored as string values associated with the parameter +-- name within the table. Parameters with multiple values are stored as array +-- containing the corresponding values. +-- @param url The url or string which contains x-www-urlencoded form data +-- @param tbl Use the given table for storing values (optional) +-- @return Table containing the urldecoded parameters +-- @see urlencode_params +function urldecode_params( url, tbl ) + + local params = tbl or { } + + if url:find("?") then + url = url:gsub( "^.+%?([^?]+)", "%1" ) + end + + for pair in url:gmatch( "[^&;]+" ) do + + -- find key and value + local key = urldecode( pair:match("^([^=]+)") ) + local val = urldecode( pair:match("^[^=]+=(.+)$") ) + + -- store + if type(key) == "string" and key:len() > 0 then + if type(val) ~= "string" then val = "" end + + if not params[key] then + params[key] = val + elseif type(params[key]) ~= "table" then + params[key] = { params[key], val } + else + table.insert( params[key], val ) + end + end + end + + return params +end + +--- Encode given string to x-www-urlencoded format. +-- @param str String to encode +-- @return String containing the encoded data +-- @see urldecode +function urlencode( str ) + + local function __chrenc( chr ) + return string.format( + "%%%02x", string.byte( chr ) + ) + end + + if type(str) == "string" then + str = str:gsub( + "([^a-zA-Z0-9$_%-%.%+!*'(),])", + __chrenc + ) + end + + return str +end + +--- Encode each key-value-pair in given table to x-www-urlencoded format, +-- separated by "&". Tables are encoded as parameters with multiple values by +-- repeating the parameter name with each value. +-- @param tbl Table with the values +-- @return String containing encoded values +-- @see urldecode_params +function urlencode_params( tbl ) + local enc = "" + + for k, v in pairs(tbl) do + if type(v) == "table" then + for i, v2 in ipairs(v) do + enc = enc .. ( #enc > 0 and "&" or "" ) .. + urlencode(k) .. "=" .. urlencode(v2) + end + else + enc = enc .. ( #enc > 0 and "&" or "" ) .. + urlencode(k) .. "=" .. urlencode(v) + end + end + + return enc +end + +-- (Internal function) +-- Initialize given parameter and coerce string into table when the parameter +-- already exists. +-- @param tbl Table where parameter should be created +-- @param key Parameter name +-- @return Always nil +local function __initval( tbl, key ) + if tbl[key] == nil then + tbl[key] = "" + elseif type(tbl[key]) == "string" then + tbl[key] = { tbl[key], "" } + else + table.insert( tbl[key], "" ) + end +end + +-- (Internal function) +-- Append given data to given parameter, either by extending the string value +-- or by appending it to the last string in the parameter's value table. +-- @param tbl Table containing the previously initialized parameter value +-- @param key Parameter name +-- @param chunk String containing the data to append +-- @return Always nil +-- @see __initval +local function __appendval( tbl, key, chunk ) + if type(tbl[key]) == "table" then + tbl[key][#tbl[key]] = tbl[key][#tbl[key]] .. chunk + else + tbl[key] = tbl[key] .. chunk + end +end + +-- (Internal function) +-- Finish the value of given parameter, either by transforming the string value +-- or - in the case of multi value parameters - the last element in the +-- associated values table. +-- @param tbl Table containing the previously initialized parameter value +-- @param key Parameter name +-- @param handler Function which transforms the parameter value +-- @return Always nil +-- @see __initval +-- @see __appendval +local function __finishval( tbl, key, handler ) + if handler then + if type(tbl[key]) == "table" then + tbl[key][#tbl[key]] = handler( tbl[key][#tbl[key]] ) + else + tbl[key] = handler( tbl[key] ) + end + end +end + + +-- Table of our process states +local process_states = { } + +-- Extract "magic", the first line of a http message. +-- Extracts the message type ("get", "post" or "response"), the requested uri +-- or the status code if the line descripes a http response. +process_states['magic'] = function( msg, chunk, err ) + + if chunk ~= nil then + -- ignore empty lines before request + if #chunk == 0 then + return true, nil + end + + -- Is it a request? + local method, uri, http_ver = chunk:match("^([A-Z]+) ([^ ]+) HTTP/([01]%.[019])$") + + -- Yup, it is + if method then + + msg.type = "request" + msg.request_method = method:lower() + msg.request_uri = uri + msg.http_version = tonumber( http_ver ) + msg.headers = { } + + -- We're done, next state is header parsing + return true, function( chunk ) + return process_states['headers']( msg, chunk ) + end + + -- Is it a response? + else + + local http_ver, code, message = chunk:match("^HTTP/([01]%.[019]) ([0-9]+) ([^\r\n]+)$") + + -- Is a response + if code then + + msg.type = "response" + msg.status_code = code + msg.status_message = message + msg.http_version = tonumber( http_ver ) + msg.headers = { } + + -- We're done, next state is header parsing + return true, function( chunk ) + return process_states['headers']( msg, chunk ) + end + end + end + end + + -- Can't handle it + return nil, "Invalid HTTP message magic" +end + + +-- Extract headers from given string. +process_states['headers'] = function( msg, chunk ) + + if chunk ~= nil then + + -- Look for a valid header format + local hdr, val = chunk:match( "^([A-Za-z][A-Za-z0-9%-_]+): +(.+)$" ) + + if type(hdr) == "string" and hdr:len() > 0 and + type(val) == "string" and val:len() > 0 + then + msg.headers[hdr] = val + + -- Valid header line, proceed + return true, nil + + elseif #chunk == 0 then + -- Empty line, we won't accept data anymore + return false, nil + else + -- Junk data + return nil, "Invalid HTTP header received" + end + else + return nil, "Unexpected EOF" + end +end + + +--- Creates a ltn12 source from the given socket. The source will return it's +-- data line by line with the trailing \r\n stripped of. +-- @param sock Readable network socket +-- @return Ltn12 source function +function header_source( sock ) + return ltn12.source.simplify( function() + + local chunk, err, part = sock:receive("*l") + + -- Line too long + if chunk == nil then + if err ~= "timeout" then + return nil, part + and "Line exceeds maximum allowed length" + or "Unexpected EOF" + else + return nil, err + end + + -- Line ok + elseif chunk ~= nil then + + -- Strip trailing CR + chunk = chunk:gsub("\r$","") + + return chunk, nil + end + end ) +end + +--- Decode a mime encoded http message body with multipart/form-data +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table withing the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +-- If an optional file callback function is given then it is feeded with the +-- file contents chunk by chunk and only the extracted file name is stored +-- within the params table. The callback function will be called subsequently +-- with three arguments: +-- o Table containing decoded (name, file) and raw (headers) mime header data +-- o String value containing a chunk of the file data +-- o Boolean which indicates wheather the current chunk is the last one (eof) +-- @param src Ltn12 source function +-- @param msg HTTP message object +-- @param filecb File callback function (optional) +-- @return Value indicating successful operation (not nil means "ok") +-- @return String containing the error if unsuccessful +-- @see parse_message_header +function mimedecode_message_body( src, msg, filecb ) + + if msg and msg.env.CONTENT_TYPE then + msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$") + end + + if not msg.mime_boundary then + return nil, "Invalid Content-Type found" + end + + + local tlen = 0 + local inhdr = false + local field = nil + local store = nil + local lchunk = nil + + local function parse_headers( chunk, field ) + + local stat + repeat + chunk, stat = chunk:gsub( + "^([A-Z][A-Za-z0-9%-_]+): +([^\r\n]+)\r\n", + function(k,v) + field.headers[k] = v + return "" + end + ) + until stat == 0 + + chunk, stat = chunk:gsub("^\r\n","") + + -- End of headers + if stat > 0 then + if field.headers["Content-Disposition"] then + if field.headers["Content-Disposition"]:match("^form%-data; ") then + field.name = field.headers["Content-Disposition"]:match('name="(.-)"') + field.file = field.headers["Content-Disposition"]:match('filename="(.+)"$') + end + end + + if not field.headers["Content-Type"] then + field.headers["Content-Type"] = "text/plain" + end + + if field.name and field.file and filecb then + __initval( msg.params, field.name ) + __appendval( msg.params, field.name, field.file ) + + store = filecb + elseif field.name then + __initval( msg.params, field.name ) + + store = function( hdr, buf, eof ) + __appendval( msg.params, field.name, buf ) + end + else + store = nil + end + + return chunk, true + end + + return chunk, false + end + + local function snk( chunk ) + + tlen = tlen + ( chunk and #chunk or 0 ) + + if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then + return nil, "Message body size exceeds Content-Length" + end + + if chunk and not lchunk then + lchunk = "\r\n" .. chunk + + elseif lchunk then + local data = lchunk .. ( chunk or "" ) + local spos, epos, found + + repeat + spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "\r\n", 1, true ) + + if not spos then + spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true ) + end + + + if spos then + local predata = data:sub( 1, spos - 1 ) + + if inhdr then + predata, eof = parse_headers( predata, field ) + + if not eof then + return nil, "Invalid MIME section header" + elseif not field.name then + return nil, "Invalid Content-Disposition header" + end + end + + if store then + store( field, predata, true ) + end + + + field = { headers = { } } + found = found or true + + data, eof = parse_headers( data:sub( epos + 1, #data ), field ) + inhdr = not eof + end + until not spos + + if found then + if #data > 78 then + lchunk = data:sub( #data - 78 + 1, #data ) + data = data:sub( 1, #data - 78 ) + + if store then + store( field, data, false ) + else + return nil, "Invalid MIME section header" + end + else + lchunk, data = data, nil + end + else + if inhdr then + lchunk, eof = parse_headers( data, field ) + inhdr = not eof + else + store( field, lchunk, false ) + lchunk, chunk = chunk, nil + end + end + end + + return true + end + + return ltn12.pump.all( src, snk ) +end + +--- Decode an urlencoded http message body with application/x-www-urlencoded +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table withing the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +-- @param src Ltn12 source function +-- @param msg HTTP message object +-- @return Value indicating successful operation (not nil means "ok") +-- @return String containing the error if unsuccessful +-- @see parse_message_header +function urldecode_message_body( src, msg ) + + local tlen = 0 + local lchunk = nil + + local function snk( chunk ) + + tlen = tlen + ( chunk and #chunk or 0 ) + + if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then + return nil, "Message body size exceeds Content-Length" + elseif tlen > HTTP_MAX_CONTENT then + return nil, "Message body size exceeds maximum allowed length" + end + + if not lchunk and chunk then + lchunk = chunk + + elseif lchunk then + local data = lchunk .. ( chunk or "&" ) + local spos, epos + + repeat + spos, epos = data:find("^.-[;&]") + + if spos then + local pair = data:sub( spos, epos - 1 ) + local key = pair:match("^(.-)=") + local val = pair:match("=([^%s]*)%s*$") + + if key and #key > 0 then + __initval( msg.params, key ) + __appendval( msg.params, key, val ) + __finishval( msg.params, key, urldecode ) + end + + data = data:sub( epos + 1, #data ) + end + until not spos + + lchunk = data + end + + return true + end + + return ltn12.pump.all( src, snk ) +end + +--- Try to extract an http message header including information like protocol +-- version, message headers and resulting CGI environment variables from the +-- given ltn12 source. +-- @param src Ltn12 source function +-- @return HTTP message object +-- @see parse_message_body +function parse_message_header( src ) + + local ok = true + local msg = { } + + local sink = ltn12.sink.simplify( + function( chunk ) + return process_states['magic']( msg, chunk ) + end + ) + + -- Pump input data... + while ok do + + -- get data + ok, err = ltn12.pump.step( src, sink ) + + -- error + if not ok and err then + return nil, err + + -- eof + elseif not ok then + + -- Process get parameters + if ( msg.request_method == "get" or msg.request_method == "post" ) and + msg.request_uri:match("?") + then + msg.params = urldecode_params( msg.request_uri ) + else + msg.params = { } + end + + -- Populate common environment variables + msg.env = { + CONTENT_LENGTH = msg.headers['Content-Length']; + CONTENT_TYPE = msg.headers['Content-Type'] or msg.headers['Content-type']; + REQUEST_METHOD = msg.request_method:upper(); + REQUEST_URI = msg.request_uri; + SCRIPT_NAME = msg.request_uri:gsub("?.+$",""); + SCRIPT_FILENAME = ""; -- XXX implement me + SERVER_PROTOCOL = "HTTP/" .. string.format("%.1f", msg.http_version); + QUERY_STRING = msg.request_uri:match("?") + and msg.request_uri:gsub("^.+?","") or "" + } + + -- Populate HTTP_* environment variables + for i, hdr in ipairs( { + 'Accept', + 'Accept-Charset', + 'Accept-Encoding', + 'Accept-Language', + 'Connection', + 'Cookie', + 'Host', + 'Referer', + 'User-Agent', + } ) do + local var = 'HTTP_' .. hdr:upper():gsub("%-","_") + local val = msg.headers[hdr] + + msg.env[var] = val + end + end + end + + return msg +end + +--- Try to extract and decode a http message body from the given ltn12 source. +-- This function will examine the Content-Type within the given message object +-- to select the appropriate content decoder. +-- Currently the application/x-www-urlencoded and application/form-data +-- mime types are supported. If the encountered content encoding can't be +-- handled then the whole message body will be stored unaltered as "content" +-- property within the given message object. +-- @param src Ltn12 source function +-- @param msg HTTP message object +-- @param filecb File data callback (optional, see mimedecode_message_body()) +-- @return Value indicating successful operation (not nil means "ok") +-- @return String containing the error if unsuccessful +-- @see parse_message_header +function parse_message_body( src, msg, filecb ) + -- Is it multipart/mime ? + if msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and + msg.env.CONTENT_TYPE:match("^multipart/form%-data") + then + + return mimedecode_message_body( src, msg, filecb ) + + -- Is it application/x-www-form-urlencoded ? + elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and + msg.env.CONTENT_TYPE:match("^application/x%-www%-form%-urlencoded") + then + return urldecode_message_body( src, msg, filecb ) + + + -- Unhandled encoding + -- If a file callback is given then feed it chunk by chunk, else + -- store whole buffer in message.content + else + + local sink + + -- If we have a file callback then feed it + if type(filecb) == "function" then + sink = filecb + + -- ... else append to .content + else + msg.content = "" + msg.content_length = 0 + + sink = function( chunk, err ) + if chunk then + if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then + msg.content = msg.content .. chunk + msg.content_length = msg.content_length + #chunk + return true + else + return nil, "POST data exceeds maximum allowed length" + end + end + return true + end + end + + -- Pump data... + while true do + local ok, err = ltn12.pump.step( src, sink ) + + if not ok and err then + return nil, err + elseif not err then + return true + end + end + + return true + end +end + +--- Table containing human readable messages for several http status codes. +-- @class table +statusmsg = { + [200] = "OK", + [206] = "Partial Content", + [301] = "Moved Permanently", + [302] = "Found", + [304] = "Not Modified", + [400] = "Bad Request", + [403] = "Forbidden", + [404] = "Not Found", + [405] = "Method Not Allowed", + [408] = "Request Time-out", + [411] = "Length Required", + [412] = "Precondition Failed", + [416] = "Requested range not satisfiable", + [500] = "Internal Server Error", + [503] = "Server Unavailable", +} diff --git a/openwrt/packages/luci/libs/http/luasrc/http/protocol/conditionals.lua b/openwrt/packages/luci/libs/http/luasrc/http/protocol/conditionals.lua new file mode 100644 index 0000000..24d6d16 --- /dev/null +++ b/openwrt/packages/luci/libs/http/luasrc/http/protocol/conditionals.lua @@ -0,0 +1,154 @@ +--[[ + +HTTP protocol implementation for LuCI - RFC2616 / 14.19, 14.24 - 14.28 +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: conditionals.lua 3652 2008-10-29 19:41:33Z jow $ + +]]-- + +--- LuCI http protocol implementation - HTTP/1.1 bits. +-- This class provides basic ETag handling and implements most of the +-- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . +module("luci.http.protocol.conditionals", package.seeall) + +local date = require("luci.http.protocol.date") + + +--- Implement 14.19 / ETag. +-- @param stat A file.stat structure +-- @return String containing the generated tag suitable for ETag headers +function mk_etag( stat ) + if stat ~= nil then + return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime ) + end +end + +--- 14.24 / If-Match +-- Test whether the given message object contains an "If-Match" header and +-- compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +function if_match( req, stat ) + local h = req.headers + local etag = mk_etag( stat ) + + -- Check for matching resource + if type(h['If-Match']) == "string" then + for ent in h['If-Match']:gmatch("([^, ]+)") do + if ( ent == '*' or ent == etag ) and stat ~= nil then + return true + end + end + + return false, 412 + end + + return true +end + +--- 14.25 / If-Modified-Since +-- Test whether the given message object contains an "If-Modified-Since" header +-- and compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +-- @return Table containing extra HTTP headers if the precondition failed +function if_modified_since( req, stat ) + local h = req.headers + + -- Compare mtimes + if type(h['If-Modified-Since']) == "string" then + local since = date.to_unix( h['If-Modified-Since'] ) + + if stat == nil or since < stat.mtime then + return true + end + + return false, 304, { + ["ETag"] = mk_etag( stat ); + ["Date"] = date.to_http( os.time() ); + ["Last-Modified"] = date.to_http( stat.mtime ) + } + end + + return true +end + +--- 14.26 / If-None-Match +-- Test whether the given message object contains an "If-None-Match" header and +-- compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +-- @return Table containing extra HTTP headers if the precondition failed +function if_none_match( req, stat ) + local h = req.headers + local etag = mk_etag( stat ) + + -- Check for matching resource + if type(h['If-None-Match']) == "string" then + for ent in h['If-None-Match']:gmatch("([^, ]+)") do + if ( ent == '*' or ent == etag ) and stat ~= nil then + if req.request_method == "get" or + req.request_method == "head" + then + return false, 304, { + ["ETag"] = mk_etag( stat ); + ["Date"] = date.to_http( os.time() ); + ["Last-Modified"] = date.to_http( stat.mtime ) + } + else + return false, 412 + end + end + end + end + + return true +end + +--- 14.27 / If-Range +-- The If-Range header is currently not implemented due to the lack of general +-- byte range stuff in luci.http.protocol . This function will always return +-- false, 412 to indicate a failed precondition. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +function if_range( req, stat ) + -- Sorry, no subranges (yet) + return false, 412 +end + +--- 14.28 / If-Unmodified-Since +-- Test whether the given message object contains an "If-Unmodified-Since" +-- header and compare it against the given stat object. +-- @param req HTTP request message object +-- @param stat A file.stat object +-- @return Boolean indicating wheather the precondition is ok +-- @return Alternative status code if the precondition failed +function if_unmodified_since( req, stat ) + local h = req.headers + + -- Compare mtimes + if type(h['If-Unmodified-Since']) == "string" then + local since = date.to_unix( h['If-Unmodified-Since'] ) + + if stat ~= nil and since <= stat.mtime then + return false, 412 + end + end + + return true +end diff --git a/openwrt/packages/luci/libs/http/luasrc/http/protocol/date.lua b/openwrt/packages/luci/libs/http/luasrc/http/protocol/date.lua new file mode 100644 index 0000000..11a2475 --- /dev/null +++ b/openwrt/packages/luci/libs/http/luasrc/http/protocol/date.lua @@ -0,0 +1,115 @@ +--[[ + +HTTP protocol implementation for LuCI - date handling +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: date.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +--- LuCI http protocol implementation - date helper class. +-- This class contains functions to parse, compare and format http dates. +module("luci.http.protocol.date", package.seeall) + +require("luci.sys.zoneinfo") + + +MONTHS = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" +} + +--- Return the time offset in seconds between the UTC and given time zone. +-- @param tz Symbolic or numeric timezone specifier +-- @return Time offset to UTC in seconds +function tz_offset(tz) + + if type(tz) == "string" then + + -- check for a numeric identifier + local s, v = tz:match("([%+%-])([0-9]+)") + if s == '+' then s = 1 else s = -1 end + if v then v = tonumber(v) end + + if s and v then + return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) ) + + -- lookup symbolic tz + elseif luci.sys.zoneinfo.OFFSET[tz:lower()] then + return luci.sys.zoneinfo.OFFSET[tz:lower()] + end + + end + + -- bad luck + return 0 +end + +--- Parse given HTTP date string and convert it to unix epoch time. +-- @param data String containing the date +-- @return Unix epoch time +function to_unix(date) + + local wd, day, mon, yr, hr, min, sec, tz = date:match( + "([A-Z][a-z][a-z]), ([0-9]+) " .. + "([A-Z][a-z][a-z]) ([0-9]+) " .. + "([0-9]+):([0-9]+):([0-9]+) " .. + "([A-Z0-9%+%-]+)" + ) + + if day and mon and yr and hr and min and sec then + -- find month + local month = 1 + for i = 1, 12 do + if MONTHS[i] == mon then + month = i + break + end + end + + -- convert to epoch time + return tz_offset(tz) + os.time( { + year = yr, + month = month, + day = day, + hour = hr, + min = min, + sec = sec + } ) + end + + return 0 +end + +--- Convert the given unix epoch time to valid HTTP date string. +-- @param time Unix epoch time +-- @return String containing the formatted date +function to_http(time) + return os.date( "%a, %d %b %Y %H:%M:%S GMT", time ) +end + +--- Compare two dates which can either be unix epoch times or HTTP date strings. +-- @param d1 The first date or epoch time to compare +-- @param d2 The first date or epoch time to compare +-- @return -1 - if d1 is lower then d2 +-- @return 0 - if both dates are equal +-- @return 1 - if d1 is higher then d2 +function compare(d1, d2) + + if d1:match("[^0-9]") then d1 = to_unix(d1) end + if d2:match("[^0-9]") then d2 = to_unix(d2) end + + if d1 == d2 then + return 0 + elseif d1 < d2 then + return -1 + else + return 1 + end +end diff --git a/openwrt/packages/luci/libs/http/luasrc/http/protocol/mime.lua b/openwrt/packages/luci/libs/http/luasrc/http/protocol/mime.lua new file mode 100644 index 0000000..49f02b8 --- /dev/null +++ b/openwrt/packages/luci/libs/http/luasrc/http/protocol/mime.lua @@ -0,0 +1,98 @@ +--[[ + +HTTP protocol implementation for LuCI - mime handling +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: mime.lua 2641 2008-07-22 01:15:39Z jow $ + +]]-- + +--- LuCI http protocol implementation - mime helper class. +-- This class provides functions to guess mime types from file extensions and +-- vice versa. +module("luci.http.protocol.mime", package.seeall) + +require("luci.util") + +--- MIME mapping table containg extension - mimetype relations. +-- @class table +MIME_TYPES = { + ["txt"] = "text/plain"; + ["js"] = "text/javascript"; + ["css"] = "text/css"; + ["htm"] = "text/html"; + ["html"] = "text/html"; + ["patch"] = "text/x-patch"; + ["c"] = "text/x-csrc"; + ["h"] = "text/x-chdr"; + ["o"] = "text/x-object"; + ["ko"] = "text/x-object"; + + ["bmp"] = "image/bmp"; + ["gif"] = "image/gif"; + ["png"] = "image/png"; + ["jpg"] = "image/jpeg"; + ["jpeg"] = "image/jpeg"; + ["svg"] = "image/svg+xml"; + + ["zip"] = "application/zip"; + ["pdf"] = "application/pdf"; + ["xml"] = "application/xml"; + ["doc"] = "application/msword"; + ["ppt"] = "application/vnd.ms-powerpoint"; + ["xls"] = "application/vnd.ms-excel"; + ["odt"] = "application/vnd.oasis.opendocument.text"; + ["odp"] = "application/vnd.oasis.opendocument.presentation"; + ["pl"] = "application/x-perl"; + ["sh"] = "application/x-shellscript"; + ["php"] = "application/x-php"; + ["deb"] = "application/x-deb"; + ["iso"] = "application/x-cd-image"; + ["tgz"] = "application/x-compressed-tar"; + + ["mp3"] = "audio/mpeg"; + ["ogg"] = "audio/x-vorbis+ogg"; + ["wav"] = "audio/x-wav"; + + ["mpg"] = "video/mpeg"; + ["mpeg"] = "video/mpeg"; + ["avi"] = "video/x-msvideo"; +} + +--- Extract extension from a filename and return corresponding mime-type or +-- "application/octet-stream" if the extension is unknown. +-- @param filename The filename for which the mime type is guessed +-- @return String containign the determined mime type +function to_mime(filename) + if type(filename) == "string" then + local ext = filename:match("[^%.]+$") + + if ext and MIME_TYPES[ext:lower()] then + return MIME_TYPES[ext:lower()] + end + end + + return "application/octet-stream" +end + +--- Return corresponding extension for a given mime type or nil if the +-- given mime-type is unknown. +-- @param mimetype The mimetype to retrieve the extension from +-- @return String with the extension or nil for unknown type +function to_ext(mimetype) + if type(mimetype) == "string" then + for ext, type in luci.util.kspairs( MIME_TYPES ) do + if type == mimetype then + return ext + end + end + end + + return nil +end diff --git a/openwrt/packages/luci/libs/httpd/Makefile b/openwrt/packages/luci/libs/httpd/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/httpd/host/runluci b/openwrt/packages/luci/libs/httpd/host/runluci new file mode 100755 index 0000000..bc56f15 --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/host/runluci @@ -0,0 +1,48 @@ +#!/usr/bin/env lua +require("luci.httpd") +require("luci.httpd.server") +require("luci.httpd.handler.file") +require("luci.httpd.handler.luci") + +SYSROOT = arg[1] +DOCROOT = SYSROOT .. arg[2] +PORT = 8080 + +collectgarbage("setpause", 150) + +serversocket = luci.httpd.Socket("0.0.0.0", PORT) + +server = luci.httpd.server.Server() +vhost = luci.httpd.server.VHost() + +server:set_default_vhost(vhost) + +pcall(function() + require "uci" + require "luci.model.uci".cursor = function(config, save) + return uci.cursor(config or SYSROOT .. "/etc/config", save or SYSROOT .. "/tmp/.uci") + end + + local x = require "luci.uvl".UVL.__init__ + require "luci.uvl".UVL.__init__ = function(self, schemedir) + x(self, schemedir or SYSROOT .. "/lib/uci/schema") + end +end) + +require("luci.sys") +luci.sys.user.checkpasswd = function() return true end + + +filehandler = luci.httpd.handler.file.Simple(DOCROOT) +vhost:set_default_handler(filehandler) + +lucihandler = luci.httpd.handler.luci.Luci() +vhost:set_handler("/luci", lucihandler) + +io.stderr:write("Starting LuCI HTTPD on port " .. PORT .. "...\n") +io.stderr:write("Point your browser to http://localhost:" .. PORT .. "/luci\n") + +--daemon = luci.httpd.Daemon() +--daemon.debug = true +luci.httpd.register(serversocket, server:create_daemon_handlers()) +luci.httpd.run() diff --git a/openwrt/packages/luci/libs/httpd/hostfiles/www/index.html b/openwrt/packages/luci/libs/httpd/hostfiles/www/index.html new file mode 100644 index 0000000..838da04 --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/hostfiles/www/index.html @@ -0,0 +1,10 @@ + + + + + + + +LuCI - Lua Configuration Interface + + diff --git a/openwrt/packages/luci/libs/httpd/luasrc/httpd.lua b/openwrt/packages/luci/libs/httpd/luasrc/httpd.lua new file mode 100644 index 0000000..609ae68 --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/luasrc/httpd.lua @@ -0,0 +1,126 @@ +--[[ + +HTTP server implementation for LuCI - core +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich +(c) 2008 Steven Barth + +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: httpd.lua 2974 2008-08-27 17:45:58Z Cyrus $ + +]]-- + +module("luci.httpd", package.seeall) +require("socket") + +THREAD_IDLEWAIT = 0.01 +THREAD_TIMEOUT = 90 +THREAD_LIMIT = nil + +local reading = {} +local clhandler = {} +local erhandler = {} + +local threadc = 0 +local threads = {} +local threadm = {} +local threadi = {} + +local _meta = {__mode = "k"} +setmetatable(threadm, _meta) +setmetatable(threadi, _meta) + + +function Socket(ip, port) + local sock, err = socket.bind( ip, port ) + + if sock then + sock:settimeout( 0, "t" ) + end + + return sock, err +end + +function corecv(socket, ...) + threadi[socket] = true + + while true do + local chunk, err, part = socket:receive(...) + + if err ~= "timeout" then + threadi[socket] = false + return chunk, err, part + end + + coroutine.yield() + end +end + +function cosend(socket, chunk, i, ...) + threadi[socket] = true + i = i or 1 + + while true do + local stat, err, sent = socket:send(chunk, i, ...) + + if err ~= "timeout" then + threadi[socket] = false + return stat, err, sent + else + i = sent and (sent + 1) or i + end + + coroutine.yield() + end +end + +function register(socket, s_clhandler, s_errhandler) + table.insert(reading, socket) + clhandler[socket] = s_clhandler + erhandler[socket] = s_errhandler +end + +function run() + while true do + step() + end +end + +function step() + local idle = true + if not THREAD_LIMIT or threadc < THREAD_LIMIT then + local now = os.time() + for i, server in ipairs(reading) do + local client = server:accept() + if client then + threadm[client] = now + threadc = threadc + 1 + threads[client] = coroutine.create(clhandler[server]) + end + end + end + + for client, thread in pairs(threads) do + coroutine.resume(thread, client) + local now = os.time() + if coroutine.status(thread) == "dead" then + threadc = threadc - 1 + threads[client] = nil + elseif threadm[client] and threadm[client] + THREAD_TIMEOUT < now then + threads[client] = nil + threadc = threadc - 1 + client:close() + elseif not threadi[client] then + threadm[client] = now + idle = false + end + end + + if idle then + socket.sleep(THREAD_IDLEWAIT) + end +end diff --git a/openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/file.lua b/openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/file.lua new file mode 100644 index 0000000..50e9a58 --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/file.lua @@ -0,0 +1,199 @@ +--[[ + +HTTP server implementation for LuCI - file handler +(c) 2008 Steven Barth +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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: file.lua 2510 2008-07-05 20:12:24Z jow $ + +]]-- + +module("luci.httpd.handler.file", package.seeall) + +require("luci.httpd.module") +require("luci.http.protocol.date") +require("luci.http.protocol.mime") +require("luci.http.protocol.conditionals") +require("luci.fs") +local ltn12 = require("luci.ltn12") + +Simple = luci.util.class(luci.httpd.module.Handler) +Response = luci.httpd.module.Response + +function Simple.__init__(self, docroot, dirlist) + luci.httpd.module.Handler.__init__(self) + self.docroot = docroot + self.dirlist = dirlist and true or false + self.proto = luci.http.protocol + self.mime = luci.http.protocol.mime + self.date = luci.http.protocol.date + self.cond = luci.http.protocol.conditionals +end + +function Simple.getfile(self, uri) + local file = self.docroot .. uri:gsub("%.%./+", "") + local stat = luci.fs.stat(file) + + return file, stat +end + +function Simple.handle_get(self, request, sourcein, sinkerr) + local file, stat = self:getfile( self.proto.urldecode( request.env.PATH_INFO, true ) ) + + if stat then + if stat.type == "regular" then + + -- Generate Entity Tag + local etag = self.cond.mk_etag( stat ) + + -- Check conditionals + local ok, code, hdrs + + ok, code, hdrs = self.cond.if_modified_since( request, stat ) + if ok then + ok, code, hdrs = self.cond.if_match( request, stat ) + if ok then + ok, code, hdrs = self.cond.if_unmodified_since( request, stat ) + if ok then + ok, code, hdrs = self.cond.if_none_match( request, stat ) + if ok then + local f, err = io.open(file) + + if f then + -- Send Response + return Response( + 200, { + ["Date"] = self.date.to_http( os.time() ); + ["Last-Modified"] = self.date.to_http( stat.mtime ); + ["Content-Type"] = self.mime.to_mime( file ); + ["Content-Length"] = stat.size; + ["ETag"] = etag; + } + ), ltn12.source.file(f) + else + return self:failure( 403, err:gsub("^.+: ", "") ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + + elseif stat.type == "directory" then + + local ruri = request.request_uri:gsub("/$","") + local duri = self.proto.urldecode( ruri, true ) + local root = self.docroot:gsub("/$","") + + -- check for index files + local index_candidates = { + "index.html", "index.htm", "default.html", "default.htm", + "index.txt", "default.txt" + } + + -- try to find an index file and redirect to it + for i, candidate in ipairs( index_candidates ) do + local istat = luci.fs.stat( + root .. "/" .. duri .. "/" .. candidate + ) + + if istat ~= nil and istat.type == "regular" then + return Response( 301, { + ["Location"] = ruri .. "/" .. candidate + } ), ltn12.source.empty() + end + end + + + local html = string.format( + '\n' .. + '\n' .. + '\n' .. + '\n' .. + 'Index of %s/\n' .. + '

Index of %s/


    ', + duri, duri + ) + + local entries = luci.fs.dir( file ) + + if type(entries) == "table" then + for i, e in luci.util.spairs( + entries, function(a,b) + if entries[a] == '..' then + return true + elseif entries[b] == '..' then + return false + else + return ( entries[a] < entries[b] ) + end + end + ) do + if e ~= '.' and ( e == '..' or e:sub(1,1) ~= '.' ) then + local estat = luci.fs.stat( file .. "/" .. e ) + + if estat.type == "directory" then + html = html .. string.format( + '
  • %s/ ' .. + '(directory)
    ' .. + 'Changed: %s

  • ', + ruri, self.proto.urlencode( e ), e, + self.date.to_http( estat.mtime ) + ) + else + html = html .. string.format( + '
  • %s ' .. + '(%s)
    ' .. + 'Size: %i Bytes | ' .. + 'Changed: %s

  • ', + ruri, self.proto.urlencode( e ), e, + self.mime.to_mime( e ), + estat.size, self.date.to_http( estat.mtime ) + ) + end + end + end + + html = html .. '

' + + return Response( + 200, { + ["Date"] = self.date.to_http( os.time() ); + ["Content-Type"] = "text/html; charset=ISO-8859-15"; + } + ), ltn12.source.string(html) + else + return self:failure(403, "Permission denied") + end + else + return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file) + end + else + return self:failure(404, "No such file: " .. file) + end +end + +function Simple.handle_head(self, ...) + local response, sourceout = self:handle_get(...) + return response +end diff --git a/openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/luci.lua b/openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/luci.lua new file mode 100644 index 0000000..e662d3f --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/luasrc/httpd/handler/luci.lua @@ -0,0 +1,96 @@ +--[[ + +HTTP server implementation for LuCI - luci handler +(c) 2008 Steven Barth + +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: luci.lua 3680 2008-11-01 10:53:51Z Cyrus $ + +]]-- + +module("luci.httpd.handler.luci", package.seeall) + +require("luci.dispatcher") +require("luci.http") +require("luci.http.protocol.date") +local ltn12 = require("luci.ltn12") + +Luci = luci.util.class(luci.httpd.module.Handler) +Response = luci.httpd.module.Response + +function Luci.__init__(self, limit) + luci.httpd.module.Handler.__init__(self) + self.limit = limit or 5 + self.running = {} + setmetatable(self.running, {__mode = "k"}) +end + +function Luci.handle_head(self, ...) + local response, sourceout = self:handle_get(...) + return response +end + +function Luci.handle_post(self, ...) + return self:handle_get(...) +end + +function Luci.handle_get(self, request, sourcein, sinkerr) + local r = luci.http.Request( + request.env, + sourcein, + sinkerr + ) + + local res, id, data1, data2 = true, 0, nil, nil + local headers = {} + local status = 200 + local active = true + + local x = coroutine.create(luci.dispatcher.httpdispatch) + while not id or id < 3 do + coroutine.yield() + + res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + status = 500 + headers["Content-Type"] = "text/plain" + local err = {id} + return Response( status, headers ), function() return table.remove(err) end + end + + if id == 1 then + status = data1 + elseif id == 2 then + headers[data1] = data2 + end + end + + local function iter() + local res, id, data = coroutine.resume(x) + if not res then + return nil, id + elseif not id or not active then + return true + elseif id == 5 then + active = false + + while (coroutine.resume(x)) do + end + + return nil + elseif id == 4 then + return data + end + if coroutine.status(x) == "dead" then + return nil + end + end + + return Response(status, headers), iter +end diff --git a/openwrt/packages/luci/libs/httpd/luasrc/httpd/module.lua b/openwrt/packages/luci/libs/httpd/luasrc/httpd/module.lua new file mode 100644 index 0000000..7f4580a --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/luasrc/httpd/module.lua @@ -0,0 +1,136 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: module.lua 2476 2008-06-29 16:15:26Z Cyrus $ +]]-- +module("luci.httpd.module", package.seeall) +require("luci.util") +require("luci.http.protocol") +local ltn12 = require("luci.ltn12") + + + +-- Server handler implementation +Handler = luci.util.class() + +-- Constructor +function Handler.__init__(self) + self.filters = {} + self.handler = {} +end + + +-- Adds a filter to the filter chain +function Handler.addfilter(self, filter) + table.insert(self.filters, filter) +end + + +-- Creates a failure reply +function Handler.failure(self, code, message) + local response = Response(code, { ["Content-Type"] = "text/plain" }) + local sourceout = ltn12.source.string(message) + + return response, sourceout +end + +-- Processes a request +function Handler.process(self, request, sourcein, sinkerr, ...) + local stat, response, sourceout + + -- Process incoming filters + for i, f in ipairs(self.filters) do + local i = f:get("input") + + if i then + sourcein = ltn12.source.chain(sourcein, i) + end + + if f.request then + f:request(request) + end + end + + -- Detect request Method + local hname = "handle_" .. request.request_method + if self[hname] then + -- Run the handler + stat, response, sourceout = luci.util.copcall( + self[hname], self, request, sourcein, sinkerr, ... + ) + + -- Check for any errors + if not stat then + response, sourceout = self:failure(500, response) + end + else + response, sourceout = self:failure(405, luci.http.protocol.statusmsg[405]) + end + + -- Check data + if not luci.util.instanceof(response, Response) then + response, sourceout = self:failure(500, "Core error: Invalid module response!") + end + + -- Process outgoing filters + for i, f in ipairs(self.filters) do + local o = f:get("output") + + if o then + sourceout = ltn12.source.chain(sourceout, o) + end + + if f.response then + f:response(response) + end + end + + return response, sourceout +end + + + +-- Server Filter implementation +Filter = luci.util.class() + +function Filter.get(self, name) + return self[name] and function(...) return self[name](self, ...) end +end + +-- Filters the incoming body stream +-- abstract function Filter.input(chunk) + +-- Filters the outgoing body stream +-- abstract function Filter.output(chunk) + +-- Filters the request object +-- abstract function Filter.request(request) + +-- Filters the response object +-- abstract function Filter.response(response) + + + +-- Handler Response +Response = luci.util.class() + +function Response.__init__(self, status, headers) + self.status = tonumber(status) or 200 + self.headers = (type(headers) == "table") and headers or {} +end + +function Response.addheader(self, key, value) + self.headers[key] = value +end + +function Response.setstatus(self, status) + self.status = status +end diff --git a/openwrt/packages/luci/libs/httpd/luasrc/httpd/server.lua b/openwrt/packages/luci/libs/httpd/luasrc/httpd/server.lua new file mode 100644 index 0000000..efd5374 --- /dev/null +++ b/openwrt/packages/luci/libs/httpd/luasrc/httpd/server.lua @@ -0,0 +1,241 @@ +--[[ + +HTTP server implementation for LuCI - helper class +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich +(c) 2008 Steven Barth + +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: server.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +module("luci.httpd.server", package.seeall) +require("socket") +require("socket.http") +require("luci.util") + +READ_BUFSIZE = 1024 +VERSION = 0.2 + + +VHost = luci.util.class() + +function VHost.__init__(self, handler) + self.handler = handler + self.dhandler = {} +end + +function VHost.process(self, request, sourcein, sinkerr, ...) + local handler = self.handler + + local uri = request.env.REQUEST_URI:match("^([^?]*)") + + -- SCRIPT_NAME + request.env.SCRIPT_NAME = "" + + -- Call URI part + request.env.PATH_INFO = uri + + for k, dhandler in pairs(self.dhandler) do + if k == uri or k.."/" == uri:sub(1, #k+1) then + handler = dhandler + request.env.SCRIPT_NAME = k + request.env.PATH_INFO = uri:sub(#k+1) + break; + end + end + + if handler then + return handler:process(request, sourcein, sinkerr, ...) + end +end + + +function VHost.set_default_handler(self, handler) + self.handler = handler +end + + +function VHost.set_handler(self, match, handler) + self.dhandler[match] = handler +end + + + +Server = luci.util.class() + +function Server.__init__(self, host) + self.host = host + self.vhosts = {} +end + +function Server.set_default_vhost(self, vhost) + self.host = vhost +end + +-- Sets a vhost +function Server.set_vhost(self, name, vhost) + self.vhosts[name] = vhost +end + +function Server.create_daemon_handlers(self) + return function(...) return self:process(...) end, + function(...) return self:error_overload(...) end +end + + +function Server.error(self, socket, code, msg) + hcode = tostring(code) + + socket:send( "HTTP/1.0 " .. hcode .. " " .. + luci.http.protocol.statusmsg[code] .. "\r\n" ) + socket:send( "Connection: close\r\n" ) + socket:send( "Content-Type: text/plain\r\n\r\n" ) + + if msg then + socket:send( "HTTP-Error " .. code .. ": " .. msg .. "\r\n" ) + end +end + +function Server.error_overload(self, socket) + self:error(socket, 503, "Too many simultaneous connections") +end + + +function Server.process( self, client ) + + -- Setup sockets and sources + local thread = { + receive = function(self, ...) return luci.httpd.corecv(client, ...) end, + send = function(self, ...) return luci.httpd.cosend(client, ...) end, + close = function(self, ...) return client:close(...) end, + getfd = function(self, ...) return client:getfd(...) end, + dirty = function(self, ...) return client:dirty(...) end + } + + client:settimeout( 0 ) + + local sourcein = ltn12.source.empty() + local sourcehdr = luci.http.protocol.header_source( thread ) + local sinkerr = ltn12.sink.file( io.stderr ) + + local close = false + + local reading = { client } + + local message, err + + repeat + -- parse headers + message, err = luci.http.protocol.parse_message_header( sourcehdr ) + + if not message then + self:error( thread, 400, err ) + break + end + + -- keep-alive + if message.http_version == 1.1 then + close = (message.env.HTTP_CONNECTION == "close") + else + close = not message.env.HTTP_CONNECTION or message.env.HTTP_CONNECTION == "close" + end + + if message.request_method == "get" or message.request_method == "head" then + -- Be happy + + elseif message.request_method == "post" then + -- If we have a HTTP/1.1 client and an Expect: 100-continue header then + -- respond with HTTP 100 Continue message + if message.http_version == 1.1 and message.headers['Expect'] and + message.headers['Expect'] == '100-continue' + then + thread:send("HTTP/1.1 100 Continue\r\n\r\n") + end + + if message.headers['Transfer-Encoding'] and + message.headers['Transfer-Encoding'] ~= "identity" then + sourcein = socket.source("http-chunked", thread) + elseif message.env.CONTENT_LENGTH then + sourcein = socket.source("by-length", thread, + tonumber(message.env.CONTENT_LENGTH)) + else + self:error( thread, 411, luci.http.protocol.statusmsg[411] ) + break; + end + + -- FIXME: Close for POST requests + close = true + else + self:error( thread, 405, luci.http.protocol.statusmsg[405] ) + break; + + end + + + local host = self.vhosts[message.env.HTTP_HOST] or self.host + if not host then + self:error( thread, 500, "Unable to find matching host" ) + break; + end + + local response, sourceout = host:process( + message, sourcein, sinkerr, + client, io.stderr + ) + if not response then + self:error( thread, 500, "Error processing handler" ) + end + + -- Post process response + local sinkmode = close and "close-when-done" or "keep-open" + + if sourceout then + if not response.headers["Content-Length"] then + if message.http_version == 1.1 then + response.headers["Transfer-Encoding"] = "chunked" + sinkmode = "http-chunked" + else + close = true + sinkmode = "close-when-done" + end + end + end + + if close then + response.headers["Connection"] = "close" + end + + + local sinkout = socket.sink(sinkmode, thread) + + local header = + message.env.SERVER_PROTOCOL .. " " .. + tostring(response.status) .. " " .. + luci.http.protocol.statusmsg[response.status] .. "\r\n" + + header = header .. "Server: LuCI HTTPd/" .. tostring(VERSION) .. "\r\n" + + + for k,v in pairs(response.headers) do + header = header .. k .. ": " .. v .. "\r\n" + end + + thread:send(header .. "\r\n") + + if sourceout then + local eof = false + repeat + coroutine.yield() + eof = not ltn12.pump.step(sourceout, sinkout) + until eof + end + until close + + client:close() +end diff --git a/openwrt/packages/luci/libs/ipkg/Makefile b/openwrt/packages/luci/libs/ipkg/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/ipkg/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/ipkg/luasrc/model/ipkg.lua b/openwrt/packages/luci/libs/ipkg/luasrc/model/ipkg.lua new file mode 100644 index 0000000..c831583 --- /dev/null +++ b/openwrt/packages/luci/libs/ipkg/luasrc/model/ipkg.lua @@ -0,0 +1,150 @@ +--[[ +LuCI - Lua Configuration Interface + +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: ipkg.lua 3837 2008-11-29 21:58:58Z Cyrus $ +]]-- + +local os = require "os" +local io = require "io" +local util = require "luci.util" + +local type = type +local pairs = pairs +local error = error + +local ipkg = "opkg" + +--- LuCI IPKG/OPKG call abstraction library +module "luci.model.ipkg" + + +-- Internal action function +local function _action(cmd, ...) + local pkg = "" + arg.n = nil + for k, v in pairs(arg) do + pkg = pkg .. " '" .. v:gsub("'", "") .. "'" + end + + local c = ipkg.." "..cmd.." "..pkg.." >/dev/null 2>&1" + local r = os.execute(c) + return (r == 0), r +end + +-- Internal parser function +local function _parselist(rawdata) + if type(rawdata) ~= "function" then + error("IPKG: Invalid rawdata given") + end + + local data = {} + local c = {} + local l = nil + + for line in rawdata do + if line:sub(1, 1) ~= " " then + local key, val = line:match("(.-): ?(.*)%s*") + + if key and val then + if key == "Package" then + c = {Package = val} + data[val] = c + elseif key == "Status" then + c.Status = {} + for j in val:gmatch("([^ ]+)") do + c.Status[j] = true + end + else + c[key] = val + end + l = key + end + else + -- Multi-line field + c[l] = c[l] .. "\n" .. line + end + end + + return data +end + +-- Internal lookup function +local function _lookup(act, pkg) + local cmd = ipkg .. " " .. act + if pkg then + cmd = cmd .. " '" .. pkg:gsub("'", "") .. "'" + end + + -- IPKG sometimes kills the whole machine because it sucks + -- Therefore we have to use a sucky approach too and use + -- tmpfiles instead of directly reading the output + local tmpfile = os.tmpname() + os.execute(cmd .. (" >%s 2>/dev/null" % tmpfile)) + + local data = _parselist(io.lines(tmpfile)) + os.remove(tmpfile) + return data +end + + +--- Return information about installed and available packages. +-- @param pkg Limit output to a (set of) packages +-- @return Table containing package information +function info(pkg) + return _lookup("info", pkg) +end + +--- Return the package status of one or more packages. +-- @param pkg Limit output to a (set of) packages +-- @return Table containing package status information +function status(pkg) + return _lookup("status", pkg) +end + +--- Install one or more packages. +-- @param ... List of packages to install +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function install(...) + return _action("install", ...) +end + +--- Determine whether a given package is installed. +-- @param pkg Package +-- @return Boolean +function installed(pkg) + local p = status(pkg)[pkg] + return (p and p.Status and p.Status.installed) +end + +--- Remove one or more packages. +-- @param ... List of packages to install +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function remove(...) + return _action("remove", ...) +end + +--- Update package lists. +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function update() + return _action("update") +end + +--- Upgrades all installed packages. +-- @return Boolean indicating the status of the action +-- @return IPKG return code +function upgrade() + return _action("upgrade") +end + diff --git a/openwrt/packages/luci/libs/json/Makefile b/openwrt/packages/luci/libs/json/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/json/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/json/luasrc/json.lua b/openwrt/packages/luci/libs/json/luasrc/json.lua new file mode 100644 index 0000000..7a5bff1 --- /dev/null +++ b/openwrt/packages/luci/libs/json/luasrc/json.lua @@ -0,0 +1,538 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: json.lua 3997 2009-01-04 20:09:13Z Cyrus $ + +Decoder: + Info: + null will be decoded to luci.json.null if first parameter of Decoder() is true + + Example: + decoder = luci.json.Decoder() + luci.ltn12.pump.all(luci.ltn12.source.string("decodableJSON"), decoder:sink()) + luci.util.dumptable(decoder:get()) + + Known issues: + does not support unicode conversion \uXXYY with XX != 00 will be ignored + + +Encoder: + Info: + Accepts numbers, strings, nil, booleans as they are + Accepts luci.json.null as replacement for nil + Accepts full associative and full numerically indexed tables + Mixed tables will loose their associative values during conversion + Iterator functions will be encoded as an array of their return values + Non-iterator functions will probably corrupt the encoder + + Example: + encoder = luci.json.Encoder(encodableData) + luci.ltn12.pump.all(encoder:source(), luci.ltn12.sink.file(io.open("someFile", w))) +]]-- + +local util = require "luci.util" +local table = require "table" +local string = require "string" +local coroutine = require "coroutine" + +local assert = assert +local tonumber = tonumber +local tostring = tostring +local error = error +local type = type +local pairs = pairs +local ipairs = ipairs +local next = next + +local getmetatable = getmetatable + +--- LuCI JSON-Library +-- @cstyle instance +module "luci.json" + +--- Null replacement function +-- @return null +function null() + return null +end + +--- Create a new JSON-Encoder. +-- @class function +-- @name Encoder +-- @param data Lua-Object to be encoded. +-- @param buffersize Blocksize of returned data source. +-- @param fastescape Use non-standard escaping (don't escape control chars) +-- @return JSON-Encoder +Encoder = util.class() + +function Encoder.__init__(self, data, buffersize, fastescape) + self.data = data + self.buffersize = buffersize or 512 + self.buffer = "" + self.fastescape = fastescape + + getmetatable(self).__call = Encoder.source +end + +--- Create an LTN12 source providing the encoded JSON-Data. +-- @return LTN12 source +function Encoder.source(self) + local source = coroutine.create(self.dispatch) + return function() + local res, data = coroutine.resume(source, self, self.data, true) + if res then + return data + else + return nil, data + end + end +end + +function Encoder.dispatch(self, data, start) + local parser = self.parsers[type(data)] + + parser(self, data) + + if start then + if #self.buffer > 0 then + coroutine.yield(self.buffer) + end + + coroutine.yield() + end +end + +function Encoder.put(self, chunk) + if self.buffersize < 2 then + corountine.yield(chunk) + else + if #self.buffer + #chunk > self.buffersize then + local written = 0 + local fbuffer = self.buffersize - #self.buffer + + coroutine.yield(self.buffer .. chunk:sub(written + 1, fbuffer)) + written = fbuffer + + while #chunk - written > self.buffersize do + fbuffer = written + self.buffersize + coroutine.yield(chunk:sub(written + 1, fbuffer)) + written = fbuffer + end + + self.buffer = chunk:sub(written + 1) + else + self.buffer = self.buffer .. chunk + end + end +end + +function Encoder.parse_nil(self) + self:put("null") +end + +function Encoder.parse_bool(self, obj) + self:put(obj and "true" or "false") +end + +function Encoder.parse_number(self, obj) + self:put(tostring(obj)) +end + +function Encoder.parse_string(self, obj) + if self.fastescape then + self:put('"' .. obj:gsub('\\', '\\\\'):gsub('"', '\\"') .. '"') + else + self:put('"' .. + obj:gsub('[%c\\"]', + function(char) + return '\\u00%02x' % char:byte() + end + ) + .. '"') + end +end + +function Encoder.parse_iter(self, obj) + if obj == null then + return self:put("null") + end + + if type(obj) == "table" and (#obj == 0 and next(obj)) then + self:put("{") + local first = true + + for key, entry in pairs(obj) do + first = first or self:put(",") + first = first and false + self:parse_string(tostring(key)) + self:put(":") + self:dispatch(entry) + end + + self:put("}") + else + self:put("[") + local first = true + + if type(obj) == "table" then + for i=1, #obj do + first = first or self:put(",") + first = first and nil + self:dispatch(obj[i]) + end + else + for entry in obj do + first = first or self:put(",") + first = first and nil + self:dispatch(entry) + end + end + + self:put("]") + end +end + +Encoder.parsers = { + ['nil'] = Encoder.parse_nil, + ['table'] = Encoder.parse_iter, + ['number'] = Encoder.parse_number, + ['string'] = Encoder.parse_string, + ['boolean'] = Encoder.parse_bool, + ['function'] = Encoder.parse_iter +} + + +--- Create a new JSON-Decoder. +-- @class function +-- @name Decoder +-- @param customnull Use luci.json.null instead of nil for decoding null +-- @return JSON-Decoder +Decoder = util.class() + +function Decoder.__init__(self, customnull) + self.cnull = customnull + getmetatable(self).__call = Decoder.sink +end + +--- Create an LTN12 sink from the decoder object which accepts the JSON-Data. +-- @return LTN12 sink +function Decoder.sink(self) + local sink = coroutine.create(self.dispatch) + return function(...) + return coroutine.resume(sink, self, ...) + end +end + + +--- Get the decoded data packets after the rawdata has been sent to the sink. +-- @return Decoded data +function Decoder.get(self) + return self.data +end + +function Decoder.dispatch(self, chunk, src_err, strict) + local robject, object + local oset = false + + while chunk do + while chunk and #chunk < 1 do + chunk = self:fetch() + end + + assert(not strict or chunk, "Unexpected EOS") + if not chunk then break end + + local char = chunk:sub(1, 1) + local parser = self.parsers[char] + or (char:match("%s") and self.parse_space) + or (char:match("[0-9-]") and self.parse_number) + or error("Unexpected char '%s'" % char) + + chunk, robject = parser(self, chunk) + + if parser ~= self.parse_space then + assert(not oset, "Scope violation: Too many objects") + object = robject + oset = true + + if strict then + return chunk, object + end + end + end + + assert(not src_err, src_err) + assert(oset, "Unexpected EOS") + + self.data = object +end + + +function Decoder.fetch(self) + local tself, chunk, src_err = coroutine.yield() + assert(chunk or not src_err, src_err) + return chunk +end + + +function Decoder.fetch_atleast(self, chunk, bytes) + while #chunk < bytes do + local nchunk = self:fetch() + assert(nchunk, "Unexpected EOS") + chunk = chunk .. nchunk + end + + return chunk +end + + +function Decoder.fetch_until(self, chunk, pattern) + local start = chunk:find(pattern) + + while not start do + local nchunk = self:fetch() + assert(nchunk, "Unexpected EOS") + chunk = chunk .. nchunk + start = chunk:find(pattern) + end + + return chunk, start +end + + +function Decoder.parse_space(self, chunk) + local start = chunk:find("[^%s]") + + while not start do + chunk = self:fetch() + if not chunk then + return nil + end + start = chunk:find("[^%s]") + end + + return chunk:sub(start) +end + + +function Decoder.parse_literal(self, chunk, literal, value) + chunk = self:fetch_atleast(chunk, #literal) + assert(chunk:sub(1, #literal) == literal, "Invalid character sequence") + return chunk:sub(#literal + 1), value +end + + +function Decoder.parse_null(self, chunk) + return self:parse_literal(chunk, "null", self.cnull and null) +end + + +function Decoder.parse_true(self, chunk) + return self:parse_literal(chunk, "true", true) +end + + +function Decoder.parse_false(self, chunk) + return self:parse_literal(chunk, "false", false) +end + + +function Decoder.parse_number(self, chunk) + local chunk, start = self:fetch_until(chunk, "[^0-9eE.+-]") + local number = tonumber(chunk:sub(1, start - 1)) + assert(number, "Invalid number specification") + return chunk:sub(start), number +end + + +function Decoder.parse_string(self, chunk) + local str = "" + local object = nil + assert(chunk:sub(1, 1) == '"', 'Expected "') + chunk = chunk:sub(2) + + while true do + local spos = chunk:find('[\\"]') + if spos then + str = str .. chunk:sub(1, spos - 1) + + local char = chunk:sub(spos, spos) + if char == '"' then -- String end + chunk = chunk:sub(spos + 1) + break + elseif char == "\\" then -- Escape sequence + chunk, object = self:parse_escape(chunk:sub(spos)) + str = str .. object + end + else + str = str .. chunk + chunk = self:fetch() + assert(chunk, "Unexpected EOS while parsing a string") + end + end + + return chunk, str +end + + +function Decoder.parse_escape(self, chunk) + local str = "" + chunk = self:fetch_atleast(chunk:sub(2), 1) + local char = chunk:sub(1, 1) + chunk = chunk:sub(2) + + if char == '"' then + return chunk, '"' + elseif char == "\\" then + return chunk, "\\" + elseif char == "u" then + chunk = self:fetch_atleast(chunk, 4) + local s1, s2 = chunk:sub(1, 2), chunk:sub(3, 4) + s1, s2 = tonumber(s1, 16), tonumber(s2, 16) + assert(s1 and s2, "Invalid Unicode character") + + -- ToDo: Unicode support + return chunk:sub(5), s1 == 0 and string.char(s2) or "" + elseif char == "/" then + return chunk, "/" + elseif char == "b" then + return chunk, "\b" + elseif char == "f" then + return chunk, "\f" + elseif char == "n" then + return chunk, "\n" + elseif char == "r" then + return chunk, "\r" + elseif char == "t" then + return chunk, "\t" + else + error("Unexpected escaping sequence '\\%s'" % char) + end +end + + +function Decoder.parse_array(self, chunk) + chunk = chunk:sub(2) + local array = {} + local nextp = 1 + + local chunk, object = self:parse_delimiter(chunk, "%]") + + if object then + return chunk, array + end + + repeat + chunk, object = self:dispatch(chunk, nil, true) + table.insert(array, nextp, object) + nextp = nextp + 1 + + chunk, object = self:parse_delimiter(chunk, ",%]") + assert(object, "Delimiter expected") + until object == "]" + + return chunk, array +end + + +function Decoder.parse_object(self, chunk) + chunk = chunk:sub(2) + local array = {} + local name + + local chunk, object = self:parse_delimiter(chunk, "}") + + if object then + return chunk, array + end + + repeat + chunk = self:parse_space(chunk) + assert(chunk, "Unexpected EOS") + + chunk, name = self:parse_string(chunk) + + chunk, object = self:parse_delimiter(chunk, ":") + assert(object, "Separator expected") + + chunk, object = self:dispatch(chunk, nil, true) + array[name] = object + + chunk, object = self:parse_delimiter(chunk, ",}") + assert(object, "Delimiter expected") + until object == "}" + + return chunk, array +end + + +function Decoder.parse_delimiter(self, chunk, delimiter) + while true do + chunk = self:fetch_atleast(chunk, 1) + local char = chunk:sub(1, 1) + if char:match("%s") then + chunk = self:parse_space(chunk) + assert(chunk, "Unexpected EOS") + elseif char:match("[%s]" % delimiter) then + return chunk:sub(2), char + else + return chunk, nil + end + end +end + + +Decoder.parsers = { + ['"'] = Decoder.parse_string, + ['t'] = Decoder.parse_true, + ['f'] = Decoder.parse_false, + ['n'] = Decoder.parse_null, + ['['] = Decoder.parse_array, + ['{'] = Decoder.parse_object +} + + +--- Create a new Active JSON-Decoder. +-- @class function +-- @name ActiveDecoder +-- @param customnull Use luci.json.null instead of nil for decoding null +-- @return Active JSON-Decoder +ActiveDecoder = util.class(Decoder) + +function ActiveDecoder.__init__(self, source, customnull) + Decoder.__init__(self, customnull) + self.source = source + self.chunk = nil + getmetatable(self).__call = self.get +end + + +--- Fetches one JSON-object from given source +-- @return Decoded object +function ActiveDecoder.get(self) + local chunk, src_err, object + if not self.chunk then + chunk, src_err = self.source() + else + chunk = self.chunk + end + + self.chunk, object = self:dispatch(chunk, src_err, true) + return object +end + + +function ActiveDecoder.fetch(self) + local chunk, src_err = self.source() + assert(chunk or not src_err, src_err) + return chunk +end diff --git a/openwrt/packages/luci/libs/lpk/Makefile b/openwrt/packages/luci/libs/lpk/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk.lua new file mode 100644 index 0000000..7117c75 --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/luasrc/lpk.lua @@ -0,0 +1,41 @@ +module("luci.lpk", package.seeall) +require("luci.lpk.util") +require("luci.lpk.core") + +__appname__ = "LuCI »lpk« Package Manager" +__version__ = "0.1" +__authors__ = "Steven Barth, Jo-Philipp Wich" +__cpyrght__ = string.format("Copyright (c) 2008 %s", __authors__) + + +options, arguments = luci.lpk.util.getopt(arg) +config = luci.util.dtable() +machine = luci.lpk.core.Machine() + +local cfgdump = loadfile("/etc/lpk.conf") +if cfgdump then + setfenv(cfgdump, config) + pcall(cfgdump) +end + +if #arguments < 1 then + luci.lpk.util.splash() +else + local task, error = machine:task(table.remove(arguments, 1), + unpack(arguments)) + + if task then + local stat, error = task:perform() + if not stat then + luci.util.perror(error or task.register.errstr or "Unknown Error") + os.exit(task.register.error or 1) + end + else + luci.util.perror((error or "Unknown Error") .. "\n") + luci.lpk.util.splash() + os.exit(1) + end +end + + + diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk/core.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core.lua new file mode 100644 index 0000000..97de4fa --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core.lua @@ -0,0 +1,107 @@ +module("luci.lpk.core", package.seeall) +require("luci.util") + +Task = luci.util.class() + +function Task.__init__(self, machine, register, start) + self.machine = machine + + -- The queue that has to be processed + self.work = {start} + + -- The queue that has to be processed in case of rollback + self.done = {} + + -- The Task register + self.register = register +end + +function Task.rollback(self) + if #self.done < 1 then + return false + end + + local state = table.remove(self.done) + if not state.rollback then + return true + end + + local ret, err = pcall(state.rollback, state, self.register) + + if ret then + return true + else + return false, err + end +end + +function Task.step(self) + local state = table.remove(self.work) + local ret, next = pcall(state.process, self.register) + + if ret then + if next then + local nstate = self.machine:state(next) + if nstate then + table.insert(self.work, state) + table.insert(self.work, nstate) + else + self.register.error = 2 + self.register.errstr = "Unknown state: " .. next + return false + end + else + table.insert(self.done, state) + end + + return #self.work > 0 + else + self.register.error = next + return false + end +end + +function Task.perform(self) + while self:step() do + end + + if not self.register.error then + return true + else + local stat, err + repeat + stat, err = self:rollback() + until not stat + + if err then + self.register.errstr = err + self.register.error = 2 + end + + return false + end +end + + +Machine = luci.util.class() + +function Machine.__init__(self, namespace) + self.namespace = namespace or _NAME +end + +function Machine.state(self, name) + local ret, state = pcall(require, self.namespace .. "." .. name) + return ret and state +end + +function Machine.task(self, name, ...) + local start = self:state(name) + + if type(start) ~= "table" or not start.entry then + return false, "No such command: " .. name + end + + local register = {} + + return start.entry(register, ...) and Task(self, register, start) +end diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/download.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/download.lua new file mode 100644 index 0000000..7b30647 --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/download.lua @@ -0,0 +1 @@ +module("luci.lpk.core.download", package.seeall) diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/install.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/install.lua new file mode 100644 index 0000000..434f618 --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/install.lua @@ -0,0 +1,16 @@ +module("luci.lpk.core.install", package.seeall) + +function entry(register, ...) + print("Requested install of " .. table.concat(arg, ", ")) + return true +end + +function process(register) + register.sometext = "Test" + if not register.retrieved then + print("Step down to retrieve") + return "retrieve" + else + print("Coming up again") + end +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/resolve.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/resolve.lua new file mode 100644 index 0000000..e69de29 diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/retrieve.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/retrieve.lua new file mode 100644 index 0000000..6176a94 --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/retrieve.lua @@ -0,0 +1,7 @@ +module("luci.lpk.core.retrieve", package.seeall) + +function process(register) + print "Now in retrieve" + print (register.sometext) + register.retrieved = true +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/unpack.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk/core/unpack.lua new file mode 100644 index 0000000..e69de29 diff --git a/openwrt/packages/luci/libs/lpk/luasrc/lpk/util.lua b/openwrt/packages/luci/libs/lpk/luasrc/lpk/util.lua new file mode 100644 index 0000000..95bdb96 --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/luasrc/lpk/util.lua @@ -0,0 +1,59 @@ +module("luci.lpk.util", package.seeall) + +function getopt( arg, options ) + options = options or "" + local tab = {} + local args = {} + for k, v in ipairs(arg) do + if v:sub(1, 2) == "--" then + local x = v:find( "=", 1, true ) + if x then + tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 ) + else + tab[ v:sub( 3 ) ] = true + end + elseif v:sub( 1, 1 ) == "-" then + local y = 2 + local l = #v + local jopt + while ( y <= l ) do + jopt = v:sub( y, y ) + if options:find( jopt, 1, true ) then + if y < l then + tab[ jopt ] = v:sub( y+1 ) + y = l + else + tab[ jopt ] = arg[ k + 1 ] + arg[ k + 1 ] = "" + end + else + tab[ jopt ] = true + end + y = y + 1 + end + elseif #v > 0 then + table.insert(args, v) + end + end + return tab, args +end + +function splash() + require("luci.lpk") + luci.util.perror(string.format("%s v%s\n%s", + luci.lpk.__appname__, luci.lpk.__version__, luci.lpk.__cpyrght__)) + luci.util.perror([[ + +Usage: + lpk [options] [arguments] + lpk [options] install|remove pkg1 [pkg2] [...] [pkgn] + +Commands: + install - Install packages + remove - Remove packages + purge - Remove packages and their configuration files + +Options: + --force-depends - Ignore unresolvable dependencies +]]) +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/lpk/root/etc/lpk.conf b/openwrt/packages/luci/libs/lpk/root/etc/lpk.conf new file mode 100644 index 0000000..7ff49f8 --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/root/etc/lpk.conf @@ -0,0 +1 @@ +backend.model = "ipkg" \ No newline at end of file diff --git a/openwrt/packages/luci/libs/lpk/root/usr/bin/lpk b/openwrt/packages/luci/libs/lpk/root/usr/bin/lpk new file mode 100755 index 0000000..6e6dcde --- /dev/null +++ b/openwrt/packages/luci/libs/lpk/root/usr/bin/lpk @@ -0,0 +1,2 @@ +#!/usr/bin/lua +require("luci.lpk") \ No newline at end of file diff --git a/openwrt/packages/luci/libs/lucittpd/Makefile b/openwrt/packages/luci/libs/lucittpd/Makefile new file mode 100644 index 0000000..3d1a911 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/Makefile @@ -0,0 +1,18 @@ +ifeq ($(CFLAGS),) + MYLDFLAGS ?= -L../../../contrib/uci/dist/usr/lib/ +endif + +include ../../build/module.mk +include ../../build/config.mk +include ../../build/gccconfig.mk + +compile: + make -Csrc \ + CFLAGS="$(CFLAGS) $(FPIC) $(LUA_CFLAGS) $(EXTRA_CFLAGS) $(WFLAGS)" \ + LDFLAGS="$(LDFLAGS) $(LUA_SHLIBS) -luci" \ + MYLDFLAGS="$(MYLDFLAGS)" + mkdir -p dist/usr/bin + cp src/lucittpd dist/usr/bin + +clean: luaclean + make -Csrc clean diff --git a/openwrt/packages/luci/libs/lucittpd/hostfiles/usr/lib/lucittpd/plugins/httpd.lua b/openwrt/packages/luci/libs/lucittpd/hostfiles/usr/lib/lucittpd/plugins/httpd.lua new file mode 100644 index 0000000..e40af98 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/hostfiles/usr/lib/lucittpd/plugins/httpd.lua @@ -0,0 +1,34 @@ +function initialize() + local lucittpd = require "luci.ttpd.server" + server = lucittpd.Server(lucittpd.VHost()) +end + +function register() + local filehnd = require "luci.ttpd.handler.file" + local filehandler = filehnd.Simple(os.getenv("LUCI_SYSROOT") .. "/www") + server:get_default_vhost():set_default_handler(filehandler) +end + +function accept() + server:process({ + _read = function(...) + local chunk, err = webuci_read(...) + return chunk or (err and error(err, 0)) + end, + + _write = function(...) + local chunk, err = webuci_write(...) + return chunk or (err and error(err, 0)) + end, + + _close = function(...) + local chunk, err = webuci_close(...) + return chunk or (err and error(err, 0)) + end, + + _sendfile = function(...) + local chunk, err = webuci_sendfile(...) + return chunk or (err and error(err, 0)) + end + }) +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/lucittpd/ipkg/postinst b/openwrt/packages/luci/libs/lucittpd/ipkg/postinst new file mode 100755 index 0000000..d3890aa --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/ipkg/postinst @@ -0,0 +1,6 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + /etc/init.d/lucittpd enabled || /etc/init.d/lucittpd enable + /etc/init.d/lucittpd start || true +} + diff --git a/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/handler/file.lua b/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/handler/file.lua new file mode 100644 index 0000000..e1f707c --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/handler/file.lua @@ -0,0 +1,252 @@ +--[[ + +HTTP server implementation for LuCI - file handler +(c) 2008 Steven Barth +(c) 2008 Freifunk Leipzig / Jo-Philipp Wich + +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$ + +]]-- + +local ipairs, type, tonumber = ipairs, type, tonumber +local io = require "io" +local os = require "os" +local fs = require "luci.fs" +local util = require "luci.util" +local ltn12 = require "luci.ltn12" +local mod = require "luci.ttpd.module" +local srv = require "luci.ttpd.server" +local string = require "string" + +local prot = require "luci.http.protocol" +local date = require "luci.http.protocol.date" +local mime = require "luci.http.protocol.mime" +local cond = require "luci.http.protocol.conditionals" + +module "luci.ttpd.handler.file" + +Simple = util.class(mod.Handler) +Response = mod.Response + +function Simple.__init__(self, docroot, dirlist) + mod.Handler.__init__(self) + self.docroot = docroot + self.dirlist = dirlist and true or false +end + +function Simple.parse_range(self, request, size) + if not request.headers.Range then + return true + end + + local from, to = request.headers.Range:match("bytes=([0-9]*)-([0-9]*)") + if not (from or to) then + return true + end + + from, to = tonumber(from), tonumber(to) + if not (from or to) then + return true + elseif not from then + from, to = size - to, size - 1 + elseif not to then + to = size - 1 + end + + -- Not satisfiable + if from >= size then + return false + end + + -- Normalize + if to >= size then + to = size - 1 + end + + local range = "bytes " .. from .. "-" .. to .. "/" .. size + return from, (1 + to - from), range +end + +function Simple.getfile(self, uri) + local file = self.docroot .. uri:gsub("%.%./+", "") + local stat = fs.stat(file) + + return file, stat +end + +function Simple.handle_get(self, request, sourcein, sinkerr) + local file, stat = self:getfile( prot.urldecode( request.env.PATH_INFO, true ) ) + + if stat then + if stat.type == "regular" then + + -- Generate Entity Tag + local etag = cond.mk_etag( stat ) + + -- Check conditionals + local ok, code, hdrs + + ok, code, hdrs = cond.if_modified_since( request, stat ) + if ok then + ok, code, hdrs = cond.if_match( request, stat ) + if ok then + ok, code, hdrs = cond.if_unmodified_since( request, stat ) + if ok then + ok, code, hdrs = cond.if_none_match( request, stat ) + if ok then + local f, err = io.open(file) + + if f then + local code = 200 + local o, s, r = self:parse_range(request, stat.size) + + if not o then + return self:failure(416, "Invalid Range") + end + + local headers = { + ["Last-Modified"] = date.to_http( stat.mtime ), + ["Content-Type"] = mime.to_mime( file ), + ["ETag"] = etag, + ["Accept-Ranges"] = "bytes", + } + + if o == true then + o = 0 + s = stat.size + else + code = 206 + headers["Content-Range"] = r + end + + headers["Content-Length"] = s + + -- Send Response + return Response(code, headers), + srv.IOResource(f, o, s) + else + return self:failure( 403, err:gsub("^.+: ", "") ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + else + return Response( code, hdrs or { } ) + end + + elseif stat.type == "directory" then + + local ruri = request.request_uri:gsub("/$","") + local duri = prot.urldecode( ruri, true ) + local root = self.docroot:gsub("/$","") + + -- check for index files + local index_candidates = { + "index.html", "index.htm", "default.html", "default.htm", + "index.txt", "default.txt" + } + + -- try to find an index file and redirect to it + for i, candidate in ipairs( index_candidates ) do + local istat = fs.stat( + root .. "/" .. duri .. "/" .. candidate + ) + + if istat ~= nil and istat.type == "regular" then + return Response( 302, { + ["Location"] = ruri .. "/" .. candidate + } ) + end + end + + + local html = string.format( + '\n' .. + '\n' .. + '\n' .. + '\n' .. + 'Index of %s/\n' .. + '

Index of %s/


    ', + duri, duri + ) + + local entries = fs.dir( file ) + + if type(entries) == "table" then + for i, e in util.spairs( + entries, function(a,b) + if entries[a] == '..' then + return true + elseif entries[b] == '..' then + return false + else + return ( entries[a] < entries[b] ) + end + end + ) do + if e ~= '.' and ( e == '..' or e:sub(1,1) ~= '.' ) then + local estat = fs.stat( file .. "/" .. e ) + + if estat.type == "directory" then + html = html .. string.format( + '
  • %s/ ' .. + '(directory)
    ' .. + 'Changed: %s

  • ', + ruri, prot.urlencode( e ), e, + date.to_http( estat.mtime ) + ) + else + html = html .. string.format( + '
  • %s ' .. + '(%s)
    ' .. + 'Size: %i Bytes | ' .. + 'Changed: %s

  • ', + ruri, prot.urlencode( e ), e, + mime.to_mime( e ), + estat.size, date.to_http( estat.mtime ) + ) + end + end + end + + html = html .. '

' + + return Response( + 200, { + ["Date"] = date.to_http( os.time() ); + ["Content-Type"] = "text/html; charset=ISO-8859-15"; + } + ), ltn12.source.string(html) + else + return self:failure(403, "Permission denied") + end + else + return self:failure(403, "Unable to transmit " .. stat.type .. " " .. file) + end + else + return self:failure(404, "No such file: " .. file) + end +end + +function Simple.handle_head(self, ...) + return (self:handle_get(...)) +end diff --git a/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/module.lua b/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/module.lua new file mode 100644 index 0000000..1a7c574 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/module.lua @@ -0,0 +1,121 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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$ +]]-- + +local pcall, ipairs, tonumber, type, next = pcall, ipairs, tonumber, type, next +local util = require "luci.util" +local http = require "luci.http.protocol" +local ltn12 = require "luci.ltn12" +local table = require "table" + +module "luci.ttpd.module" + + +-- Server handler implementation +Handler = util.class() + +-- Constructor +function Handler.__init__(self) + self.handler = {} + self.filters = {} + self.modifiers = {} +end + +-- Add a filter +function Handler.setfilter(self, filter, key) + self.filters[(key) or (#self.filters+1)] = filter +end + +-- Add a modifier +function Handler.setmodifier(self, modifier, key) + self.modifiers[(pos) or (#self.modifiers+1)] = modifier +end + +-- Creates a failure reply +function Handler.failure(self, code, message) + local response = Response(code, { ["Content-Type"] = "text/plain" }) + local sourceout = ltn12.source.string(message) + + return response, sourceout +end + +-- Processes a request +function Handler.process(self, request, sourcein, sinkerr) + local stat, response, sourceout + + -- Detect request Method + local hname = "handle_" .. request.request_method + if self[hname] then + local t = { + processor = self[hname], + handler = self, + request = request, + sourcein = sourcein, + sinkerr = sinkerr + } + + if next(self.modifiers) then + for _, mod in util.kspairs(self.modifiers) do + mod(t) + end + end + + -- Run the handler + stat, response, sourceout = pcall( + t.processor, t.handler, t.request, t.sourcein, t.sinkerr + ) + + -- Check for any errors + if not stat then + response, sourceout = self:failure(500, response) + elseif next(self.filters) then + local t = { + response = response, + sourceout = sourceout, + sinkerr = t.sinkerr + } + + for _, filter in util.kspairs(self.filters) do + filter(t) + end + + response = t.response + sourceout = t.sourceout + end + else + response, sourceout = self:failure(405, http.protocol.statusmsg[405]) + end + + -- Check data + if not util.instanceof(response, Response) then + response, sourceout = self:failure(500, "Core error: Invalid module response!") + end + + return response, sourceout +end + +-- Handler Response +Response = util.class() + +function Response.__init__(self, status, headers) + self.status = tonumber(status) or 200 + self.headers = (type(headers) == "table") and headers or {} +end + +function Response.addheader(self, key, value) + self.headers[key] = value +end + +function Response.setstatus(self, status) + self.status = status +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/server.lua b/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/server.lua new file mode 100644 index 0000000..a2c7ffc --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/luasrc/ttpd/server.lua @@ -0,0 +1,444 @@ +--[[ +LuCIttpd +(c) 2008 Steven Barth +(c) 2008 Jo-Philipp Wich + +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$ +]]-- + +local ipairs, pairs = ipairs, pairs +local tostring, tonumber = tostring, tonumber +local pcall, assert = pcall, assert + +local os = require "os" +local io = require "io" +local uci = require "luci.model.uci" +local util = require "luci.util" +local ltn12 = require "luci.ltn12" +local proto = require "luci.http.protocol" +local string = require "string" +local date = require "luci.http.protocol.date" + +module "luci.ttpd.server" + +BUFSIZE = 4096 +VERSION = 0.91 + + +-- File Resource +IOResource = util.class() + +function IOResource.__init__(self, fd, offset, len) + self.fd, self.offset, self.len = fd, offset, len +end + + +VHost = util.class() + +function VHost.__init__(self, handler) + self.handler = handler + self.dhandler = {} +end + +function VHost.process(self, request, sourcein, sinkerr, ...) + local handler = self.handler + + local uri = request.env.REQUEST_URI:match("^([^?]*)") + + -- SCRIPT_NAME + request.env.SCRIPT_NAME = "" + + -- Call URI part + request.env.PATH_INFO = uri + + for k, dhandler in pairs(self.dhandler) do + if k == uri or k.."/" == uri:sub(1, #k+1) then + handler = dhandler + request.env.SCRIPT_NAME = k + request.env.PATH_INFO = uri:sub(#k+1) + break; + end + end + + if handler then + return handler:process(request, sourcein, sinkerr, ...) + end +end + +function VHost.get_default_handler(self) + return self.handler +end + +function VHost.set_default_handler(self, handler) + self.handler = handler +end + +function VHost.get_handlers(self) + return self.dhandler +end + +function VHost.set_handler(self, match, handler) + self.dhandler[match] = handler +end + + + +Server = util.class() + +function Server.__init__(self, host) + self.uci = uci.cursor() + self.host = host + self.vhosts = {} + + self.rbuf = "" + self.wbuf = "" +end + +function Server.get_default_vhost(self) + return self.host +end + +function Server.set_default_vhost(self, vhost) + self.host = vhost +end + +function Server.get_vhosts(self) + return self.vhosts +end + +function Server.set_vhost(self, name, vhost) + self.vhosts[name] = vhost +end + +function Server.flush(self) + if #self.wbuf > 0 then + self._write(self.wbuf) + self.wbuf = "" + end +end + +function Server.read(self, len) + while #self.rbuf < len do + self.rbuf = self.rbuf .. self._read(len - #self.rbuf) + end + + local chunk = self.rbuf:sub(1, len) + self.rbuf = self.rbuf:sub(len + 1) + return chunk +end + +function Server.limitsource(self, limit) + limit = limit or 0 + + return function() + if limit < 1 then + return nil + else + local read = (limit > BUFSIZE) and BUFSIZE or limit + limit = limit - read + return self:read(read) + end + end +end + +-- Adapted from Luaposix +function Server.receiveheaders(self) + local line, name, value, err + local headers = {} + -- get first line + line, err = self:readline() + if err then return nil, err end + -- headers go until a blank line is found + while line do + -- get field-name and value + _, _, name, value = line:find("^(.-):%s*(.*)") + if not (name and value) then return nil, "malformed reponse headers" end + name = name:lower() + -- get next line (value might be folded) + line, err = self:readline() + if err then return nil, err end + -- unfold any folded values + while line:find("^%s") do + value = value .. line + line = self:readline() + if err then return nil, err end + end + -- save pair in table + if headers[name] then headers[name] = headers[name] .. ", " .. value + else headers[name] = value end + end + return headers +end + +function Server.readchunk(self) + -- get chunk size, skip extention + local line, err = self:readline() + if err then return nil, err end + local size = tonumber(line:gsub(";.*", ""), 16) + if not size then return nil, "invalid chunk size" end + -- was it the last chunk? + if size > 0 then + -- if not, get chunk and skip terminating CRLF + local chunk, err, part = self:read(size) + if chunk then self:readline() end + return chunk, err + else + -- if it was, read trailers into headers table + headers, err = self:receiveheaders() + if not headers then return nil, err end + end +end + +function Server.readline(self) + if #self.rbuf < 1 then + self.rbuf = self._read(BUFSIZE) + end + + while true do + local le = self.rbuf:find("\r\n", nil, true) + if le then + if le == 1 then -- EoH + self.rbuf = self.rbuf:sub(le + 2) + return nil + else -- Header + local line = self.rbuf:sub(1, le - 1) + self.rbuf = self.rbuf:sub(le + 2) + return line + end + else + if #self.rbuf >= BUFSIZE then + return nil, "Invalid Request" + end + self.rbuf = self.rbuf .. self._read(BUFSIZE-#self.rbuf) + end + end +end + +function Server.sink(self) + return function(chunk, err) + if err then + return nil, err + elseif chunk then + local stat, err = pcall(self.write, self, chunk) + if stat then + return stat + else + return nil, err + end + else + return true + end + end +end + +function Server.chunksink(self) + return function(chunk, err) + local stat, err = pcall(self.writechunk, self, chunk) + if stat then + return stat + else + return nil, err + end + end +end + +function Server.writechunk(self, chunk, err) + self:flush() + if not chunk then return self._write("0\r\n\r\n") end + local size = string.format("%X\r\n", #chunk) + return self._write(size .. chunk .. "\r\n") +end + +function Server.write(self, chunk) + while #chunk > 0 do + local missing = BUFSIZE - #self.wbuf + self.wbuf = self.wbuf .. chunk:sub(1, missing) + chunk = chunk:sub(missing + 1) + if #self.wbuf == BUFSIZE then + assert(self._write(self.wbuf)) + self.wbuf = "" + end + end +end + +function Server.close(self) + self:flush() + self._close() +end + +function Server.sendfile(self, fd, offset, len) + self:flush() + self._sendfile(fd, offset, len) +end + + +function Server.error(self, code, msg) + hcode = tostring(code) + + self:write( "HTTP/1.0 " .. hcode .. " " .. + proto.statusmsg[code] .. "\r\n" ) + self:write( "Connection: close\r\n" ) + self:write( "Content-Type: text/plain\r\n\r\n" ) + + if msg then + self:write( "HTTP-Error " .. code .. ": " .. msg .. "\r\n" ) + end +end + + +function Server.process(self, functions) + util.update(self, functions) + + local sourcein = ltn12.source.empty() + local sourcehdr = function() return self:readline() or "" end + local sinkerr = ltn12.sink.file( io.stderr ) + local sinkout = self:sink() + + local close = false + local stat, message, err + + repeat + -- parse headers + stat, message, err = pcall(proto.parse_message_header, sourcehdr) + + -- remote socket closed + if not stat and message == 0 then + break + end + + -- remote timeout + if not stat and message == 11 then + --self:error(408) + break + end + + -- any other error + if not stat or not message then + self:error(400, err) + break + end + + -- keep-alive + if message.http_version == 1.1 then + close = (message.env.HTTP_CONNECTION == "close") + else + close = not message.env.HTTP_CONNECTION or message.env.HTTP_CONNECTION == "close" + end + -- Uncomment this to disable keep-alive + close = not (self.uci:get("lucittpd", "lucittpd", "keepalive") == "1") + + if message.request_method == "get" or message.request_method == "head" then + -- Be happy + + elseif message.request_method == "post" then + -- If we have a HTTP/1.1 client and an Expect: 100-continue header then + -- respond with HTTP 100 Continue message + if message.http_version == 1.1 and message.headers['Expect'] and + message.headers['Expect'] == '100-continue' + then + self:write("HTTP/1.1 100 Continue\r\n\r\n") + end + + if message.headers['Transfer-Encoding'] and + message.headers['Transfer-Encoding'] ~= "identity" then + sourcein = function() return self:readchunk() end + elseif message.env.CONTENT_LENGTH then + sourcein = self:limitsource( + tonumber(message.env.CONTENT_LENGTH) + ) + else + self:error( 411, proto.statusmsg[411] ) + break + end + else + self:error( 405, proto.statusmsg[405] ) + break + + end + + + local host = self.vhosts[message.env.HTTP_HOST] or self.host + if not host then + self:error( 500, "Unable to find matching host" ) + break; + end + + local response, sourceout = host:process( + message, sourcein, sinkerr, + client, io.stderr + ) + if not response then + self:error( 500, "Error processing handler" ) + end + + -- Post process response + if sourceout then + if util.instanceof(sourceout, IOResource) then + if not response.headers["Content-Length"] then + response.headers["Content-Length"] = sourceout.len + end + end + if not response.headers["Content-Length"] then + if message.http_version == 1.1 then + response.headers["Transfer-Encoding"] = "chunked" + sinkout = self:chunksink() + else + close = true + end + end + elseif message.request_method ~= "head" then + response.headers["Content-Length"] = 0 + end + + if close then + response.headers["Connection"] = "close" + end + + response.headers["Date"] = date.to_http(os.time()) + + local header = + message.env.SERVER_PROTOCOL .. " " .. + tostring(response.status) .. " " .. + proto.statusmsg[response.status] .. "\r\n" + + header = header .. "Server: LuCIttpd/" .. tostring(VERSION) .. "\r\n" + + + for k,v in pairs(response.headers) do + header = header .. k .. ": " .. v .. "\r\n" + end + + -- Output + local stat, err = pcall(function() + self:write(header .. "\r\n") + + if sourceout then + if util.instanceof(sourceout, IOResource) then + self:sendfile(sourceout.fd, sourceout.offset, sourceout.len) + else + ltn12.pump.all(sourceout, sinkout) + end + end + + self:flush() + end) + + -- Write errors + if not stat then + if err == 107 then + -- Remote end closed the socket, so do we + elseif err then + io.stderr:write("Error sending data: " .. err .. "\n") + end + break + end + until close + + self:close() +end diff --git a/openwrt/packages/luci/libs/lucittpd/root/etc/config/lucittpd b/openwrt/packages/luci/libs/lucittpd/root/etc/config/lucittpd new file mode 100644 index 0000000..803a6e5 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/root/etc/config/lucittpd @@ -0,0 +1,6 @@ +config lucittpd lucittpd + option port 80 + option timeout 90 + option keepalive 0 + option path /usr/lib/lucittpd/plugins/ + option root /www diff --git a/openwrt/packages/luci/libs/lucittpd/root/etc/init.d/lucittpd b/openwrt/packages/luci/libs/lucittpd/root/etc/init.d/lucittpd new file mode 100755 index 0000000..a7f78e0 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/root/etc/init.d/lucittpd @@ -0,0 +1,44 @@ +#!/bin/sh /etc/rc.common +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/lucittpd +NAME=lucittpd +DESC="HTTP server" +START=49 + +test -x $DAEMON || exit 0 +set -e + +start() { + echo -n "Starting $DESC: $NAME" + start-stop-daemon -b -S -q -x $DAEMON + echo "." +} + +stop() { + echo -n "Stopping $DESC: $NAME" + start-stop-daemon -K -q -x $DAEMON + echo "." +} + +restart() { + # echo -n "Restarting $DESC: $NAME... " + # start-stop-daemon -K -s HUP -q -x $DAEMON + # echo "done." + stop + sleep 3 + start +} + +reload() { + # + # If the daemon can reload its config files on the fly + # for example by sending it SIGHUP, do it here. + # + # If the daemon responds to changes in its config file + # directly anyway, make this a do-nothing entry. + # + # echo -n "Reloading $DESC configuration... " + # start-stop-daemon -K -s 1 -q -x $DAEMON + # echo "done." + restart +} diff --git a/openwrt/packages/luci/libs/lucittpd/root/usr/lib/lucittpd/plugins/httpd.lua b/openwrt/packages/luci/libs/lucittpd/root/usr/lib/lucittpd/plugins/httpd.lua new file mode 100644 index 0000000..2d3a9d8 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/root/usr/lib/lucittpd/plugins/httpd.lua @@ -0,0 +1,35 @@ +function initialize() + local lucittpd = require "luci.ttpd.server" + server = lucittpd.Server(lucittpd.VHost()) +end + +function register() + local filehnd = require "luci.ttpd.handler.file" + local uci = require "luci.model.uci".cursor() + local filehandler = filehnd.Simple((uci:get("lucittpd", "lucittpd", "root") or "/www")) + server:get_default_vhost():set_default_handler(filehandler) +end + +function accept() + server:process({ + _read = function(...) + local chunk, err = webuci_read(...) + return chunk or (err and error(err, 0)) + end, + + _write = function(...) + local chunk, err = webuci_write(...) + return chunk or (err and error(err, 0)) + end, + + _close = function(...) + local chunk, err = webuci_close(...) + return chunk or (err and error(err, 0)) + end, + + _sendfile = function(...) + local chunk, err = webuci_sendfile(...) + return chunk or (err and error(err, 0)) + end + }) +end diff --git a/openwrt/packages/luci/libs/lucittpd/src/.gitignore b/openwrt/packages/luci/libs/lucittpd/src/.gitignore new file mode 100644 index 0000000..882c68c --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/.gitignore @@ -0,0 +1 @@ +lucittpd diff --git a/openwrt/packages/luci/libs/lucittpd/src/Makefile b/openwrt/packages/luci/libs/lucittpd/src/Makefile new file mode 100644 index 0000000..1e70faf --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/Makefile @@ -0,0 +1,20 @@ +PROGS=lucittpd +STRIP?=strip +CFLAGS?= +CFLAGS+=-pedantic -Werror -Wall -std=gnu99 -I/usr/include/lua5.1/ +CPPFLAGS=-I./include +LDFLAGS?= +LDFLAGS+=-luci -llua5.1 +OBJS=main.o lib/log.o lib/signal.o lib/uci.o lib/luaplugin.o + +all: $(PROGS) + +$(PROGS): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(MYLDFLAGS) $^ -o $@ + #$(CC) $(CFLAGS) -shared -Wl,-soname,gdata $(LDFLAGS) $^ -o $@ + +clean: + rm -f $(PROGS) *.o *.so lib/*.o + +%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(MYCFLAGS) -c $^ -o $@ diff --git a/openwrt/packages/luci/libs/lucittpd/src/include/lib/list.h b/openwrt/packages/luci/libs/lucittpd/src/include/lib/list.h new file mode 100644 index 0000000..2959a06 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/include/lib/list.h @@ -0,0 +1,601 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#include +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#ifndef container_of +#define container_of(ptr, type, member) ( \ + (type *)( (char *)ptr - offsetof(type,member) )) +#endif + + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = NULL; + entry->prev = NULL; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = NULL; + n->pprev = NULL; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos; pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after current point + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from current point + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop cursor. + * @pos: the &struct hlist_node to use as a loop cursor. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +#endif diff --git a/openwrt/packages/luci/libs/lucittpd/src/include/lib/log.h b/openwrt/packages/luci/libs/lucittpd/src/include/lib/log.h new file mode 100644 index 0000000..1199578 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/include/lib/log.h @@ -0,0 +1,24 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Provided by fon.com + * Copyright (C) 2008 John Crispin + */ + +#ifndef _LOG_H__ +#define _LOG_H__ +void log_printf(char *fmt, ...); +void log_start(int daemon); +#endif diff --git a/openwrt/packages/luci/libs/lucittpd/src/include/lib/luaplugin.h b/openwrt/packages/luci/libs/lucittpd/src/include/lib/luaplugin.h new file mode 100644 index 0000000..fca6cb7 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/include/lib/luaplugin.h @@ -0,0 +1,71 @@ +/* + * luaplugin - fast lua plugin indexing + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __LUAPLUGIN_H +#define __LUAPLUGIN_H + +#include +#include +#include +#include +#include "list.h" + +struct luaplugin_entry { + struct luaplugin_ctx *ctx; + struct list_head list; + time_t timestamp; + int checked; + bool loaded; + bool reload; + char *name; + char *module; + + /* privdata for the caller */ + void *priv; +}; + +struct luaplugin_ctx { + const char *path; + const struct luaplugin_ops *ops; + lua_State *L; + int checked; + struct list_head *last; + struct list_head entries; +}; + +/** luaplugin_init: + * initialize the luaplugin context (allocates a new lua context) + */ +extern int luaplugin_init(struct luaplugin_ctx *ctx, const char *path); + +/** luaplugin_scan: + * rescan the plugin cache + */ +extern void luaplugin_scan(struct luaplugin_ctx *ctx); + +/** luaplugin_call: + * call out to a lua function. + * to be able to use this, you need to push the function name on the lua stack (ctx->L) + * and then narg function arguments afterwards. + * this call pops (narg + 1) arguments from the stack + * returns -ENOENT if the function was not found + */ +extern int luaplugin_call(struct luaplugin_entry *e, int narg); + +/** luaplugin_done: + * drop the luaplugin context (and associated lua context) + * frees all memory allocated by the library + */ +extern void luaplugin_done(struct luaplugin_ctx *ctx); + +#endif diff --git a/openwrt/packages/luci/libs/lucittpd/src/include/lib/signal.h b/openwrt/packages/luci/libs/lucittpd/src/include/lib/signal.h new file mode 100644 index 0000000..cfcce0a --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/include/lib/signal.h @@ -0,0 +1,25 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Provided by fon.com + * Copyright (C) 2008 John Crispin + */ + +#ifndef _SIGNAL_H__ +#define _SIGNAL_H__ + +void setup_signals(void); + +#endif diff --git a/openwrt/packages/luci/libs/lucittpd/src/include/lib/uci.h b/openwrt/packages/luci/libs/lucittpd/src/include/lib/uci.h new file mode 100644 index 0000000..4a1a01c --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/include/lib/uci.h @@ -0,0 +1,54 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2008 John Crispin + */ + +#ifndef _UCI_H__ +#define _UCI_H__ +#include +#include + +struct ucilist { + struct list_head list; + char *val; +}; + +struct uci_context* ucix_init(const char *config_file); +struct uci_context* ucix_init_path(const char *path, const char *config_file); +void ucix_cleanup(struct uci_context *ctx); +void ucix_save(struct uci_context *ctx); +void ucix_save_state(struct uci_context *ctx); +const char* ucix_get_option(struct uci_context *ctx, + const char *p, const char *s, const char *o); +int ucix_get_option_list(struct uci_context *ctx, const char *p, + const char *s, const char *o, struct list_head *l); +int ucix_get_option_int(struct uci_context *ctx, + const char *p, const char *s, const char *o, int def); +void ucix_add_section(struct uci_context *ctx, + const char *p, const char *s, const char *t); +void ucix_add_option(struct uci_context *ctx, + const char *p, const char *s, const char *o, const char *t); +void ucix_add_option_int(struct uci_context *ctx, + const char *p, const char *s, const char *o, int t); +void ucix_for_each_section_type(struct uci_context *ctx, + const char *p, const char *t, + void (*cb)(const char*, void*), void *priv); +int ucix_commit(struct uci_context *ctx, const char *p); +void ucix_revert(struct uci_context *ctx, + const char *p, const char *s, const char *o); +void ucix_del(struct uci_context *ctx, const char *p, + const char *s, const char *o); +#endif diff --git a/openwrt/packages/luci/libs/lucittpd/src/include/uci.h b/openwrt/packages/luci/libs/lucittpd/src/include/uci.h new file mode 100644 index 0000000..d48ea7c --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/include/uci.h @@ -0,0 +1,543 @@ +/* + * libuci - Library for the Unified Configuration Interface + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LIBUCI_H +#define __LIBUCI_H + +#include "uci_config.h" + +/* + * you can use these defines to enable debugging behavior for + * apps compiled against libuci: + * + * #define UCI_DEBUG_TYPECAST: + * enable uci_element typecast checking at run time + * + */ + +#include +#include +#include + +#define UCI_CONFDIR "/etc/config" +#define UCI_SAVEDIR "/tmp/.uci" +#define UCI_DIRMODE 0700 +#define UCI_FILEMODE 0600 + +enum +{ + UCI_OK = 0, + UCI_ERR_MEM, + UCI_ERR_INVAL, + UCI_ERR_NOTFOUND, + UCI_ERR_IO, + UCI_ERR_PARSE, + UCI_ERR_DUPLICATE, + UCI_ERR_UNKNOWN, + UCI_ERR_LAST +}; + +struct uci_list; +struct uci_list +{ + struct uci_list *next; + struct uci_list *prev; +}; + +struct uci_ptr; +struct uci_element; +struct uci_package; +struct uci_section; +struct uci_option; +struct uci_history; +struct uci_context; +struct uci_backend; +struct uci_parse_context; + + +/** + * uci_alloc_context: Allocate a new uci context + */ +extern struct uci_context *uci_alloc_context(void); + +/** + * uci_free_context: Free the uci context including all of its data + */ +extern void uci_free_context(struct uci_context *ctx); + +/** + * uci_perror: Print the last uci error that occured + * @ctx: uci context + * @str: string to print before the error message + */ +extern void uci_perror(struct uci_context *ctx, const char *str); + +/** + * uci_geterror: Get an error string for the last uci error + * @ctx: uci context + * @dest: target pointer for the string + * @str: prefix for the error message + * + * Note: string must be freed by the caller + */ +extern void uci_get_errorstr(struct uci_context *ctx, char **dest, const char *str); + +/** + * uci_import: Import uci config data from a stream + * @ctx: uci context + * @stream: file stream to import from + * @name: (optional) assume the config has the given name + * @package: (optional) store the last parsed config package in this variable + * @single: ignore the 'package' keyword and parse everything into a single package + * + * the name parameter is for config files that don't explicitly use the 'package <...>' keyword + * if 'package' points to a non-null struct pointer, enable history tracking and merge + */ +extern int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct uci_package **package, bool single); + +/** + * uci_export: Export one or all uci config packages + * @ctx: uci context + * @stream: output stream + * @package: (optional) uci config package to export + * @header: include the package header + */ +extern int uci_export(struct uci_context *ctx, FILE *stream, struct uci_package *package, bool header); + +/** + * uci_load: Parse an uci config file and store it in the uci context + * + * @ctx: uci context + * @name: name of the config file (relative to the config directory) + * @package: store the loaded config package in this variable + */ +extern int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package); + +/** + * uci_unload: Unload a config file from the uci context + * + * @ctx: uci context + * @package: pointer to the uci_package struct + */ +extern int uci_unload(struct uci_context *ctx, struct uci_package *p); + +/** + * uci_lookup_ptr: Split an uci tuple string and look up an element tree + * @ctx: uci context + * @ptr: lookup result struct + * @str: uci tuple string to look up + * @extended: allow extended syntax lookup + * + * if extended is set to true, uci_lookup_ptr supports the following + * extended syntax: + * + * Examples: + * network.@interface[0].ifname ('ifname' option of the first interface section) + * network.@interface[-1] (last interface section) + * Note: uci_lookup_ext will automatically load a config package if necessary + */ +extern int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended); + +/** + * uci_add_section: Add an unnamed section + * @ctx: uci context + * @p: package to add the section to + * @type: section type + * @res: pointer to store a reference to the new section in + */ +extern int uci_add_section(struct uci_context *ctx, struct uci_package *p, const char *type, struct uci_section **res); + +/** + * uci_set: Set an element's value; create the element if necessary + * @ctx: uci context + * @ptr: uci pointer + * + * The updated/created element is stored in ptr->last + */ +extern int uci_set(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_add_list: Append a string to an element list + * @ctx: uci context + * @ptr: uci pointer (with value) + * + * Note: if the given option already contains a string value, + * it will be converted to an 1-element-list before appending the next element + */ +extern int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_rename: Rename an element + * @ctx: uci context + * @ptr: uci pointer (with value) + */ +extern int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_delete: Delete a section or option + * @ctx: uci context + * @ptr: uci pointer + */ +extern int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_save: save change history for a package + * @ctx: uci context + * @p: uci_package struct + */ +extern int uci_save(struct uci_context *ctx, struct uci_package *p); + +/** + * uci_commit: commit changes to a package + * @ctx: uci context + * @p: uci_package struct pointer + * @overwrite: overwrite existing config data and flush history + * + * committing may reload the whole uci_package data, + * the supplied pointer is updated accordingly + */ +extern int uci_commit(struct uci_context *ctx, struct uci_package **p, bool overwrite); + +/** + * uci_list_configs: List available uci config files + * @ctx: uci context + * + * caller is responsible for freeing the allocated memory behind list + */ +extern int uci_list_configs(struct uci_context *ctx, char ***list); + +/** + * uci_set_savedir: override the default history save directory + * @ctx: uci context + * @dir: directory name + */ +extern int uci_set_savedir(struct uci_context *ctx, const char *dir); + +/** + * uci_set_savedir: override the default config storage directory + * @ctx: uci context + * @dir: directory name + */ +extern int uci_set_confdir(struct uci_context *ctx, const char *dir); + +/** + * uci_add_history_path: add a directory to the search path for change history files + * @ctx: uci context + * @dir: directory name + * + * This function allows you to add directories, which contain 'overlays' + * for the active config, that will never be committed. + */ +extern int uci_add_history_path(struct uci_context *ctx, const char *dir); + +/** + * uci_revert: revert all changes to a config item + * @ctx: uci context + * @ptr: uci pointer + */ +extern int uci_revert(struct uci_context *ctx, struct uci_ptr *ptr); + +/** + * uci_parse_argument: parse a shell-style argument, with an arbitrary quoting style + * @ctx: uci context + * @stream: input stream + * @str: pointer to the current line (use NULL for parsing the next line) + * @result: pointer for the result + */ +extern int uci_parse_argument(struct uci_context *ctx, FILE *stream, char **str, char **result); + +/** + * uci_set_backend: change the default backend + * @ctx: uci context + * @name: name of the backend + * + * The default backend is "file", which uses /etc/config for config storage + */ +extern int uci_set_backend(struct uci_context *ctx, const char *name); + +/** + * uci_validate_text: validate a value string for uci options + * @str: value + * + * this function checks whether a given string is acceptable as value + * for uci options + */ +extern bool uci_validate_text(const char *str); + +/* UCI data structures */ +enum uci_type { + UCI_TYPE_UNSPEC = 0, + UCI_TYPE_HISTORY = 1, + UCI_TYPE_PACKAGE = 2, + UCI_TYPE_SECTION = 3, + UCI_TYPE_OPTION = 4, + UCI_TYPE_PATH = 5, + UCI_TYPE_BACKEND = 6, + UCI_TYPE_ITEM = 7, +}; + +enum uci_option_type { + UCI_TYPE_STRING = 0, + UCI_TYPE_LIST = 1, +}; + +enum uci_flags { + UCI_FLAG_STRICT = (1 << 0), /* strict mode for the parser */ + UCI_FLAG_PERROR = (1 << 1), /* print parser error messages */ + UCI_FLAG_EXPORT_NAME = (1 << 2), /* when exporting, name unnamed sections */ + UCI_FLAG_SAVED_HISTORY = (1 << 3), /* store the saved history in memory as well */ +}; + +struct uci_element +{ + struct uci_list list; + enum uci_type type; + char *name; +}; + +struct uci_backend +{ + struct uci_element e; + char **(*list_configs)(struct uci_context *ctx); + struct uci_package *(*load)(struct uci_context *ctx, const char *name); + void (*commit)(struct uci_context *ctx, struct uci_package **p, bool overwrite); + + /* private: */ + const void *ptr; + void *priv; +}; + +struct uci_context +{ + /* list of config packages */ + struct uci_list root; + + /* parser context, use for error handling only */ + struct uci_parse_context *pctx; + + /* backend for import and export */ + struct uci_backend *backend; + struct uci_list backends; + + /* uci runtime flags */ + enum uci_flags flags; + + char *confdir; + char *savedir; + + /* search path for history files */ + struct uci_list history_path; + + /* private: */ + int err; + const char *func; + jmp_buf trap; + bool internal, nested; + char *buf; + int bufsz; +}; + +struct uci_package +{ + struct uci_element e; + struct uci_list sections; + struct uci_context *ctx; + bool has_history; + char *path; + + /* private: */ + struct uci_backend *backend; + void *priv; + int n_section; + struct uci_list history; + struct uci_list saved_history; +}; + +struct uci_section +{ + struct uci_element e; + struct uci_list options; + struct uci_package *package; + bool anonymous; + char *type; +}; + +struct uci_option +{ + struct uci_element e; + struct uci_section *section; + enum uci_option_type type; + union { + struct uci_list list; + char *string; + } v; +}; + +enum uci_command { + UCI_CMD_ADD, + UCI_CMD_REMOVE, + UCI_CMD_CHANGE, + UCI_CMD_RENAME, + UCI_CMD_LIST_ADD, +}; + +struct uci_history +{ + struct uci_element e; + enum uci_command cmd; + char *section; + char *value; +}; + +struct uci_ptr +{ + enum uci_type target; + enum { + UCI_LOOKUP_DONE = (1 << 0), + UCI_LOOKUP_COMPLETE = (1 << 1), + UCI_LOOKUP_EXTENDED = (1 << 2), + } flags; + + struct uci_package *p; + struct uci_section *s; + struct uci_option *o; + struct uci_element *last; + + const char *package; + const char *section; + const char *option; + const char *value; +}; + + +/* linked list handling */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + */ +#define container_of(ptr, type, member) \ + ((type *) ((char *)ptr - offsetof(type,member))) + + +/** + * uci_list_entry: casts an uci_list pointer to the containing struct. + * @_type: config, section or option + * @_ptr: pointer to the uci_list struct + */ +#define list_to_element(ptr) \ + container_of(ptr, struct uci_element, list) + +/** + * uci_foreach_entry: loop through a list of uci elements + * @_list: pointer to the uci_list struct + * @_ptr: iteration variable, struct uci_element + * + * use like a for loop, e.g: + * uci_foreach(&list, p) { + * ... + * } + */ +#define uci_foreach_element(_list, _ptr) \ + for(_ptr = list_to_element((_list)->next); \ + &_ptr->list != (_list); \ + _ptr = list_to_element(_ptr->list.next)) + +/** + * uci_foreach_entry_safe: like uci_foreach_safe, but safe for deletion + * @_list: pointer to the uci_list struct + * @_tmp: temporary variable, struct uci_element * + * @_ptr: iteration variable, struct uci_element * + * + * use like a for loop, e.g: + * uci_foreach(&list, p) { + * ... + * } + */ +#define uci_foreach_element_safe(_list, _tmp, _ptr) \ + for(_ptr = list_to_element((_list)->next), \ + _tmp = list_to_element(_ptr->list.next); \ + &_ptr->list != (_list); \ + _ptr = _tmp, _tmp = list_to_element(_ptr->list.next)) + +/** + * uci_list_empty: returns true if a list is empty + * @list: list head + */ +#define uci_list_empty(list) ((list)->next == (list)) + +/* wrappers for dynamic type handling */ +#define uci_type_backend UCI_TYPE_BACKEND +#define uci_type_history UCI_TYPE_HISTORY +#define uci_type_package UCI_TYPE_PACKAGE +#define uci_type_section UCI_TYPE_SECTION +#define uci_type_option UCI_TYPE_OPTION + +/* element typecasting */ +#ifdef UCI_DEBUG_TYPECAST +static const char *uci_typestr[] = { + [uci_type_backend] = "backend", + [uci_type_history] = "history", + [uci_type_package] = "package", + [uci_type_section] = "section", + [uci_type_option] = "option", +}; + +static void uci_typecast_error(int from, int to) +{ + fprintf(stderr, "Invalid typecast from '%s' to '%s'\n", uci_typestr[from], uci_typestr[to]); +} + +#define BUILD_CAST(_type) \ + static inline struct uci_ ## _type *uci_to_ ## _type (struct uci_element *e) \ + { \ + if (e->type != uci_type_ ## _type) { \ + uci_typecast_error(e->type, uci_type_ ## _type); \ + } \ + return (struct uci_ ## _type *) e; \ + } + +BUILD_CAST(backend) +BUILD_CAST(history) +BUILD_CAST(package) +BUILD_CAST(section) +BUILD_CAST(option) + +#else +#define uci_to_backend(ptr) container_of(ptr, struct uci_backend, e) +#define uci_to_history(ptr) container_of(ptr, struct uci_history, e) +#define uci_to_package(ptr) container_of(ptr, struct uci_package, e) +#define uci_to_section(ptr) container_of(ptr, struct uci_section, e) +#define uci_to_option(ptr) container_of(ptr, struct uci_option, e) +#endif + +/** + * uci_alloc_element: allocate a generic uci_element, reserve a buffer and typecast + * @ctx: uci context + * @type: {package,section,option} + * @name: string containing the name of the element + * @datasize: additional buffer size to reserve at the end of the struct + */ +#define uci_alloc_element(ctx, type, name, datasize) \ + uci_to_ ## type (uci_alloc_generic(ctx, uci_type_ ## type, name, sizeof(struct uci_ ## type) + datasize)) + +#define uci_dataptr(ptr) \ + (((char *) ptr) + sizeof(*ptr)) + +#endif diff --git a/openwrt/packages/luci/libs/lucittpd/src/include/uci_config.h b/openwrt/packages/luci/libs/lucittpd/src/include/uci_config.h new file mode 100644 index 0000000..0dd76cc --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/include/uci_config.h @@ -0,0 +1,3 @@ +#define UCI_PLUGIN_SUPPORT 1 +#undef UCI_DEBUG +#undef UCI_DEBUG_TYPECAST diff --git a/openwrt/packages/luci/libs/lucittpd/src/lib/log.c b/openwrt/packages/luci/libs/lucittpd/src/lib/log.c new file mode 100644 index 0000000..b6ce8c2 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/lib/log.c @@ -0,0 +1,45 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Provided by fon.com + * Copyright (C) 2008 John Crispin + */ + +#include +#include +#include + +static int daemonize = 0; + +void log_start(int daemon) +{ + daemonize = daemon; + openlog("lucittpd", 0, 0); +} + +void log_printf(char *fmt, ...) +{ + char p[256]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(p, 256, fmt, ap); + va_end(ap); + + if(daemonize) + syslog(10, p); + else + printf(p); +} diff --git a/openwrt/packages/luci/libs/lucittpd/src/lib/luaplugin.c b/openwrt/packages/luci/libs/lucittpd/src/lib/luaplugin.c new file mode 100644 index 0000000..6a0e1ca --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/lib/luaplugin.c @@ -0,0 +1,383 @@ +/* + * luaplugin - fast lua plugin indexing + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE /* XXX: portability hack for timestamp */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +//#define DEBUG 1 +#ifdef DEBUG +#define DPRINTF(...) fprintf(stderr, __VA_ARGS__) +#else +#define DPRINTF(...) do {} while (0) +#endif + +/** + * list_for_each_offset - iterate over a list, start with the provided pointer + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_offset(pos, head, offset) \ + for (pos = (offset)->next; pos != (offset); \ + pos = ((pos->next == (head)) && ((offset) != (head)) ? (head)->next : pos->next)) + +static char pbuf[PATH_MAX]; +static void load_module(struct luaplugin_ctx *ctx, struct luaplugin_entry *e); + +static struct luaplugin_entry * +find_entry(struct luaplugin_ctx *ctx, const char *name, bool modname) +{ + struct list_head *p; + + if (!ctx->last) + ctx->last = &ctx->entries; + + list_for_each_offset(p, &ctx->entries, ctx->last) { + struct luaplugin_entry *e; + const char *cmp; + + e = container_of(p, struct luaplugin_entry, list); + if (modname) + cmp = e->module; + else + cmp = e->name; + + if (!strcmp(cmp, name)) + return e; + } + return NULL; +} + +static struct luaplugin_entry * +new_entry(struct luaplugin_ctx *ctx, const char *name, const char *modname) +{ + struct luaplugin_entry *e; + char *c; + + e = malloc(sizeof(struct luaplugin_entry)); + if (!e) + goto error; + + memset(e, 0, sizeof(struct luaplugin_entry)); + INIT_LIST_HEAD(&e->list); + e->ctx = ctx; + e->loaded = false; + + e->name = strdup(name); + if (!e->name) + goto error1; + + e->module = strdup(modname); + if (!e->module) + goto error2; + + /* strip filename extension */ + c = strrchr(e->module, '.'); + if (c) + *c = 0; + + /* lua namespace: replace / with . */ + c = e->module; + while ((c = strchr(c, '/')) != NULL) { + *c = '.'; + } + return e; + +error2: + free(e->name); +error1: + free(e); +error: + return NULL; +} + +static const char *module_loader = +"loader = function (newgt, filename)\n" +" setmetatable(newgt, { __index = _G })\n" +" local f = loadfile(filename)\n" +" if (type(f) == \"function\") then\n" +" setfenv(f, newgt)\n" +" f()\n" +" else\n" +" error(f)\n" +" end\n" +"end\n"; + +static void +access_plugin_table (lua_State *L, const char *modname, bool set) +{ + const char *e; + + lua_pushvalue(L, LUA_GLOBALSINDEX); + do { + bool _set = true; + + e = strchr(modname, '.'); + if (e == NULL) { + e = modname + strlen(modname); + _set = set; + } + + lua_pushlstring(L, modname, e - modname); + lua_rawget(L, -2); + if (lua_isnil(L, -1) || + /* no such field or last field */ + (lua_istable(L, -1) && (*e != '.'))) { + lua_pop(L, 1); /* remove this result */ + + if (_set) { + if (*e != '.') + lua_pushvalue(L, -2); /* use table from given index */ + else + lua_createtable(L, 0, 1); /* new table for field */ + } + + lua_pushlstring(L, modname, e - modname); + + if (_set) { + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } else { + lua_gettable(L, -2); + } + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2 + !!set); /* remove table and values */ + return; + } + lua_remove(L, -2); /* remove previous table */ + modname = e + 1; + } while (*e == '.'); + if (set) + lua_pop(L, 2); +} + + +static void +load_module(struct luaplugin_ctx *ctx, struct luaplugin_entry *e) +{ + lua_State *L = ctx->L; + int ret; + + /* grab the loader wrapper function */ + ret = luaL_dostring(L, module_loader); + if (ret) + return; + + lua_getglobal(L, "loader"); + lua_pushnil(L); + lua_setglobal(L, "loader"); + + e->loaded = true; + e->reload = false; + + /* new environment table for function call */ + lua_newtable(L); + + /* register the table globally */ + lua_pushvalue(L, -1); + access_plugin_table(L, e->module, true); + + lua_pushstring(L, e->name); + + if (lua_pcall(L, 2, 0, 0) != 0) { + const char *err = "unknown error"; + + if (lua_isstring(L, -1)) + err = lua_tostring(L, -1); + + fprintf(stderr, err); + } +} + +static void +free_entry(struct luaplugin_ctx *ctx, struct luaplugin_entry *e) +{ + lua_State *L = ctx->L; + + if (e->loaded && L) { + /* allow the gc to free the module */ + lua_pushnil(L); + access_plugin_table(L, e->module, true); + } + list_del(&e->list); + free(e->name); + free(e->module); + free(e); +} + +static void +__luaplugin_scan(struct luaplugin_ctx *ctx, int base_len, int rec) +{ + int gl_flags = GLOB_NOESCAPE | GLOB_NOSORT | GLOB_MARK; + glob_t gl; + int i; + + strncpy(pbuf + base_len, "*.lua", PATH_MAX - base_len); + if (glob(pbuf, gl_flags, NULL, &gl) < 0) { + globfree(&gl); + return; + } + + for (i = 0; i < gl.gl_pathc; i++) { + const char *entry = gl.gl_pathv[i]; + struct luaplugin_entry *e; + struct stat st; + int elen; + + elen = strlen(entry); + + /* should not happen */ + if ((elen <= base_len) || (strncmp(entry, pbuf, base_len) != 0)) { + fprintf(stderr, "[%s] sanity check failed in %s(%d)!\n", __FILE__, __func__, __LINE__); + continue; + } + + /* descend into subdirectories */ + if (entry[elen - 1] == '/') { + strncpy(pbuf + base_len, entry + base_len, PATH_MAX - base_len); + __luaplugin_scan(ctx, base_len, rec + 1); + pbuf[base_len] = '\0'; + continue; + } + + if (stat(gl.gl_pathv[i], &st)) + continue; + + if ((st.st_mode & S_IFMT) != S_IFREG) + continue; + + e = find_entry(ctx, entry + base_len, false); + if (!e) { + e = new_entry(ctx, entry, entry + base_len); + list_add_tail(&e->list, &ctx->entries); + } + if (!e) + continue; + + e->checked = ctx->checked; + e->reload = (e->timestamp < st.st_mtime); + e->timestamp = st.st_mtime; + } + globfree(&gl); +} + +int +luaplugin_call(struct luaplugin_entry *e, int narg) +{ + struct luaplugin_ctx *ctx = e->ctx; + lua_State *L = ctx->L; + const char *func; + int ret; + + func = luaL_checkstring(L, -1 - narg); + + /* grab a reference to the plugin's table */ + access_plugin_table(L, e->module, false); + lua_getfield(L, -1, func); + if (!lua_isfunction(L, -1)) { + lua_pop(L, narg + 1); + ret = -ENOENT; + goto done; + } + + /* replace function name with a ref to the function */ + lua_replace(L, -3 - narg); + + /* pop the table */ + lua_pop(L, 1); + ret = lua_pcall(L, narg, 0, 0); + + if (ret != 0) { + fprintf(stderr, lua_tostring(L, -1)); + } + +done: + return ret; +} + +void +luaplugin_scan(struct luaplugin_ctx *ctx) +{ + struct list_head *tmp, *p; + + sprintf(pbuf, "%s/", ctx->path); + + ctx->checked++; + __luaplugin_scan(ctx, strlen(pbuf), 0); + + /* expire old entries */ + list_for_each_safe(p, tmp, &ctx->entries) { + struct luaplugin_entry *e = container_of(p, struct luaplugin_entry, list); + if (e->checked < ctx->checked) + free_entry(ctx, e); + else if (e->reload) + load_module(ctx, e); + } +} + +int +luaplugin_init(struct luaplugin_ctx *ctx, const char *path) +{ + memset(ctx, 0, sizeof(struct luaplugin_ctx)); + INIT_LIST_HEAD(&ctx->entries); + ctx->path = path; + + ctx->L = luaL_newstate(); + if (!ctx->L) + return -ENOMEM; + + luaL_openlibs(ctx->L); + + /* disable the module functionality, a plugin is restricted to its own environment */ + /* + lua_pushcfunction(ctx->L, luaplugin_module); + lua_setfield(ctx->L, LUA_GLOBALSINDEX, "module"); + */ + + return 0; +} + +void +luaplugin_done(struct luaplugin_ctx *ctx) +{ + struct list_head *p, *tmp; + + lua_close(ctx->L); + ctx->L = NULL; + + list_for_each_safe(p, tmp, &ctx->entries) { + struct luaplugin_entry *e; + e = container_of(p, struct luaplugin_entry, list); + free_entry(ctx, e); + } +} diff --git a/openwrt/packages/luci/libs/lucittpd/src/lib/signal.c b/openwrt/packages/luci/libs/lucittpd/src/lib/signal.c new file mode 100644 index 0000000..2b11f47 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/lib/signal.c @@ -0,0 +1,52 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Provided by fon.com + * Copyright (C) 2008 John Crispin + */ + +#include +#include +#include +#include +#include +#include + +#include + +void handler_INT(int signo) +{ + log_printf("away we go\n"); + exit(0); +} + +void handler_CHLD(int signo) +{ + while(waitpid(-1, NULL, WNOHANG) > 0); +} + +void setup_signals(void) +{ + struct sigaction s1, s2, s3; + s1.sa_handler = handler_INT; + s1.sa_flags = 0; + sigaction(SIGINT, &s1, NULL); + s2.sa_handler = handler_INT; + s2.sa_flags = 0; + sigaction(SIGTERM, &s2, NULL); + s3.sa_handler = handler_CHLD; + s3.sa_flags = SA_RESTART; + sigaction(SIGCHLD, &s3, NULL); +} diff --git a/openwrt/packages/luci/libs/lucittpd/src/lib/uci.c b/openwrt/packages/luci/libs/lucittpd/src/lib/uci.c new file mode 100644 index 0000000..33254ee --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/lib/uci.c @@ -0,0 +1,206 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2008 John Crispin + */ + +#include +#include + +#include +#include +#include +#include + +static struct uci_ptr ptr; +static struct uci_package *p = NULL; + +static inline int ucix_get_ptr(struct uci_context *ctx, const char *p, const char *s, const char *o, const char *t) +{ + memset(&ptr, 0, sizeof(ptr)); + ptr.package = p; + ptr.section = s; + ptr.option = o; + ptr.value = t; + return uci_lookup_ptr(ctx, &ptr, NULL, true); +} + +struct uci_context* ucix_init(const char *config_file) +{ + struct uci_context *ctx = uci_alloc_context(); + uci_add_history_path(ctx, "/var/state"); + uci_set_savedir(ctx, "/var/state/"); + if(uci_load(ctx, config_file, &p) != UCI_OK) + { + log_printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file); + return NULL; + } + return ctx; +} + +struct uci_context* ucix_init_path(const char *path, const char *config_file) +{ + struct uci_context *ctx = uci_alloc_context(); + if(path) + uci_set_confdir(ctx, path); + if(uci_load(ctx, config_file, NULL) != UCI_OK) + { + log_printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file); + return NULL; + } + return ctx; +} + +void ucix_cleanup(struct uci_context *ctx) +{ + uci_free_context(ctx); +} + +void ucix_save(struct uci_context *ctx) +{ + uci_set_savedir(ctx, "/tmp/.uci"); + uci_save(ctx, p); +} + +void ucix_save_state(struct uci_context *ctx) +{ + uci_save(ctx, p); +} + +int ucix_get_option_list(struct uci_context *ctx, const char *p, + const char *s, const char *o, struct list_head *l) +{ + struct uci_element *e = NULL; + if(ucix_get_ptr(ctx, p, s, o, NULL)) + return 1; + if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) + return 1; + e = ptr.last; + switch (e->type) + { + case UCI_TYPE_OPTION: + switch(ptr.o->type) { + case UCI_TYPE_LIST: + uci_foreach_element(&ptr.o->v.list, e) + { + struct ucilist *ul = malloc(sizeof(struct ucilist)); + ul->val = strdup((e->name)?(e->name):("")); + INIT_LIST_HEAD(&ul->list); + list_add(&ul->list, l); + } + break; + default: + break; + } + break; + default: + return 1; + } + + return 0; +} + +const char* ucix_get_option(struct uci_context *ctx, const char *p, const char *s, const char *o) +{ + struct uci_element *e = NULL; + const char *value = NULL; + if(ucix_get_ptr(ctx, p, s, o, NULL)) + return NULL; + if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) + return NULL; + e = ptr.last; + switch (e->type) + { + case UCI_TYPE_SECTION: + value = uci_to_section(e)->type; + break; + case UCI_TYPE_OPTION: + switch(ptr.o->type) { + case UCI_TYPE_STRING: + value = ptr.o->v.string; + break; + default: + value = NULL; + break; + } + break; + default: + return 0; + } + + return value; +} + +int ucix_get_option_int(struct uci_context *ctx, const char *p, const char *s, const char *o, int def) +{ + const char *tmp = ucix_get_option(ctx, p, s, o); + int ret = def; + + if (tmp) + ret = atoi(tmp); + return ret; +} + +void ucix_add_section(struct uci_context *ctx, const char *p, const char *s, const char *t) +{ + if(ucix_get_ptr(ctx, p, s, NULL, t)) + return; + uci_set(ctx, &ptr); +} + +void ucix_add_option(struct uci_context *ctx, const char *p, const char *s, const char *o, const char *t) +{ + if(ucix_get_ptr(ctx, p, s, o, (t)?(t):(""))) + return; + uci_set(ctx, &ptr); +} + +void ucix_add_option_int(struct uci_context *ctx, const char *p, const char *s, const char *o, int t) +{ + char tmp[64]; + snprintf(tmp, 64, "%d", t); + ucix_add_option(ctx, p, s, o, tmp); +} + +void ucix_del(struct uci_context *ctx, const char *p, const char *s, const char *o) +{ + if(!ucix_get_ptr(ctx, p, s, o, NULL)) + uci_delete(ctx, &ptr); +} + +void ucix_revert(struct uci_context *ctx, const char *p, const char *s, const char *o) +{ + if(!ucix_get_ptr(ctx, p, s, o, NULL)) + uci_revert(ctx, &ptr); +} + +void ucix_for_each_section_type(struct uci_context *ctx, + const char *p, const char *t, + void (*cb)(const char*, void*), void *priv) +{ + struct uci_element *e; + if(ucix_get_ptr(ctx, p, NULL, NULL, NULL)) + return; + uci_foreach_element(&ptr.p->sections, e) + if (!strcmp(t, uci_to_section(e)->type)) + cb(e->name, priv); +} + +int ucix_commit(struct uci_context *ctx, const char *p) +{ + if(ucix_get_ptr(ctx, p, NULL, NULL, NULL)) + return 1; + return uci_commit(ctx, &ptr.p, false); +} diff --git a/openwrt/packages/luci/libs/lucittpd/src/main.c b/openwrt/packages/luci/libs/lucittpd/src/main.c new file mode 100644 index 0000000..3ee5506 --- /dev/null +++ b/openwrt/packages/luci/libs/lucittpd/src/main.c @@ -0,0 +1,333 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2008 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef __UCLIBC__ +#include +#endif + +#define BACKLOG 10 + +static int port = 0; +static const char *plugin_path = NULL; +static struct luaplugin_ctx ctx; +static struct luaplugin_entry *e; +static struct timeval timeout; + +static void load_config(void) +{ + timeout.tv_usec = 0; + + static struct uci_context* uci = 0; + uci = ucix_init("lucittpd"); + if(uci) + { + plugin_path = ucix_get_option(uci, "lucittpd", "lucittpd", "path"); + port = ucix_get_option_int(uci, "lucittpd", "lucittpd", "port", 80); + timeout.tv_sec = ucix_get_option_int(uci, "lucittpd", "lucittpd", "timeout", 90); + } else { + port = 8080; + timeout.tv_sec = 90; + } + if(!plugin_path) + plugin_path = strdup("/usr/lib/lucittpd/plugins/"); + + // ToDo: Check why below command segfaults in uci_free_context + //ucix_cleanup(uci); +} + +static int webuci_read(lua_State *L) +{ + int len = luaL_checkinteger(L, 1); + if (len <= 0) { + return luaL_argerror(L, 1, "too low"); + } + + char *buffer = malloc(len); + if (!buffer) { + return luaL_error(L, "malloc() failed"); + } + + int sockfd = lua_tointeger(L, lua_upvalueindex(1)); + + len = read(sockfd, buffer, len); + if (len > 0) { + lua_pushlstring(L, buffer, len); + free(buffer); + } else { + free(buffer); + lua_pushnil(L); + lua_pushinteger(L, (len == 0) ? 0 : errno); + return 2; + } + + /* fprintf(stderr, "%s:%s[%d] %d %d\n", __FILE__, __func__, __LINE__, sockfd, len); */ + + return 1; +} + +static int webuci_close(lua_State *L) +{ + int sockfd = lua_tointeger(L, lua_upvalueindex(1)); + int result = shutdown(sockfd, SHUT_RDWR); + close(sockfd); + /*log_printf("%s:%s[%d] %d %d\n", __FILE__, __func__, __LINE__, sockfd, result);*/ + + if (result < 0) { + lua_pushnil(L); + lua_pushinteger(L, errno); + return 2; + } else { + lua_pushboolean(L, 1); + return 1; + } +} + +static int webuci_write(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TSTRING); + + size_t len; + const char *data = lua_tolstring(L, 1, &len); + int sockfd = lua_tointeger(L, lua_upvalueindex(1)); + + len = send(sockfd, data, len, 0); + /*log_printf("%s:%s[%d] %d %d - %s\n", __FILE__, __func__, __LINE__, sockfd, len, data);*/ + if (len < 0) { + lua_pushnil(L); + lua_pushinteger(L, errno); + return 2; + } else { + lua_pushinteger(L, len); + return 1; + } +} + +static int webuci_sendfile(lua_State *L) +{ + FILE **fp = (FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE); + if (*fp == NULL) { + return luaL_error(L, "attempt to use a closed file"); + } + + off_t offset = luaL_checkinteger(L, 2); + size_t size = luaL_checkinteger(L, 3); + + int sockfd = lua_tointeger(L, lua_upvalueindex(1)); + + int cork = 1; + setsockopt(sockfd, SOL_TCP, TCP_CORK, &cork, sizeof(cork)); + +#ifdef __UCLIBC__ + // uclibc is teh sux, it does not implement sendfile correctly + char tmp[1024]; + size_t c, toread = size, oldpos = ftell(*fp); + + fseek(*fp, offset, SEEK_SET); + + while(toread > 0 && (c = fread(tmp, 1, (toread < 1024) ? toread : 1024, *fp)) > 0) + { + size += c; + toread -= c; + write(sockfd, tmp, c); + } + + fseek(*fp, oldpos, SEEK_SET); +#else + size = sendfile(sockfd, fileno(*fp), &offset, size); + /*log_printf("%s:%s[%d] %d %d - %d\n", __FILE__, __func__, __LINE__, sockfd, fileno(*fp), size);*/ +#endif + + cork = 0; + setsockopt(sockfd, SOL_TCP, TCP_CORK, &cork, sizeof(cork)); + + if (size < 1) { + lua_pushnil(L); + lua_pushinteger(L, errno); + } else { + lua_pushinteger(L, size); + lua_pushinteger(L, offset); + } + + return 2; +} + + +static void load_luci(const char *plugindir) +{ + luaplugin_init(&ctx, plugindir); + luaplugin_scan(&ctx); + + list_for_each_entry(e, &ctx.entries, list) + { + lua_pushstring(ctx.L, "initialize"); + luaplugin_call(e, 0); + } + + list_for_each_entry(e, &ctx.entries, list) + { + lua_pushstring(ctx.L, "register"); + luaplugin_call(e, 0); + } + + list_for_each_entry(e, &ctx.entries, list) + { + lua_pushstring(ctx.L, "filter"); + luaplugin_call(e, 0); + } +} + +static void run_luci(int sockfd) +{ + lua_pushinteger(ctx.L, sockfd); + lua_pushcclosure(ctx.L, webuci_read, 1); + lua_setfield(ctx.L, LUA_GLOBALSINDEX, "webuci_read"); + + lua_pushinteger(ctx.L, sockfd); + lua_pushcclosure(ctx.L, webuci_write, 1); + lua_setfield(ctx.L, LUA_GLOBALSINDEX, "webuci_write"); + + lua_pushinteger(ctx.L, sockfd); + lua_pushcclosure(ctx.L, webuci_close, 1); + lua_setfield(ctx.L, LUA_GLOBALSINDEX, "webuci_close"); + + lua_pushinteger(ctx.L, sockfd); + lua_pushcclosure(ctx.L, webuci_sendfile, 1); + lua_setfield(ctx.L, LUA_GLOBALSINDEX, "webuci_sendfile"); + + list_for_each_entry(e, &ctx.entries, list) + { + lua_pushstring(ctx.L, "accept"); + luaplugin_call(e, 0); + } +} + +static void cleanup_luci(void) +{ + luaplugin_done(&ctx); +} + +int main(int argc, char **argv) +{ + int sockfd, new_fd; + struct sockaddr_storage their_addr; + socklen_t sin_size; + int yes = 1; + struct sockaddr_in myaddr; + + log_start(1); + + load_config(); + + setup_signals(); + + /* used by sdk to override plugin dir */ + if(argc != 2) + { + load_luci(plugin_path); + } else { + load_luci(argv[1]); + port = 8080; + } + + myaddr.sin_family = AF_INET; + myaddr.sin_port = htons(port); + //inet_pton(AF_INET, "63.161.169.137", &myaddr.sin_addr.s_addr); + myaddr.sin_addr.s_addr = INADDR_ANY; + + sockfd = socket(PF_INET, SOCK_STREAM, 0); + + if(sockfd == -1) + { + perror("server: socket"); + exit(1); + } + + if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) + { + perror("setsockopt"); + exit(1); + } + + if(bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) + { + close(sockfd); + perror("server: bind"); + exit(1); + } + + if(listen(sockfd, BACKLOG) == -1) + { + perror("listen"); + exit(1); + } + + /*log_printf("server: waiting for connections...\n");*/ + + while(1) + { + sin_size = sizeof their_addr; + new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); + if(new_fd == -1) + { + perror("accept"); + continue; + } + + /*inet_ntop(their_addr.ss_family, + (void*)&((struct sockaddr_in*)&their_addr)->sin_addr, s, sizeof s); + log_printf("server: got connection from %s\n", s);*/ + + if(!fork()) + { + /* child */ + close(sockfd); + + setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(new_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + + run_luci(new_fd); + cleanup_luci(); + close(new_fd); + + exit(0); + } + close(new_fd); + } + + return 0; +} diff --git a/openwrt/packages/luci/libs/sgi-cgi/Makefile b/openwrt/packages/luci/libs/sgi-cgi/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-cgi/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/libs/sgi-cgi/htdocs/cgi-bin/luci b/openwrt/packages/luci/libs/sgi-cgi/htdocs/cgi-bin/luci new file mode 100755 index 0000000..529d1d0 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-cgi/htdocs/cgi-bin/luci @@ -0,0 +1,5 @@ +#!/usr/bin/lua +require "luci.cacheloader" +require "luci.sgi.cgi" +luci.dispatcher.indexcache = "/tmp/luci-indexcache" +luci.sgi.cgi.run() \ No newline at end of file diff --git a/openwrt/packages/luci/libs/sgi-cgi/htdocs/index.html b/openwrt/packages/luci/libs/sgi-cgi/htdocs/index.html new file mode 100644 index 0000000..a229860 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-cgi/htdocs/index.html @@ -0,0 +1,10 @@ + + + + + + + +Flukso Configuration Interface + + diff --git a/openwrt/packages/luci/libs/sgi-cgi/luasrc/sgi/cgi.lua b/openwrt/packages/luci/libs/sgi-cgi/luasrc/sgi/cgi.lua new file mode 100644 index 0000000..00d9636 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-cgi/luasrc/sgi/cgi.lua @@ -0,0 +1,90 @@ +--[[ +LuCI - SGI-Module for CGI + +Description: +Server Gateway Interface for CGI + +FileId: +$Id: cgi.lua 3739 2008-11-08 20:25:49Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.sgi.cgi", package.seeall) +local ltn12 = require("luci.ltn12") +require("luci.http") +require("luci.sys") +require("luci.dispatcher") + +-- Limited source to avoid endless blocking +local function limitsource(handle, limit) + limit = limit or 0 + local BLOCKSIZE = ltn12.BLOCKSIZE + + return function() + if limit < 1 then + handle:close() + return nil + else + local read = (limit > BLOCKSIZE) and BLOCKSIZE or limit + limit = limit - read + + local chunk = handle:read(read) + if not chunk then handle:close() end + return chunk + end + end +end + +function run() + local r = luci.http.Request( + luci.sys.getenv(), + limitsource(io.stdin, tonumber(luci.sys.getenv("CONTENT_LENGTH"))), + ltn12.sink.file(io.stderr) + ) + + local x = coroutine.create(luci.dispatcher.httpdispatch) + local hcache = "" + local active = true + + while coroutine.status(x) ~= "dead" do + local res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + print("Status: 500 Internal Server Error") + print("Content-Type: text/plain\n") + print(id) + break; + end + + if active then + if id == 1 then + io.write("Status: " .. tostring(data1) .. " " .. data2 .. "\r\n") + elseif id == 2 then + hcache = hcache .. data1 .. ": " .. data2 .. "\r\n" + elseif id == 3 then + io.write(hcache) + io.write("\r\n") + elseif id == 4 then + io.write(data1) + elseif id == 5 then + io.flush() + io.close() + active = false + end + end + end +end diff --git a/openwrt/packages/luci/libs/sgi-luci/Makefile b/openwrt/packages/luci/libs/sgi-luci/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-luci/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/libs/sgi-luci/hostfiles/usr/lib/lucittpd/plugins/luci-webui.lua b/openwrt/packages/luci/libs/sgi-luci/hostfiles/usr/lib/lucittpd/plugins/luci-webui.lua new file mode 100644 index 0000000..073e567 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-luci/hostfiles/usr/lib/lucittpd/plugins/luci-webui.lua @@ -0,0 +1,29 @@ +function initialize() + pcall(function() + local SYSROOT = os.getenv("LUCI_SYSROOT") + require "uci" + require "luci.model.uci".cursor = function(config, save) + return uci.cursor(config or SYSROOT .. "/etc/config", save or SYSROOT .. "/tmp/.uci") + end + + local x = require "luci.uvl".UVL.__init__ + require "luci.uvl".UVL.__init__ = function(self, schemedir) + x(self, schemedir or SYSROOT .. "/lib/uci/schema") + end + + require("luci.sys") + luci.sys.user.checkpasswd = function() return true end + + require "luci.dispatcher" + require "luci.uvl" + require "luci.cbi" + require "luci.template" + require "luci.json" + end) +end + +-- Initialize LuCI +function register() + local lucihnd = require "luci.ttpd.handler.luci" + httpd.server:get_default_vhost():set_handler("/luci", lucihnd.Luci()) +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/sgi-luci/luasrc/ttpd/handler/luci.lua b/openwrt/packages/luci/libs/sgi-luci/luasrc/ttpd/handler/luci.lua new file mode 100644 index 0000000..eb60625 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-luci/luasrc/ttpd/handler/luci.lua @@ -0,0 +1,92 @@ +--[[ + +HTTP server implementation for LuCI - luci handler +(c) 2008 Steven Barth + +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$ + +]]-- +local dsp = require "luci.dispatcher" +local util = require "luci.util" +local http = require "luci.http" +local ltn12 = require "luci.ltn12" +local mod = require "luci.ttpd.module" +local table = require "table" +local coroutine = require "coroutine" + +module "luci.ttpd.handler.luci" + +Luci = util.class(mod.Handler) +Response = mod.Response + +function Luci.__init__(self, limit) + mod.Handler.__init__(self) +end + +function Luci.handle_head(self, ...) + return (self:handle_get(...)) +end + +function Luci.handle_post(self, ...) + return self:handle_get(...) +end + +function Luci.handle_get(self, request, sourcein, sinkerr) + local r = http.Request( + request.env, + sourcein, + sinkerr + ) + + local res, id, data1, data2 = true, 0, nil, nil + local headers = {} + local status = 200 + local active = true + + local x = coroutine.create(dsp.httpdispatch) + while not id or id < 3 do + res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + status = 500 + headers["Content-Type"] = "text/plain" + local err = {id} + return Response( status, headers ), function() return table.remove(err) end + end + + if id == 1 then + status = data1 + elseif id == 2 then + headers[data1] = data2 + end + end + + local function iter() + local res, id, data = coroutine.resume(x) + if not res then + return nil, id + elseif not id or not active then + return true + elseif id == 5 then + active = false + + while (coroutine.resume(x)) do + end + + return nil + elseif id == 4 then + return data + end + if coroutine.status(x) == "dead" then + return nil + end + end + + return Response(status, headers), iter +end diff --git a/openwrt/packages/luci/libs/sgi-luci/root/usr/lib/lucittpd/plugins/luci-webui.lua b/openwrt/packages/luci/libs/sgi-luci/root/usr/lib/lucittpd/plugins/luci-webui.lua new file mode 100644 index 0000000..1204667 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-luci/root/usr/lib/lucittpd/plugins/luci-webui.lua @@ -0,0 +1,17 @@ +-- Initialize LuCI +function initialize() + pcall(function() + require "luci.dispatcher" + require "luci.uvl" + require "luci.cbi" + require "luci.template" + require "luci.json" + end) +end + +-- Register luci +function register() + local lucihnd = require "luci.ttpd.handler.luci".Luci() + httpd.server:get_default_vhost():set_handler("/luci", lucihnd) + httpd.server:get_default_vhost():set_handler("/cgi-bin/luci", lucihnd) +end diff --git a/openwrt/packages/luci/libs/sgi-webuci/.gitignore b/openwrt/packages/luci/libs/sgi-webuci/.gitignore new file mode 100644 index 0000000..2e8c134 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/.gitignore @@ -0,0 +1,2 @@ +boa-patches/series +boa-*.* diff --git a/openwrt/packages/luci/libs/sgi-webuci/Makefile b/openwrt/packages/luci/libs/sgi-webuci/Makefile new file mode 100644 index 0000000..81ed3fe --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/Makefile @@ -0,0 +1,52 @@ +include ../../build/config.mk +include ../../build/gccconfig.mk +include ../../build/module.mk + +BOA_VERSION = 0.94.13 +BOA_SITE = http://www.boa.org +BOA_DIR = boa-$(BOA_VERSION) +BOA_FILE = $(BOA_DIR).tar.gz +BOA_URL = $(BOA_SITE)/$(BOA_FILE) +BOA_PATCHDIR = boa-patches + +$(BOA_FILE): + wget -O $@ $(BOA_URL) || rm -f $@ + +$(BOA_PATCHDIR)/series: + (cd $(BOA_PATCHDIR); ls *.patch | sort > series) + +$(BOA_DIR)/.prepared: $(BOA_FILE) + rm -rf $(BOA_DIR) + tar xvfz $(BOA_FILE) + ln -s ../$(BOA_PATCHDIR) $(BOA_DIR)/patches + touch $@ + +$(BOA_DIR)/.patched: $(BOA_DIR)/.prepared $(BOA_PATCHDIR)/series + (cd $(BOA_DIR); \ + if [ -x "$$(which quilt 2>/dev/null)" ]; then \ + [ "$$(quilt top 2>/dev/null)" = "$$(tail -n1 patches/series)" ] || quilt push -a; \ + else \ + cat patches/*.patch | patch -p1; \ + fi; \ + ) + touch $@ + +$(BOA_DIR)/.configured: $(BOA_DIR)/.patched + (cd $(BOA_DIR)/src; ./configure --disable-debug) + touch $@ + +boa-compile: $(BOA_DIR)/.configured + $(MAKE) -C $(BOA_DIR)/src CC=$(CC) CFLAGS="$(CFLAGS) -DINET6 -DACCEPT_ON -DWHEN_DOES_THIS_APPLY" + +%.o: %.c + $(COMPILE) $(LUA_CFLAGS) -I$(BOA_DIR)/src $(FPIC) -c -o $@ $< + +compile: boa-compile src/luci.o src/cgi.o + mkdir -p dist/usr/bin dist/usr/lib/boa + cp $(BOA_DIR)/src/boa $(BOA_DIR)/src/boa_indexer dist/usr/bin + $(LINK) $(SHLIB_FLAGS) -o dist/usr/lib/boa/luci.so src/luci.o src/cgi.o $(LDFLAGS) $(LUA_LIBS) + +clean: + rm -rf $(BOA_DIR) $(BOA_FILE) + rm -f boa-patches/series + rm -f src/*.o diff --git a/openwrt/packages/luci/libs/sgi-webuci/boa-patches/100-no_tz.patch b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/100-no_tz.patch new file mode 100644 index 0000000..639677e --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/100-no_tz.patch @@ -0,0 +1,22 @@ +diff -urN boa-0.94.13/src/util.c boa/src/util.c +--- boa-0.94.13/src/util.c 2002-07-08 01:22:18.000000000 +0200 ++++ boa/src/util.c 2008-04-25 21:56:20.000000000 +0200 +@@ -95,14 +95,9 @@ + static char buf[30]; + int time_offset; + +- if (use_localtime) { +- t = localtime(¤t_time); +- time_offset = TIMEZONE_OFFSET(t); +- } else { +- t = gmtime(¤t_time); +- time_offset = 0; +- } +- ++ t = gmtime(¤t_time); ++ time_offset = 0; ++ + p = buf + 29; + *p-- = '\0'; + *p-- = ' '; + diff --git a/openwrt/packages/luci/libs/sgi-webuci/boa-patches/110-host_lookup.patch b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/110-host_lookup.patch new file mode 100644 index 0000000..89467e4 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/110-host_lookup.patch @@ -0,0 +1,22 @@ +Index: boa-0.94.13/src/config.c +=================================================================== +--- boa-0.94.13.orig/src/config.c 2008-06-29 00:55:19.000000000 +0200 ++++ boa-0.94.13/src/config.c 2008-06-29 00:59:08.000000000 +0200 +@@ -273,12 +273,12 @@ + } + + he = gethostbyname(temp_name); +- if (he == NULL) { +- perror("gethostbyname:"); +- exit(1); +- } ++ if (he && he->h_name) ++ server_name = he->h_name; ++ else ++ server_name = "OpenWrt"; + +- server_name = strdup(he->h_name); ++ server_name = strdup(server_name); + if (server_name == NULL) { + perror("strdup:"); + exit(1); diff --git a/openwrt/packages/luci/libs/sgi-webuci/boa-patches/120-setuid_fix.patch b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/120-setuid_fix.patch new file mode 100644 index 0000000..1ea62b4 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/120-setuid_fix.patch @@ -0,0 +1,13 @@ +Index: boa-0.94.13/src/boa.c +=================================================================== +--- boa-0.94.13.orig/src/boa.c 2002-07-23 17:50:29.000000000 +0200 ++++ boa-0.94.13/src/boa.c 2008-06-29 01:12:31.000000000 +0200 +@@ -222,7 +222,7 @@ + /* test for failed-but-return-was-successful setuid + * http://www.securityportal.com/list-archive/bugtraq/2000/Jun/0101.html + */ +- if (setuid(0) != -1) { ++ if ((server_uid != 0) && (setuid(0) != -1)) { + DIE("icky Linux kernel bug!"); + } + } else { diff --git a/openwrt/packages/luci/libs/sgi-webuci/boa-patches/200-plugin_api.patch b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/200-plugin_api.patch new file mode 100644 index 0000000..c287ec5 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/200-plugin_api.patch @@ -0,0 +1,1109 @@ +Index: boa-0.94.13/src/list.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ boa-0.94.13/src/list.h 2008-06-29 01:12:36.000000000 +0200 +@@ -0,0 +1,601 @@ ++#ifndef _LINUX_LIST_H ++#define _LINUX_LIST_H ++ ++#include ++/** ++ * container_of - cast a member of a structure out to the containing structure ++ * @ptr: the pointer to the member. ++ * @type: the type of the container struct this is embedded in. ++ * @member: the name of the member within the struct. ++ * ++ */ ++#ifndef container_of ++#define container_of(ptr, type, member) ( \ ++ (type *)( (char *)ptr - offsetof(type,member) )) ++#endif ++ ++ ++/* ++ * Simple doubly linked list implementation. ++ * ++ * Some of the internal functions ("__xxx") are useful when ++ * manipulating whole lists rather than single entries, as ++ * sometimes we already know the next/prev entries and we can ++ * generate better code by using them directly rather than ++ * using the generic single-entry routines. ++ */ ++ ++struct list_head { ++ struct list_head *next, *prev; ++}; ++ ++#define LIST_HEAD_INIT(name) { &(name), &(name) } ++ ++#define LIST_HEAD(name) \ ++ struct list_head name = LIST_HEAD_INIT(name) ++ ++static inline void INIT_LIST_HEAD(struct list_head *list) ++{ ++ list->next = list; ++ list->prev = list; ++} ++ ++/* ++ * Insert a new entry between two known consecutive entries. ++ * ++ * This is only for internal list manipulation where we know ++ * the prev/next entries already! ++ */ ++static inline void __list_add(struct list_head *new, ++ struct list_head *prev, ++ struct list_head *next) ++{ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ prev->next = new; ++} ++ ++/** ++ * list_add - add a new entry ++ * @new: new entry to be added ++ * @head: list head to add it after ++ * ++ * Insert a new entry after the specified head. ++ * This is good for implementing stacks. ++ */ ++static inline void list_add(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head, head->next); ++} ++ ++ ++/** ++ * list_add_tail - add a new entry ++ * @new: new entry to be added ++ * @head: list head to add it before ++ * ++ * Insert a new entry before the specified head. ++ * This is useful for implementing queues. ++ */ ++static inline void list_add_tail(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head->prev, head); ++} ++ ++ ++/* ++ * Delete a list entry by making the prev/next entries ++ * point to each other. ++ * ++ * This is only for internal list manipulation where we know ++ * the prev/next entries already! ++ */ ++static inline void __list_del(struct list_head * prev, struct list_head * next) ++{ ++ next->prev = prev; ++ prev->next = next; ++} ++ ++/** ++ * list_del - deletes entry from list. ++ * @entry: the element to delete from the list. ++ * Note: list_empty() on entry does not return true after this, the entry is ++ * in an undefined state. ++ */ ++static inline void list_del(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++ entry->next = NULL; ++ entry->prev = NULL; ++} ++ ++/** ++ * list_replace - replace old entry by new one ++ * @old : the element to be replaced ++ * @new : the new element to insert ++ * ++ * If @old was empty, it will be overwritten. ++ */ ++static inline void list_replace(struct list_head *old, ++ struct list_head *new) ++{ ++ new->next = old->next; ++ new->next->prev = new; ++ new->prev = old->prev; ++ new->prev->next = new; ++} ++ ++static inline void list_replace_init(struct list_head *old, ++ struct list_head *new) ++{ ++ list_replace(old, new); ++ INIT_LIST_HEAD(old); ++} ++ ++/** ++ * list_del_init - deletes entry from list and reinitialize it. ++ * @entry: the element to delete from the list. ++ */ ++static inline void list_del_init(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++ INIT_LIST_HEAD(entry); ++} ++ ++/** ++ * list_move - delete from one list and add as another's head ++ * @list: the entry to move ++ * @head: the head that will precede our entry ++ */ ++static inline void list_move(struct list_head *list, struct list_head *head) ++{ ++ __list_del(list->prev, list->next); ++ list_add(list, head); ++} ++ ++/** ++ * list_move_tail - delete from one list and add as another's tail ++ * @list: the entry to move ++ * @head: the head that will follow our entry ++ */ ++static inline void list_move_tail(struct list_head *list, ++ struct list_head *head) ++{ ++ __list_del(list->prev, list->next); ++ list_add_tail(list, head); ++} ++ ++/** ++ * list_is_last - tests whether @list is the last entry in list @head ++ * @list: the entry to test ++ * @head: the head of the list ++ */ ++static inline int list_is_last(const struct list_head *list, ++ const struct list_head *head) ++{ ++ return list->next == head; ++} ++ ++/** ++ * list_empty - tests whether a list is empty ++ * @head: the list to test. ++ */ ++static inline int list_empty(const struct list_head *head) ++{ ++ return head->next == head; ++} ++ ++/** ++ * list_empty_careful - tests whether a list is empty and not being modified ++ * @head: the list to test ++ * ++ * Description: ++ * tests whether a list is empty _and_ checks that no other CPU might be ++ * in the process of modifying either member (next or prev) ++ * ++ * NOTE: using list_empty_careful() without synchronization ++ * can only be safe if the only activity that can happen ++ * to the list entry is list_del_init(). Eg. it cannot be used ++ * if another CPU could re-list_add() it. ++ */ ++static inline int list_empty_careful(const struct list_head *head) ++{ ++ struct list_head *next = head->next; ++ return (next == head) && (next == head->prev); ++} ++ ++static inline void __list_splice(struct list_head *list, ++ struct list_head *head) ++{ ++ struct list_head *first = list->next; ++ struct list_head *last = list->prev; ++ struct list_head *at = head->next; ++ ++ first->prev = head; ++ head->next = first; ++ ++ last->next = at; ++ at->prev = last; ++} ++ ++/** ++ * list_splice - join two lists ++ * @list: the new list to add. ++ * @head: the place to add it in the first list. ++ */ ++static inline void list_splice(struct list_head *list, struct list_head *head) ++{ ++ if (!list_empty(list)) ++ __list_splice(list, head); ++} ++ ++/** ++ * list_splice_init - join two lists and reinitialise the emptied list. ++ * @list: the new list to add. ++ * @head: the place to add it in the first list. ++ * ++ * The list at @list is reinitialised ++ */ ++static inline void list_splice_init(struct list_head *list, ++ struct list_head *head) ++{ ++ if (!list_empty(list)) { ++ __list_splice(list, head); ++ INIT_LIST_HEAD(list); ++ } ++} ++ ++/** ++ * list_entry - get the struct for this entry ++ * @ptr: the &struct list_head pointer. ++ * @type: the type of the struct this is embedded in. ++ * @member: the name of the list_struct within the struct. ++ */ ++#define list_entry(ptr, type, member) \ ++ container_of(ptr, type, member) ++ ++/** ++ * list_first_entry - get the first element from a list ++ * @ptr: the list head to take the element from. ++ * @type: the type of the struct this is embedded in. ++ * @member: the name of the list_struct within the struct. ++ * ++ * Note, that list is expected to be not empty. ++ */ ++#define list_first_entry(ptr, type, member) \ ++ list_entry((ptr)->next, type, member) ++ ++/** ++ * list_for_each - iterate over a list ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @head: the head for your list. ++ */ ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); \ ++ pos = pos->next) ++ ++/** ++ * __list_for_each - iterate over a list ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @head: the head for your list. ++ * ++ * This variant differs from list_for_each() in that it's the ++ * simplest possible list iteration code, no prefetching is done. ++ * Use this for code that knows the list to be very short (empty ++ * or 1 entry) most of the time. ++ */ ++#define __list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++ ++/** ++ * list_for_each_prev - iterate over a list backwards ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @head: the head for your list. ++ */ ++#define list_for_each_prev(pos, head) \ ++ for (pos = (head)->prev; pos != (head); \ ++ pos = pos->prev) ++ ++/** ++ * list_for_each_safe - iterate over a list safe against removal of list entry ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @n: another &struct list_head to use as temporary storage ++ * @head: the head for your list. ++ */ ++#define list_for_each_safe(pos, n, head) \ ++ for (pos = (head)->next, n = pos->next; pos != (head); \ ++ pos = n, n = pos->next) ++ ++/** ++ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @n: another &struct list_head to use as temporary storage ++ * @head: the head for your list. ++ */ ++#define list_for_each_prev_safe(pos, n, head) \ ++ for (pos = (head)->prev, n = pos->prev; \ ++ pos != (head); \ ++ pos = n, n = pos->prev) ++ ++/** ++ * list_for_each_entry - iterate over list of given type ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ */ ++#define list_for_each_entry(pos, head, member) \ ++ for (pos = list_entry((head)->next, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_entry(pos->member.next, typeof(*pos), member)) ++ ++/** ++ * list_for_each_entry_reverse - iterate backwards over list of given type. ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ */ ++#define list_for_each_entry_reverse(pos, head, member) \ ++ for (pos = list_entry((head)->prev, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_entry(pos->member.prev, typeof(*pos), member)) ++ ++/** ++ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() ++ * @pos: the type * to use as a start point ++ * @head: the head of the list ++ * @member: the name of the list_struct within the struct. ++ * ++ * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). ++ */ ++#define list_prepare_entry(pos, head, member) \ ++ ((pos) ? : list_entry(head, typeof(*pos), member)) ++ ++/** ++ * list_for_each_entry_continue - continue iteration over list of given type ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ * ++ * Continue to iterate over list of given type, continuing after ++ * the current position. ++ */ ++#define list_for_each_entry_continue(pos, head, member) \ ++ for (pos = list_entry(pos->member.next, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_entry(pos->member.next, typeof(*pos), member)) ++ ++/** ++ * list_for_each_entry_continue_reverse - iterate backwards from the given point ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ * ++ * Start to iterate over list of given type backwards, continuing after ++ * the current position. ++ */ ++#define list_for_each_entry_continue_reverse(pos, head, member) \ ++ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_entry(pos->member.prev, typeof(*pos), member)) ++ ++/** ++ * list_for_each_entry_from - iterate over list of given type from the current point ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ * ++ * Iterate over list of given type, continuing from current position. ++ */ ++#define list_for_each_entry_from(pos, head, member) \ ++ for (; &pos->member != (head); \ ++ pos = list_entry(pos->member.next, typeof(*pos), member)) ++ ++/** ++ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ */ ++#define list_for_each_entry_safe(pos, n, head, member) \ ++ for (pos = list_entry((head)->next, typeof(*pos), member), \ ++ n = list_entry(pos->member.next, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_entry(n->member.next, typeof(*n), member)) ++ ++/** ++ * list_for_each_entry_safe_continue ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ * ++ * Iterate over list of given type, continuing after current point, ++ * safe against removal of list entry. ++ */ ++#define list_for_each_entry_safe_continue(pos, n, head, member) \ ++ for (pos = list_entry(pos->member.next, typeof(*pos), member), \ ++ n = list_entry(pos->member.next, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_entry(n->member.next, typeof(*n), member)) ++ ++/** ++ * list_for_each_entry_safe_from ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ * ++ * Iterate over list of given type from current point, safe against ++ * removal of list entry. ++ */ ++#define list_for_each_entry_safe_from(pos, n, head, member) \ ++ for (n = list_entry(pos->member.next, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_entry(n->member.next, typeof(*n), member)) ++ ++/** ++ * list_for_each_entry_safe_reverse ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_struct within the struct. ++ * ++ * Iterate backwards over list of given type, safe against removal ++ * of list entry. ++ */ ++#define list_for_each_entry_safe_reverse(pos, n, head, member) \ ++ for (pos = list_entry((head)->prev, typeof(*pos), member), \ ++ n = list_entry(pos->member.prev, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_entry(n->member.prev, typeof(*n), member)) ++ ++/* ++ * Double linked lists with a single pointer list head. ++ * Mostly useful for hash tables where the two pointer list head is ++ * too wasteful. ++ * You lose the ability to access the tail in O(1). ++ */ ++ ++struct hlist_head { ++ struct hlist_node *first; ++}; ++ ++struct hlist_node { ++ struct hlist_node *next, **pprev; ++}; ++ ++#define HLIST_HEAD_INIT { .first = NULL } ++#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } ++#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) ++static inline void INIT_HLIST_NODE(struct hlist_node *h) ++{ ++ h->next = NULL; ++ h->pprev = NULL; ++} ++ ++static inline int hlist_unhashed(const struct hlist_node *h) ++{ ++ return !h->pprev; ++} ++ ++static inline int hlist_empty(const struct hlist_head *h) ++{ ++ return !h->first; ++} ++ ++static inline void __hlist_del(struct hlist_node *n) ++{ ++ struct hlist_node *next = n->next; ++ struct hlist_node **pprev = n->pprev; ++ *pprev = next; ++ if (next) ++ next->pprev = pprev; ++} ++ ++static inline void hlist_del(struct hlist_node *n) ++{ ++ __hlist_del(n); ++ n->next = NULL; ++ n->pprev = NULL; ++} ++ ++static inline void hlist_del_init(struct hlist_node *n) ++{ ++ if (!hlist_unhashed(n)) { ++ __hlist_del(n); ++ INIT_HLIST_NODE(n); ++ } ++} ++ ++ ++static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) ++{ ++ struct hlist_node *first = h->first; ++ n->next = first; ++ if (first) ++ first->pprev = &n->next; ++ h->first = n; ++ n->pprev = &h->first; ++} ++ ++ ++/* next must be != NULL */ ++static inline void hlist_add_before(struct hlist_node *n, ++ struct hlist_node *next) ++{ ++ n->pprev = next->pprev; ++ n->next = next; ++ next->pprev = &n->next; ++ *(n->pprev) = n; ++} ++ ++static inline void hlist_add_after(struct hlist_node *n, ++ struct hlist_node *next) ++{ ++ next->next = n->next; ++ n->next = next; ++ next->pprev = &n->next; ++ ++ if(next->next) ++ next->next->pprev = &next->next; ++} ++ ++#define hlist_entry(ptr, type, member) container_of(ptr,type,member) ++ ++#define hlist_for_each(pos, head) \ ++ for (pos = (head)->first; pos; pos = pos->next) ++ ++#define hlist_for_each_safe(pos, n, head) \ ++ for (pos = (head)->first; pos; pos = n) ++ ++/** ++ * hlist_for_each_entry - iterate over list of given type ++ * @tpos: the type * to use as a loop cursor. ++ * @pos: the &struct hlist_node to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry(tpos, pos, head, member) \ ++ for (pos = (head)->first; pos && \ ++ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ ++ pos = pos->next) ++ ++/** ++ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point ++ * @tpos: the type * to use as a loop cursor. ++ * @pos: the &struct hlist_node to use as a loop cursor. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry_continue(tpos, pos, member) \ ++ for (pos = (pos)->next; pos && \ ++ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ ++ pos = pos->next) ++ ++/** ++ * hlist_for_each_entry_from - iterate over a hlist continuing from current point ++ * @tpos: the type * to use as a loop cursor. ++ * @pos: the &struct hlist_node to use as a loop cursor. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry_from(tpos, pos, member) \ ++ for (; pos && \ ++ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ ++ pos = pos->next) ++ ++/** ++ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry ++ * @tpos: the type * to use as a loop cursor. ++ * @pos: the &struct hlist_node to use as a loop cursor. ++ * @n: another &struct hlist_node to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ ++ for (pos = (head)->first; \ ++ pos && ({ n = pos->next; 1; }) && \ ++ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ ++ pos = n) ++ ++#endif +Index: boa-0.94.13/src/plugin.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ boa-0.94.13/src/plugin.c 2008-06-29 02:02:42.000000000 +0200 +@@ -0,0 +1,191 @@ ++/* ++ * Simple plugin API for boa ++ * Copyright (C) 2008 John Crispin ++ * Copyright (C) 2008 Felix Fietkau ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include "boa.h" ++#include "list.h" ++#include ++#include ++ ++static LIST_HEAD(plugins); ++ ++struct httpd_plugin *plugin_lookup(request *req) ++{ ++ struct list_head *l; ++ list_for_each(l, &plugins) ++ { ++ struct httpd_plugin *p = ++ container_of(l, struct httpd_plugin, list); ++ ++ if (!strncmp(req->request_uri, p->prefix, strlen(p->prefix))) ++ return p; ++ } ++ return NULL; ++} ++ ++static int plugin_run(request *req, struct httpd_plugin *p) ++{ ++ struct http_context ctx; ++ int child_pid; ++ ++ SQUASH_KA(req); ++ ++ memset(&ctx, 0, sizeof(ctx)); ++ ctx.uri = req->request_uri; ++ switch(req->method) { ++ case M_POST: ++ ctx.request_method = "POST"; ++ break; ++ case M_HEAD: ++ ctx.request_method = "HEAD"; ++ break; ++ case M_GET: ++ ctx.request_method = "GET"; ++ break; ++ } ++ ctx.server_addr = req->local_ip_addr; ++ ctx.server_proto = req->http_version; ++ ctx.query_string = req->query_string; ++ ctx.remote_addr = req->remote_ip_addr; ++ ctx.remote_port = req->remote_port; ++ ctx.cookie = req->cookie; ++ if (req->method == M_POST) { ++ if (req->content_type) ++ ctx.content_type = req->content_type; ++ else ++ ctx.content_type = default_type; ++ ctx.content_length = req->content_length; ++ } ++#ifdef ACCEPT_ON ++ if (req->accept[0]) ++ ctx.http_accept = req->accept; ++#endif ++ ++ p->prepare_req(p, &ctx); ++ child_pid = fork(); ++ ++ switch(child_pid) { ++ case -1: ++ log_error_time(); ++ perror("fork"); ++ send_r_error(req); ++ return 0; ++ ++ case 0: ++ if (dup2(req->fd, STDOUT_FILENO) == -1) { ++ log_error_time(); ++ perror("dup2 - fd"); ++ _exit(1); ++ } ++ if (set_block_fd(req->fd) == -1) { ++ log_error_time(); ++ perror("cgi-fcntl"); ++ _exit(1); ++ } ++ if (req->method == M_POST) { ++ dup2(req->read_data_fd, STDIN_FILENO); ++ close(req->read_data_fd); ++ close(req->post_data_fd); ++ set_block_fd(STDIN_FILENO); ++ } ++ close_access_log(); ++ ++ if (cgi_log_fd) ++ dup2(cgi_log_fd, STDERR_FILENO); ++ ++ p->handle_req(p, &ctx); ++ exit(0); ++ break; ++ } ++ ++ return 1; ++} ++ ++int plugin_handle(request * req) ++{ ++ struct httpd_plugin *p; ++ ++ p = plugin_lookup(req); ++ if (!p) ++ return 0; ++ ++ return plugin_run(req, p); ++} ++ ++static void plugin_load(const char *p, const char *dir) ++{ ++ struct httpd_plugin *plugin; ++ void *dl; ++ ++ /* ignore directories */ ++ if (p[strlen(p) - 1] == '/') ++ return; ++ ++ dl = dlopen(p, RTLD_NOW | RTLD_GLOBAL); ++ if (!dl) { ++ fprintf(stderr, "Unable to load plugin '%s': %d\n", p, dlerror()); ++ return; ++ } ++ ++ plugin = dlsym(dl, "httpd_plugin"); ++ if (!plugin) ++ goto error; ++ ++ INIT_LIST_HEAD(&plugin->list); ++ plugin->dir = dir; ++ ++ if (plugin->init(plugin) != 1) ++ goto error; ++ ++ if (!plugin->prefix) ++ goto error_init; ++ ++ list_add(&plugin->list, &plugins); ++ return; ++ ++error_init: ++ plugin->done(plugin); ++error: ++ fprintf(stderr, "Plugin '%s' failed to initialize\n", p); ++ dlclose(dl); ++} ++ ++#define WILDCARD_SUFFIX "/*.so" ++ ++int plugin_init(char *path) ++{ ++ int buflen = 128; ++ char *plugindir; ++ glob_t g; ++ char *s; ++ int i; ++ ++ s = malloc(strlen(path) + sizeof(WILDCARD_SUFFIX) + 1); ++ strcpy(s, path); ++ strcat(s, WILDCARD_SUFFIX); ++ glob(s, GLOB_MARK, NULL, &g); ++ free(s); ++ ++ for (i = 0; i < g.gl_pathc; i++) ++ plugin_load(g.gl_pathv[i], path); ++ ++ globfree(&g); ++ return 1; ++} ++ ++ +Index: boa-0.94.13/src/request.c +=================================================================== +--- boa-0.94.13.orig/src/request.c 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/request.c 2008-06-29 01:49:46.000000000 +0200 +@@ -50,6 +50,7 @@ + dequeue(&request_free, request_free); /* dequeue the head */ + } else { + req = (request *) malloc(sizeof (request)); ++ memset(req, 0, sizeof(request)); + if (!req) { + log_error_time(); + perror("malloc for new request"); +@@ -603,6 +604,8 @@ + + int process_header_end(request * req) + { ++ int ret; ++ + if (!req->logline) { + send_r_error(req); + return 0; +@@ -630,11 +633,26 @@ + } + + if (req->method == M_POST) { +- req->post_data_fd = create_temporary_file(1, NULL, 0); +- if (req->post_data_fd == 0) +- return(0); +- return(1); /* success */ +- } ++ if (!req->plugin) { ++ req->post_data_fd = create_temporary_file(1, NULL, 0); ++ } else { ++ int fd[2]; ++ if (pipe(&fd[0]) != -1) { ++ req->post_data_fd = fd[1]; ++ req->read_data_fd = fd[0]; ++ set_nonblock_fd(req->post_data_fd); ++ } ++ } ++ if (req->post_data_fd == 0) { ++ return(0); ++ } ++ if (!req->plugin) ++ return(1); /* success */ ++ } ++ ++ ret = plugin_handle(req); ++ if (ret) ++ return ret; + + if (req->is_cgi) { + return init_cgi(req); +@@ -698,6 +716,8 @@ + req->header_user_agent = value; + if (!add_cgi_env(req, "USER_AGENT", value, 1)) + return 0; ++ } else if (!memcmp(line, "COOKIE", 7)) { ++ req->cookie = value; + } else { + if (!add_cgi_env(req, line, value, 1)) + return 0; +Index: boa-0.94.13/src/Makefile.in +=================================================================== +--- boa-0.94.13.orig/src/Makefile.in 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/Makefile.in 2008-06-29 01:12:36.000000000 +0200 +@@ -20,7 +20,7 @@ + srcdir = @srcdir@ + VPATH = @srcdir@:@srcdir@/../extras + LDFLAGS = @LDFLAGS@ +-LIBS = @LIBS@ ++LIBS = @LIBS@ -ldl + CFLAGS = @CFLAGS@ -I. + + # Change these if necessary +@@ -32,7 +32,8 @@ + + SOURCES = alias.c boa.c buffer.c cgi.c cgi_header.c config.c escape.c \ + get.c hash.c ip.c log.c mmap_cache.c pipe.c queue.c read.c \ +- request.c response.c select.c signals.c util.c sublog.c ++ request.c response.c select.c signals.c util.c sublog.c \ ++ plugin.c + + OBJS = y.tab.o lex.yy.o $(SOURCES:.c=.o) timestamp.o @STRUTIL@ + +Index: boa-0.94.13/src/boa.h +=================================================================== +--- boa-0.94.13.orig/src/boa.h 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/boa.h 2008-06-29 01:12:36.000000000 +0200 +@@ -37,6 +37,7 @@ + #include + #include /* OPEN_MAX */ + #include ++#include + + #include + #include +@@ -50,6 +51,7 @@ + #include "compat.h" /* oh what fun is porting */ + #include "defines.h" + #include "globals.h" ++#include "boa-plugin.h" + + /* alias */ + void add_alias(char *fakename, char *realname, int script); +@@ -192,4 +194,9 @@ + /* select */ + void select_loop(int server_s); + ++/* plugins */ ++int plugin_init(char *path); ++int plugin_handle(request * req); ++struct httpd_plugin *plugin_lookup(request *req); ++ + #endif +Index: boa-0.94.13/src/config.c +=================================================================== +--- boa-0.94.13.orig/src/config.c 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/config.c 2008-06-29 01:12:36.000000000 +0200 +@@ -61,6 +61,7 @@ + char *error_log_name; + char *access_log_name; + char *cgi_log_name; ++char *plugin_root = NULL; + + int use_localtime; + +@@ -116,6 +117,7 @@ + {"SinglePostLimit", S1A, c_set_int, &single_post_limit}, + {"CGIPath", S1A, c_set_string, &cgi_path}, + {"MaxConnections", S1A, c_set_int, &max_connections}, ++ {"PluginRoot", S1A, c_set_string, &plugin_root}, + }; + + static void c_set_user(char *v1, char *v2, void *t) +@@ -323,6 +325,22 @@ + free(dirmaker); + dirmaker = temp; + } ++ if (plugin_root) { ++ char *plugin_path = plugin_root; ++ char *next; ++ ++ do { ++ next = strchr(plugin_path, ':'); ++ if (next) { ++ *next = 0; ++ next++; ++ } ++ ++ plugin_init(normalize_path(plugin_path)); ++ plugin_path = next; ++ } while (plugin_path); ++ free(plugin_root); ++ } + + #if 0 + if (mime_types) { +Index: boa-0.94.13/src/alias.c +=================================================================== +--- boa-0.94.13.orig/src/alias.c 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/alias.c 2008-06-29 01:12:36.000000000 +0200 +@@ -213,6 +213,7 @@ + uri_len = strlen(req->request_uri); + + current = find_alias(req->request_uri, uri_len); ++ req->plugin = !!plugin_lookup(req); + if (current) { + + if (current->type == SCRIPTALIAS) /* Script */ +@@ -237,7 +238,7 @@ + } + + if (current->type == REDIRECT) { /* Redirect */ +- if (req->method == M_POST) { /* POST to non-script */ ++ if ((req->method == M_POST) && !req->plugin) { /* POST to non-script */ + /* it's not a cgi, but we try to POST??? */ + send_r_bad_request(req); + return 0; /* not a script alias, therefore begin filling in data */ +@@ -361,7 +362,7 @@ + else + req->is_cgi = CGI; + return 1; +- } else if (req->method == M_POST) { /* POST to non-script */ ++ } else if ((req->method == M_POST) && !req->plugin) { /* POST to non-script */ + /* it's not a cgi, but we try to POST??? */ + send_r_bad_request(req); + return 0; +Index: boa-0.94.13/src/globals.h +=================================================================== +--- boa-0.94.13.orig/src/globals.h 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/globals.h 2008-06-29 01:47:25.000000000 +0200 +@@ -47,6 +47,7 @@ + struct request { /* pending requests */ + int fd; /* client's socket fd */ + int status; /* see #defines.h */ ++ bool plugin; + time_t time_last; /* time of last succ. op. */ + char *pathname; /* pathname of requested file */ + int simple; /* simple request? */ +@@ -92,6 +93,7 @@ + char *header_referer; + + int post_data_fd; /* fd for post data tmpfile */ ++ int read_data_fd; /* fd for post data input (plugin) */ + + char *path_info; /* env variable */ + char *path_translated; /* env variable */ +@@ -99,6 +101,7 @@ + char *query_string; /* env variable */ + char *content_type; /* env variable */ + char *content_length; /* env variable */ ++ char *cookie; /* env variable */ + + struct mmap_entry *mmap_entry_var; + +Index: boa-0.94.13/src/read.c +=================================================================== +--- boa-0.94.13.orig/src/read.c 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/read.c 2008-06-29 01:12:36.000000000 +0200 +@@ -338,8 +338,11 @@ + + if (bytes_to_write == 0) { /* nothing left in buffer to write */ + req->header_line = req->header_end = req->buffer; +- if (req->filepos >= req->filesize) +- return init_cgi(req); ++ if (req->filepos >= req->filesize) { ++ if (req->post_data_fd > 0) ++ close(req->post_data_fd); ++ return init_cgi(req); ++ } + /* if here, we can safely assume that there is more to read */ + req->status = BODY_READ; + return 1; +Index: boa-0.94.13/src/boa-plugin.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ boa-0.94.13/src/boa-plugin.h 2008-06-29 02:02:27.000000000 +0200 +@@ -0,0 +1,68 @@ ++#ifndef _HTTPD_PLUGIN_H__ ++#define _HTTPD_PLUGIN_H__ ++ ++#include "list.h" ++ ++/* ++ * Definition for HTTP server plugins ++ * ++ * The context that the plugin is called with for ++ * a single http request. It gets allocated in the ++ * persistent context before prepare_req and freed ++ * there afterwards (still active in the forked ++ * context at handle_req time) ++ */ ++struct http_context ++{ ++ char *uri; ++ char *request_method; ++ char *server_addr; ++ char *server_proto; ++ char *query_string; ++ char *remote_addr; ++ unsigned int remote_port; ++ char *content_type; ++ char *content_length; ++ char *http_accept; ++ char *cookie; ++ ++ void *priv; ++}; ++ ++/* ++ * the main data structure of httpd plugins. ++ */ ++struct httpd_plugin ++{ ++ /* used by the web server */ ++ struct list_head list; ++ ++ /* only page requests matching 'prefix' are passed ++ * to prepare_req and handle_req */ ++ const char *prefix; ++ ++ /* directory that the plugin was found in */ ++ const char *dir; ++ ++ /* initialize the plugin, if the return value is nonzero, ++ * the plugin will not be used */ ++ int (*init)(struct httpd_plugin *); ++ ++ /* free all memory associated with the plugin */ ++ void (*done)(struct httpd_plugin *); ++ ++ /* prepare a page request. this is executed in the main context, ++ * so pay attention to memory usage. should not print any data ++ * to stdout */ ++ int (*prepare_req)(struct httpd_plugin *, struct http_context *); ++ ++ /* handle the request. can print output data to stdout */ ++ int (*handle_req)(struct httpd_plugin *, struct http_context *); ++ ++ /* pointer for private data structures of the plugin */ ++ void *priv; ++}; ++ ++#define HTTPD_PLUGIN struct httpd_plugin httpd_plugin = ++ ++#endif diff --git a/openwrt/packages/luci/libs/sgi-webuci/boa-patches/210-accept_fix.patch b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/210-accept_fix.patch new file mode 100644 index 0000000..5a3bdf8 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/210-accept_fix.patch @@ -0,0 +1,15 @@ +Index: boa-0.94.13/src/request.c +=================================================================== +--- boa-0.94.13.orig/src/request.c 2008-06-29 01:11:52.000000000 +0200 ++++ boa-0.94.13/src/request.c 2008-10-07 18:10:59.000000000 +0200 +@@ -281,6 +281,10 @@ + if (req->script_name) + free(req->script_name); + ++#ifdef ACCEPT_ON ++ req->accept[0] = '\0'; ++#endif ++ + if ((req->keepalive == KA_ACTIVE) && + (req->response_status < 500) && req->kacount > 0) { + int bytes_to_move; diff --git a/openwrt/packages/luci/libs/sgi-webuci/boa-patches/220-ipv6-vs-ipv4.patch b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/220-ipv6-vs-ipv4.patch new file mode 100644 index 0000000..5d0eb6a --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/boa-patches/220-ipv6-vs-ipv4.patch @@ -0,0 +1,257 @@ +diff -urN boa-0.94.13.orig/src/boa.c boa-0.94.13/src/boa.c +--- boa-0.94.13.orig/src/boa.c 2008-10-28 16:15:45.000000000 +0100 ++++ boa-0.94.13/src/boa.c 2008-10-28 15:56:27.000000000 +0100 +@@ -27,6 +27,12 @@ + #include + + /* globals */ ++ ++#ifdef INET6 ++int server_addr_family; ++socklen_t server_addr_len; ++#endif ++ + int backlog = SO_MAXCONN; + time_t start_time; + +@@ -164,14 +170,36 @@ + return 0; + } + ++#ifdef INET6 ++sa_family_t *get_addr_family(struct sockaddr *address) ++{ ++ if(server_addr_family == AF_INET6) { ++ return &(((struct sockaddr_in6 *) address)->sin6_family); ++ } ++ ++ return &(((struct sockaddr_in *) address)->sin_family); ++} ++#endif ++ + static int create_server_socket(void) + { + int server_s; + +- server_s = socket(SERVER_AF, SOCK_STREAM, IPPROTO_TCP); ++#ifdef INET6 ++ server_addr_family = AF_INET6; ++ server_addr_len = sizeof(struct sockaddr_in6); ++ server_s = socket(server_addr_family, SOCK_STREAM, IPPROTO_TCP); + if (server_s == -1) { +- DIE("unable to create socket"); ++ server_addr_family = AF_INET; ++ server_addr_len = sizeof(struct sockaddr_in); ++#endif ++ server_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ++ if (server_s == -1) { ++ DIE("unable to create socket"); ++ } ++#ifdef INET6 + } ++#endif + + /* server socket is nonblocking */ + if (set_nonblock_fd(server_s) == -1) { +diff -urN boa-0.94.13.orig/src/boa.h boa-0.94.13/src/boa.h +--- boa-0.94.13.orig/src/boa.h 2008-10-28 16:15:58.000000000 +0100 ++++ boa-0.94.13/src/boa.h 2008-10-28 14:45:52.000000000 +0100 +@@ -199,4 +199,12 @@ + int plugin_handle(request * req); + struct httpd_plugin *plugin_lookup(request *req); + ++/* IPv6 */ ++ ++#ifdef INET6 ++extern int server_addr_family; ++extern socklen_t server_addr_len; ++sa_family_t *get_addr_family(struct sockaddr *address); ++#endif ++ + #endif +diff -urN boa-0.94.13.orig/src/compat.h boa-0.94.13/src/compat.h +--- boa-0.94.13.orig/src/compat.h 2002-06-06 07:02:28.000000000 +0200 ++++ boa-0.94.13/src/compat.h 2008-10-28 15:31:16.000000000 +0100 +@@ -71,11 +71,13 @@ + + #ifdef INET6 + #define SOCKADDR sockaddr_storage +-#define S_FAMILY __s_family +-#define SERVER_AF AF_INET6 ++#define SOCKADDR_LEN server_addr_len ++#define S_FAMILY(address) (*get_addr_family((struct sockaddr *) (address))) ++#define SERVER_AF server_addr_family + #else + #define SOCKADDR sockaddr_in +-#define S_FAMILY sin_family ++#define SOCKADDR_LEN sizeof(struct sockaddr_in) ++#define S_FAMILY(address) ((*address).sin_family) + #define SERVER_AF AF_INET + #endif + +diff -urN boa-0.94.13.orig/src/ip.c boa-0.94.13/src/ip.c +--- boa-0.94.13.orig/src/ip.c 2002-01-21 03:19:16.000000000 +0100 ++++ boa-0.94.13/src/ip.c 2008-10-28 15:52:05.000000000 +0100 +@@ -44,52 +44,64 @@ + + #include "boa.h" + #include /* inet_ntoa */ ++#include + + /* Binds to the existing server_s, based on the configuration string + in server_ip. IPv6 version doesn't pay attention to server_ip yet. */ + int bind_server(int server_s, char *server_ip) + { ++ struct sockaddr *server_sockaddr; ++ struct sockaddr_in server_sockaddr4; ++ + #ifdef INET6 +- struct sockaddr_in6 server_sockaddr; +- server_sockaddr.sin6_family = AF_INET6; +- memcpy(&server_sockaddr.sin6_addr, &in6addr_any, sizeof (in6addr_any)); +- server_sockaddr.sin6_port = htons(server_port); +-#else +- struct sockaddr_in server_sockaddr; +- memset(&server_sockaddr, 0, sizeof server_sockaddr); ++ struct sockaddr_in6 server_sockaddr6; ++ if(SERVER_AF == AF_INET6) { ++ server_sockaddr6.sin6_family = AF_INET6; ++ memcpy(&server_sockaddr6.sin6_addr, &in6addr_any, sizeof (in6addr_any)); ++ server_sockaddr6.sin6_port = htons(server_port); ++ server_sockaddr = (struct sockaddr *) &server_sockaddr6; ++ } else { ++#endif ++ memset(&server_sockaddr4, 0, SOCKADDR_LEN); + #ifdef HAVE_SIN_LEN /* uncomment for BSDs */ +- server_sockaddr.sin_len = sizeof server_sockaddr; ++ server_sockaddr4.sin_len = SOCKADDR_LEN; + #endif +- server_sockaddr.sin_family = AF_INET; +- if (server_ip != NULL) { +- inet_aton(server_ip, &server_sockaddr.sin_addr); +- } else { +- server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); ++ server_sockaddr4.sin_family = AF_INET; ++ if (server_ip != NULL) { ++ inet_aton(server_ip, &server_sockaddr4.sin_addr); ++ } else { ++ server_sockaddr4.sin_addr.s_addr = htonl(INADDR_ANY); ++ } ++ server_sockaddr4.sin_port = htons(server_port); ++ server_sockaddr = (struct sockaddr *) &server_sockaddr4; ++#ifdef INET6 + } +- server_sockaddr.sin_port = htons(server_port); + #endif + +- return bind(server_s, (struct sockaddr *) &server_sockaddr, +- sizeof (server_sockaddr)); ++ return bind(server_s, server_sockaddr, SOCKADDR_LEN); + } + + char *ascii_sockaddr(struct SOCKADDR *s, char *dest, int len) + { + #ifdef INET6 +- if (getnameinfo((struct sockaddr *) s, +- sizeof(struct SOCKADDR), +- dest, len, NULL, 0, NI_NUMERICHOST)) { +- fprintf(stderr, "[IPv6] getnameinfo failed\n"); +- *dest = '\0'; +- } ++ if(SERVER_AF == AF_INET6) { ++ if (getnameinfo((struct sockaddr *) s, ++ SOCKADDR_LEN, ++ dest, len, NULL, 0, NI_NUMERICHOST)) { ++ fprintf(stderr, "[IPv6] getnameinfo failed\n"); ++ *dest = '\0'; ++ } + #ifdef WHEN_DOES_THIS_APPLY +- if ((s->__ss_family == AF_INET6) && +- IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *) s)->sin6_addr))) { +- memmove(dest, dest+7, NI_MAXHOST); +- } ++ if (((((struct sockaddr_in6 *) s)->sin6_family) == AF_INET6) && ++ IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *) s)->sin6_addr))) { ++ memmove(dest, dest+7, NI_MAXHOST); ++ } + #endif +-#else +- memmove(dest, inet_ntoa(s->sin_addr), len); ++ } else { ++#endif ++ memmove(dest, inet_ntoa(((struct sockaddr_in *) s)->sin_addr), len); ++#ifdef INET6 ++ } + #endif + return dest; + } +@@ -98,17 +110,21 @@ + { + int p = -1; + #ifdef INET6 +- char serv[NI_MAXSERV]; ++ if(SERVER_AF == AF_INET6) { ++ char serv[NI_MAXSERV]; + +- if (getnameinfo((struct sockaddr *) s, +- sizeof(struct SOCKADDR), +- NULL, 0, serv, sizeof(serv), NI_NUMERICSERV)) { +- fprintf(stderr, "[IPv6] getnameinfo failed\n"); ++ if (getnameinfo((struct sockaddr *) s, ++ SOCKADDR_LEN, ++ NULL, 0, serv, sizeof(serv), NI_NUMERICSERV)) { ++ fprintf(stderr, "[IPv6] getnameinfo failed\n"); ++ } else { ++ p = atoi(serv); ++ } + } else { +- p = atoi(serv); ++#endif ++ p = ntohs(((struct sockaddr_in *) s)->sin_port); ++#ifdef INET6 + } +-#else +- p = ntohs(s->sin_port); + #endif + return p; + } +diff -urN boa-0.94.13.orig/src/mmap_cache.c boa-0.94.13/src/mmap_cache.c +--- boa-0.94.13.orig/src/mmap_cache.c 2002-03-24 23:35:34.000000000 +0100 ++++ boa-0.94.13/src/mmap_cache.c 2008-10-28 14:55:16.000000000 +0100 +@@ -67,7 +67,7 @@ + + m = mmap(0, s->st_size, PROT_READ, MAP_OPTIONS, data_fd, 0); + +- if ((int) m == -1) { ++ if ((ssize_t) m == -1) { + /* boa_perror(req,"mmap"); */ + return NULL; + } +diff -urN boa-0.94.13.orig/src/request.c boa-0.94.13/src/request.c +--- boa-0.94.13.orig/src/request.c 2008-10-28 16:16:03.000000000 +0100 ++++ boa-0.94.13/src/request.c 2008-10-28 15:17:20.000000000 +0100 +@@ -75,12 +75,12 @@ + int fd; /* socket */ + struct SOCKADDR remote_addr; /* address */ + struct SOCKADDR salocal; +- int remote_addrlen = sizeof (struct SOCKADDR); ++ int remote_addrlen = SOCKADDR_LEN; + request *conn; /* connection */ +- size_t len; ++ socklen_t len; + static int system_bufsize = 0; /* Default size of SNDBUF given by system */ + +- remote_addr.S_FAMILY = 0xdead; ++ S_FAMILY(&remote_addr) = 0xdead; + fd = accept(server_s, (struct sockaddr *) &remote_addr, + &remote_addrlen); + +@@ -133,7 +133,7 @@ + } + #endif + +- len = sizeof(salocal); ++ len = SOCKADDR_LEN; + + if (getsockname(fd, (struct sockaddr *) &salocal, &len) != 0) { + WARN("getsockname"); diff --git a/openwrt/packages/luci/libs/sgi-webuci/host/buildconfig.sh b/openwrt/packages/luci/libs/sgi-webuci/host/buildconfig.sh new file mode 100755 index 0000000..9889637 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/host/buildconfig.sh @@ -0,0 +1,20 @@ +#!/bin/sh +CWD=$1 +cat < + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.sgi.webuci", package.seeall) +local ltn12 = require("luci.ltn12") +require("luci.http") +require("luci.util") +require("luci.dispatcher") + +function run(env, vars) + local r = luci.http.Request( + env, + ltn12.source.empty(), + ltn12.sink.file(io.stderr) + ) + + r.message.params = vars + + local x = coroutine.create(luci.dispatcher.httpdispatch) + local status = "" + local headers = {} + local active = true + + while coroutine.status(x) ~= "dead" do + local res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + print(env.SERVER_PROTOCOL .. " 500 Internal Server Error") + print("Content-Type: text/plain\n") + print(id) + break; + end + + if active then + if id == 1 then + status = env.SERVER_PROTOCOL .. " " .. tostring(data1) .. " " .. data2 .. "\r\n" + elseif id == 2 then + headers[data1] = data2 + elseif id == 3 then + io.write(status) + for k, v in pairs(headers) do + io.write(k .. ": " .. v .. "\r\n") + end + io.write("\r\n") + elseif id == 4 then + io.write(data1) + elseif id == 5 then + active = false + end + end + end +end diff --git a/openwrt/packages/luci/libs/sgi-webuci/root/etc/boa/boa.conf b/openwrt/packages/luci/libs/sgi-webuci/root/etc/boa/boa.conf new file mode 100644 index 0000000..c152caa --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/root/etc/boa/boa.conf @@ -0,0 +1,17 @@ +Port 80 +ErrorLog /dev/stderr +AccessLog /dev/stderr +DocumentRoot /www +DirectoryMaker /usr/lib/boa/boa_indexer +KeepAliveMax 1000 +KeepAliveTimeout 10 +MimeTypes /etc/mime.types +DefaultType text/plain +ServerName localhost +CGIPath /bin:/usr/bin + +AddType application/x-httpd-cgi cgi +AddType application/x-httpd-cgi sh + +ScriptAlias /cgi-bin/ /www/cgi-bin +PluginRoot /usr/lib/boa diff --git a/openwrt/packages/luci/libs/sgi-webuci/root/etc/init.d/boa b/openwrt/packages/luci/libs/sgi-webuci/root/etc/init.d/boa new file mode 100755 index 0000000..2a11ed7 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/root/etc/init.d/boa @@ -0,0 +1,57 @@ +#!/bin/sh /etc/rc.common +# +# Written by Miquel van Smoorenburg . +# Modified for Debian GNU/Linux +# by Ian Murdock . +# Modified for boa by Bill Allombert . +# Modified for OpenWrt by Steven Barth . + +### BEGIN INIT INFO +# Provides: boa +# Required-Start: $local_fs $remote_fs $network +# Required-Stop: $local_fs $remote_fs $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Boa: lightweight and high performance web server +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/boa +NAME=boa +DESC="HTTP server" +START=49 + +test -x $DAEMON || exit 0 + +set -e + +start() { + echo -n "Starting $DESC: $NAME" + start-stop-daemon -S -q -x $DAEMON + echo "." +} + +stop() { + echo -n "Stopping $DESC: $NAME" + start-stop-daemon -K -q -x $DAEMON + echo "." +} + +restart() { + echo -n "Restarting $DESC: $NAME... " + start-stop-daemon -K -s HUP -q -x $DAEMON + echo "done." +} + +reload() { + # + # If the daemon can reload its config files on the fly + # for example by sending it SIGHUP, do it here. + # + # If the daemon responds to changes in its config file + # directly anyway, make this a do-nothing entry. + # + echo -n "Reloading $DESC configuration... " + start-stop-daemon -K -s 1 -q -x $DAEMON + echo "done." +} diff --git a/openwrt/packages/luci/libs/sgi-webuci/root/etc/mime.types b/openwrt/packages/luci/libs/sgi-webuci/root/etc/mime.types new file mode 100644 index 0000000..ee11c1b --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/root/etc/mime.types @@ -0,0 +1,748 @@ +############################################################################### +# +# MIME-TYPES and the extensions that represent them +# +# This file is part of the "mime-support" package. Please send email (not a +# bug report) to mime-support@packages.debian.org if you would like new types +# and/or extensions to be added. +# +# The reason that all types are managed by the mime-support package instead +# allowing individual packages to install types in much the same way as they +# add entries in to the mailcap file is so these types can be referenced by +# other programs (such as a web server) even if the specific support package +# for that type is not installed. +# +# Users can add their own types if they wish by creating a ".mime.types" +# file in their home directory. Definitions included there will take +# precedence over those listed here. +# +# Note: Compression schemes like "gzip", "bzip", and "compress" are not +# actually "mime-types". They are "encodings" and hence must _not_ have +# entries in this file to map their extensions. The "mime-type" of an +# encoded file refers to the type of data that has been encoded, not the +# type of encoding. +# +############################################################################### + + +application/activemessage +application/andrew-inset ez +application/applefile +application/atom atom +application/atomcat+xml atomcat +application/atomserv+xml atomsrv +application/atomicmail +application/batch-SMTP +application/beep+xml +application/cals-1840 +application/cap cap pcap +application/commonground +application/cu-seeme cu +application/cybercash +application/dca-rft +application/dec-dx +application/docbook+xml +application/dsptype tsp +application/dvcs +application/edi-consent +application/edi-x12 +application/edifact +application/eshop +application/font-tdpfr +application/futuresplash spl +application/ghostview +application/hta hta +application/http +application/hyperstudio +application/iges +application/index +application/index.cmd +application/index.obj +application/index.response +application/index.vnd +application/iotp +application/ipp +application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/macwriteii +application/marc +application/mathematica nb +application/mathematica-old +application/ms-tnef +application/msaccess mdb +application/msword doc dot +application/news-message-id +application/news-transmission +application/ocsp-request +application/ocsp-response +application/octet-stream bin +application/oda oda +application/ogg ogg +application/parityfec +application/pdf pdf +application/pgp-encrypted +application/pgp-keys key +application/pgp-signature pgp +application/pics-rules prf +application/pkcs10 +application/pkcs7-mime +application/pkcs7-signature +application/pkix-cert +application/pkix-crl +application/pkixcmp +application/postscript ps ai eps +application/prs.alvestrand.titrax-sheet +application/prs.cww +application/prs.nprend +application/qsig +application/rar rar +application/rdf+xml rdf +application/remote-printing +application/riscos +application/rss+xml rss +application/rtf rtf +application/sdp +application/set-payment +application/set-payment-initiation +application/set-registration +application/set-registration-initiation +application/sgml +application/sgml-open-catalog +application/sieve +application/slate +application/smil smi smil +application/timestamp-query +application/timestamp-reply +application/vemmi +application/whoispp-query +application/whoispp-response +application/wita +application/wordperfect wpd +application/wordperfect5.1 wp5 +application/x400-bp +application/xhtml+xml xhtml xht +application/xml xml xsl +application/xml-dtd +application/xml-external-parsed-entity +application/zip zip +application/vnd.3M.Post-it-Notes +application/vnd.accpac.simply.aso +application/vnd.accpac.simply.imp +application/vnd.acucobol +application/vnd.aether.imp +application/vnd.anser-web-certificate-issue-initiation +application/vnd.anser-web-funds-transfer-initiation +application/vnd.audiograph +application/vnd.bmi +application/vnd.businessobjects +application/vnd.canon-cpdl +application/vnd.canon-lips +application/vnd.cinderella cdy +application/vnd.claymore +application/vnd.commerce-battelle +application/vnd.commonspace +application/vnd.comsocaller +application/vnd.contact.cmsg +application/vnd.cosmocaller +application/vnd.ctc-posml +application/vnd.cups-postscript +application/vnd.cups-raster +application/vnd.cups-raw +application/vnd.cybank +application/vnd.dna +application/vnd.dpgraph +application/vnd.dxr +application/vnd.ecdis-update +application/vnd.ecowin.chart +application/vnd.ecowin.filerequest +application/vnd.ecowin.fileupdate +application/vnd.ecowin.series +application/vnd.ecowin.seriesrequest +application/vnd.ecowin.seriesupdate +application/vnd.enliven +application/vnd.epson.esf +application/vnd.epson.msf +application/vnd.epson.quickanime +application/vnd.epson.salt +application/vnd.epson.ssf +application/vnd.ericsson.quickcall +application/vnd.eudora.data +application/vnd.fdf +application/vnd.ffsns +application/vnd.flographit +application/vnd.framemaker +application/vnd.fsc.weblaunch +application/vnd.fujitsu.oasys +application/vnd.fujitsu.oasys2 +application/vnd.fujitsu.oasys3 +application/vnd.fujitsu.oasysgp +application/vnd.fujitsu.oasysprs +application/vnd.fujixerox.ddd +application/vnd.fujixerox.docuworks +application/vnd.fujixerox.docuworks.binder +application/vnd.fut-misnet +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq +application/vnd.groove-account +application/vnd.groove-identity-message +application/vnd.groove-injector +application/vnd.groove-tool-message +application/vnd.groove-tool-template +application/vnd.groove-vcard +application/vnd.hhe.lesson-player +application/vnd.hp-HPGL +application/vnd.hp-PCL +application/vnd.hp-PCLXL +application/vnd.hp-hpid +application/vnd.hp-hps +application/vnd.httphone +application/vnd.hzn-3d-crossword +application/vnd.ibm.MiniPay +application/vnd.ibm.afplinedata +application/vnd.ibm.modcap +application/vnd.informix-visionary +application/vnd.intercon.formnet +application/vnd.intertrust.digibox +application/vnd.intertrust.nncp +application/vnd.intu.qbo +application/vnd.intu.qfx +application/vnd.irepository.package+xml +application/vnd.is-xpr +application/vnd.japannet-directory-service +application/vnd.japannet-jpnstore-wakeup +application/vnd.japannet-payment-wakeup +application/vnd.japannet-registration +application/vnd.japannet-registration-wakeup +application/vnd.japannet-setstore-wakeup +application/vnd.japannet-verification +application/vnd.japannet-verification-wakeup +application/vnd.koan +application/vnd.lotus-1-2-3 +application/vnd.lotus-approach +application/vnd.lotus-freelance +application/vnd.lotus-notes +application/vnd.lotus-organizer +application/vnd.lotus-screencam +application/vnd.lotus-wordpro +application/vnd.mcd +application/vnd.mediastation.cdkey +application/vnd.meridian-slingshot +application/vnd.mif +application/vnd.minisoft-hp3000-save +application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf +application/vnd.mobius.dis +application/vnd.mobius.msl +application/vnd.mobius.plc +application/vnd.mobius.txf +application/vnd.motorola.flexsuite +application/vnd.motorola.flexsuite.adsi +application/vnd.motorola.flexsuite.fis +application/vnd.motorola.flexsuite.gotap +application/vnd.motorola.flexsuite.kmr +application/vnd.motorola.flexsuite.ttc +application/vnd.motorola.flexsuite.wem +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry +application/vnd.ms-asf +application/vnd.ms-excel xls xlb xlt +application/vnd.ms-lrm +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +application/vnd.ms-powerpoint ppt pps +application/vnd.ms-project +application/vnd.ms-tnef +application/vnd.ms-works +application/vnd.mseq +application/vnd.msign +application/vnd.music-niff +application/vnd.musician +application/vnd.netfpx +application/vnd.noblenet-directory +application/vnd.noblenet-sealer +application/vnd.noblenet-web +application/vnd.novadigm.EDM +application/vnd.novadigm.EDX +application/vnd.novadigm.EXT +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +application/vnd.osa.netdeploy +application/vnd.palm +application/vnd.pg.format +application/vnd.pg.osasli +application/vnd.powerbuilder6 +application/vnd.powerbuilder6-s +application/vnd.powerbuilder7 +application/vnd.powerbuilder7-s +application/vnd.powerbuilder75 +application/vnd.powerbuilder75-s +application/vnd.previewsystems.box +application/vnd.publishare-delta-tree +application/vnd.pvi.ptid1 +application/vnd.pwg-xhtml-print+xml +application/vnd.rapid +application/vnd.rim.cod cod +application/vnd.s3sms +application/vnd.seemail +application/vnd.shana.informed.formdata +application/vnd.shana.informed.formtemplate +application/vnd.shana.informed.interchange +application/vnd.shana.informed.package +application/vnd.smaf mmf +application/vnd.sss-cod +application/vnd.sss-dtf +application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.chart sds +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math sdf +application/vnd.stardivision.writer sdw +application/vnd.stardivision.writer-global sgl +application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +application/vnd.svd +application/vnd.swiftview-ics +application/vnd.symbian.install sis +application/vnd.triscape.mxs +application/vnd.trueapp +application/vnd.truedoc +application/vnd.tve-trigger +application/vnd.ufdl +application/vnd.uplanet.alert +application/vnd.uplanet.alert-wbxml +application/vnd.uplanet.bearer-choice +application/vnd.uplanet.bearer-choice-wbxml +application/vnd.uplanet.cacheop +application/vnd.uplanet.cacheop-wbxml +application/vnd.uplanet.channel +application/vnd.uplanet.channel-wbxml +application/vnd.uplanet.list +application/vnd.uplanet.list-wbxml +application/vnd.uplanet.listcmd +application/vnd.uplanet.listcmd-wbxml +application/vnd.uplanet.signal +application/vnd.vcx +application/vnd.vectorworks +application/vnd.vidsoft.vidconference +application/vnd.visio vsd +application/vnd.vividence.scriptfile +application/vnd.wap.sic +application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo +application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf +application/vnd.xara +application/vnd.xfdl +application/vnd.yellowriver-custom-menu +application/x-123 wk +application/x-7z-compressed 7z +application/x-abiword abw +application/x-apple-diskimage dmg +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-cab cab +application/x-cbr cbr +application/x-cbz cbz +application/x-cdf cdf +application/x-cdlink vcd +application/x-chess-pgn pgn +application/x-core +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dcr dir dxr +application/x-dms dms +application/x-doom wad +application/x-dvi dvi +application/x-httpd-eruby rhtml +application/x-executable +application/x-flac flac +application/x-font pfa pfb gsf pcf pcf.Z +application/x-freemind mm +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-go-sgf sgf +application/x-graphing-calculator gcf +application/x-gtar gtar tgz taz +application/x-hdf hdf +application/x-httpd-php phtml pht php +application/x-httpd-php-source phps +application/x-httpd-php3 php3 +application/x-httpd-php3-preprocessed php3p +application/x-httpd-php4 php4 +application/x-ica ica +application/x-internet-signup ins isp +application/x-iphone iii +application/x-iso9660-image iso +application/x-java-applet +application/x-java-bean +application/x-java-jnlp-file jnlp +application/x-javascript js +application/x-jmol jmz +application/x-kchart chrt +application/x-kdelnk +application/x-killustrator kil +application/x-koan skp skd skt skm +application/x-kpresenter kpr kpt +application/x-kspread ksp +application/x-kword kwd kwt +application/x-latex latex +application/x-lha lha +application/x-lyx lyx +application/x-lzh lzh +application/x-lzx lzx +application/x-maker frm maker frame fm fb book fbdoc +application/x-mif mif +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-msdos-program com exe bat dll +application/x-msi msi +application/x-netcdf nc +application/x-ns-proxy-autoconfig pac +application/x-nwc nwc +application/x-object o +application/x-oz-application oza +application/x-pkcs7-certreqresp p7r +application/x-pkcs7-crl crl +application/x-python-code pyc pyo +application/x-quicktimeplayer qtl +application/x-redhat-package-manager rpm +application/x-rx +application/x-sh sh +application/x-shar shar +application/x-shellscript +application/x-shockwave-flash swf swfl +application/x-stuffit sit sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex-gf gf +application/x-tex-pk pk +application/x-texinfo texinfo texi +application/x-trash ~ % bak old sik +application/x-troff t tr roff +application/x-troff-man man +application/x-troff-me me +application/x-troff-ms ms +application/x-ustar ustar +application/x-videolan +application/x-wais-source src +application/x-wingz wz +application/x-x509-ca-cert crt +application/x-xcf xcf +application/x-xfig fig +application/x-xpinstall xpi + +audio/32kadpcm +audio/3gpp +audio/basic au snd +audio/g.722.1 +audio/l16 +audio/midi mid midi kar +audio/mp4a-latm +audio/mpa-robust +audio/mpeg mpga mpega mp2 mp3 m4a +audio/mpegurl m3u +audio/parityfec +audio/prs.sid sid +audio/telephone-event +audio/tone +audio/vnd.cisco.nse +audio/vnd.cns.anp1 +audio/vnd.cns.inf1 +audio/vnd.digital-winds +audio/vnd.everad.plj +audio/vnd.lucent.voice +audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 +audio/vnd.nuera.ecelp7470 +audio/vnd.nuera.ecelp9600 +audio/vnd.octel.sbc +audio/vnd.qcelp +audio/vnd.rhetorex.32kadpcm +audio/vnd.vmx.cvsd +audio/x-aiff aif aiff aifc +audio/x-gsm gsm +audio/x-mpegurl m3u +audio/x-ms-wma wma +audio/x-ms-wax wax +audio/x-pn-realaudio-plugin +audio/x-pn-realaudio ra rm ram +audio/x-realaudio ra +audio/x-scpls pls +audio/x-sd2 sd2 +audio/x-wav wav + +chemical/x-alchemy alc +chemical/x-cache cac cache +chemical/x-cache-csf csf +chemical/x-cactvs-binary cbin cascii ctab +chemical/x-cdx cdx +chemical/x-cerius cer +chemical/x-chem3d c3d +chemical/x-chemdraw chm +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-compass cpa +chemical/x-crossfire bsd +chemical/x-csml csml csm +chemical/x-ctx ctx +chemical/x-cxf cxf cef +#chemical/x-daylight-smiles smi +chemical/x-embl-dl-nucleotide emb embl +chemical/x-galactic-spc spc +chemical/x-gamess-input inp gam gamin +chemical/x-gaussian-checkpoint fch fchk +chemical/x-gaussian-cube cub +chemical/x-gaussian-input gau gjc gjf +chemical/x-gaussian-log gal +chemical/x-gcg8-sequence gcg +chemical/x-genbank gen +chemical/x-hin hin +chemical/x-isostar istr ist +chemical/x-jcamp-dx jdx dx +chemical/x-kinemage kin +chemical/x-macmolecule mcm +chemical/x-macromodel-input mmd mmod +chemical/x-mdl-molfile mol +chemical/x-mdl-rdfile rd +chemical/x-mdl-rxnfile rxn +chemical/x-mdl-sdfile sd sdf +chemical/x-mdl-tgf tgf +#chemical/x-mif mif +chemical/x-mmcif mcif +chemical/x-mol2 mol2 +chemical/x-molconn-Z b +chemical/x-mopac-graph gpt +chemical/x-mopac-input mop mopcrt mpc dat zmt +chemical/x-mopac-out moo +chemical/x-mopac-vib mvb +chemical/x-ncbi-asn1 asn +chemical/x-ncbi-asn1-ascii prt ent +chemical/x-ncbi-asn1-binary val aso +chemical/x-ncbi-asn1-spec asn +chemical/x-pdb pdb ent +chemical/x-rosdal ros +chemical/x-swissprot sw +chemical/x-vamas-iso14976 vms +chemical/x-vmd vmd +chemical/x-xtel xtel +chemical/x-xyz xyz + +image/cgm +image/g3fax +image/gif gif +image/ief ief +image/jpeg jpeg jpg jpe +image/naplps +image/pcx pcx +image/png png +image/prs.btif +image/prs.pti +image/svg+xml svg svgz +image/tiff tiff tif +image/vnd.cns.inf2 +image/vnd.djvu djvu djv +image/vnd.dwg +image/vnd.dxf +image/vnd.fastbidsheet +image/vnd.fpx +image/vnd.fst +image/vnd.fujixerox.edmics-mmr +image/vnd.fujixerox.edmics-rlc +image/vnd.mix +image/vnd.net-fpx +image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff +image/x-cmu-raster ras +image/x-coreldraw cdr +image/x-coreldrawpattern pat +image/x-coreldrawtemplate cdt +image/x-corelphotopaint cpt +image/x-icon ico +image/x-jg art +image/x-jng jng +image/x-ms-bmp bmp +image/x-photoshop psd +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd + +inode/chardevice +inode/blockdevice +inode/directory-locked +inode/directory +inode/fifo +inode/socket + +message/delivery-status +message/disposition-notification +message/external-body +message/http +message/s-http +message/news +message/partial +message/rfc822 eml + +model/iges igs iges +model/mesh msh mesh silo +model/vnd.dwf +model/vnd.flatland.3dml +model/vnd.gdl +model/vnd.gs-gdl +model/vnd.gtw +model/vnd.mts +model/vnd.vtu +model/vrml wrl vrml + +multipart/alternative +multipart/appledouble +multipart/byteranges +multipart/digest +multipart/encrypted +multipart/form-data +multipart/header-set +multipart/mixed +multipart/parallel +multipart/related +multipart/report +multipart/signed +multipart/voice-message + +text/calendar ics icz +text/css css +text/csv csv +text/directory +text/english +text/enriched +text/h323 323 +text/html html htm shtml +text/iuls uls +text/mathml mml +text/parityfec +text/plain asc txt text pot +text/prs.lines.tag +text/rfc822-headers +text/richtext rtx +text/rtf +text/scriptlet sct wsc +text/t140 +text/texmacs tm ts +text/tab-separated-values tsv +text/uri-list +text/vnd.abc +text/vnd.curl +text/vnd.DMClientScript +text/vnd.flatland.3dml +text/vnd.fly +text/vnd.fmi.flexstor +text/vnd.in3d.3dml +text/vnd.in3d.spot +text/vnd.IPTC.NewsML +text/vnd.IPTC.NITF +text/vnd.latex-z +text/vnd.motorola.reflex +text/vnd.ms-mediapackage +text/vnd.sun.j2me.app-descriptor jad +text/vnd.wap.si +text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-bibtex bib +text/x-boo boo +text/x-c++hdr h++ hpp hxx hh +text/x-c++src c++ cpp cxx cc +text/x-chdr h +text/x-component htc +text/x-crontab +text/x-csh csh +text/x-csrc c +text/x-dsrc d +text/x-diff diff patch +text/x-haskell hs +text/x-java java +text/x-literate-haskell lhs +text/x-makefile +text/x-moc moc +text/x-pascal p pas +text/x-pcs-gcd gcd +text/x-perl pl pm +text/x-python py +text/x-server-parsed-html +text/x-setext etx +text/x-sh sh +text/x-tcl tcl tk +text/x-tex tex ltx sty cls +text/x-vcalendar vcs +text/x-vcard vcf + +video/3gpp 3gp +video/dl dl +video/dv dif dv +video/fli fli +video/gl gl +video/mpeg mpeg mpg mpe +video/mp4 mp4 +video/quicktime qt mov +video/mp4v-es +video/parityfec +video/pointer +video/vnd.fvt +video/vnd.motorola.video +video/vnd.motorola.videop +video/vnd.mpegurl mxu +video/vnd.mts +video/vnd.nokia.interleaved-multimedia +video/vnd.vivo +video/x-la-asf lsf lsx +video/x-mng mng +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie + +x-conference/x-cooltalk ice + +x-epoc/x-sisx-app sisx +x-world/x-vrml vrm vrml wrl diff --git a/openwrt/packages/luci/libs/sgi-webuci/root/usr/lib/boa/luci.lua b/openwrt/packages/luci/libs/sgi-webuci/root/usr/lib/boa/luci.lua new file mode 100644 index 0000000..2bb9313 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/root/usr/lib/boa/luci.lua @@ -0,0 +1,66 @@ +module("luci-plugin", package.seeall) + +function normalize(path) + local newpath + while newpath ~= path do + if (newpath) then + path = newpath + end + newpath = string.gsub(path, "/[^/]+/../", "/") + end + return newpath +end + +function init(path) + -- NB: path points to ROOT/usr/lib/boa, change it to /usr/lib/lua + root = normalize(path .. '/../../../') + path = normalize(path .. '/../lua/') + package.cpath = path..'?.so;'..package.cpath + package.path = path..'?.lua;'..package.path + + require("luci.dispatcher") + require("luci.sgi.webuci") + require("luci.model.uci") + + if (root ~= '/') then + -- Entering dummy mode + luci.model.uci.cursor = function(config, ...) + return uci.cursor(config or root .. "/etc/config", ...) + end + + luci.sys.hostname = function() return "" end + luci.sys.loadavg = function() return 0,0,0,0,0 end + luci.sys.reboot = function() return end + luci.sys.sysinfo = function() return "","","" end + luci.sys.syslog = function() return "" end + + luci.sys.net.arptable = function() return {} end + luci.sys.net.devices = function() return {} end + luci.sys.net.routes = function() return {} end + luci.sys.wifi.getiwconfig = function() return {} end + luci.sys.wifi.iwscan = function() return {} end + + luci.sys.user.checkpasswd = function() return true end + end +end + +function prepare_req(uri) + luci.dispatcher.createindex() + env = {} + env.REQUEST_URI = uri + -- TODO: setting luci-plugin.reload = true allows this function to trigger a context reload +end + +function handle_req(context) + env.SERVER_PROTOCOL = context.server_proto + env.REMOTE_ADDR = context.remote_addr + env.REQUEST_METHOD = context.request_method + env.PATH_INFO = context.uri + env.REMOTE_PORT = context.remote_port + env.SERVER_ADDR = context.server_addr + env.HTTP_COOKIE = context.cookie + env.HTTP_ACCEPT = context.http_accept + env.SCRIPT_NAME = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO) + + luci.sgi.webuci.run(env, vars) +end diff --git a/openwrt/packages/luci/libs/sgi-webuci/src/cgi.c b/openwrt/packages/luci/libs/sgi-webuci/src/cgi.c new file mode 100644 index 0000000..f8bf404 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/src/cgi.c @@ -0,0 +1,530 @@ +/* + * CGI routines for luci + * Copyright (C) 2008 Felix Fietkau + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Based on code from cgilib: + * + * cgi.c - Some simple routines for CGI programming + * Copyright (c) 1996-9,2007,8 Martin Schulze + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 128 + +static char * +cgiGetLine (FILE *stream) +{ + static char *line = NULL; + static size_t size = 0; + char buf[BUFSIZE]; + char *cp; + + if (!line) { + if ((line = (char *)malloc (BUFSIZE)) == NULL) + return NULL; + size = BUFSIZE; + } + line[0] = '\0'; + + while (!feof (stream)) { + if ((cp = fgets (buf, sizeof (buf), stream)) == NULL) + return NULL; + + if (strlen(line)+strlen(buf)+1 > size) { + if ((cp = (char *)realloc (line, size + BUFSIZE)) == NULL) + return line; + size += BUFSIZE; + line = cp; + } + + strcat (line, buf); + if (line[strlen(line)-1] == '\n') { + line[strlen(line)-1] = '\0'; + if (line[strlen(line)-1] == '\r') + line[strlen(line)-1] = '\0'; + return line; + } + } + + return NULL; +} + + +static const char * +luci_getenv(lua_State *L, const char *name) +{ + const char *ret; + + lua_getfield(L, lua_upvalueindex(2), name); + ret = lua_tostring(L, -1); + lua_pop(L, 1); + return ret; +} + +static void +luci_setvar(lua_State *L, const char *name, const char *value, bool append) +{ + /* Check if there is an existing value already */ + lua_getfield(L, lua_upvalueindex(1), name); + if (lua_isnil(L, -1)) { + /* nope, we're safe - add a new one */ + lua_pushstring(L, value); + lua_setfield(L, lua_upvalueindex(1), name); + } else if (lua_istable(L, -1) && append) { + /* it's a table already, but appending is requested + * take the last element and append the new string to it */ + int tlast = lua_objlen(L, -1); + lua_rawgeti(L, -1, tlast); + lua_pushstring(L, value); + lua_pushstring(L, "\n"); + lua_concat(L, 3); + lua_rawseti(L, -2, tlast); + } else if (lua_istable(L, -1)) { + /* it's a table, which means we already have two + * or more entries, add the next one */ + + int tnext = lua_objlen(L, -1) + 1; /* next entry */ + + lua_pushstring(L, value); + luaL_setn(L, -2, tnext); + lua_rawseti(L, -2, tnext); + } else if (lua_isstring(L, -1) && append) { + /* append the new string to the existing variable */ + lua_pushstring(L, value); + lua_pushstring(L, "\n"); + lua_concat(L, 3); + lua_setfield(L, lua_upvalueindex(1), name); + } else if (lua_isstring(L, -1)) { + /* we're trying to add a variable that already has + * a string value. convert the string value to a + * table and add our new value to the table as well + */ + lua_createtable(L, 2, 0); + lua_pushvalue(L, -2); /* copy of the initial string value */ + lua_rawseti(L, -2, 1); + + lua_pushstring(L, value); + lua_rawseti(L, -2, 2); + lua_setfield(L, lua_upvalueindex(1), name); + } else { + luaL_error(L, "Invalid table entry type for index '%s'", name); + } +} + +char *cgiDecodeString (char *text) +{ + char *cp, *xp; + + for (cp=text,xp=text; *cp; cp++) { + if (*cp == '%') { + if (strchr("0123456789ABCDEFabcdef", *(cp+1)) + && strchr("0123456789ABCDEFabcdef", *(cp+2))) { + if (islower(*(cp+1))) + *(cp+1) = toupper(*(cp+1)); + if (islower(*(cp+2))) + *(cp+2) = toupper(*(cp+2)); + *(xp) = (*(cp+1) >= 'A' ? *(cp+1) - 'A' + 10 : *(cp+1) - '0' ) * 16 + + (*(cp+2) >= 'A' ? *(cp+2) - 'A' + 10 : *(cp+2) - '0'); + xp++;cp+=2; + } + } else { + *(xp++) = *cp; + } + } + memset(xp, 0, cp-xp); + return text; +} + +#if 0 +/* cgiReadFile() + * + * Read and save a file fro a multipart request + */ +#include +char *cgiReadFile (FILE *stream, char *boundary) +{ + char *crlfboundary, *buf; + size_t boundarylen; + int c; + unsigned int pivot; + char *cp; + char template[]= "/tmp/cgilibXXXXXX"; + FILE *tmpfile; + int fd; + + boundarylen = strlen(boundary)+3; + if ((crlfboundary = (char *)malloc (boundarylen)) == NULL) + return NULL; + sprintf (crlfboundary, "\r\n%s", boundary); + + if ((buf = (char *)malloc (boundarylen)) == NULL) { + free (crlfboundary); + return NULL; + } + memset (buf, 0, boundarylen); + pivot = 0; + + if ((fd = mkstemp (template)) == -1) { + free (crlfboundary); + free (buf); + return NULL; + } + + if ((tmpfile = fdopen (fd, "w")) == NULL) { + free (crlfboundary); + free (buf); + unlink (template); + return NULL; + } + + while (!feof (stream)) { + c = fgetc (stream); + + if (c == 0) { + if (strlen (buf)) { + for (cp=buf; *cp; cp++) + putc (*cp, tmpfile); + memset (buf, 0, boundarylen); + pivot = 0; + } + putc (c, tmpfile); + continue; + } + + if (strlen (buf)) { + if (crlfboundary[pivot+1] == c) { + buf[++pivot] = c; + + if (strlen (buf) == strlen (crlfboundary)) + break; + else + continue; + } else { + for (cp=buf; *cp; cp++) + putc (*cp, tmpfile); + memset (buf, 0, boundarylen); + pivot = 0; + } + } + + if (crlfboundary[0] == c) { + buf[0] = c; + } else { + fputc (c, tmpfile); + } + } + + if (!feof (stream)) + fgets (buf, boundarylen, stream); + + fclose (tmpfile); + + free (crlfboundary); + free (buf); + + return strdup (template); +} +#endif + +/* + * Decode multipart/form-data + */ +#define MULTIPART_DELTA 5 +void luci_parse_multipart (lua_State *L, char *boundary) +{ + char *line; + char *cp, *xp; + char *name = NULL, *type = NULL; + char *fname = NULL; + int header = 1; + bool append = false; + + while ((line = cgiGetLine (stdin)) != NULL) { + if (!strncmp (line, boundary, strlen(boundary))) { + header = 1; + if (name) + free(name); + if (type) + free(type); + name = NULL; + type = NULL; + append = false; + } else if (header && !name && !strncasecmp (line, "Content-Disposition: form-data; ", 32)) { + if ((cp = strstr (line, "name=\"")) == NULL) + continue; + cp += 6; + if ((xp = strchr (cp, '\"')) == NULL) + continue; + name = malloc(xp-cp + 1); + strncpy(name, cp, xp-cp); + name[xp-cp] = 0; + cgiDecodeString (name); + + if ((cp = strstr (line, "filename=\"")) == NULL) + continue; + cp += 10; + if ((xp = strchr (cp, '\"')) == NULL) + continue; + fname = malloc(xp-cp + 1); + strncpy(fname, cp, xp-cp); + fname[xp-cp] = 0; + cgiDecodeString (fname); + } else if (header && !type && !strncasecmp (line, "Content-Type: ", 14)) { + cp = line + 14; + type = strdup (cp); + } else if (header) { + if (!strlen(line)) { + header = 0; + + if (fname) { +#if 0 + header = 1; + tmpfile = cgiReadFile (stdin, boundary); + + if (!tmpfile) { + free (name); + free (fname); + if (type) + free (type); + name = fname = type = NULL; + } + + cgiDebugOutput (2, "Wrote %s (%s) to file: %s", name, fname, tmpfile); + + if (!strlen (fname)) { + cgiDebugOutput (3, "Found empty filename, removing"); + unlink (tmpfile); + free (tmpfile); + free (name); + free (fname); + if (type) + free (type); + name = fname = type = NULL; + } else { + if ((file = (s_file *)malloc (sizeof (s_file))) == NULL) { + cgiDebugOutput (3, "malloc failed, ignoring %s=%s", name, fname); + unlink (tmpfile); + free (tmpfile); + free (name); + free (fname); + if (type) + free (type); + name = fname = type = NULL; + continue; + } + + file->name = name; + file->type = type; + file->tmpfile = tmpfile; + if ((cp = rindex (fname, '/')) == NULL) + file->filename = fname; + else { + file->filename = strdup (++cp); + free (fname); + } + name = type = fname = NULL; + + if (!files) { + if ((files = (s_file **)malloc(2*sizeof (s_file *))) == NULL) { + cgiDebugOutput (3, "malloc failed, ignoring %s=%s", name, fname); + unlink (tmpfile); + free (tmpfile); + free (name); + name = NULL; + if (type) { + free (type); + type = NULL; + } + free (file->filename); + free (file); + continue; + } + memset (files, 0, 2*sizeof (s_file *)); + index = 0; + } else { + for (index=0; files[index]; index++); + if ((tmpf = (s_file **)realloc(files, (index+2)*sizeof (s_file *))) == NULL) { + cgiDebugOutput (3, "realloc failed, ignoring %s=%s", name, fname); + unlink (tmpfile); + free (tmpfile); + free (name); + if (type) + free (type); + free (file->filename); + free (file); + name = type = fname = NULL; + continue; + } + files = tmpf; + memset (files + index, 0, 2*sizeof (s_file *)); + } + files[index] = file; + } +#else + free(fname); + fname = NULL; +#endif + } + } + } else { + if (!name) + return; + + cgiDecodeString(line); + luci_setvar(L, name, line, append); + if (!append) /* beginning of variable contents */ + append = true; + } + } +} + +/* parse the request header and store variables + * in the array supplied as function argument 1 on the stack + */ +int luci_parse_header (lua_State *L) +{ + int length; + char *line = NULL; + int numargs; + char *cp = NULL, *ip = NULL, *esp = NULL; + const char *ct, *il; + int i; + + if (!lua_istable(L, lua_upvalueindex(1))) + luaL_error(L, "Invalid argument"); + + if (!lua_istable(L, lua_upvalueindex(2))) + luaL_error(L, "Invalid argument"); + + ct = luci_getenv(L, "content_type"); + if (ct) { + ct = cp = strdup(ct); + } + if (cp && strstr(cp, "multipart/form-data") && strstr(cp, "boundary=")) { + cp = strstr(cp, "boundary=") + strlen ("boundary=") - 2; + *cp = *(cp+1) = '-'; + luci_parse_multipart(L, cp); + free((char *) ct); + return 0; + } + free((char *) ct); + + ct = luci_getenv(L, "request_method"); + il = luci_getenv(L, "content_length"); + + if (!ct) { + fprintf(stderr, "no request method!\n"); + return 0; + } + + if (!strcmp(ct, "POST")) { + if (il) { + length = atoi(il); + if (length <= 0) + return 0; + line = (char *)malloc (length+2); + if (line) + fgets(line, length+1, stdin); + } + } else if (!strcmp(ct, "GET")) { + ct = luci_getenv(L, "query_string"); + if (ct) + esp = strdup(ct); + if (esp && strlen(esp)) { + line = (char *)malloc (strlen(esp)+2); + if (line) + strcpy (line, esp); + } + free(esp); + } + + if (!line) + return 0; + + /* + * From now on all cgi variables are stored in the variable line + * and look like foo=bar&foobar=barfoo&foofoo= + */ + for (cp=line; *cp; cp++) + if (*cp == '+') + *cp = ' '; + + if (strlen(line)) { + for (numargs=1,cp=line; *cp; cp++) + if (*cp == '&' || *cp == ';' ) numargs++; + } else + numargs = 0; + + cp = line; + i=0; + while (*cp) { + char *name; + char *value; + + if ((ip = (char *)strchr(cp, '&')) != NULL) { + *ip = '\0'; + } else if ((ip = (char *)strchr(cp, ';')) != NULL) { + *ip = '\0'; + } else + ip = cp + strlen(cp); + + if ((esp=(char *)strchr(cp, '=')) == NULL) + goto skip; + + if (!strlen(esp)) + goto skip; + + if (i >= numargs) + goto skip; + + esp[0] = 0; + name = cp; + cgiDecodeString (name); + + cp = ++esp; + value = cp; + cgiDecodeString (value); + + luci_setvar(L, name, value, false); +skip: + cp = ++ip; + } + free(line); + return 0; +} + diff --git a/openwrt/packages/luci/libs/sgi-webuci/src/luci.c b/openwrt/packages/luci/libs/sgi-webuci/src/luci.c new file mode 100644 index 0000000..44a44af --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-webuci/src/luci.c @@ -0,0 +1,236 @@ +/* + * luci + * Copyright (C) 2008 John Crispin + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define LUAMAIN "luci.lua" + +static lua_State *L = NULL; + +extern int luci_parse_header (lua_State *L); + +static lua_State *luci_context_init(struct httpd_plugin *p) +{ + char *path = NULL; + lua_State *Lnew; + int ret = 0; + + Lnew = luaL_newstate(); + if (!Lnew) + goto error; + + luaL_openlibs(Lnew); + + path = malloc(strlen(p->dir) + sizeof(LUAMAIN) + 2); + strcpy(path, p->dir); + strcat(path, "/" LUAMAIN); + + ret = luaL_dofile(Lnew, path); + + lua_getfield(Lnew, LUA_GLOBALSINDEX, "luci-plugin"); + do { + if (!lua_istable(Lnew, -1)) { + ret = 1; + break; + } + + lua_getfield(Lnew, -1, "init"); + if (!lua_isfunction(Lnew, -1)) + break; + + lua_pushstring(Lnew, p->dir); + ret = lua_pcall(Lnew, 1, 0, 0); + } while (0); + free(path); + + if (ret != 0) + goto error; + + return Lnew; + +error: + fprintf(stderr, "Error: "); + if (Lnew) { + const char *s = lua_tostring(Lnew, -1); + if (!s) + s = "unknown error"; + fprintf(stderr, "%s\n", s); + lua_close(Lnew); + } else { + fprintf(stderr, "Out of memory!\n"); + } + return NULL; +} + +static int luci_init(struct httpd_plugin *p) +{ + L = luci_context_init(p); + return (L != NULL); +} + +static void pushvar(char *name, char *val) +{ + if (!val) + return; + + lua_pushstring(L, val); + lua_setfield(L, -2, name); +} + +static int luci_pcall(lua_State *L, char *func, int narg) +{ + int ret; + + ret = lua_pcall(L, narg, narg, 0); + if (ret) { + const char *s = lua_tostring(L, -1); + if (s) + fprintf(stderr, "Error running %s: %s\n", func, s); + return ret; + } + if (!narg) + return ret; + + ret = lua_isnumber(L, -1); + if (!ret) + goto done; + + ret = lua_tonumber(L, -1); + +done: + lua_pop(L, 1); + return ret; +} + +static int luci_prepare_req(struct httpd_plugin *p, struct http_context *ctx) +{ + int ret; + bool reload = false; + + lua_getglobal(L, "luci-plugin"); + lua_getfield(L, -1, "reload"); + if (lua_isboolean(L, -1)) + reload = lua_toboolean(L, -1); + lua_pop(L, 1); + + if (reload) { + lua_close(L); + L = luci_context_init(p); + lua_getglobal(L, "luci-plugin"); + } + + lua_getfield(L, -1, "prepare_req"); + + ret = lua_isfunction(L, -1); + if (!ret) + goto done; + + lua_pushstring(L, ctx->uri); + + ret = luci_pcall(L, "prepare_req", 1); + +done: + lua_pop(L, 1); + return ret; +} + +static int luci_handle_req(struct httpd_plugin *p, struct http_context *ctx) +{ + int ret; + + lua_newtable(L); /* new table for the http context */ + + /* convert http_context data structure to lua table */ +#define PUSH(x) pushvar(#x, ctx->x) + PUSH(cookie); + PUSH(request_method); + PUSH(server_addr); + PUSH(server_proto); + PUSH(query_string); + PUSH(remote_addr); + lua_pushinteger(L, ctx->remote_port); + lua_setfield(L, -2, "remote_port"); + PUSH(content_type); + PUSH(content_length); + PUSH(http_accept); +#undef PUSH + + if (!strncmp(ctx->uri, p->prefix, strlen(p->prefix))) + pushvar("uri", ctx->uri + strlen(p->prefix)); + else + pushvar("uri", ctx->uri); + + + /* make sure the global 'luci' table is prepared */ + lua_getglobal(L, "luci-plugin"); + if (!lua_istable(L, -1)) + return 0; + + lua_getfield(L, -1, "init_req"); + if (!lua_isfunction(L, -1)) { + /* ignore error */ + lua_pop(L, 1); + } else { + lua_pushvalue(L, -3); + luci_pcall(L, "init_req", 1); + } + + /* storage space for cgi variables */ + lua_newtable(L); + lua_pushvalue(L, -1); /* copy for setfield */ + lua_setfield(L, -3, "vars"); + + lua_pushvalue(L, -3); /* the http context table */ + + /* + * make luci_parse_header a closure + * argument 1: the luci.vars table + * argument 2: the http context table + */ + lua_pushcclosure(L, luci_parse_header, 2); + ret = luci_pcall(L, "parse_header", 0); + + lua_getfield(L, -1, "handle_req"); + ret = lua_isfunction(L, -1); + if (!ret) + goto done; + + lua_pushvalue(L, -3); + ret = luci_pcall(L, "handle_req", 1); + + /* pop the luci and http context tables */ +done: + lua_pop(L, 2); + return ret; +} + +static void luci_unload(struct httpd_plugin *p) +{ + lua_close(L); +} + +HTTPD_PLUGIN { + .prefix = "/luci/", + .init = luci_init, + .done = luci_unload, + .prepare_req = luci_prepare_req, + .handle_req = luci_handle_req, +}; diff --git a/openwrt/packages/luci/libs/sgi-wsapi/Makefile b/openwrt/packages/luci/libs/sgi-wsapi/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-wsapi/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/libs/sgi-wsapi/luasrc/sgi/wsapi.lua b/openwrt/packages/luci/libs/sgi-wsapi/luasrc/sgi/wsapi.lua new file mode 100644 index 0000000..1d6e118 --- /dev/null +++ b/openwrt/packages/luci/libs/sgi-wsapi/luasrc/sgi/wsapi.lua @@ -0,0 +1,79 @@ +--[[ +LuCI - SGI-Module for WSAPI + +Description: +Server Gateway Interface for WSAPI + +FileId: +$Id: wsapi.lua 2656 2008-07-23 18:52:12Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.sgi.wsapi", package.seeall) +local ltn12 = require("luci.ltn12") +require("luci.http") +require("luci.dispatcher") +require("luci.http.protocol") + +function run(wsapi_env) + local r = luci.http.Request( + wsapi_env, + ltn12.source.file(wsapi_env.input), + ltn12.sink.file(wsapi_env.error) + ) + + local res, id, data1, data2 = true, 0, nil, nil + local headers = {} + local status = 200 + + local x = coroutine.create(luci.dispatcher.httpdispatch) + local active = true + + while id < 3 do + res, id, data1, data2 = coroutine.resume(x, r) + + if not res then + status = 500 + headers["Content-Type"] = "text/plain" + local err = {id} + return status, headers, function() local x = table.remove(err) return x end + end + + if id == 1 then + status = data1 + elseif id == 2 then + headers[data1] = data2 + end + end + + local function iter() + local res, id, data = coroutine.resume(x) + if id == 4 and active then + return data + elseif id == 5 then + active = false + return "" + else + return "" + end + if coroutine.status(x) == "dead" then + return nil + end + end + + return status, headers, iter +end diff --git a/openwrt/packages/luci/libs/sys/Makefile b/openwrt/packages/luci/libs/sys/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/sys/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/sys/luasrc/sys.lua b/openwrt/packages/luci/libs/sys/luasrc/sys.lua new file mode 100644 index 0000000..38a25f9 --- /dev/null +++ b/openwrt/packages/luci/libs/sys/luasrc/sys.lua @@ -0,0 +1,782 @@ +--[[ +LuCI - System library + +Description: +Utilities for interaction with the Linux system + +FileId: +$Id: sys.lua 3867 2008-12-07 19:49:45Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + + +local io = require "io" +local os = require "os" +local posix = require "posix" +local table = require "table" + +local luci = {} +luci.util = require "luci.util" +luci.fs = require "luci.fs" +luci.ip = require "luci.ip" + +local tonumber, ipairs, pairs, pcall = tonumber, ipairs, pairs, pcall + + +--- LuCI Linux and POSIX system utilities. +module "luci.sys" + +--- Execute a given shell command and return the error code +-- @class function +-- @name call +-- @param ... Command to call +-- @return Error code of the command +function call(...) + return os.execute(...) / 256 +end + +--- Execute a given shell command and capture its standard output +-- @class function +-- @name exec +-- @param command Command to call +-- @return String containg the return the output of the command +exec = luci.util.exec + +--- Invoke the luci-flash executable to write an image to the flash memory. +-- @param image Local path or URL to image file +-- @param kpattern Pattern of files to keep over flash process +-- @return Return value of os.execute() +function flash(image, kpattern) + local cmd = "luci-flash " + if kpattern then + cmd = cmd .. "-k '" .. kpattern:gsub("'", "") .. "' " + end + cmd = cmd .. "'" .. image:gsub("'", "") .. "' >/dev/null 2>&1" + + return os.execute(cmd) +end + +--- Retrieve information about currently mounted file systems. +-- @return Table containing mount information +function mounts() + local data = {} + local k = {"fs", "blocks", "used", "available", "percent", "mountpoint"} + local ps = luci.util.execi("df") + + if not ps then + return + else + ps() + end + + for line in ps do + local row = {} + + local j = 1 + for value in line:gmatch("[^%s]+") do + row[k[j]] = value + j = j + 1 + end + + if row[k[1]] then + + -- this is a rather ugly workaround to cope with wrapped lines in + -- the df output: + -- + -- /dev/scsi/host0/bus0/target0/lun0/part3 + -- 114382024 93566472 15005244 86% /mnt/usb + -- + + if not row[k[2]] then + j = 2 + line = ps() + for value in line:gmatch("[^%s]+") do + row[k[j]] = value + j = j + 1 + end + end + + table.insert(data, row) + end + end + + return data +end + +--- Retrieve environment variables. If no variable is given then a table +-- containing the whole environment is returned otherwise this function returns +-- the corresponding string value for the given name or nil if no such variable +-- exists. +-- @class function +-- @name getenv +-- @param var Name of the environment variable to retrieve (optional) +-- @return String containg the value of the specified variable +-- @return Table containing all variables if no variable name is given +getenv = posix.getenv + +--- Determine the current hostname. +-- @return String containing the system hostname +function hostname() + return posix.uname("%n") +end + +--- Returns the contents of a documented referred by an URL. +-- @param url The URL to retrieve +-- @param stream Return a stream instead of a buffer +-- @param target Directly write to target file name +-- @return String containing the contents of given the URL +function httpget(url, stream, target) + if not target then + local source = stream and io.popen or luci.util.exec + return source("wget -qO- '"..url:gsub("'", "").."'") + else + return os.execute("wget -qO '%s' '%s'" % + {target:gsub("'", ""), url:gsub("'", "")}) + end +end + +--- Returns the system load average values. +-- @return String containing the average load value 1 minute ago +-- @return String containing the average load value 5 minutes ago +-- @return String containing the average load value 15 minutes ago +-- @return String containing the active and total number of processes +-- @return String containing the last used pid +function loadavg() + local loadavg = io.lines("/proc/loadavg")() + return loadavg:match("^(.-) (.-) (.-) (.-) (.-)$") +end + +--- Initiate a system reboot. +-- @return Return value of os.execute() +function reboot() + return os.execute("reboot >/dev/null 2>&1") +end + +--- Returns the system type, cpu name and installed physical memory. +-- @return String containing the system or platform identifier +-- @return String containing hardware model information +-- @return String containing the total memory amount in kB +-- @return String containing the memory used for caching in kB +-- @return String containing the memory used for buffering in kB +-- @return String containing the free memory amount in kB +function sysinfo() + local cpuinfo = luci.fs.readfile("/proc/cpuinfo") + local meminfo = luci.fs.readfile("/proc/meminfo") + + local system = cpuinfo:match("system typ.-:%s*([^\n]+)") + local model = "" + local memtotal = tonumber(meminfo:match("MemTotal:%s*(%d+)")) + local memcached = tonumber(meminfo:match("\nCached:%s*(%d+)")) + local memfree = tonumber(meminfo:match("MemFree:%s*(%d+)")) + local membuffers = tonumber(meminfo:match("Buffers:%s*(%d+)")) + + if not system then + system = posix.uname("%m") + model = cpuinfo:match("model name.-:%s*([^\n]+)") + if not model then + model = cpuinfo:match("Processor.-:%s*([^\n]+)") + end + else + model = cpuinfo:match("cpu model.-:%s*([^\n]+)") + end + + return system, model, memtotal, memcached, membuffers, memfree +end + +--- Retrieves the output of the "logread" command. +-- @return String containing the current log buffer +function syslog() + return luci.util.exec("logread") +end + +--- Retrieves the output of the "dmesg" command. +-- @return String containing the current log buffer +function dmesg() + return luci.util.exec("dmesg") +end + +--- Generates a random id with specified length. +-- @param bytes Number of bytes for the unique id +-- @return String containing hex encoded id +function uniqueid(bytes) + local fp = io.open("/dev/urandom") + local chunk = { fp:read(bytes):byte(1, bytes) } + fp:close() + + local hex = "" + + local pattern = "%02X" + for i, byte in ipairs(chunk) do + hex = hex .. pattern:format(byte) + end + + return hex +end + +--- Returns the current system uptime stats. +-- @return String containing total uptime in seconds +-- @return String containing idle time in seconds +function uptime() + local loadavg = io.lines("/proc/uptime")() + return loadavg:match("^(.-) (.-)$") +end + +--- LuCI system utilities / POSIX user group related functions. +-- @class module +-- @name luci.sys.group +group = {} + +--- Returns information about a POSIX user group. +-- @class function +-- @name getgroup +-- @param group Group ID or name of a system user group +-- @return Table with information about the requested group +group.getgroup = posix.getgroup + + +--- LuCI system utilities / network related functions. +-- @class module +-- @name luci.sys.net +net = {} + +--- Returns the current arp-table entries as two-dimensional table. +-- @return Table of table containing the current arp entries. +-- The following fields are defined for arp entry objects: +-- { "IP address", "HW address", "HW type", "Flags", "Mask", "Device" } +function net.arptable() + return _parse_delimited_table(io.lines("/proc/net/arp"), "%s%s+") +end + +--- Returns conntrack information +-- @return Table with the currently tracked IP connections +function net.conntrack() + local connt = {} + if luci.fs.access("/proc/net/nf_conntrack", "r") then + for line in io.lines("/proc/net/nf_conntrack") do + line = line:match "^(.-( [^ =]+=).-)%2" + local entry, flags = _parse_mixed_record(line, " +") + entry.layer3 = flags[1] + entry.layer4 = flags[3] + for i=1, #entry do + entry[i] = nil + end + + connt[#connt+1] = entry + end + elseif luci.fs.access("/proc/net/ip_conntrack", "r") then + for line in io.lines("/proc/net/ip_conntrack") do + line = line:match "^(.-( [^ =]+=).-)%2" + local entry, flags = _parse_mixed_record(line, " +") + entry.layer3 = "ipv4" + entry.layer4 = flags[1] + for i=1, #entry do + entry[i] = nil + end + + connt[#connt+1] = entry + end + else + return nil + end + return connt +end + +--- Determine the current IPv4 default route. If multiple default routes exist, +-- return the one with the lowest metric. +-- @return Table with the properties of the current default route. +-- The following fields are defined: +-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt", +-- "flags", "device" } +function net.defaultroute() + local route = nil + for _, r in pairs(net.routes()) do + if r.dest:prefix() == 0 and (not route or route.metric > r.metric) then + route = r + end + end + return route +end + +--- Determine the current IPv6 default route. If multiple default routes exist, +-- return the one with the lowest metric. +-- @return Table with the properties of the current default route. +-- The following fields are defined: +-- { "source", "dest", "nexthop", "metric", "refcount", "usecount", +-- "flags", "device" } +function net.defaultroute6() + local route = nil + local routes6 = net.routes6() + if routes6 then + for _, r in pairs(routes6) do + if r.dest:prefix() == 0 and + (not route or route.metric > r.metric) + then + route = r + end + end + end + return route +end + +--- Determine the names of available network interfaces. +-- @return Table containing all current interface names +function net.devices() + local devices = {} + for line in io.lines("/proc/net/dev") do + table.insert(devices, line:match(" *(.-):")) + end + return devices +end + + +--- Return information about available network interfaces. +-- @return Table containing all current interface names and their information +function net.deviceinfo() + local devices = {} + for line in io.lines("/proc/net/dev") do + local name, data = line:match("^ *(.-): *(.*)$") + if name and data then + devices[name] = luci.util.split(data, " +", nil, true) + end + end + return devices +end + + +-- Determine the MAC address belonging to the given IP address. +-- @param ip IPv4 address +-- @return String containing the MAC address or nil if it cannot be found +function net.ip4mac(ip) + local mac = nil + + for i, l in ipairs(net.arptable()) do + if l["IP address"] == ip then + mac = l["HW address"] + end + end + + return mac +end + +--- Returns the current kernel routing table entries. +-- @return Table of tables with properties of the corresponding routes. +-- The following fields are defined for route entry tables: +-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt", +-- "flags", "device" } +function net.routes() + local routes = { } + + for line in io.lines("/proc/net/route") do + + local dev, dst_ip, gateway, flags, refcnt, usecnt, metric, + dst_mask, mtu, win, irtt = line:match( + "([^%s]+)\t([A-F0-9]+)\t([A-F0-9]+)\t([A-F0-9]+)\t" .. + "(%d+)\t(%d+)\t(%d+)\t([A-F0-9]+)\t(%d+)\t(%d+)\t(%d+)" + ) + + if dev then + gateway = luci.ip.Hex( gateway, 32, luci.ip.FAMILY_INET4 ) + dst_mask = luci.ip.Hex( dst_mask, 32, luci.ip.FAMILY_INET4 ) + dst_ip = luci.ip.Hex( + dst_ip, dst_mask:prefix(dst_mask), luci.ip.FAMILY_INET4 + ) + + routes[#routes+1] = { + dest = dst_ip, + gateway = gateway, + metric = tonumber(metric), + refcount = tonumber(refcnt), + usecount = tonumber(usecnt), + mtu = tonumber(mtu), + window = tonumber(window), + irtt = tonumber(irtt), + flags = tonumber(flags, 16), + device = dev + } + end + end + + return routes +end + +--- Returns the current ipv6 kernel routing table entries. +-- @return Table of tables with properties of the corresponding routes. +-- The following fields are defined for route entry tables: +-- { "source", "dest", "nexthop", "metric", "refcount", "usecount", +-- "flags", "device" } +function net.routes6() + if luci.fs.access("/proc/net/ipv6_route", "r") then + local routes = { } + + for line in io.lines("/proc/net/ipv6_route") do + + local dst_ip, dst_prefix, src_ip, src_prefix, nexthop, + metric, refcnt, usecnt, flags, dev = line:match( + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) +([^%s]+)" + ) + + src_ip = luci.ip.Hex( + src_ip, tonumber(src_prefix, 16), luci.ip.FAMILY_INET6, false + ) + + dst_ip = luci.ip.Hex( + dst_ip, tonumber(dst_prefix, 16), luci.ip.FAMILY_INET6, false + ) + + nexthop = luci.ip.Hex( nexthop, 128, luci.ip.FAMILY_INET6, false ) + + routes[#routes+1] = { + source = src_ip, + dest = dst_ip, + nexthop = nexthop, + metric = tonumber(metric, 16), + refcount = tonumber(refcnt, 16), + usecount = tonumber(usecnt, 16), + flags = tonumber(flags, 16), + device = dev + } + end + + return routes + end +end + +--- Tests whether the given host responds to ping probes. +-- @param host String containing a hostname or IPv4 address +-- @return Number containing 0 on success and >= 1 on error +function net.pingtest(host) + return os.execute("ping -c1 '"..host:gsub("'", '').."' >/dev/null 2>&1") +end + + +--- LuCI system utilities / process related functions. +-- @class module +-- @name luci.sys.process +process = {} + +--- Get the current process id. +-- @class function +-- @name process.info +-- @return Number containing the current pid +process.info = posix.getpid + +--- Retrieve information about currently running processes. +-- @return Table containing process information +function process.list() + local data = {} + local k + local ps = luci.util.execi("top -bn1") + + if not ps then + return + end + + while true do + local line = ps() + if not line then + return + end + + k = luci.util.split(luci.util.trim(line), "%s+", nil, true) + if k[1] == "PID" then + break + end + end + + for line in ps do + local row = {} + + line = luci.util.trim(line) + for i, value in ipairs(luci.util.split(line, "%s+", #k-1, true)) do + row[k[i]] = value + end + + local pid = tonumber(row[k[1]]) + if pid then + data[pid] = row + end + end + + return data +end + +--- Set the gid of a process identified by given pid. +-- @param pid Number containing the process id +-- @param gid Number containing the Unix group id +-- @return Boolean indicating successful operation +-- @return String containing the error message if failed +-- @return Number containing the error code if failed +function process.setgroup(pid, gid) + return posix.setpid("g", pid, gid) +end + +--- Set the uid of a process identified by given pid. +-- @param pid Number containing the process id +-- @param uid Number containing the Unix user id +-- @return Boolean indicating successful operation +-- @return String containing the error message if failed +-- @return Number containing the error code if failed +function process.setuser(pid, uid) + return posix.setpid("u", pid, uid) +end + +--- Send a signal to a process identified by given pid. +-- @class function +-- @name process.signal +-- @param pid Number containing the process id +-- @param sig Signal to send (default: 15 [SIGTERM]) +-- @return Boolean indicating successful operation +-- @return Number containing the error code if failed +process.signal = posix.kill + + +--- LuCI system utilities / user related functions. +-- @class module +-- @name luci.sys.user +user = {} + +--- Retrieve user informations for given uid. +-- @class function +-- @name getuser +-- @param uid Number containing the Unix user id +-- @return Table containing the following fields: +-- { "uid", "gid", "name", "passwd", "dir", "shell", "gecos" } +user.getuser = posix.getpasswd + +--- Test whether given string matches the password of a given system user. +-- @param username String containing the Unix user name +-- @param password String containing the password to compare +-- @return Boolean indicating wheather the passwords are equal +function user.checkpasswd(username, password) + local account = user.getuser(username) + + if account then + local pwd = account.passwd + local shadowpw + if #pwd == 1 then + if luci.fs.stat("/etc/shadow") then + if not pcall(function() + for l in io.lines("/etc/shadow") do + shadowpw = l:match("^%s:([^:]+)" % username) + if shadowpw then + pwd = shadowpw + break + end + end + end) then + return nil, "Unable to access shadow-file" + end + end + + if pwd == "!" then + return true + end + end + + if pwd and #pwd > 0 and password and #password > 0 then + return (pwd == posix.crypt(password, pwd)) + end + end + + return false +end + +--- Change the password of given user. +-- @param username String containing the Unix user name +-- @param password String containing the password to compare +-- @return Number containing 0 on success and >= 1 on error +function user.setpasswd(username, password) + if password then + password = password:gsub("'", "") + end + + if username then + username = username:gsub("'", "") + end + + local cmd = "(echo '"..password.."';sleep 1;echo '"..password.."')|" + cmd = cmd .. "passwd '"..username.."' >/dev/null 2>&1" + return os.execute(cmd) +end + + +--- LuCI system utilities / wifi related functions. +-- @class module +-- @name luci.sys.wifi +wifi = {} + +--- Get iwconfig output for all wireless devices. +-- @return Table of tables containing the iwconfing output for each wifi device +function wifi.getiwconfig() + local cnt = luci.util.exec("PATH=/sbin:/usr/sbin iwconfig 2>/dev/null") + local iwc = {} + + for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do + local k = l:match("^(.-) ") + l = l:gsub("^(.-) +", "", 1) + if k then + local entry, flags = _parse_mixed_record(l) + if entry then + entry.flags = flags + end + iwc[k] = entry + end + end + + return iwc +end + +--- Get iwlist scan output from all wireless devices. +-- @return Table of tables contaiing all scan results +function wifi.iwscan(iface) + local siface = iface or "" + local cnt = luci.util.exec("iwlist "..siface.." scan 2>/dev/null") + local iws = {} + + for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do + local k = l:match("^(.-) ") + l = l:gsub("^[^\n]+", "", 1) + l = luci.util.trim(l) + if k then + iws[k] = {} + for j, c in pairs(luci.util.split(l, "\n Cell")) do + c = c:gsub("^(.-)- ", "", 1) + c = luci.util.split(c, "\n", 7) + c = table.concat(c, "\n", 1) + local entry, flags = _parse_mixed_record(c) + if entry then + entry.flags = flags + end + table.insert(iws[k], entry) + end + end + end + + return iface and (iws[iface] or {}) or iws +end + + +--- LuCI system utilities / init related functions. +-- @class module +-- @name luci.sys.init +init = {} +init.dir = "/etc/init.d/" + +--- Get the names of all installed init scripts +-- @return Table containing the names of all inistalled init scripts +function init.names() + local names = { } + for _, name in ipairs(luci.fs.glob(init.dir.."*")) do + names[#names+1] = luci.fs.basename(name) + end + return names +end + +--- Test whether the given init script is enabled +-- @param name Name of the init script +-- @return Boolean indicating whether init is enabled +function init.enabled(name) + if luci.fs.access(init.dir..name) then + return ( call(init.dir..name.." enabled") == 0 ) + end + return false +end + +--- Get the index of he given init script +-- @param name Name of the init script +-- @return Numeric index value +function init.index(name) + if luci.fs.access(init.dir..name) then + return call("source "..init.dir..name.."; exit $START") + end +end + +--- Enable the given init script +-- @param name Name of the init script +-- @return Boolean indicating success +function init.enable(name) + if luci.fs.access(init.dir..name) then + return ( call(init.dir..name.." enable") == 1 ) + end +end + +--- Disable the given init script +-- @param name Name of the init script +-- @return Boolean indicating success +function init.disable(name) + if luci.fs.access(init.dir..name) then + return ( call(init.dir..name.." disable") == 0 ) + end +end + + +-- Internal functions + +function _parse_delimited_table(iter, delimiter) + delimiter = delimiter or "%s+" + + local data = {} + local trim = luci.util.trim + local split = luci.util.split + + local keys = split(trim(iter()), delimiter, nil, true) + for i, j in pairs(keys) do + keys[i] = trim(keys[i]) + end + + for line in iter do + local row = {} + line = trim(line) + if #line > 0 then + for i, j in pairs(split(line, delimiter, nil, true)) do + if keys[i] then + row[keys[i]] = j + end + end + end + table.insert(data, row) + end + + return data +end + +function _parse_mixed_record(cnt, delimiter) + delimiter = delimiter or " " + local data = {} + local flags = {} + + for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n")) do + for j, f in pairs(luci.util.split(luci.util.trim(l), delimiter, nil, true)) do + local k, x, v = f:match('([^%s][^:=]*) *([:=]*) *"*([^\n"]*)"*') + + if k then + if x == "" then + table.insert(flags, k) + else + data[k] = v + end + end + end + end + + return data, flags +end diff --git a/openwrt/packages/luci/libs/sys/luasrc/sys/iptparser.lua b/openwrt/packages/luci/libs/sys/luasrc/sys/iptparser.lua new file mode 100644 index 0000000..524dfd9 --- /dev/null +++ b/openwrt/packages/luci/libs/sys/luasrc/sys/iptparser.lua @@ -0,0 +1,244 @@ +--[[ +LuCI - Iptables parser and query library + +Copyright 2008 Jo-Philipp Wich + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +$Id: iptparser.lua 2733 2008-08-06 21:40:48Z Cyrus $ + +]]-- + +module("luci.sys.iptparser", package.seeall) +require("luci.util") + + +IptParser = luci.util.class() + +--[[ +IptParser.__init__( ... ) + +The class constructor, initializes the internal lookup table. +]]-- + +function IptParser.__init__( self, ... ) + self._rules = { } + self._chain = nil + self:_parse_rules() +end + + +--[[ +IptParser.find( args ) + +Find all firewall rules that match the given criteria. Expects a table with search criteria as only argument. +If args is nil or an empty table then all rules will be returned. + +The following keys in the args table are recognized: + + - table Match rules that are located within the given table + - chain Match rules that are located within the given chain + - target Match rules with the given target + - protocol Match rules that match the given protocol, rules with protocol "all" are always matched + - source Match rules with the given source, rules with source "0.0.0.0/0" are always matched + - destination Match rules with the given destination, rules with destination "0.0.0.0/0" are always matched + - inputif Match rules with the given input interface, rules with input interface "*" (=all) are always matched + - outputif Match rules with the given output interface, rules with output interface "*" (=all) are always matched + - flags Match rules that match the given flags, current supported values are "-f" (--fragment) and "!f" (! --fragment) + - options Match rules containing all given options + +The return value is a list of tables representing the matched rules. +Each rule table contains the following fields: + + - index The index number of the rule + - table The table where the rule is located, can be one of "filter", "nat" or "mangle" + - chain The chain where the rule is located, e.g. "INPUT" or "postrouting_wan" + - target The rule target, e.g. "REJECT" or "DROP" + - protocol The matching protocols, e.g. "all" or "tcp" + - flags Special rule options ("--", "-f" or "!f") + - inputif Input interface of the rule, e.g. "eth0.0" or "*" for all interfaces + - outputif Output interface of the rule, e.g. "eth0.0" or "*" for all interfaces + - source The source ip range, e.g. "0.0.0.0/0" + - destination The destination ip range, e.g. "0.0.0.0/0" + - options A list of specific options of the rule, e.g. { "reject-with", "tcp-reset" } + - packets The number of packets matched by the rule + - bytes The number of total bytes matched by the rule + +Example: + +ip = luci.sys.iptparser.IptParser() +result = ip.find( { + target="REJECT", + protocol="tcp", + options={ "reject-with", "tcp-reset" } +} ) + +This will match all rules with target "-j REJECT", protocol "-p tcp" (or "-p all") and the option "--reject-with tcp-reset". + +]]-- + +function IptParser.find( self, args ) + + local args = args or { } + local rv = { } + + for i, rule in ipairs(self._rules) do + local match = true + + -- match table + if not ( not args.table or args.table == rule.table ) then + match = false + end + + -- match chain + if not ( match == true and ( not args.chain or args.chain == rule.chain ) ) then + match = false + end + + -- match target + if not ( match == true and ( not args.target or args.target == rule.target ) ) then + match = false + end + + -- match protocol + if not ( match == true and ( not args.protocol or rule.protocol == "all" or args.protocol == rule.protocol ) ) then + match = false + end + + -- match source (XXX: implement ipcalc stuff so that 192.168.1.0/24 matches 0.0.0.0/0 etc.) + if not ( match == true and ( not args.source or rule.source == "0.0.0.0/0" or rule.source == args.source ) ) then + match = false + end + + -- match destination (XXX: implement ipcalc stuff so that 192.168.1.0/24 matches 0.0.0.0/0 etc.) + if not ( match == true and ( not args.destination or rule.destination == "0.0.0.0/0" or rule.destination == args.destination ) ) then + match = false + end + + -- match input interface + if not ( match == true and ( not args.inputif or rule.inputif == "*" or args.inputif == rule.inputif ) ) then + match = false + end + + -- match output interface + if not ( match == true and ( not args.outputif or rule.outputif == "*" or args.outputif == rule.outputif ) ) then + match = false + end + + -- match flags (the "opt" column) + if not ( match == true and ( not args.flags or rule.flags == args.flags ) ) then + match = false + end + + -- match specific options + if not ( match == true and ( not args.options or self:_match_options( rule.options, args.options ) ) ) then + match = false + end + + + -- insert match + if match == true then + table.insert( rv, rule ) + end + end + + return rv +end + + +--[[ +IptParser.resync() + +Rebuild the internal lookup table, for example when rules have changed through external commands. +]]-- + +function IptParser.resync( self ) + self._rules = { } + self._chain = nil + self:_parse_rules() +end + + +--[[ +IptParser._parse_rules() + +[internal] Parse iptables output from all tables. +]]-- + +function IptParser._parse_rules( self ) + + for i, tbl in ipairs({ "filter", "nat", "mangle" }) do + + for i, rule in ipairs(luci.util.execl("iptables -t " .. tbl .. " --line-numbers -nxvL")) do + + if rule:find( "Chain " ) == 1 then + + self._chain = rule:gsub("Chain ([^%s]*) .*", "%1") + + else + if rule:find("%d") == 1 then + + local rule_parts = luci.util.split( rule, "%s+", nil, true ) + local rule_details = { } + + rule_details["table"] = tbl + rule_details["chain"] = self._chain + rule_details["index"] = tonumber(rule_parts[1]) + rule_details["packets"] = tonumber(rule_parts[2]) + rule_details["bytes"] = tonumber(rule_parts[3]) + rule_details["target"] = rule_parts[4] + rule_details["protocol"] = rule_parts[5] + rule_details["flags"] = rule_parts[6] + rule_details["inputif"] = rule_parts[7] + rule_details["outputif"] = rule_parts[8] + rule_details["source"] = rule_parts[9] + rule_details["destination"] = rule_parts[10] + rule_details["options"] = { } + + for i = 11, #rule_parts - 1 do + rule_details["options"][i-10] = rule_parts[i] + end + + table.insert( self._rules, rule_details ) + end + end + end + end + + self._chain = nil +end + + +--[[ +IptParser._match_options( optlist1, optlist2 ) + +[internal] Return true if optlist1 contains all elements of optlist2. Return false in all other cases. +]]-- + +function IptParser._match_options( self, o1, o2 ) + + -- construct a hashtable of first options list to speed up lookups + local oh = { } + for i, opt in ipairs( o1 ) do oh[opt] = true end + + -- iterate over second options list + -- each string in o2 must be also present in o1 + -- if o2 contains a string which is not found in o1 then return false + for i, opt in ipairs( o2 ) do + if not oh[opt] then + return false + end + end + + return true +end diff --git a/openwrt/packages/luci/libs/sys/luasrc/sys/zoneinfo.lua b/openwrt/packages/luci/libs/sys/luasrc/sys/zoneinfo.lua new file mode 100644 index 0000000..d6de704 --- /dev/null +++ b/openwrt/packages/luci/libs/sys/luasrc/sys/zoneinfo.lua @@ -0,0 +1,572 @@ +--[[ +LuCI - Autogenerated Zoneinfo Module + +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 + +]]-- + +module "luci.sys.zoneinfo" + +TZ = { + { 'Africa/Abidjan', 'GMT0' }, + { 'Africa/Accra', 'GMT0' }, + { 'Africa/Addis Ababa', 'EAT-3' }, + { 'Africa/Algiers', 'CET-1' }, + { 'Africa/Asmara', 'EAT-3' }, + { 'Africa/Bamako', 'GMT0' }, + { 'Africa/Bangui', 'WAT-1' }, + { 'Africa/Banjul', 'GMT0' }, + { 'Africa/Bissau', 'GMT0' }, + { 'Africa/Blantyre', 'CAT-2' }, + { 'Africa/Brazzaville', 'WAT-1' }, + { 'Africa/Bujumbura', 'CAT-2' }, + { 'Africa/Casablanca', 'WET0' }, + { 'Africa/Ceuta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Africa/Conakry', 'GMT0' }, + { 'Africa/Dakar', 'GMT0' }, + { 'Africa/Dar es Salaam', 'EAT-3' }, + { 'Africa/Djibouti', 'EAT-3' }, + { 'Africa/Douala', 'WAT-1' }, + { 'Africa/El Aaiun', 'WET0' }, + { 'Africa/Freetown', 'GMT0' }, + { 'Africa/Gaborone', 'CAT-2' }, + { 'Africa/Harare', 'CAT-2' }, + { 'Africa/Johannesburg', 'SAST-2' }, + { 'Africa/Kampala', 'EAT-3' }, + { 'Africa/Khartoum', 'EAT-3' }, + { 'Africa/Kigali', 'CAT-2' }, + { 'Africa/Kinshasa', 'WAT-1' }, + { 'Africa/Lagos', 'WAT-1' }, + { 'Africa/Libreville', 'WAT-1' }, + { 'Africa/Lome', 'GMT0' }, + { 'Africa/Luanda', 'WAT-1' }, + { 'Africa/Lubumbashi', 'CAT-2' }, + { 'Africa/Lusaka', 'CAT-2' }, + { 'Africa/Malabo', 'WAT-1' }, + { 'Africa/Maputo', 'CAT-2' }, + { 'Africa/Maseru', 'SAST-2' }, + { 'Africa/Mbabane', 'SAST-2' }, + { 'Africa/Mogadishu', 'EAT-3' }, + { 'Africa/Monrovia', 'GMT0' }, + { 'Africa/Nairobi', 'EAT-3' }, + { 'Africa/Ndjamena', 'WAT-1' }, + { 'Africa/Niamey', 'WAT-1' }, + { 'Africa/Nouakchott', 'GMT0' }, + { 'Africa/Ouagadougou', 'GMT0' }, + { 'Africa/Porto-Novo', 'WAT-1' }, + { 'Africa/Sao Tome', 'GMT0' }, + { 'Africa/Tripoli', 'EET-2' }, + { 'Africa/Tunis', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Africa/Windhoek', 'WAT-1WAST,M9.1.0,M4.1.0' }, + { 'America/Adak', 'HAST10HADT,M3.2.0,M11.1.0' }, + { 'America/Anchorage', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Anguilla', 'AST4' }, + { 'America/Antigua', 'AST4' }, + { 'America/Araguaina', 'BRT3' }, + { 'America/Argentina/Buenos Aires', 'ART3ARST,M10.3.0/0,M3.3.0/0' }, + { 'America/Argentina/Catamarca', 'ART3' }, + { 'America/Argentina/Cordoba', 'ART3ARST,M10.3.0/0,M3.3.0/0' }, + { 'America/Argentina/Jujuy', 'ART3' }, + { 'America/Argentina/La Rioja', 'ART3' }, + { 'America/Argentina/Mendoza', 'ART3' }, + { 'America/Argentina/Rio Gallegos', 'ART3' }, + { 'America/Argentina/Salta', 'ART3' }, + { 'America/Argentina/San Juan', 'ART3' }, + { 'America/Argentina/San Luis', 'ART3' }, + { 'America/Argentina/Tucuman', 'ART3ARST,M10.3.0/0,M3.3.0/0' }, + { 'America/Argentina/Ushuaia', 'ART3' }, + { 'America/Aruba', 'AST4' }, + { 'America/Asuncion', 'PYT4PYST,M10.3.0/0,M3.2.0/0' }, + { 'America/Atikokan', 'EST5' }, + { 'America/Bahia', 'BRT3' }, + { 'America/Barbados', 'AST4' }, + { 'America/Belem', 'BRT3' }, + { 'America/Belize', 'CST6' }, + { 'America/Blanc-Sablon', 'AST4' }, + { 'America/Boa Vista', 'AMT4' }, + { 'America/Bogota', 'COT5' }, + { 'America/Boise', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Cambridge Bay', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Campo Grande', 'AMT4AMST,M10.3.0/0,M2.3.0/0' }, + { 'America/Cancun', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Caracas', 'VET4:30' }, + { 'America/Cayenne', 'GFT3' }, + { 'America/Cayman', 'EST5' }, + { 'America/Chicago', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Chihuahua', 'MST7MDT,M4.1.0,M10.5.0' }, + { 'America/Costa Rica', 'CST6' }, + { 'America/Cuiaba', 'AMT4AMST,M10.3.0/0,M2.3.0/0' }, + { 'America/Curacao', 'AST4' }, + { 'America/Danmarkshavn', 'GMT0' }, + { 'America/Dawson', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Dawson Creek', 'MST7' }, + { 'America/Denver', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Detroit', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Dominica', 'AST4' }, + { 'America/Edmonton', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Eirunepe', 'AMT4' }, + { 'America/El Salvador', 'CST6' }, + { 'America/Fortaleza', 'BRT3' }, + { 'America/Glace Bay', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Goose Bay', 'AST4ADT,M3.2.0/0:01,M11.1.0/0:01' }, + { 'America/Grand Turk', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Grenada', 'AST4' }, + { 'America/Guadeloupe', 'AST4' }, + { 'America/Guatemala', 'CST6' }, + { 'America/Guayaquil', 'ECT5' }, + { 'America/Guyana', 'GYT4' }, + { 'America/Halifax', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Havana', 'CST5CDT,M3.3.0/0,M10.5.0/1' }, + { 'America/Hermosillo', 'MST7' }, + { 'America/Indiana/Indianapolis', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Knox', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Marengo', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Petersburg', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Tell City', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Vevay', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Vincennes', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Indiana/Winamac', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Inuvik', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Iqaluit', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Jamaica', 'EST5' }, + { 'America/Juneau', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Kentucky/Louisville', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Kentucky/Monticello', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/La Paz', 'BOT4' }, + { 'America/Lima', 'PET5' }, + { 'America/Los Angeles', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Maceio', 'BRT3' }, + { 'America/Managua', 'CST6' }, + { 'America/Manaus', 'AMT4' }, + { 'America/Marigot', 'AST4' }, + { 'America/Martinique', 'AST4' }, + { 'America/Mazatlan', 'MST7MDT,M4.1.0,M10.5.0' }, + { 'America/Menominee', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Merida', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Mexico City', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Miquelon', 'PMST3PMDT,M3.2.0,M11.1.0' }, + { 'America/Moncton', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Monterrey', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Montevideo', 'UYT3UYST,M10.1.0,M3.2.0' }, + { 'America/Montreal', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Montserrat', 'AST4' }, + { 'America/Nassau', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/New York', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Nipigon', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Nome', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Noronha', 'FNT2' }, + { 'America/North Dakota/Center', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/North Dakota/New Salem', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Panama', 'EST5' }, + { 'America/Pangnirtung', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Paramaribo', 'SRT3' }, + { 'America/Phoenix', 'MST7' }, + { 'America/Port of Spain', 'AST4' }, + { 'America/Port-au-Prince', 'EST5' }, + { 'America/Porto Velho', 'AMT4' }, + { 'America/Puerto Rico', 'AST4' }, + { 'America/Rainy River', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Rankin Inlet', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Recife', 'BRT3' }, + { 'America/Regina', 'CST6' }, + { 'America/Resolute', 'EST5' }, + { 'America/Rio Branco', 'AMT4' }, + { 'America/Santarem', 'BRT3' }, + { 'America/Santo Domingo', 'AST4' }, + { 'America/Sao Paulo', 'BRT3BRST,M10.3.0/0,M2.3.0/0' }, + { 'America/Scoresbysund', 'EGT1EGST,M3.5.0/0,M10.5.0/1' }, + { 'America/Shiprock', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/St Barthelemy', 'AST4' }, + { 'America/St Johns', 'NST3:30NDT,M3.2.0/0:01,M11.1.0/0:01' }, + { 'America/St Kitts', 'AST4' }, + { 'America/St Lucia', 'AST4' }, + { 'America/St Thomas', 'AST4' }, + { 'America/St Vincent', 'AST4' }, + { 'America/Swift Current', 'CST6' }, + { 'America/Tegucigalpa', 'CST6' }, + { 'America/Thule', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Thunder Bay', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Tijuana', 'PST8PDT,M4.1.0,M10.5.0' }, + { 'America/Toronto', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Tortola', 'AST4' }, + { 'America/Vancouver', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Whitehorse', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'Antarctica/Casey', 'WST-8' }, + { 'Antarctica/Davis', 'DAVT-7' }, + { 'Antarctica/DumontDUrville', 'DDUT-10' }, + { 'Antarctica/Mawson', 'MAWT-6' }, + { 'Antarctica/McMurdo', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Antarctica/Rothera', 'ROTT3' }, + { 'Antarctica/South Pole', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Antarctica/Syowa', 'SYOT-3' }, + { 'Antarctica/Vostok', 'VOST-6' }, + { 'Arctic/Longyearbyen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Asia/Aden', 'AST-3' }, + { 'Asia/Almaty', 'ALMT-6' }, + { 'Asia/Amman', 'EET-2EEST,M3.5.4/0,M10.5.5/1' }, + { 'Asia/Anadyr', 'ANAT-12ANAST,M3.5.0,M10.5.0/3' }, + { 'Asia/Aqtau', 'AQTT-5' }, + { 'Asia/Aqtobe', 'AQTT-5' }, + { 'Asia/Ashgabat', 'TMT-5' }, + { 'Asia/Baghdad', 'AST-3' }, + { 'Asia/Bahrain', 'AST-3' }, + { 'Asia/Baku', 'AZT-4AZST,M3.5.0/4,M10.5.0/5' }, + { 'Asia/Bangkok', 'ICT-7' }, + { 'Asia/Beirut', 'EET-2EEST,M3.5.0/0,M10.5.0/0' }, + { 'Asia/Bishkek', 'KGT-6' }, + { 'Asia/Brunei', 'BNT-8' }, + { 'Asia/Choibalsan', 'CHOT-8' }, + { 'Asia/Chongqing', 'CST-8' }, + { 'Asia/Colombo', 'IST-5:30' }, + { 'Asia/Damascus', 'EET-2EEST,M4.1.5/0,J305/0' }, + { 'Asia/Dhaka', 'BDT-6' }, + { 'Asia/Dili', 'TLT-9' }, + { 'Asia/Dubai', 'GST-4' }, + { 'Asia/Dushanbe', 'TJT-5' }, + { 'Asia/Gaza', 'EET-2EEST,J91/0,M8.5.4' }, + { 'Asia/Harbin', 'CST-8' }, + { 'Asia/Ho Chi Minh', 'ICT-7' }, + { 'Asia/Hong Kong', 'HKT-8' }, + { 'Asia/Hovd', 'HOVT-7' }, + { 'Asia/Irkutsk', 'IRKT-8IRKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Jakarta', 'WIT-7' }, + { 'Asia/Jayapura', 'EIT-9' }, + { 'Asia/Kabul', 'AFT-4:30' }, + { 'Asia/Kamchatka', 'PETT-12PETST,M3.5.0,M10.5.0/3' }, + { 'Asia/Karachi', 'PKT-5' }, + { 'Asia/Kashgar', 'CST-8' }, + { 'Asia/Katmandu', 'NPT-5:45' }, + { 'Asia/Kolkata', 'IST-5:30' }, + { 'Asia/Krasnoyarsk', 'KRAT-7KRAST,M3.5.0,M10.5.0/3' }, + { 'Asia/Kuala Lumpur', 'MYT-8' }, + { 'Asia/Kuching', 'MYT-8' }, + { 'Asia/Kuwait', 'AST-3' }, + { 'Asia/Macau', 'CST-8' }, + { 'Asia/Magadan', 'MAGT-11MAGST,M3.5.0,M10.5.0/3' }, + { 'Asia/Makassar', 'CIT-8' }, + { 'Asia/Manila', 'PHT-8' }, + { 'Asia/Muscat', 'GST-4' }, + { 'Asia/Nicosia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Asia/Novosibirsk', 'NOVT-6NOVST,M3.5.0,M10.5.0/3' }, + { 'Asia/Omsk', 'OMST-6OMSST,M3.5.0,M10.5.0/3' }, + { 'Asia/Oral', 'ORAT-5' }, + { 'Asia/Phnom Penh', 'ICT-7' }, + { 'Asia/Pontianak', 'WIT-7' }, + { 'Asia/Pyongyang', 'KST-9' }, + { 'Asia/Qatar', 'AST-3' }, + { 'Asia/Qyzylorda', 'QYZT-6' }, + { 'Asia/Rangoon', 'MMT-6:30' }, + { 'Asia/Riyadh', 'AST-3' }, + { 'Asia/Sakhalin', 'SAKT-10SAKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Samarkand', 'UZT-5' }, + { 'Asia/Seoul', 'KST-9' }, + { 'Asia/Shanghai', 'CST-8' }, + { 'Asia/Singapore', 'SGT-8' }, + { 'Asia/Taipei', 'CST-8' }, + { 'Asia/Tashkent', 'UZT-5' }, + { 'Asia/Tbilisi', 'GET-4' }, + { 'Asia/Thimphu', 'BTT-6' }, + { 'Asia/Tokyo', 'JST-9' }, + { 'Asia/Ulaanbaatar', 'ULAT-8' }, + { 'Asia/Urumqi', 'CST-8' }, + { 'Asia/Vientiane', 'ICT-7' }, + { 'Asia/Vladivostok', 'VLAT-10VLAST,M3.5.0,M10.5.0/3' }, + { 'Asia/Yakutsk', 'YAKT-9YAKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Yekaterinburg', 'YEKT-5YEKST,M3.5.0,M10.5.0/3' }, + { 'Asia/Yerevan', 'AMT-4AMST,M3.5.0,M10.5.0/3' }, + { 'Atlantic/Azores', 'AZOT1AZOST,M3.5.0/0,M10.5.0/1' }, + { 'Atlantic/Bermuda', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'Atlantic/Canary', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Cape Verde', 'CVT1' }, + { 'Atlantic/Faroe', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Madeira', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Atlantic/Reykjavik', 'GMT0' }, + { 'Atlantic/South Georgia', 'GST2' }, + { 'Atlantic/St Helena', 'GMT0' }, + { 'Atlantic/Stanley', 'FKT4FKST,M9.1.0,M4.3.0' }, + { 'Australia/Adelaide', 'CST-9:30CST,M10.1.0,M4.1.0/3' }, + { 'Australia/Brisbane', 'EST-10' }, + { 'Australia/Broken Hill', 'CST-9:30CST,M10.1.0,M4.1.0/3' }, + { 'Australia/Currie', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Australia/Darwin', 'CST-9:30' }, + { 'Australia/Eucla', 'CWST-8:45' }, + { 'Australia/Hobart', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Australia/Lindeman', 'EST-10' }, + { 'Australia/Lord Howe', 'LHST-10:30LHST-11,M10.1.0,M4.1.0' }, + { 'Australia/Melbourne', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Australia/Perth', 'WST-8' }, + { 'Australia/Sydney', 'EST-10EST,M10.1.0,M4.1.0/3' }, + { 'Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Andorra', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Athens', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Belgrade', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Berlin', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Bratislava', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Brussels', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Bucharest', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Budapest', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Chisinau', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Copenhagen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Dublin', 'GMT0IST,M3.5.0/1,M10.5.0' }, + { 'Europe/Gibraltar', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Guernsey', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Helsinki', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Isle of Man', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Istanbul', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Jersey', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Kaliningrad', 'EET-2EEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Kiev', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Lisbon', 'WET0WEST,M3.5.0/1,M10.5.0' }, + { 'Europe/Ljubljana', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/London', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Luxembourg', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Madrid', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Malta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Mariehamn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Minsk', 'EET-2EEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Monaco', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Moscow', 'MSK-3MSD,M3.5.0,M10.5.0/3' }, + { 'Europe/Oslo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Paris', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Podgorica', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Prague', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Riga', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Rome', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Samara', 'SAMT-4SAMST,M3.5.0,M10.5.0/3' }, + { 'Europe/San Marino', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Sarajevo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Simferopol', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Skopje', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Sofia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Stockholm', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Tallinn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Tirane', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Uzhgorod', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Vaduz', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vatican', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vienna', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Vilnius', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Volgograd', 'VOLT-3VOLST,M3.5.0,M10.5.0/3' }, + { 'Europe/Warsaw', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zagreb', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zaporozhye', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Europe/Zurich', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Indian/Antananarivo', 'EAT-3' }, + { 'Indian/Chagos', 'IOT-6' }, + { 'Indian/Christmas', 'CXT-7' }, + { 'Indian/Cocos', 'CCT-6:30' }, + { 'Indian/Comoro', 'EAT-3' }, + { 'Indian/Kerguelen', 'TFT-5' }, + { 'Indian/Mahe', 'SCT-4' }, + { 'Indian/Maldives', 'MVT-5' }, + { 'Indian/Mauritius', 'MUT-4MUST,M10.5.0,M3.5.0/3' }, + { 'Indian/Mayotte', 'EAT-3' }, + { 'Indian/Reunion', 'RET-4' }, + { 'Pacific/Apia', 'WST11' }, + { 'Pacific/Auckland', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Pacific/Chatham', 'CHAST-12:45CHADT,M9.5.0/2:45,M4.1.0/3:45' }, + { 'Pacific/Efate', 'VUT-11' }, + { 'Pacific/Enderbury', 'PHOT-13' }, + { 'Pacific/Fakaofo', 'TKT10' }, + { 'Pacific/Fiji', 'FJT-12' }, + { 'Pacific/Funafuti', 'TVT-12' }, + { 'Pacific/Galapagos', 'GALT6' }, + { 'Pacific/Gambier', 'GAMT9' }, + { 'Pacific/Guadalcanal', 'SBT-11' }, + { 'Pacific/Guam', 'ChST-10' }, + { 'Pacific/Honolulu', 'HST10' }, + { 'Pacific/Johnston', 'HST10' }, + { 'Pacific/Kiritimati', 'LINT-14' }, + { 'Pacific/Kosrae', 'KOST-11' }, + { 'Pacific/Kwajalein', 'MHT-12' }, + { 'Pacific/Majuro', 'MHT-12' }, + { 'Pacific/Marquesas', 'MART9:30' }, + { 'Pacific/Midway', 'SST11' }, + { 'Pacific/Nauru', 'NRT-12' }, + { 'Pacific/Niue', 'NUT11' }, + { 'Pacific/Norfolk', 'NFT-11:30' }, + { 'Pacific/Noumea', 'NCT-11' }, + { 'Pacific/Pago Pago', 'SST11' }, + { 'Pacific/Palau', 'PWT-9' }, + { 'Pacific/Pitcairn', 'PST8' }, + { 'Pacific/Ponape', 'PONT-11' }, + { 'Pacific/Port Moresby', 'PGT-10' }, + { 'Pacific/Rarotonga', 'CKT10' }, + { 'Pacific/Saipan', 'ChST-10' }, + { 'Pacific/Tahiti', 'TAHT10' }, + { 'Pacific/Tarawa', 'GILT-12' }, + { 'Pacific/Tongatapu', 'TOT-13' }, + { 'Pacific/Truk', 'TRUT-10' }, + { 'Pacific/Wake', 'WAKT-12' }, + { 'Pacific/Wallis', 'WFT-12' }, +} + +OFFSET = { + gmt = 0, -- GMT + eat = 10800, -- EAT + cet = 3600, -- CET + wat = 3600, -- WAT + cat = 7200, -- CAT + wet = 0, -- WET + sast = 7200, -- SAST + eet = 7200, -- EET + hast = -36000, -- HAST + hadt = -32400, -- HADT + akst = -32400, -- AKST + akdt = -28800, -- AKDT + ast = -14400, -- AST + brt = -10800, -- BRT + art = -10800, -- ART + arst = -7200, -- ARST + pyt = -14400, -- PYT + pyst = -10800, -- PYST + est = -18000, -- EST + cst = -21600, -- CST + amt = -14400, -- AMT + cot = -18000, -- COT + mst = -25200, -- MST + mdt = -21600, -- MDT + vet = -16200, -- VET + gft = -10800, -- GFT + pst = -28800, -- PST + pdt = -25200, -- PDT + ect = -18000, -- ECT + gyt = -14400, -- GYT + bot = -14400, -- BOT + pet = -18000, -- PET + pmst = -10800, -- PMST + pmdt = -7200, -- PMDT + uyt = -10800, -- UYT + uyst = -7200, -- UYST + fnt = -7200, -- FNT + srt = -10800, -- SRT + egt = -3600, -- EGT + egst = 0, -- EGST + nst = -12600, -- NST + ndt = -9000, -- NDT + wst = 28800, -- WST + davt = 25200, -- DAVT + ddut = 36000, -- DDUT + mawt = 21600, -- MAWT + nzst = 43200, -- NZST + nzdt = 46800, -- NZDT + rott = -10800, -- ROTT + syot = 10800, -- SYOT + vost = 21600, -- VOST + almt = 21600, -- ALMT + anat = 43200, -- ANAT + anast = 46800, -- ANAST + aqtt = 18000, -- AQTT + tmt = 18000, -- TMT + azt = 14400, -- AZT + azst = 18000, -- AZST + ict = 25200, -- ICT + kgt = 21600, -- KGT + bnt = 28800, -- BNT + chot = 28800, -- CHOT + ist = 19800, -- IST + bdt = 21600, -- BDT + tlt = 32400, -- TLT + gst = 14400, -- GST + tjt = 18000, -- TJT + hkt = 28800, -- HKT + hovt = 25200, -- HOVT + irkt = 28800, -- IRKT + irkst = 32400, -- IRKST + wit = 25200, -- WIT + eit = 32400, -- EIT + aft = 16200, -- AFT + pett = 43200, -- PETT + petst = 46800, -- PETST + pkt = 18000, -- PKT + npt = 20700, -- NPT + krat = 25200, -- KRAT + krast = 28800, -- KRAST + myt = 28800, -- MYT + magt = 39600, -- MAGT + magst = 43200, -- MAGST + cit = 28800, -- CIT + pht = 28800, -- PHT + novt = 21600, -- NOVT + novst = 25200, -- NOVST + omst = 21600, -- OMST + omsst = 25200, -- OMSST + orat = 18000, -- ORAT + kst = 32400, -- KST + qyzt = 21600, -- QYZT + mmt = 23400, -- MMT + sakt = 36000, -- SAKT + sakst = 39600, -- SAKST + uzt = 18000, -- UZT + sgt = 28800, -- SGT + get = 14400, -- GET + btt = 21600, -- BTT + jst = 32400, -- JST + ulat = 28800, -- ULAT + vlat = 36000, -- VLAT + vlast = 39600, -- VLAST + yakt = 32400, -- YAKT + yakst = 36000, -- YAKST + yekt = 18000, -- YEKT + yekst = 21600, -- YEKST + azot = -3600, -- AZOT + azost = 0, -- AZOST + cvt = -3600, -- CVT + fkt = -14400, -- FKT + fkst = -10800, -- FKST + cwst = 31500, -- CWST + lhst = 37800, -- LHST + lhst = 39600, -- LHST + msk = 10800, -- MSK + msd = 14400, -- MSD + samt = 14400, -- SAMT + samst = 18000, -- SAMST + volt = 10800, -- VOLT + volst = 14400, -- VOLST + iot = 21600, -- IOT + cxt = 25200, -- CXT + cct = 23400, -- CCT + tft = 18000, -- TFT + sct = 14400, -- SCT + mvt = 18000, -- MVT + mut = 14400, -- MUT + must = 18000, -- MUST + ret = 14400, -- RET + chast = 45900, -- CHAST + chadt = 49500, -- CHADT + vut = 39600, -- VUT + phot = 46800, -- PHOT + tkt = -36000, -- TKT + fjt = 43200, -- FJT + tvt = 43200, -- TVT + galt = -21600, -- GALT + gamt = -32400, -- GAMT + sbt = 39600, -- SBT + hst = -36000, -- HST + lint = 50400, -- LINT + kost = 39600, -- KOST + mht = 43200, -- MHT + mart = -34200, -- MART + sst = -39600, -- SST + nrt = 43200, -- NRT + nut = -39600, -- NUT + nft = 41400, -- NFT + nct = 39600, -- NCT + pwt = 32400, -- PWT + pont = 39600, -- PONT + pgt = 36000, -- PGT + ckt = -36000, -- CKT + taht = -36000, -- TAHT + gilt = 43200, -- GILT + tot = 46800, -- TOT + trut = 36000, -- TRUT + wakt = 43200, -- WAKT + wft = 43200, -- WFT +} diff --git a/openwrt/packages/luci/libs/uci/Makefile b/openwrt/packages/luci/libs/uci/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/libs/uci/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uci/luasrc/model/uci.lua b/openwrt/packages/luci/libs/uci/luasrc/model/uci.lua new file mode 100644 index 0000000..6c6b93b --- /dev/null +++ b/openwrt/packages/luci/libs/uci/luasrc/model/uci.lua @@ -0,0 +1,333 @@ +--[[ +LuCI - UCI model + +Description: +Generalized UCI model + +FileId: +$Id: uci.lua 4190 2009-01-30 15:36:49Z jow $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +local os = require "os" +local uci = require "uci" +local util = require "luci.util" +local table = require "table" + + +local setmetatable, rawget, rawset = setmetatable, rawget, rawset +local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring +local require, getmetatable, type = require, getmetatable, type + +--- LuCI UCI model library. +-- @cstyle instance +module "luci.model.uci" + +--- Create a new UCI-Cursor. +-- @class function +-- @name cursor +-- @return UCI-Cursor +cursor = uci.cursor + +APIVERSION = uci.APIVERSION + +--- Create a new Cursor initialized to the state directory. +-- @return UCI cursor +function cursor_state() + return cursor(nil, "/var/state") +end + + +local Cursor = getmetatable(cursor()) + +--- Applies UCI configuration changes +-- @param configlist List of UCI configurations +-- @param command Don't apply only return the command +function Cursor.apply(self, configlist, command) + configlist = self:_affected(configlist) + local reloadcmd = "/sbin/luci-reload " .. table.concat(configlist, " ") + + return command and reloadcmd or os.execute(reloadcmd .. " >/dev/null 2>&1") +end + + +--- Delete all sections of a given type that match certain criteria. +-- @param config UCI config +-- @param type UCI section type +-- @param comparator Function that will be called for each section and +-- returns a boolean whether to delete the current section (optional) +function Cursor.delete_all(self, config, stype, comparator) + local del = {} + + if type(comparator) == "table" then + local tbl = comparator + comparator = function(section) + for k, v in pairs(tbl) do + if section[k] ~= v then + return false + end + end + return true + end + end + + local function helper (section) + + if not comparator or comparator(section) then + del[#del+1] = section[".name"] + end + end + + self:foreach(config, stype, helper) + + for i, j in ipairs(del) do + self:delete(config, j) + end +end + +--- Create a new section and initialize it with data. +-- @param config UCI config +-- @param type UCI section type +-- @param name UCI section name (optional) +-- @param values Table of key - value pairs to initialize the section with +-- @return Name of created section +function Cursor.section(self, config, type, name, values) + local stat = true + if name then + stat = self:set(config, name, type) + else + name = self:add(config, type) + stat = name and true + end + + if stat and values then + stat = self:tset(config, name, values) + end + + return stat and name +end + +--- Updated the data of a section using data from a table. +-- @param config UCI config +-- @param section UCI section name (optional) +-- @param values Table of key - value pairs to update the section with +function Cursor.tset(self, config, section, values) + local stat = true + for k, v in pairs(values) do + if k:sub(1, 1) ~= "." then + stat = stat and self:set(config, section, k, v) + end + end + return stat +end + +--- Get a boolean option and return it's value as true or false. +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option +-- @return Boolean +function Cursor.get_bool(self, ...) + local val = self:get(...) + return ( val == "1" or val == "true" or val == "yes" or val == "on" ) +end + +--- Get an option or list and return values as table. +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option +-- @return UCI value +function Cursor.get_list(self, config, section, option) + if config and section and option then + local val = self:get(config, section, option) + return ( type(val) == "table" and val or { val } ) + end + return nil +end + +--- Set given values as list. +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option +-- @param value UCI value +-- @return Boolean whether operation succeeded +function Cursor.set_list(self, config, section, option, value) + if config and section and option then + return self:set( + config, section, option, + ( type(value) == "table" and value or { value } ) + ) + end + return false +end + +-- Return a list of initscripts affected by configuration changes. +function Cursor._affected(self, configlist) + configlist = type(configlist) == "table" and configlist or {configlist} + + local c = cursor() + c:load("ucitrack") + + -- Resolve dependencies + local reloadlist = {} + + local function _resolve_deps(name) + local reload = {name} + local deps = {} + + c:foreach("ucitrack", name, + function(section) + if section.affects then + for i, aff in ipairs(section.affects) do + deps[#deps+1] = aff + end + end + end) + + for i, dep in ipairs(deps) do + for j, add in ipairs(_resolve_deps(dep)) do + reload[#reload+1] = add + end + end + + return reload + end + + -- Collect initscripts + for j, config in ipairs(configlist) do + for i, e in ipairs(_resolve_deps(config)) do + if not util.contains(reloadlist, e) then + reloadlist[#reloadlist+1] = e + end + end + end + + return reloadlist +end + + +--- Add an anonymous section. +-- @class function +-- @name Cursor.add +-- @param config UCI config +-- @param type UCI section type +-- @return Name of created section + +--- Get a table of unsaved changes. +-- @class function +-- @name Cursor.changes +-- @param config UCI config +-- @return Table of changes + +--- Commit unsaved changes. +-- @class function +-- @name Cursor.commit +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.revert + +--- Deletes a section or an option. +-- @class function +-- @name Cursor.delete +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option (optional) +-- @return Boolean whether operation succeeded + +--- Call a function for every section of a certain type. +-- @class function +-- @name Cursor.foreach +-- @param config UCI config +-- @param type UCI section type +-- @param callback Function to be called +-- @return Boolean whether operation succeeded + +--- Get a section type or an option +-- @class function +-- @name Cursor.get +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option (optional) +-- @return UCI value + +--- Get all sections of a config or all values of a section. +-- @class function +-- @name Cursor.get_all +-- @param config UCI config +-- @param section UCI section name (optional) +-- @return Table of UCI sections or table of UCI values + +--- Manually load a config. +-- @class function +-- @name Cursor.load +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.save +-- @see Cursor.unload + +--- Revert unsaved changes. +-- @class function +-- @name Cursor.revert +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.commit + +--- Saves changes made to a config to make them committable. +-- @class function +-- @name Cursor.save +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.load +-- @see Cursor.unload + +--- Set a value or create a named section. +-- @class function +-- @name Cursor.set +-- @param config UCI config +-- @param section UCI section name +-- @param option UCI option or UCI section type +-- @param value UCI value or nil if you want to create a section +-- @return Boolean whether operation succeeded + +--- Get the configuration directory. +-- @class function +-- @name Cursor.get_confdir +-- @return Configuration directory + +--- Get the directory for uncomitted changes. +-- @class function +-- @name Cursor.get_savedir +-- @return Save directory + +--- Set the configuration directory. +-- @class function +-- @name Cursor.set_confdir +-- @param directory UCI configuration directory +-- @return Boolean whether operation succeeded + +--- Set the directory for uncommited changes. +-- @class function +-- @name Cursor.set_savedir +-- @param directory UCI changes directory +-- @return Boolean whether operation succeeded + +--- Discard changes made to a config. +-- @class function +-- @name Cursor.unload +-- @param config UCI config +-- @return Boolean whether operation succeeded +-- @see Cursor.load +-- @see Cursor.save diff --git a/openwrt/packages/luci/libs/uci/root/etc/config/ucitrack b/openwrt/packages/luci/libs/uci/root/etc/config/ucitrack new file mode 100644 index 0000000..8b647fd --- /dev/null +++ b/openwrt/packages/luci/libs/uci/root/etc/config/ucitrack @@ -0,0 +1,55 @@ +config network + option init network + list affects dhcp + +config wireless + list affects network + +config firewall + option init firewall + list affects luci-splash + list affects qos + +config olsr + option init olsrd + +config dhcp + option init dnsmasq + +config dropbear + option init dropbear + +config httpd + option init httpd + +config fstab + option init fstab + +config qos + option init qos + +config system + option init led + +config luci_hosts + option init luci_hosts + list affects dhcp + +config luci_ethers + option init luci_ethers + list affects dhcp + +config luci_splash + option init luci_splash + +config upnpd + option init miniupnpd + +config ntpclient + option init ntpclient + +config samba + option init samba + +config tinyproxy + option init tinyproxy diff --git a/openwrt/packages/luci/libs/uci/root/sbin/luci-reload b/openwrt/packages/luci/libs/uci/root/sbin/luci-reload new file mode 100755 index 0000000..b6b1ff6 --- /dev/null +++ b/openwrt/packages/luci/libs/uci/root/sbin/luci-reload @@ -0,0 +1,34 @@ +#!/bin/sh +. /etc/functions.sh + +apply_config() { + config_get init "$1" init + config_get exec "$1" exec + config_get test "$1" test + + [ -n "$init" ] && reload_init "$2" "$init" "$test" + [ -n "$exec" ] && reload_exec "$2" "$exec" "$test" +} + +reload_exec() { + [ -x $2 ] && { + echo "Reloading $1... " + $2 >/dev/null 2>&1 + [ -n "$3" -a "$?" != "$3" ] && echo '!!! Failed to reload' $1 '!!!' + } +} + +reload_init() { + [ -x /etc/init.d/$2 ] && /etc/init.d/$2 enabled && { + echo "Reloading $1... " + /etc/init.d/$2 reload >/dev/null 2>&1 + [ -n "$3" -a "$?" != "$3" ] && echo '!!! Failed to reload' $1 '!!!' + } +} + +config_load ucitrack + +for i in $* +do + config_foreach apply_config $i $i +done diff --git a/openwrt/packages/luci/libs/uvl/Makefile b/openwrt/packages/luci/libs/uvl/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.lua b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.lua new file mode 100644 index 0000000..7962161 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.lua @@ -0,0 +1,39 @@ +uvl_err_uciload = 'Fehler beim Laden der Konfiguration \"%p\": %1' +uvl_err_scheme = 'Fehler in Schema \"%p\":\n%c' +uvl_err_config = 'Fehler in Konfiguration \"%p\":\n%c' +uvl_err_section = 'Fehler in Sektion \"%i\" (%I):\n%c' +uvl_err_option = 'Fehler in Option \"%i\" (%I):\n%c' +uvl_err_reference = 'Option \"%i\" hat eine ungültige Referenz-Spezifikation %1:\n%c' +uvl_err_dependency = 'Nicht erfüllte Abhängigkeiten in %t \"%i\":\n%c' +uvl_err_sme_find = 'Schema \"%p\" nicht in Verzeichnis \"%1\" gefunden' +uvl_err_sme_read = 'Fehlende Dateizugriffsrechte auf \"%1\"' +uvl_err_sme_reqfld = 'Notwendiges Feld \"%1\" fehlt in Schema \"%i\"' +uvl_err_sme_invref = 'Ungültige Referenz \"%1\" verweist auf eine anonyme Sektion' +uvl_err_sme_badref = 'Syntaxfehler in Referenzspezifikation \"%1\"' +uvl_err_sme_baddep = 'Syntaxfehler in Abhängigkeitsbeschreibung \"%1\" von \"%i\"' +uvl_err_sme_badval = 'Syntaxfehler in Validatorspezifikation \"%1\" von \"%i\"' +uvl_err_sme_errval = 'Fehler in externem Validator \"%1\": %2' +uvl_err_sme_vbadpack = 'Option \"%o\" in Schema \"%p\" referenziert unbekanntes Paket \"%1\"' +uvl_err_sme_vbadsect = 'Option \"%o\" in Schema \"%p\" referenziert unbekannte Sektion \"%1\"' +uvl_err_sme_ebadpack = 'Aufzählung \"%v\" in Schema \"%p\" referenziert unbekanntes Paket \"%1\"' +uvl_err_sme_ebadsect = 'Aufzählung \"%v\" in Schema \"%p\" referenziert unbekannte Sektion \"%1\"' +uvl_err_sme_ebadopt = 'Aufzählung \"%v\" in Schema \"%p\" referenziert unbekannte Option \"%1\"' +uvl_err_sme_ebadtype = 'Aufzählung \"%v\" in Schema \"%p\" referenziert Nicht-Aufzählungs-Option \"%p.%s.%o\"' +uvl_err_sme_ebaddef = 'Aufzählung \"%v\" in Schema \"%p\" überschreibt den Standardwert von \"%p.%s.%o\"' +uvl_err_sect_unknown = 'Sektion \"%i\" (%I) nicht in Schema gefunden' +uvl_err_sect_required = 'Benötigte Sektion vom Typ \"%I\" nicht in Konfiguration gefunden' +uvl_err_sect_unique = 'Einzigartige Sektion \"%i\" (%I) kommt mehrfach in der Konfiguration vor' +uvl_err_sect_named = 'Die Sektion vom Typ \"%I\" ist anonym in der Konfiguration gespeichert, muss aber einen Namen haben' +uvl_err_sect_notfound = 'Sektion vom Typ \"%I\" nicht in der Konfiguration gefunden' +uvl_err_opt_unknown = 'Option \"%i\" (%I) nicht im Schema gefunden' +uvl_err_opt_required = 'Die benötigte Option \"%i\" hat keinen Wert gesetzt' +uvl_err_opt_badvalue = 'Der Wert \"%1\" von Option \"%i\" ist nicht in der Aufzählung %2 definiert' +uvl_err_opt_invvalue = 'Der Wert \"%1\" von Option \"%i\" ist kein gültiger \"%2\" Datentyp' +uvl_err_opt_notlist = 'Option \"%i\" ist als Liste definiert aber als einfache Option gespeichert' +uvl_err_opt_datatype = 'Option \"%i\" hat unbekannten Datentyp \"%1\"' +uvl_err_opt_notfound = 'Option \"%i\" nicht in der Konfiguration gefunden' +uvl_err_dep_notequal = 'Abhängigkeit (%1) nicht erfüllt:\nOption \"%i\" ist nicht \"%2\"' +uvl_err_dep_novalue = 'Abhängigkeit (%1) nicht erfüllt:\nOption \"%i\" hat keinen Wert gesetzt' +uvl_err_dep_notvalid = 'Abhängigkeit (%1) nicht erfüllt:\n%c' +uvl_err_dep_recursive = 'Rekursive Abhängkeit in Option \"%i\" gefunden' +uvl_err_dep_badenum = 'Nicht erfüllte Abhängigkeiten in Aufzählung \"%i\":\n%c' diff --git a/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.xml b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.xml new file mode 100644 index 0000000..9d6ddee --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.de.xml @@ -0,0 +1,45 @@ + + + + +Fehler beim Laden der Konfiguration "%p": %1 +Fehler in Schema "%p": %c +Fehler in Konfiguration "%p": %c +Fehler in Sektion "%i" (%I): %c +Fehler in Option "%i" (%I): %c +Option "%i" hat eine ungültige Referenz-Spezifikation %1: %c +Nicht erfüllte Abhängigkeiten in %t "%i": %c +Schema "%p" nicht in Verzeichnis "%1" gefunden +Fehlende Dateizugriffsrechte auf "%1" +Notwendiges Feld "%1" fehlt in Schema "%i" +Ungültige Referenz "%1" verweist auf eine anonyme Sektion +Syntaxfehler in Referenzspezifikation "%1" +Syntaxfehler in Abhängigkeitsbeschreibung "%1" von "%i" +Syntaxfehler in Validatorspezifikation "%1" von "%i" +Fehler in externem Validator "%1": %2 +Option "%o" in Schema "%p" referenziert unbekanntes Paket "%1" +Option "%o" in Schema "%p" referenziert unbekannte Sektion "%1" +Aufzählung "%v" in Schema "%p" referenziert unbekanntes Paket "%1" +Aufzählung "%v" in Schema "%p" referenziert unbekannte Sektion "%1" +Aufzählung "%v" in Schema "%p" referenziert unbekannte Option "%1" +Aufzählung "%v" in Schema "%p" referenziert Nicht-Aufzählungs-Option "%p.%s.%o" +Aufzählung "%v" in Schema "%p" überschreibt den Standardwert von "%p.%s.%o" +Sektion "%i" (%I) nicht in Schema gefunden +Benötigte Sektion vom Typ "%I" nicht in Konfiguration gefunden +Einzigartige Sektion "%i" (%I) kommt mehrfach in der Konfiguration vor +Die Sektion vom Typ "%I" ist anonym in der Konfiguration gespeichert, muss aber einen Namen haben +Sektion vom Typ "%I" nicht in der Konfiguration gefunden +Option "%i" (%I) nicht im Schema gefunden +Die benötigte Option "%i" hat keinen Wert gesetzt +Der Wert "%1" von Option "%i" ist nicht in der Aufzählung %2 definiert +Der Wert "%1" von Option "%i" ist kein gültiger "%2" Datentyp +Option "%i" ist als Liste definiert aber als einfache Option gespeichert +Option "%i" hat unbekannten Datentyp "%1" +Option "%i" nicht in der Konfiguration gefunden +Abhängigkeit (%1) nicht erfüllt: Option "%i" ist nicht "%2" +Abhängigkeit (%1) nicht erfüllt: Option "%i" hat keinen Wert gesetzt +Abhängigkeit (%1) nicht erfüllt: %c +Rekursive Abhängkeit in Option "%i" gefunden +Nicht erfüllte Abhängigkeiten in Aufzählung "%i": %c + + diff --git a/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.lua b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.lua new file mode 100644 index 0000000..b0944a2 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.lua @@ -0,0 +1,39 @@ +uvl_err_uciload = 'Unable to load config \"%p\": %1' +uvl_err_scheme = 'Error in scheme \"%p\":\n%c' +uvl_err_config = 'Error in config \"%p\":\n%c' +uvl_err_section = 'Error in section \"%i\" (%I):\n%c' +uvl_err_option = 'Error in option \"%i\" (%I):\n%c' +uvl_err_reference = 'Option \"%i\" has invalid reference specification %1:\n%c' +uvl_err_dependency = 'In dependency check for %t \"%i\":\n%c' +uvl_err_sme_find = 'Can not find scheme \"%p\" in \"%1\"' +uvl_err_sme_read = 'Can not access file \"%1\"' +uvl_err_sme_reqfld = 'Missing required scheme field \"%1\" in \"%i\"' +uvl_err_sme_invref = 'Illegal reference \"%1\" to an anonymous section' +uvl_err_sme_badref = 'Malformed reference in \"%1\"' +uvl_err_sme_baddep = 'Malformed dependency specification \"%1\" in \"%i\"' +uvl_err_sme_badval = 'Malformed validator specification \"%1\" in \"%i\"' +uvl_err_sme_errval = 'External validator \"%1\" failed: %2' +uvl_err_sme_vbadpack = 'Variable \"%o\" in scheme \"%p\" references unknown package \"%1\"' +uvl_err_sme_vbadsect = 'Variable \"%o\" in scheme \"%p\" references unknown section \"%1\"' +uvl_err_sme_ebadpack = 'Enum \"%v\" in scheme \"%p\" references unknown package \"%1\"' +uvl_err_sme_ebadsect = 'Enum \"%v\" in scheme \"%p\" references unknown section \"%1\"' +uvl_err_sme_ebadopt = 'Enum \"%v\" in scheme \"%p\" references unknown option \"%1\"' +uvl_err_sme_ebadtype = 'Enum \"%v\" in scheme \"%p\" references non-enum option \"%p.%s.%o\"' +uvl_err_sme_ebaddef = 'Enum \"%v\" in scheme \"%p\" redeclares the default value of \"%p.%s.%o\"' +uvl_err_sect_unknown = 'Section \"%i\" (%I) not found in scheme' +uvl_err_sect_required = 'Required section \"%p.%s\" not found in config' +uvl_err_sect_unique = 'Unique section \"%p.%s\" occurs multiple times in config' +uvl_err_sect_named = 'The section of type \"%p.%s\" is stored anonymously in config but must be named' +uvl_err_sect_notfound = 'Section \"%p.%s\" not found in config' +uvl_err_opt_unknown = 'Option \"%i\" (%I) not found in scheme' +uvl_err_opt_required = 'Required option \"%i\" has no value' +uvl_err_opt_badvalue = 'Value \"%1\" of option \"%i\" is not defined in enum %2' +uvl_err_opt_invvalue = 'Value \"%1\" of option \"%i\" does not validate as datatype \"%2\"' +uvl_err_opt_notlist = 'Option \"%i\" is defined as list but stored as plain value' +uvl_err_opt_datatype = 'Option \"%i\" has unknown datatype \"%1\"' +uvl_err_opt_notfound = 'Option \"%p.%s.%o\" not found in config' +uvl_err_dep_notequal = 'Dependency (%1) failed:\noption \"%i\" is not eqal \"%2\"' +uvl_err_dep_novalue = 'Dependency (%1) failed:\noption \"%i\" has no value' +uvl_err_dep_notvalid = 'Dependency (%1) failed:\n%c' +uvl_err_dep_recursive = 'Recursive dependency for option \"%i\" detected' +uvl_err_dep_badenum = 'In dependency check for enum value \"%i\":\n%c' diff --git a/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.xml b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.xml new file mode 100644 index 0000000..e26f947 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.en.xml @@ -0,0 +1,45 @@ + + + + +Unable to load config "%p": %1 +Error in scheme "%p": %c +Error in config "%p": %c +Error in section "%i" (%I): %c +Error in option "%i" (%I): %c +Option "%i" has invalid reference specification %1: %c +In dependency check for %t "%i": %c +Can not find scheme "%p" in "%1" +Can not access file "%1" +Missing required scheme field "%1" in "%i" +Illegal reference "%1" to an anonymous section +Malformed reference in "%1" +Malformed dependency specification "%1" in "%i" +Malformed validator specification "%1" in "%i" +External validator "%1" failed: %2 +Variable "%o" in scheme "%p" references unknown package "%1" +Variable "%o" in scheme "%p" references unknown section "%1" +Enum "%v" in scheme "%p" references unknown package "%1" +Enum "%v" in scheme "%p" references unknown section "%1" +Enum "%v" in scheme "%p" references unknown option "%1" +Enum "%v" in scheme "%p" references non-enum option "%p.%s.%o" +Enum "%v" in scheme "%p" redeclares the default value of "%p.%s.%o" +Section "%i" (%I) not found in scheme +Required section "%p.%s" not found in config +Unique section "%p.%s" occurs multiple times in config +The section of type "%p.%s" is stored anonymously in config but must be named +Section "%p.%s" not found in config +Option "%i" (%I) not found in scheme +Required option "%i" has no value +Value "%1" of option "%i" is not defined in enum %2 +Value "%1" of option "%i" does not validate as datatype "%2" +Option "%i" is defined as list but stored as plain value +Option "%i" has unknown datatype "%1" +Option "%p.%s.%o" not found in config +Dependency (%1) failed: option "%i" is not eqal "%2" +Dependency (%1) failed: option "%i" has no value +Dependency (%1) failed: %c +Recursive dependency for option "%i" detected +In dependency check for enum value "%i": %c + + diff --git a/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.lua b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.lua new file mode 100644 index 0000000..baf789a --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.lua @@ -0,0 +1,39 @@ +uvl_err_uciload = 'Não foi possível carregar a configuração \"%p\": %1' +uvl_err_scheme = 'Erro no esquema \"%p\":\n%c' +uvl_err_config = 'Erro na configuração \"%p\":\n%c' +uvl_err_section = 'Erro na seção \"%i\" (%I):\n%c' +uvl_err_option = 'Erro na opção \"%i\" (%I):\n%c' +uvl_err_reference = 'Opção \"%i\" tem especificação de referência inválida %1:\n%c' +uvl_err_dependency = 'Na dependência de verificação %t \"%i\":\n%c' +uvl_err_sme_find = 'Não é possível encontrar o esquema \"%p\" in \"%1\"' +uvl_err_sme_read = 'Não é possível acessar o arquivo \"%1\"' +uvl_err_sme_reqfld = 'Faltando campo requerido no esquema: \"%1\" em \"%i\"' +uvl_err_sme_invref = 'Referência \"1%\" ilegal para uma seção anônima' +uvl_err_sme_badref = 'Referência mal elaborada em \"%1\"' +uvl_err_sme_baddep = 'Especificação de dependência mal elaborada: \"%1\" em \"%i\"' +uvl_err_sme_badval = 'Especificação de validador mal elaborada: \"%1\" em \"%i\"' +uvl_err_sme_errval = 'Validador externo \"%1\" falhou: %2' +uvl_err_sme_vbadpack = 'Variável \"%o\" no esquema \"%p\" faz referência para um pacote desconecido \"%1\"' +uvl_err_sme_vbadsect = 'Variável \"%o\" no esquema \"%p\" faz referência para uma seção desconecida \"%1\"' +uvl_err_sme_ebadpack = 'Enum \"%v\" no esquema \"%p\" faz referência para um pacote desconecido \"%1\"' +uvl_err_sme_ebadsect = 'Enum \"%v\" no esquema \"%p\" faz referência para uma seção desconecida \"%1\"' +uvl_err_sme_ebadopt = 'Enum \"%v\" no esquema \"%p\" faz referência para uma opção desconecida \"%1\"' +uvl_err_sme_ebadtype = 'Enum \"%v\" no esquema \"%p\" faz referência para uma opção não-enum \"%p.%s.%o\"' +uvl_err_sme_ebaddef = 'Enum \"%v\" no esquema \"%p\" redeclara o valor padrão de \"%p.%s.%o\"' +uvl_err_sect_unknown = 'Seção \"%i\" (%I) não encontrada no esquema' +uvl_err_sect_required = 'Seção requerida \"%p.%s\" não encontrada na configuração' +uvl_err_sect_unique = 'Seção única \"%p.%s\" ocorre várias vezes na configuração' +uvl_err_sect_named = 'A seção do tipo \"%p.%s\" está armazenada na configuração como anônima, mas deve ser nomeada' +uvl_err_sect_notfound = 'Seção \"%p.%s\" não encontrada na configuração' +uvl_err_opt_unknown = 'Opção \"%i\" (%I) não encontrada no esquema' +uvl_err_opt_required = 'Opção requerida \"%i\" não tem nenhum valor' +uvl_err_opt_badvalue = 'Valor \"%1\" da opção \"%i\" não está definido no enum %2' +uvl_err_opt_invvalue = 'Valor \"%1\" da opção \"%i\" não foi validado como tipo de dados \"%2\"' +uvl_err_opt_notlist = 'Opção \"%i\" está definida como lista, mas armazenada como um valor simples' +uvl_err_opt_datatype = 'Opção \"%i\" tem o tipo de dados desconhecido \"%1\"' +uvl_err_opt_notfound = 'Opção \"%p.%s.%o\" não encontrada na configuração' +uvl_err_dep_notequal = 'Dependência (%1) falhou:\nopção \"%i\" is not eqal à \"%2\"' +uvl_err_dep_novalue = 'Dependência (%1) falhou:\nopção \"%i\" não tem nenhum valor' +uvl_err_dep_notvalid = 'Dependência (%1) falhou:\n%c' +uvl_err_dep_recursive = 'Dependência recursiva para a opção \"%i\" detectada' +uvl_err_dep_badenum = 'Na dependência, verificar pelo valor enum \"%i\":\n%c' diff --git a/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.xml b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.xml new file mode 100644 index 0000000..a209fed --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/i18n/uvl.pt-br.xml @@ -0,0 +1,45 @@ + + + + +Não foi possível carregar a configuração "%p": %1 +Erro no esquema "%p": %c +Erro na configuração "%p": %c +Erro na seção "%i" (%I): %c +Erro na opção "%i" (%I): %c +Opção "%i" tem especificação de referência inválida %1: %c +Na dependência de verificação %t "%i": %c +Não é possível encontrar o esquema "%p" in "%1" +Não é possível acessar o arquivo "%1" +Faltando campo requerido no esquema: "%1" em "%i" +Referência "1%" ilegal para uma seção anônima +Referência mal elaborada em "%1" +Especificação de dependência mal elaborada: "%1" em "%i" +Especificação de validador mal elaborada: "%1" em "%i" +Validador externo "%1" falhou: %2 +Variável "%o" no esquema "%p" faz referência para um pacote desconecido "%1" +Variável "%o" no esquema "%p" faz referência para uma seção desconecida "%1" +Enum "%v" no esquema "%p" faz referência para um pacote desconecido "%1" +Enum "%v" no esquema "%p" faz referência para uma seção desconecida "%1" +Enum "%v" no esquema "%p" faz referência para uma opção desconecida "%1" +Enum "%v" no esquema "%p" faz referência para uma opção não-enum "%p.%s.%o" +Enum "%v" no esquema "%p" redeclara o valor padrão de "%p.%s.%o" +Seção "%i" (%I) não encontrada no esquema +Seção requerida "%p.%s" não encontrada na configuração +Seção única "%p.%s" ocorre várias vezes na configuração +A seção do tipo "%p.%s" está armazenada na configuração como anônima, mas deve ser nomeada +Seção "%p.%s" não encontrada na configuração +Opção "%i" (%I) não encontrada no esquema +Opção requerida "%i" não tem nenhum valor +Valor "%1" da opção "%i" não está definido no enum %2 +Valor "%1" da opção "%i" não foi validado como tipo de dados "%2" +Opção "%i" está definida como lista, mas armazenada como um valor simples +Opção "%i" tem o tipo de dados desconhecido "%1" +Opção "%p.%s.%o" não encontrada na configuração +Dependência (%1) falhou: opção "%i" is not eqal à "%2" +Dependência (%1) falhou: opção "%i" não tem nenhum valor +Dependência (%1) falhou: %c +Dependência recursiva para a opção "%i" detectada +Na dependência, verificar pelo valor enum "%i": %c + + diff --git a/openwrt/packages/luci/libs/uvl/luasrc/uvl.lua b/openwrt/packages/luci/libs/uvl/luasrc/uvl.lua new file mode 100644 index 0000000..1eed5e0 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/uvl.lua @@ -0,0 +1,1209 @@ +--[[ + +UCI Validation Layer - Main Library +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: uvl.lua 4087 2009-01-18 00:02:52Z jow $ + +]]-- + + +--- UVL - UCI Validation Layer +-- @class module +-- @cstyle instance + +local fs = require "luci.fs" +local uci = require "luci.model.uci" +local util = require "luci.util" +local table = require "table" +local string = require "string" + +local require, pcall, ipairs, pairs = require, pcall, ipairs, pairs +local type, error, tonumber, tostring = type, error, tonumber, tostring +local unpack, loadfile = unpack, loadfile + +module "luci.uvl" + +local ERR = require "luci.uvl.errors" +local datatypes = require "luci.uvl.datatypes" +local validation = require "luci.uvl.validation" +local dependencies = require "luci.uvl.dependencies" + +local TYPE_SCHEME = 0x00 +local TYPE_CONFIG = 0x01 +local TYPE_SECTION = 0x02 +local TYPE_OPTION = 0x03 +local TYPE_ENUM = 0x04 + +--- Boolean; default true; +-- treat sections found in config but not in scheme as error +STRICT_UNKNOWN_SECTIONS = true + +--- Boolean; default true; +-- treat options found in config but not in scheme as error +STRICT_UNKNOWN_OPTIONS = true + +--- Boolean; default true; +-- treat failed external validators as error +STRICT_EXTERNAL_VALIDATORS = true + +--- Boolean; default true; +-- treat list values stored as options like errors +STRICT_LIST_TYPE = true + + +local default_schemedir = "/lib/uci/schema" +local default_savedir = "/tmp/.uvl" + + +--- Object constructor +-- @class function +-- @name UVL +-- @param schemedir Path to the scheme directory (optional) +-- @param configdir Override config directory (optional) +-- @return Instance object +UVL = util.class() + +function UVL.__init__( self, schemedir, configdir ) + self.schemedir = schemedir or default_schemedir + self.configdir = configdir + self.packages = { } + self.beenthere = { } + self.depseen = { } + self.uci = uci + self.err = ERR + self.dep = dependencies + self.datatypes = datatypes +end + + +--- Parse given scheme and return the scheme tree. +-- @param scheme Name of the scheme to parse +-- @return Table containing the parsed scheme or nil on error +-- @return String containing the reason for errors (if any) +function UVL.get_scheme( self, scheme ) + if not self.packages[scheme] then + local ok, err = self:read_scheme( scheme ) + if not ok then + return nil, err + end + end + return self.packages[scheme], nil +end + +--- Validate given configuration, section or option. +-- @param config Name of the configuration to validate +-- @param section Name of the section to validate (optional) +-- @param option Name of the option to validate (optional) +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate( self, config, section, option ) + if config and section and option then + return self:validate_option( config, section, option ) + elseif config and section then + return self:validate_section( config, section ) + elseif config then + return self:validate_config( config ) + end +end + +--- Validate given configuration. +-- @param cfg Name of the configuration to validate +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate_config( self, cfg, uci ) + + if not self.packages[cfg] then + local ok, err = self:read_scheme(cfg) + if not ok then + return false, err + end + end + + local co = config( self, uci or cfg, uci and cfg ) + local sc = { } + + self.beenthere = { } + self.depseen = { } + + if not co:config() then + return false, co:errors() + end + + local function _uci_foreach( type, func ) + for k, v in pairs(co:config()) do + if v['.type'] == type then + sc[type] = sc[type] + 1 + local ok, err = func( k, v ) + if not ok then co:error(err) end + end + end + end + + for k, v in pairs( self.packages[cfg].sections ) do + sc[k] = 0 + _uci_foreach( k, + function(s) + return self:_validate_section( co:section(s) ) + end + ) + end + + if STRICT_UNKNOWN_SECTIONS then + for k, v in pairs(co:config()) do + local so = co:section(k) + if not self.beenthere[so:cid()] then + co:error(ERR.SECT_UNKNOWN(so)) + end + end + end + + for _, k in ipairs(util.keys(sc)) do + local so = co:section(k) + if so:scheme('required') and sc[k] == 0 then + co:error(ERR.SECT_REQUIRED(so)) + elseif so:scheme('unique') and sc[k] > 1 then + co:error(ERR.SECT_UNIQUE(so)) + end + end + + return co:ok(), co:errors() +end + +--- Validate given config section. +-- @param config Name of the configuration to validate +-- @param section Name of the section to validate +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate_section( self, cfg, section, uci ) + + if not self.packages[cfg] then + local ok, err = self:read_scheme( cfg ) + if not ok then + return false, err + end + end + + local co = config( self, uci or cfg, uci and cfg ) + local so = co:section( section ) + + self.beenthere = { } + self.depseen = { } + + if not co:config() then + return false, co:errors() + end + + if so:config() then + return self:_validate_section( so ) + else + return false, ERR.SECT_NOTFOUND(so) + end +end + +--- Validate given config option. +-- @param config Name of the configuration to validate +-- @param section Name of the section to validate +-- @param option Name of the option to validate +-- @return Boolean indicating whether the given config validates +-- @return String containing the reason for errors (if any) +function UVL.validate_option( self, cfg, section, option, uci ) + + if not self.packages[cfg] then + local ok, err = self:read_scheme( cfg ) + if not ok then + return false, err + end + end + + local co = config( self, uci or cfg, uci and cfg ) + local so = co:section( section ) + local oo = so:option( option ) + + if not co:config() then + return false, co:errors() + end + + if so:config() and oo:config() then + return self:_validate_option( oo ) + else + return false, ERR.OPT_NOTFOUND(oo) + end +end + + +function UVL._validate_section( self, section ) + + self.beenthere[section:cid()] = true + + if section:config() then + if section:scheme('named') == true and + section:config('.anonymous') == true + then + return false, ERR.SECT_NAMED(section) + end + + for _, v in ipairs(section:variables()) do + local ok, err = self:_validate_option( v ) + if not ok and ( + v:scheme('required') or v:scheme('type') == "enum" or ( + not err:is(ERR.ERR_DEP_NOTEQUAL) and + not err:is(ERR.ERR_DEP_NOVALUE) + ) + ) then + section:error(err) + end + end + + local ok, err = dependencies.check( self, section ) + if not ok then + section:error(err) + end + else + return false, ERR.SECT_NOTFOUND(section) + end + + if STRICT_UNKNOWN_OPTIONS and not section:scheme('dynamic') then + for k, v in pairs(section:config()) do + local oo = section:option(k) + if k:sub(1,1) ~= "." and not self.beenthere[oo:cid()] then + section:error(ERR.OPT_UNKNOWN(oo)) + end + end + end + + return section:ok(), section:errors() +end + +function UVL._validate_option( self, option, nodeps ) + + self.beenthere[option:cid()] = true + + if not option:scheme() and not option:parent():scheme('dynamic') then + if STRICT_UNKNOWN_OPTIONS then + return false, option:error(ERR.OPT_UNKNOWN(option)) + else + return true + end + + elseif option:scheme() then + if not nodeps then + local ok, err = dependencies.check( self, option ) + if not ok then + if not err:is_all( + ERR.ERR_OPT_REQUIRED, + ERR.ERR_DEP_NOTEQUAL, + ERR.ERR_DEP_NOVALUE + ) then + option:error(err) + return false, option:errors() + else + return true + end + end + end + + if option:scheme('required') and not option:value() then + return false, option:error(ERR.OPT_REQUIRED(option)) + + elseif option:value() then + local val = option:value() + + if option:scheme('type') == "reference" or + option:scheme('type') == "enum" + then + local scheme_values = option:scheme('values') or { } + local config_values = ( type(val) == "table" and val or { val } ) + for _, v in ipairs(config_values) do + if not scheme_values[v] then + return false, option:error( ERR.OPT_BADVALUE( + option, { v, util.serialize_data( + util.keys(scheme_values) + ) } + ) ) + end + end + elseif option:scheme('type') == "list" then + if type(val) ~= "table" and STRICT_LIST_TYPE then + return false, option:error(ERR.OPT_NOTLIST(option)) + end + end + + if option:scheme('datatype') then + local dt = option:scheme('datatype') + + if self.datatypes[dt] then + val = ( type(val) == "table" and val or { val } ) + for i, v in ipairs(val) do + if not self.datatypes[dt]( v ) then + return false, option:error( + ERR.OPT_INVVALUE(option, { v, dt }) + ) + end + end + else + return false, option:error(ERR.OPT_DATATYPE(option, dt)) + end + end + + val = ( type(val) == "table" and val or { val } ) + for _, v in ipairs(val) do + if option:scheme('minlength') then + if #v < option:scheme('minlength') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + if option:scheme('maxlength') then + if #v > option:scheme('maxlength') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + local w = tonumber(v) + + if option:scheme('minimum') then + if not w or w < option:scheme('minimum') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + if option:scheme('maximum') then + if not w or w > option:scheme('maximum') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + end + end + + local ok, err = validation.check( self, option ) + if not ok and STRICT_EXTERNAL_VALIDATORS then + return false, option:error(err) + end + end + + return option:ok(), option:errors() +end + +--- Find all parts of given scheme and construct validation tree. +-- This is normally done on demand, so you don't have to call this function +-- by yourself. +-- @param shm Name of the scheme to parse +-- @param alias Create an alias for the loaded scheme +function UVL.read_scheme( self, shm, alias ) + + local so = scheme( self, shm ) + local bc = "%s/bytecode/%s.lua" %{ self.schemedir, shm } + + if not fs.access(bc) then + local files = fs.glob(self.schemedir .. '/*/' .. shm) + + if files then + local ok, err + for i, file in ipairs( files ) do + if not fs.access(file) then + return false, so:error(ERR.SME_READ(so,file)) + end + + local uci = uci.cursor( fs.dirname(file), default_savedir ) + + local sname = fs.basename(file) + local sd, err = uci:load( sname ) + + if not sd then + return false, ERR.UCILOAD(so, err) + end + + ok, err = pcall(function() + uci:foreach(sname, "package", function(s) + self:_parse_package(so, s[".name"], s) + end) + uci:foreach(sname, "section", function(s) + self:_parse_section(so, s[".name"], s) + end) + uci:foreach(sname, "variable", function(s) + self:_parse_var(so, s[".name"], s) + end) + uci:foreach(sname, "enum", function(s) + self:_parse_enum(so, s[".name"], s) + end) + + end) + end + + if ok and alias then self.packages[alias] = self.packages[shm] end + return ok and self, err + else + return false, so:error(ERR.SME_FIND(so, self.schemedir)) + end + else + local sc = loadfile(bc) + if sc then + self.packages[shm] = sc() + return true + else + return false, so:error(ERR.SME_READ(so,bc)) + end + end +end + +-- helper function to check for required fields +local function _req( t, n, c, r ) + for i, v in ipairs(r) do + if not c[v] then + local p, o = scheme:sid(), nil + + if t == TYPE_SECTION then + o = section( scheme, nil, p, n ) + elseif t == TYPE_OPTION then + o = option( scheme, nil, p, '(nil)', n ) + elseif t == TYPE_ENUM then + o = enum( scheme, nil, p, '(nil)', '(nil)', n ) + end + + return false, ERR.SME_REQFLD(o,v) + end + end + return true +end + +-- helper function to validate references +local function _ref( c, t ) + local r, k, n = {} + if c == TYPE_SECTION then + k = "package" + n = 1 + elseif c == TYPE_OPTION then + k = "section" + n = 2 + elseif c == TYPE_ENUM then + k = "variable" + n = 3 + end + + for o in t[k]:gmatch("[^.]+") do + r[#r+1] = o + end + r[1] = ( #r[1] > 0 and r[1] or scheme:sid() ) + + if #r ~= n then + return false, ERR.SME_BADREF(scheme, k) + end + + return r +end + +-- helper function to read bools +local function _bool( v ) + return ( v == "true" or v == "yes" or v == "on" or v == "1" ) +end + +-- Step 0: get package meta information +function UVL._parse_package(self, scheme, k, v) + local sid = scheme:sid() + local pkg = self.packages[sid] or { + ["name"] = sid; + ["sections"] = { }; + ["variables"] = { }; + } + + pkg.title = v.title + pkg.description = v.description + + self.packages[sid] = pkg +end + +-- Step 1: get all sections +function UVL._parse_section(self, scheme, k, v) + local ok, err = _req( TYPE_SECTION, k, v, { "name", "package" } ) + if err then error(scheme:error(err)) end + + local r, err = _ref( TYPE_SECTION, v ) + if err then error(scheme:error(err)) end + + local p = self.packages[r[1]] or { + ["name"] = r[1]; + ["sections"] = { }; + ["variables"] = { }; + } + p.sections[v.name] = p.sections[v.name] or { } + p.variables[v.name] = p.variables[v.name] or { } + self.packages[r[1]] = p + + local s = p.sections[v.name] + local so = scheme:section(v.name) + + for k, v2 in pairs(v) do + if k ~= "name" and k ~= "package" and k:sub(1,1) ~= "." then + if k == "depends" then + s.depends = self:_read_dependency( v2, s.depends ) + if not s.depends then + return false, scheme:error( + ERR.SME_BADDEP(so, util.serialize_data(s.depends)) + ) + end + elseif k == "dynamic" or k == "unique" or + k == "required" or k == "named" + then + s[k] = _bool(v2) + else + s[k] = v2 + end + end + end + + s.dynamic = s.dynamic or false + s.unique = s.unique or false + s.required = s.required or false + s.named = s.named or false +end + +-- Step 2: get all variables +function UVL._parse_var(self, scheme, k, v) + local ok, err = _req( TYPE_OPTION, k, v, { "name", "section" } ) + if err then error(scheme:error(err)) end + + local r, err = _ref( TYPE_OPTION, v ) + if err then error(scheme:error(err)) end + + local p = self.packages[r[1]] + if not p then + error(scheme:error( + ERR.SME_VBADPACK({scheme:sid(), '', v.name}, r[1]) + )) + end + + local s = p.variables[r[2]] + if not s then + error(scheme:error( + ERR.SME_VBADSECT({scheme:sid(), '', v.name}, r[2]) + )) + end + + s[v.name] = s[v.name] or { } + + local t = s[v.name] + local so = scheme:section(r[2]) + local to = so:option(v.name) + + for k, v2 in pairs(v) do + if k ~= "name" and k ~= "section" and k:sub(1,1) ~= "." then + if k == "depends" then + t.depends = self:_read_dependency( v2, t.depends ) + if not t.depends then + error(scheme:error(so:error( + ERR.SME_BADDEP(to, util.serialize_data(v2)) + ))) + end + elseif k == "validator" then + t.validators = self:_read_validator( v2, t.validators ) + if not t.validators then + error(scheme:error(so:error( + ERR.SME_BADVAL(to, util.serialize_data(v2)) + ))) + end + elseif k == "valueof" then + local values, err = self:_read_reference( v2 ) + if err then + error(scheme:error(so:error( + ERR.REFERENCE(to, util.serialize_data(v2)):child(err) + ))) + end + t.type = "reference" + t.values = values + t.valueof = type(v2) == "table" and v2 or {v2} + elseif k == "required" then + t[k] = _bool(v2) + elseif k == "minlength" or k == "maxlength" or + k == "minimum" or k == "maximum" + then + t[k] = tonumber(v2) + else + t[k] = t[k] or v2 + end + end + end + + t.type = t.type or "variable" + t.datatype = t.datatype or "string" + t.required = t.required or false +end + +-- Step 3: get all enums +function UVL._parse_enum(self, scheme, k, v) + local ok, err = _req( TYPE_ENUM, k, v, { "value", "variable" } ) + if err then error(scheme:error(err)) end + + local r, err = _ref( TYPE_ENUM, v ) + if err then error(scheme:error(err)) end + + local p = self.packages[r[1]] + if not p then + error(scheme:error( + ERR.SME_EBADPACK({scheme:sid(), '', '', v.value}, r[1]) + )) + end + + local s = p.variables[r[2]] + if not s then + error(scheme:error( + ERR.SME_EBADSECT({scheme:sid(), '', '', v.value}, r[2]) + )) + end + + local t = s[r[3]] + if not t then + error(scheme:error( + ERR.SME_EBADOPT({scheme:sid(), '', '', v.value}, r[3]) + )) + end + + + local so = scheme:section(r[2]) + local oo = so:option(r[3]) + local eo = oo:enum(v.value) + + if t.type ~= "enum" and t.type ~= "reference" then + error(scheme:error(ERR.SME_EBADTYPE(eo))) + end + + if not t.values then + t.values = { [v.value] = v.title or v.value } + t.valuelist = { {value = v.value, title = v.title} } + else + t.values[v.value] = v.title or v.value + t.valuelist[#t.valuelist + 1] = {value = v.value, title = v.title} + end + + if not t.enum_depends then + t.enum_depends = { } + end + + if v.default then + if t.default then + error(scheme:error(ERR.SME_EBADDEF(eo))) + end + t.default = v.value + end + + if v.depends then + t.enum_depends[v.value] = self:_read_dependency( + v.depends, t.enum_depends[v.value] + ) + + if not t.enum_depends[v.value] then + error(scheme:error(so:error(oo:error( + ERR.SME_BADDEP(eo, util.serialize_data(v.depends)) + )))) + end + end +end + +-- Read a dependency specification +function UVL._read_dependency( self, values, deps ) + local expr = "%$?[%w_]+" + if values then + values = ( type(values) == "table" and values or { values } ) + for _, value in ipairs(values) do + local condition = { } + for val in value:gmatch("[^,]+") do + local k, e, v = val:match("%s*([%w$_.]+)%s*(=?)%s*(.*)") + + if k and ( + k:match("^"..expr.."%."..expr.."%."..expr.."$") or + k:match("^"..expr.."%."..expr.."$") or + k:match("^"..expr.."$") + ) then + condition[k] = (e == '=') and v or true + else + return nil + end + end + + if not deps then + deps = { condition } + else + deps[#deps+1] = condition + end + end + end + + return deps +end + +-- Read a validator specification +function UVL._read_validator( self, values, validators ) + if values then + values = ( type(values) == "table" and values or { values } ) + for _, value in ipairs(values) do + local validator + + if value:match("^exec:") then + validator = value:gsub("^exec:","") + elseif value:match("^lua:") then + validator = self:_resolve_function( (value:gsub("^lua:","") ) ) + elseif value:match("^regexp:") then + local pattern = value:gsub("^regexp:","") + validator = function( type, dtype, pack, sect, optn, ... ) + local values = { ... } + for _, v in ipairs(values) do + local ok, match = + pcall( string.match, v, pattern ) + + if not ok then + return false, match + elseif not match then + return false, + 'Value "%s" does not match pattern "%s"' % { + v, pattern + } + end + end + return true + end + end + + if validator then + if not validators then + validators = { validator } + else + validators[#validators+1] = validator + end + else + return nil + end + end + + return validators + end +end + +-- Read a reference specification (XXX: We should validate external configs too...) +function UVL._read_reference( self, values ) + local val = { } + values = ( type(values) == "table" and values or { values } ) + + for _, value in ipairs(values) do + local ref = util.split(value, ".") + + if #ref == 2 or #ref == 3 then + local co = config( self, ref[1] ) + if not co:config() then return false, co:errors() end + + for k, v in pairs(co:config()) do + if v['.type'] == ref[2] then + if #ref == 2 then + if v['.anonymous'] == true then + return false, ERR.SME_INVREF('', value) + end + val[k] = k -- XXX: title/description would be nice + elseif v[ref[3]] then + val[v[ref[3]]] = v[ref[3]] -- XXX: dito + end + end + end + else + return false, ERR.SME_BADREF('', value) + end + end + + return val, nil +end + +-- Resolve given path +function UVL._resolve_function( self, value ) + local path = util.split(value, ".") + + for i=1, #path-1 do + local stat, mod = pcall( + require, table.concat(path, ".", 1, i) + ) + + if stat and mod then + for j=i+1, #path-1 do + if not type(mod) == "table" then + break + end + mod = mod[path[j]] + if not mod then + break + end + end + mod = type(mod) == "table" and mod[path[#path]] or nil + if type(mod) == "function" then + return mod + end + end + end +end + + +--- Object representation of an uvl item - base class. +uvlitem = util.class() + +function uvlitem.cid(self) + if #self.cref == 1 then + return self.cref[1] + else + local r = { unpack(self.cref) } + local c = self.c + if c and c[r[2]] and c[r[2]]['.anonymous'] and c[r[2]]['.index'] then + r[2] = '@' .. c[r[2]]['.type'] .. + '[' .. tostring(c[r[2]]['.index']) .. ']' + end + return table.concat( r, '.' ) + end +end + +function uvlitem.sid(self) + return table.concat( self.sref, '.' ) +end + +function uvlitem.scheme(self, opt) + local s = self.s and self.s.packages + s = s and s[self.sref[1]] + if #self.sref == 4 or #self.sref == 3 then + s = s and s.variables + s = s and s[self.sref[2]] + s = s and s[self.sref[3]] + elseif #self.sref == 2 then + s = s and s.sections + s = s and s[self.sref[2]] + end + + if s and opt then + return s[opt] + elseif s then + return s + end +end + +function uvlitem.config(self, opt) + local c = self.c + + if #self.cref >= 2 and #self.cref <= 4 then + c = c and self.c[self.cref[2]] or nil + if #self.cref >= 3 then + c = c and c[self.cref[3]] or nil + end + end + + if c and opt then + return c[opt] + elseif c then + return c + end +end + +function uvlitem.title(self) + return self:scheme() and self:scheme('title') or + self.cref[3] or self.cref[2] or self.cref[1] +end + +function uvlitem.type(self) + if self.t == TYPE_CONFIG then + return 'config' + elseif self.t == TYPE_SECTION then + return 'section' + elseif self.t == TYPE_OPTION then + return 'option' + elseif self.t == TYPE_ENUM then + return 'enum' + end +end + +function uvlitem.error(self, ...) + if not self.e then + local errconst = { ERR.CONFIG, ERR.SECTION, ERR.OPTION, ERR.OPTION } + self.e = errconst[#self.cref]( self ) + end + + return self.e:child( ... ) +end + +function uvlitem.errors(self) + return self.e +end + +function uvlitem.ok(self) + return not self:errors() +end + +function uvlitem.parent(self) + if self.p then + return self.p + elseif #self.cref == 3 or #self.cref == 4 then + return section( self.s, self.c, self.cref[1], self.cref[2] ) + elseif #self.cref == 2 then + return config( self.s, self.c, self.cref[1] ) + else + return nil + end +end + +function uvlitem._loadconf(self, co, c, configdir) + co = co or self._configcache + if not co then + local err + co, err = uci.cursor(configdir):get_all(c) + + if err then + self:error(ERR.UCILOAD(self, err)) + end + + self._configcache = co + end + return co +end + + +--- Object representation of a scheme. +-- @class scheme +-- @cstyle instance +-- @name luci.uvl.scheme + +--- Scheme instance constructor. +-- @class function +-- @name scheme +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @return Config instance +scheme = util.class(uvlitem) + +function scheme.__init__(self, scheme, co, c) + if not c then + c, co = co, nil + end + + self.cref = { c } + self.sref = { c } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_SCHEME +end + +--- Add an error to scheme. +-- @return Scheme error context +function scheme.error(self, ...) + if not self.e then self.e = ERR.SCHEME( self ) end + return self.e:child( ... ) +end + +--- Get an associated config object. +-- @return Config instance +function scheme.config(self) + local co = config( self.s, self.cref[1] ) + co.p = self + + return co +end + +--- Get all section objects associated with this scheme. +-- @return Table containing all associated luci.uvl.section instances +function scheme.sections(self) + local v = { } + if self.s.packages[self.sref[1]].sections then + for o, _ in pairs( self.s.packages[self.sref[1]].sections ) do + v[#v+1] = option( + self.s, self.c, self.cref[1], self.cref[2], o + ) + end + end + return v +end + +--- Get an associated section object. +-- @param s Section to select +-- @return Section instance +function scheme.section(self, s) + local so = section( self.s, self.c, self.cref[1], s ) + so.p = self + + return so +end + + +--- Object representation of a config. +-- @class config +-- @cstyle instance +-- @name luci.uvl.config + +--- Config instance constructor. +-- @class function +-- @name config +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @return Config instance +config = util.class(uvlitem) + +function config.__init__(self, scheme, co, c) + if not c then + c, co = co, nil + end + self.cref = { c } + self.sref = { c } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_CONFIG +end + +--- Get all section objects associated with this config. +-- @return Table containing all associated luci.uvl.section instances +function config.sections(self) + local v = { } + if self.s.packages[self.sref[1]].sections then + for o, _ in pairs( self.s.packages[self.sref[1]].sections ) do + v[#v+1] = option( + self.s, self.c, self.cref[1], self.cref[2], o + ) + end + end + return v +end + +--- Get an associated section object. +-- @param s Section to select +-- @return Section instance +function config.section(self, s) + local so = section( self.s, self.c, self.cref[1], s ) + so.p = self + + return so +end + + +--- Object representation of a scheme/config section. +-- @class module +-- @cstyle instance +-- @name luci.uvl.section + +--- Section instance constructor. +-- @class function +-- @name section +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @param s Section name +-- @return Section instance +section = util.class(uvlitem) + +function section.__init__(self, scheme, co, c, s) + self.cref = { c, s } + self.sref = { c, co and co[s] and co[s]['.type'] or s } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_SECTION +end + +--- Get all option objects associated with this section. +-- @return Table containing all associated luci.uvl.option instances +function section.variables(self) + local v = { } + if self.s.packages[self.sref[1]].variables[self.sref[2]] then + for o, _ in pairs( + self.s.packages[self.sref[1]].variables[self.sref[2]] + ) do + v[#v+1] = option( + self.s, self.c, self.cref[1], self.cref[2], o + ) + end + end + return v +end + +--- Get an associated option object. +-- @param o Option to select +-- @return Option instance +function section.option(self, o) + local oo = option( self.s, self.c, self.cref[1], self.cref[2], o ) + oo.p = self + + return oo +end + + +--- Object representation of a scheme/config option. +-- @class module +-- @cstyle instance +-- @name luci.uvl.option + +--- Section instance constructor. +-- @class function +-- @name option +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @param s Section name +-- @param o Option name +-- @return Option instance +option = util.class(uvlitem) + +function option.__init__(self, scheme, co, c, s, o) + self.cref = { c, s, o } + self.sref = { c, co and co[s] and co[s]['.type'] or s, o } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_OPTION +end + +--- Get the value of this option. +-- @return The associated configuration value +function option.value(self) + local v = self:config() or self:scheme('default') + if v and self:scheme('multival') then + v = util.split( v, "%s+", nil, true ) + end + return v +end + +--- Get the associated section information in scheme. +-- @return Table containing the scheme properties +function option.section(self) + return self.s.packages[self.sref[1]].sections[self.sref[2]] +end + +--- Construct an enum object instance from given or default value. +-- @param v Value to select +-- @return Enum instance for selected value +function option.enum(self, val) + return enum( + self.s, self.c, + self.cref[1], self.cref[2], self.cref[3], + val or self:value() + ) +end + + +--- Object representation of a enum value. +-- @class module +-- @cstyle instance +-- @name luci.uvl.enum + +--- Section instance constructor. +-- @class function +-- @name enum +-- @param scheme Scheme instance +-- @param co Configuration data +-- @param c Configuration name +-- @param s Section name +-- @param o Enum name +-- @param v Enum value +-- @return Enum value instance +enum = util.class(option) + +function enum.__init__(self, scheme, co, c, s, o, v) + self.cref = { c, s, o, v } + self.sref = { c, co and co[s] and co[s]['.type'] or s, o, v } + self.c = self:_loadconf(co, c, scheme.configdir) + self.s = scheme + self.t = TYPE_ENUM +end diff --git a/openwrt/packages/luci/libs/uvl/luasrc/uvl/datatypes.lua b/openwrt/packages/luci/libs/uvl/luasrc/uvl/datatypes.lua new file mode 100644 index 0000000..b6aeb2e --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/uvl/datatypes.lua @@ -0,0 +1,187 @@ +--[[ + +UCI Validation Layer - Datatype Tests +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: datatypes.lua 3569 2008-10-12 22:38:30Z jow $ + +]]-- + +local fs = require "luci.fs" +local ip = require "luci.ip" +local math = require "math" +local util = require "luci.util" + +local tonumber = tonumber + +module "luci.uvl.datatypes" + + +function boolean( val ) + if val == "1" or val == "yes" or val == "on" or val == "true" then + return true + elseif val == "0" or val == "no" or val == "off" or val == "false" then + return true + elseif val == "" or val == nil then + return true + end + + return false +end + +function uint( val ) + local n = tonumber(val) + if n ~= nil and math.floor(n) == n and n >= 0 then + return true + end + + return false +end + +function integer( val ) + local n = tonumber(val) + if n ~= nil and math.floor(n) == n then + return true + end + + return false +end + +function float( val ) + return ( tonumber(val) ~= nil ) +end + +function ipaddr( val ) + return ip4addr(val) or ip6addr(val) +end + +function ip4addr( val ) + if val then + return ip.IPv4(val) and true or false + end + + return false +end + +function ip4prefix( val ) + val = tonumber(val) + return ( val and val >= 0 and val <= 32 ) +end + +function ip6addr( val ) + if val then + return ip.IPv6(val) and true or false + end + + return false +end + +function ip6prefix( val ) + val = tonumber(val) + return ( val and val >= 0 and val <= 128 ) +end + +function port( val ) + val = tonumber(val) + return ( val and val >= 1 and val <= 65535 ) +end + +function portrange( val ) + local p1, p2 = val:match("^(%d+)%-(%d+)$") + if p1 and p2 and port(p1) and port(p2) then + return true + else + return port(val) + end +end + +function macaddr( val ) + if val and val:match( + "^[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+:" .. + "[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+$" + ) then + local parts = util.split( val, ":" ) + + for i = 1,6 do + parts[i] = tonumber( parts[i], 16 ) + if parts[i] < 0 or parts[i] > 255 then + return false + end + end + + return true + end + + return false +end + +function hostname( val ) + if val and val:match("[a-zA-Z0-9_][a-zA-Z0-9_%-%.]*") then + return true -- XXX: ToDo: need better solution + end + + return false +end + +function host( val ) + return hostname(val) or ipaddr(val) +end + +function string( val ) + return true -- Everything qualifies as valid string +end + +function directory( val, seen ) + local s = fs.stat( val ) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "directory" then + return true + elseif s.type == "link" then + return directory( fs.readlink(val), seen ) + end + end + + return false +end + +function file( val, seen ) + local s = fs.stat( val ) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "regular" then + return true + elseif s.type == "link" then + return file( fs.readlink(val), seen ) + end + end + + return false +end + +function device( val, seen ) + local s = fs.stat( val ) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "character device" or s.type == "block device" then + return true + elseif s.type == "link" then + return device( fs.readlink(val), seen ) + end + end + + return false +end diff --git a/openwrt/packages/luci/libs/uvl/luasrc/uvl/dependencies.lua b/openwrt/packages/luci/libs/uvl/luasrc/uvl/dependencies.lua new file mode 100644 index 0000000..567b972 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/uvl/dependencies.lua @@ -0,0 +1,196 @@ +--[[ + +UCI Validation Layer - Dependency helper +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: dependencies.lua 3260 2008-09-13 09:09:38Z Cyrus $ + +]]-- + +local uvl = require "luci.uvl" +local ERR = require "luci.uvl.errors" +local util = require "luci.util" +local table = require "table" + +local type, unpack = type, unpack +local ipairs, pairs = ipairs, pairs + +module "luci.uvl.dependencies" + + + +function _parse_reference( r, c, s, o ) + local ref = { } + local vars = { + config = c, + section = s, + option = o + } + + for v in r:gmatch("[^.]+") do + ref[#ref+1] = (v:gsub( "%$(.+)", vars )) + end + + if #ref < 2 then + table.insert(ref, 1, s or '$section') + end + if #ref < 3 then + table.insert(ref, 1, c or '$config') + end + + return ref +end + +function _serialize_dependency( dep, v ) + local str + + for k, v in util.spairs( dep, + function(a,b) + a = ( type(dep[a]) ~= "boolean" and "_" or "" ) .. a + b = ( type(dep[b]) ~= "boolean" and "_" or "" ) .. b + return a < b + end + ) do + str = ( str and str .. " and " or "" ) .. k .. + ( type(v) ~= "boolean" and "=" .. v or "" ) + end + + return str +end + +function check( self, object, nodeps ) + + local derr = ERR.DEPENDENCY(object) + + if not self.depseen[object:cid()] then + self.depseen[object:cid()] = true + else + return false, derr:child(ERR.DEP_RECURSIVE(object)) + end + + if object:scheme('depends') then + local ok = true + local valid = false + + for _, dep in ipairs(object:scheme('depends')) do + local subcondition = true + for k, v in pairs(dep) do + -- XXX: better error + local ref = _parse_reference( k, unpack(object.cref) ) + + if not ref then + return false, derr:child(ERR.SME_BADDEP(object,k)) + end + + local option = uvl.option( self, object.c, unpack(ref) ) + + valid, err = self:_validate_option( option, true ) + if valid then + if not ( + ( type(v) == "boolean" and option:value() ) or + ( ref[3] and option:value() ) == v + ) then + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + derr:child( + type(v) == "boolean" + and ERR.DEP_NOVALUE(option, depstr) + or ERR.DEP_NOTEQUAL(option, {depstr, v}) + ) + + break + end + else + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + derr:child(ERR.DEP_NOTVALID(option, depstr):child(err)) + + break + end + end + + if subcondition then + ok = true + break + else + ok = false + end + end + + if not ok then + return false, derr + end + else + return true + end + + if object:scheme("type") == "enum" and + object:scheme("enum_depends")[object:value()] + then + local ok = true + local valid = false + local enum = object:enum() + local eerr = ERR.DEP_BADENUM(enum) + + for _, dep in ipairs(enum:scheme('enum_depends')[object:value()]) do + local subcondition = true + for k, v in pairs(dep) do + -- XXX: better error + local ref = _parse_reference( k, unpack(object.cref) ) + + if not ref then + return false, derr:child(eerr:child(ERR.SME_BADDEP(enum,k))) + end + + local option = luci.uvl.option( self, object.c, unpack(ref) ) + + valid, err = self:_validate_option( option, true ) + if valid then + if not ( + ( type(v) == "boolean" and object.config[ref[2]][ref[3]] ) or + ( ref[3] and object:config() ) == v + ) then + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + eerr:child( + type(v) == "boolean" + and ERR.DEP_NOVALUE(option, depstr) + or ERR.DEP_NOTEQUAL(option, {depstr, v}) + ) + + break + end + else + subcondition = false + + local depstr = _serialize_dependency( dep, v ) + eerr:child(ERR.DEP_NOTVALID(option, depstr):child(err)) + + break + end + end + + if subcondition then + return true + else + ok = false + end + end + + if not ok then + return false, derr:child(eerr) + end + end + + return true +end diff --git a/openwrt/packages/luci/libs/uvl/luasrc/uvl/errors.lua b/openwrt/packages/luci/libs/uvl/luasrc/uvl/errors.lua new file mode 100644 index 0000000..e2a9f2c --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/uvl/errors.lua @@ -0,0 +1,204 @@ +--[[ + +UCI Validation Layer - Error handling +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: errors.lua 3711 2008-11-04 23:50:14Z jow $ + +]]-- + +local uci = require "luci.model.uci" +local uvl = require "luci.uvl" +local util = require "luci.util" +local string = require "string" + +local ipairs, error, type = ipairs, error, type +local tonumber, unpack = tonumber, unpack + + +local luci = luci + +module "luci.uvl.errors" + +ERRCODES = { + { 'UCILOAD', 'Unable to load config "%p": %1' }, + + { 'SCHEME', 'Error in scheme "%p":\n%c' }, + { 'CONFIG', 'Error in config "%p":\n%c' }, + { 'SECTION', 'Error in section "%i" (%I):\n%c' }, + { 'OPTION', 'Error in option "%i" (%I):\n%c' }, + { 'REFERENCE', 'Option "%i" has invalid reference specification %1:\n%c' }, + { 'DEPENDENCY', 'In dependency check for %t "%i":\n%c' }, + + { 'SME_FIND', 'Can not find scheme "%p" in "%1"' }, + { 'SME_READ', 'Can not access file "%1"' }, + { 'SME_REQFLD', 'Missing required scheme field "%1" in "%i"' }, + { 'SME_INVREF', 'Illegal reference "%1" to an anonymous section' }, + { 'SME_BADREF', 'Malformed reference in "%1"' }, + { 'SME_BADDEP', 'Malformed dependency specification "%1" in "%i"' }, + { 'SME_BADVAL', 'Malformed validator specification "%1" in "%i"' }, + { 'SME_ERRVAL', 'External validator "%1" failed: %2' }, + { 'SME_VBADPACK', 'Variable "%o" in scheme "%p" references unknown package "%1"' }, + { 'SME_VBADSECT', 'Variable "%o" in scheme "%p" references unknown section "%1"' }, + { 'SME_EBADPACK', 'Enum "%v" in scheme "%p" references unknown package "%1"' }, + { 'SME_EBADSECT', 'Enum "%v" in scheme "%p" references unknown section "%1"' }, + { 'SME_EBADOPT', 'Enum "%v" in scheme "%p" references unknown option "%1"' }, + { 'SME_EBADTYPE', 'Enum "%v" in scheme "%p" references non-enum option "%I"' }, + { 'SME_EBADDEF', 'Enum "%v" in scheme "%p" redeclares the default value of "%I"' }, + + { 'SECT_UNKNOWN', 'Section "%i" (%I) not found in scheme' }, + { 'SECT_REQUIRED', 'Required section "%p.%S" not found in config' }, + { 'SECT_UNIQUE', 'Unique section "%p.%S" occurs multiple times in config' }, + { 'SECT_NAMED', 'The section of type "%p.%S" is stored anonymously in config but must be named' }, + { 'SECT_NOTFOUND', 'Section "%p.%s" not found in config' }, + + { 'OPT_UNKNOWN', 'Option "%i" (%I) not found in scheme' }, + { 'OPT_REQUIRED', 'Required option "%i" has no value' }, + { 'OPT_BADVALUE', 'Value "%1" of option "%i" is not defined in enum %2' }, + { 'OPT_INVVALUE', 'Value "%1" of option "%i" does not validate as datatype "%2"' }, + { 'OPT_NOTLIST', 'Option "%i" is defined as list but stored as plain value' }, + { 'OPT_DATATYPE', 'Option "%i" has unknown datatype "%1"' }, + { 'OPT_NOTFOUND', 'Option "%p.%s.%o" not found in config' }, + { 'OPT_RANGE', 'Option "%p.%s.%o" is not within the specified range' }, + + { 'DEP_NOTEQUAL', 'Dependency (%1) failed:\nOption "%i" is not eqal "%2"' }, + { 'DEP_NOVALUE', 'Dependency (%1) failed:\nOption "%i" has no value' }, + { 'DEP_NOTVALID', 'Dependency (%1) failed:\n%c' }, + { 'DEP_RECURSIVE', 'Recursive dependency for option "%i" detected' }, + { 'DEP_BADENUM', 'In dependency check for enum value "%i":\n%c' } +} + +-- build error constants and instance constructors +for i, v in ipairs(ERRCODES) do + _M[v[1]] = function(...) + return error(i, ...) + end + + _M['ERR_'..v[1]] = i +end + + +function i18n(key, def) + if luci.i18n then + return luci.i18n.translate(key,def) + else + return def + end +end + + +error = util.class() + +function error.__init__(self, code, pso, args) + + self.code = code + self.args = ( type(args) == "table" and args or { args } ) + + if util.instanceof( pso, uvl.uvlitem ) then + self.stype = pso.sref[2] + self.package, self.section, self.option, self.value = unpack(pso.cref) + self.object = pso + self.value = self.value or ( pso.value and pso:value() ) + else + pso = ( type(pso) == "table" and pso or { pso } ) + + if pso[2] then + local uci = uci.cursor() + self.stype = uci:get(pso[1], pso[2]) or pso[2] + end + + self.package, self.section, self.option, self.value = unpack(pso) + end +end + +function error.child(self, err) + if not self.childs then + self.childs = { err } + else + self.childs[#self.childs+1] = err + end + return self +end + +function error.string(self,pad) + pad = pad or " " + + local str = i18n( + 'uvl_err_%s' % string.lower(ERRCODES[self.code][1]), + ERRCODES[self.code][2] + ) + :gsub("\n", "\n"..pad) + :gsub("%%i", self:cid()) + :gsub("%%I", self:sid()) + :gsub("%%p", self.package or '(nil)') + :gsub("%%s", self.section or '(nil)') + :gsub("%%S", self.stype or '(nil)') + :gsub("%%o", self.option or '(nil)') + :gsub("%%v", self.value or '(nil)') + :gsub("%%t", self.object and self.object:type() or '(nil)' ) + :gsub("%%T", self.object and self.object:title() or '(nil)' ) + :gsub("%%([1-9])", function(n) return self.args[tonumber(n)] or '(nil)' end) + :gsub("%%c", + function() + local s = "" + for _, err in ipairs(self.childs or {}) do + s = s .. err:string(pad.." ") .. "\n" .. pad + end + return s + end + ) + + return (str:gsub("%s+$","")) +end + +function error.cid(self) + return self.object and self.object:cid() or self.package .. + ( self.section and '.' .. self.section or '' ) .. + ( self.option and '.' .. self.option or '' ) .. + ( self.value and '.' .. self.value or '' ) +end + +function error.sid(self) + return self.object and self.object:sid() or self.package .. + ( self.stype and '.' .. self.stype or '' ) .. + ( self.option and '.' .. self.option or '' ) .. + ( self.value and '.' .. self.value or '' ) +end + +function error.is(self, code) + if self.code == code then + return true + elseif self.childs then + for _, c in ipairs(self.childs) do + if c:is(code) then + return true + end + end + end + return false +end + +function error.is_all(self, ...) + local codes = { ... } + + if util.contains(codes, self.code) then + return true + else + local equal = false + for _, c in ipairs(self.childs) do + if c.childs then + equal = c:is_all(...) + else + equal = util.contains(codes, c.code) + end + end + return equal + end +end diff --git a/openwrt/packages/luci/libs/uvl/luasrc/uvl/validation.lua b/openwrt/packages/luci/libs/uvl/luasrc/uvl/validation.lua new file mode 100644 index 0000000..24f2f0c --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/luasrc/uvl/validation.lua @@ -0,0 +1,72 @@ +--[[ + +UCI Validation Layer - Validation helper +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: validation.lua 3260 2008-09-13 09:09:38Z Cyrus $ + +]]-- + +local os = require "os" +local fs = require "luci.fs" +local sys = require "luci.sys" +local ERR = require "luci.uvl.errors" + +local ipairs, unpack, type, tostring = ipairs, unpack, type, tostring + +module "luci.uvl.validation" + +function _exec( bin, args ) + local cmd, output = "", nil + + for _, v in ipairs({ bin, unpack(args) }) do + cmd = cmd .. ("%q " % v):gsub("([%$`])","\\%1") + end + + local tmpfile = "/tmp/uvl" .. sys.uniqueid(8) + local retval = os.execute( cmd .. " 1>" .. tmpfile .. " 2>" .. tmpfile ) + + if fs.access(tmpfile) then + output = fs.readfile(tmpfile) + fs.unlink(tmpfile) + end + + return retval, output +end + +function check( self, object ) + if object:scheme('validators') then + for _, val in ipairs(object:scheme('validators')) do + local ok, err = false, nil + + local values = object:value() + values = type(values) == "table" and values or { values } + + local args = { + object:scheme('type'), object:scheme('datatype'), + object.cref[1], object.cref[2], object.cref[3] or '', + unpack(values) + } + + if type(val) == "function" then + ok, err = val(unpack(args)) + else + ok, err = _exec( val, args ) + ok = ( ok == 0 ) + end + + if not ok then + return false, ERR.SME_ERRVAL(object, {tostring(val), err}) + end + end + end + + return true, nil +end diff --git a/openwrt/packages/luci/libs/uvl/root/lib/uci/schema/meta/schema b/openwrt/packages/luci/libs/uvl/root/lib/uci/schema/meta/schema new file mode 100644 index 0000000..a2f29aa --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/root/lib/uci/schema/meta/schema @@ -0,0 +1,403 @@ +# UVL - Reference-Spec +# This is a meta scheme defining the format of uci schemes. +# $Id: schema 3709 2008-11-04 21:28:07Z jow $ + +package schema + +#------------------------------------------------------------------------------- +# Central package definition +# +# config package +# option ... +#------------------------------------------------------------------------------- + +# Section definition (schema.@package) +config section + option name 'package' + option title 'Definition of uci package' + option package 'schema' + option required false + option named false + option unique true + option dynamic false + +# Section title (schema.@package.title) +config variable + option name 'title' + option title 'Title of the defined package' + option section 'schema.package' + option type 'variable' + option datatype 'string' + option required false + +# Section description (schema.@package.description) +config variable + option name 'description' + option title 'Description of the defined package' + option section 'schema.package' + option type 'lazylist' + option datatype 'string' + option required false + + +#------------------------------------------------------------------------------- +# Central section definition +# +# config section +# option ... +#------------------------------------------------------------------------------- + +# Section definition (schema.@section) +config section + option name 'section' + option title 'Definition of uci section' + option package 'schema' + option required false + option named false + option unique false + option dynamic false + +# Section name (schema.@section.name) +config variable + option name 'name' + option title 'Name of the defined section' + option section 'schema.section' + option type 'variable' + option datatype 'string' + option required true + +# Section package (schema.@section.package) +config variable + option name 'package' + option title 'Parent package of the defined section' + option section 'schema.section' + option type 'variable' + option datatype 'string' + option required true + +# Section title (schema.@section.title) +config variable + option name 'title' + option title 'Title of the defined section' + option section 'schema.section' + option type 'variable' + option datatype 'string' + option required false + +# Section description (schema.@section.description) +config variable + option name 'description' + option title 'Description of the defined section' + option section 'schema.section' + option type 'lazylist' + option datatype 'string' + option required false + +# Section dependencies (schema.@section.depends) +config variable + option name 'depends' + option title 'List of dependencies within and between defined sections' + option section 'schema.section' + option type 'lazylist' + option datatype 'string' + option required false + +# Section required flag (schema.@section.required) +config variable + option name 'required' + option title 'Specify whether at least one instance of this section type must be defined in config' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + +# Section unique flag (schema.@section.unique) +config variable + option name 'unique' + option title 'Specify whether only one instance of this section type is allowed in config' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + +# Section named flag (schema.@section.named) +config variable + option name 'named' + option title 'Specify whether sections of this type must have a name set (are not anonymous)' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + +# Section dynamic flag (schema.@section.dynamic) +config variable + option name 'dynamic' + option title 'Specify whether sections of this type may contain arbitary, not specified options' + option section 'schema.section' + option type 'variable' + option datatype 'boolean' + option required false + + +#------------------------------------------------------------------------------- +# Central variable definition +# +# config variable +# option ... +#------------------------------------------------------------------------------- + +# Variable definition (schema.@variable) +config section + option name 'variable' + option title 'Definition of uci variable' + option package 'schema' + option required false + option named false + option unique false + option dynamic false + +# Variable name (schema.@variable.name) +config variable + option name 'name' + option title 'Name of the defined variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required true + +# Variable section (schema.@variable.section) +config variable + option name 'section' + option title 'Parent section of the defined variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required true + +# Variable title (schema.@variable.title) +config variable + option name 'title' + option title 'Title of the defined variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required false + +# Variable description (schema.@variable.description) +config variable + option name 'description' + option title 'Description of the defined variable' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + +# Variable dependencies (schema.@variable.depends) +config variable + option name 'depends' + option title 'List of dependencies between defined variables' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + +# Variable required flag (schema.@variable.required) +config variable + option name 'required' + option title 'Specify whether this variable must be set in config' + option section 'schema.variable' + option type 'variable' + option datatype 'boolean' + option required false + +# Variable multiple values flag (schema.@variable.multival) +config variable + option name 'multival' + option title 'Specify whether this variable may contain multiple values separated by space' + option section 'schema.variable' + option type 'variable' + option datatype 'boolean' + option required false + +# Variable type (schema.@variable.type) +config variable + option name 'type' + option title 'Type of this variable' + option section 'schema.variable' + option type 'enum' + option datatype 'string' + option required false + +# Plain variable type (schema.@variable.type=variable) +config enum + option value 'variable' + option title 'This is a plain variable' + option variable 'schema.variable.type' + +# Enum variable type (schema.@variable.type=enum) +config enum + option value 'enum' + option title 'This is a enum variable' + option variable 'schema.variable.type' + +# List variable type (schema.@variable.type=list) +config enum + option value 'list' + option title 'This is a list variable' + option variable 'schema.variable.type' + +# List-or-Option variable type (schema.@variable.type=lazylist) +config enum + option value 'lazylist' + option title 'This is a list or option variable' + option variable 'schema.variable.type' + +# Reference variable type (schema.@variable.type=reference) +config enum + option value 'reference' + option title 'This is a reference (valueof) variable' + option variable 'schema.variable.type' + +# Variable datatype (schema.@variable.datatype) +config variable + option name 'datatype' + option title 'Datatype of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required false + +# Variable default value (schema.@variable.default) +config variable + option name 'default' + option title 'Default value of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'string' + option required false + +# Variable minimum length (schema.@variable.minlength) +config variable + option name 'minlength' + option title 'Minimum length of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'uint' + option required false + +# Variable maximum length (schema.@variable.minlength) +config variable + option name 'maxlength' + option title 'Maximum length of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'uint' + option required false + +# Variable minimum value (schema.@variable.minlength) +config variable + option name 'minimum' + option title 'Minimum value of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'integer' + option required false + +# Variable maximum value (schema.@variable.minlength) +config variable + option name 'maximum' + option title 'Maximum value of this variable' + option section 'schema.variable' + option type 'variable' + option datatype 'integer' + option required false + +# Variable validators (schema.@variable.validator) +config variable + option name 'validator' + option title 'Datatype of this variable' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + +# Variable value references (schema.@variable.valueof) +config variable + option name 'valueof' + option title 'Reference to section or option to read values from' + option section 'schema.variable' + option type 'lazylist' + option datatype 'string' + option required false + + +#------------------------------------------------------------------------------- +# Central enum definition +# +# config enum +# option ... +#------------------------------------------------------------------------------- + +# Enum definition (schema.@enum) +config section + option name 'enum' + option title 'Definition of uci enum value' + option package 'schema' + option required false + option named false + option unique false + option dynamic false + +# Enum value (schema.@enum.value) +config variable + option name 'value' + option title 'Value of the defined enum value' + option section 'schema.enum' + option type 'variable' + option datatype 'string' + option required true + +# Enum variable (schema.@enum.variable) +config variable + option name 'variable' + option title 'Parent variable of the defined enum value' + option section 'schema.enum' + option type 'variable' + option datatype 'string' + option required true + +# Enum value title (schema.@enum.title) +config variable + option name 'title' + option title 'Title of the defined enum value' + option section 'schema.enum' + option type 'variable' + option datatype 'string' + option required false + +# Enum value description (schema.@enum.description) +config variable + option name 'description' + option title 'Description of the defined enum value' + option section 'schema.enum' + option type 'lazylist' + option datatype 'string' + option required false + +# Enum value dependencies (schema.@enum.depends) +config variable + option name 'depends' + option title 'List of dependencies on defined variables' + option section 'schema.enum' + option type 'lazylist' + option datatype 'string' + option required false + +# Enum value default flag (schema.@enum.default) +config variable + option name 'default' + option title 'Specify whether this value is the default value of the parent enum' + option section 'schema.enum' + option type 'variable' + option datatype 'boolean' + option required false diff --git a/openwrt/packages/luci/libs/uvl/root/usr/bin/uvl b/openwrt/packages/luci/libs/uvl/root/usr/bin/uvl new file mode 100755 index 0000000..2eb6c31 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/root/usr/bin/uvl @@ -0,0 +1,241 @@ +#!/usr/bin/lua +--[[ + +UCI Validation Layer - Command Line Utility +(c) 2008 Jo-Philipp Wich +(c) 2008 Steven Barth + +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: uvl 4085 2009-01-17 23:51:28Z jow $ + +]]-- + +require("luci.uvl") +require("luci.util") + + +function getopt( arg, options ) + options = options or "" + local tab = {} + local args = {} + for k, v in ipairs(arg) do + if v:sub(1, 2) == "--" then + local x = v:find( "=", 1, true ) + if x then + tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 ) + else + tab[ v:sub( 3 ) ] = true + end + elseif v:sub( 1, 1 ) == "-" then + local y = 2 + local l = #v + local jopt + while ( y <= l ) do + jopt = v:sub( y, y ) + if options:find( jopt, 1, true ) then + if y < l then + tab[ jopt ] = v:sub( y+1 ) + y = l + else + tab[ jopt ] = arg[ k + 1 ] + arg[ k + 1 ] = "" + end + else + tab[ jopt ] = true + end + y = y + 1 + end + elseif #v > 0 then + table.insert(args, v) + end + end + return tab, args +end + +function genspec(conf) + require("luci.model.uci") + require("luci.uvl.datatypes") + + local uci = luci.model.uci.cursor() + local ok, err = uci:load(conf) + + if not ok then + print("Can not load config:", err) + os.exit(1) + else + local function _guess_datatype(v) + if type(v) == "table" then v = v[1] end + + for _, type in ipairs({ + "boolean", "integer", "float", "ip4addr", "ip6addr", + "macaddr", "directory", "file" + }) do + if luci.uvl.datatypes[type](v) then + return type + end + end + return "string" + end + + + local co = uci:get_all(conf) + local ct = { } + local ca = { } + local so = { } + local to = { } + + -- count section types + for _, section in pairs(co) do + ct[section['.type']] = ( ct[section['.type']] or 0 ) + 1 + ca[section['.type']] = section['.anonymous'] + so[section['.type']] = so[section['.type']] or { } + to[section['.type']] = to[section['.type']] or { } + + for option, value in pairs(section) do + if option:sub(1,1) ~= "." then + so[section['.type']][option] = _guess_datatype(value) + to[section['.type']][option] = ( type(value) == "table" and "list" or "variable" ) + end + end + end + + -- package name + print( "package %s" % conf ) + + -- write section schemes + for type, count in luci.util.kspairs(ct) do + print( "\nconfig section" ) + print( "\toption name '%s'" % type ) + print( "\toption title 'Section %s'" % type ) + print( "\toption package '%s'"% conf ) + print( "\toption named %s" % ( ca[type] and 'false' or 'true' ) ) + print( "\toption unique %s" % ( ct[type] > 1 and 'false' or ( ca[type] and 'false' or 'true' ) ) ) + print( "\toption dynamic false" ) + print( "\toption required false" ) + + -- write option schemes + for opt, val in luci.util.kspairs(so[type]) do + print( "\nconfig variable" ) + print( "\toption name '%s'" % opt ) + print( "\toption title 'Option %s'" % opt ) + print( "\toption section '%s.%s'" %{ conf, type } ) + print( "\toption datatype '%s'" % so[type][opt] ) + + if to[type][opt] ~= "variable" then + print( "\toption type '%s'" % to[type][opt] ) + end + end + + print("") + end + + end +end + + +local options, arguments = getopt( arg ) + +if #arguments ~= 2 or options.help then + print([=[ + +uvl - UCI Validation Layer +$Id: uvl 4085 2009-01-17 23:51:28Z jow $ +(c) 2008 Jo-Philipp Wich, Steven Barth + +Usage: + uvl --help + uvl [--silent] [--schemedir=DIR] [--configdir=DIR] [--no-strict-sections] \ + [--no-strict-options] [--no-strict-validators] [--no-strict-lists] \ + {verify|verify-scheme|genspec} config[.section[.option]] + +Options: + --help + Display this help message. + + --silent + Don't produce any output. + + --schemedir=DIR + Use DIR as scheme directory. + + --configdir=DIR + Use DIR as config directory. + + --no-strict-sections + Don't treat sections found in config but not in scheme as error. + + --no-strict-options + Don't treat options found in config but not in scheme as error. + + --no-strict-validators + Don't invalidate config if an external validator fails. + + --no-strict-lists + Don't invalidate lists that are stored options. + +Actions: + verify + Validate given configuration, section or option. + + verify-scheme + Validate given scheme against the reference meta scheme. + + genspec + Generate a scheme skeleton from given configuration. + ]=]) + os.exit(255) +elseif arguments[1] == "verify" or arguments[1] == "verify-scheme" then + luci.uvl.STRICT_UNKNOWN_SECTIONS = + ( not options['no-strict-sections'] and true or false ) + luci.uvl.STRICT_UNKNOWN_OPTIONS = + ( not options['no-strict-options'] and true or false ) + luci.uvl.STRICT_EXTERNAL_VALIDATORS = + ( not options['no-strict-validators'] and true or false ) + luci.uvl.STRICT_LIST_TYPE = + ( not options['no-strict-lists'] and true or false ) + + local uvl = luci.uvl.UVL( + type(options.schemedir) == "string" and options.schemedir, + type(options.configdir) == "string" and options.configdir + ) + + local cso = luci.util.split( arguments[2], "." ) + local ok, err + + if arguments[1] == "verify-scheme" then + uvl:read_scheme( 'schema', cso[1] ) + + local uci = uvl.uci.cursor( + type(options.configdir) == "string" + and options.configdir or uvl.schemedir .. '/default' + ) + + ok, err = uvl:validate_config( cso[1], uci:get_all(cso[1]) ) + if err then err.code = luci.uvl.errors.ERR_SCHEME end + else + ok, err = uvl:validate( unpack(cso) ) + end + + if ok then + if not options.silent then + print( string.format( + '%s "%s" validates fine!', + ( arguments[1] == "verify-scheme" and "Scheme" or + ( #cso == 1 and "Config" or + ( #cso == 2 and "Section" or "Option" ) ) ), + table.concat(cso, ".") + ) ) + end + os.exit( 0 ) + else + if not options.silent then print( err and err:string() or "Unknown error" ) end + os.exit( 1 ) + end +else + genspec( arguments[2] ) +end diff --git a/openwrt/packages/luci/libs/uvl/root/usr/bin/uvlc b/openwrt/packages/luci/libs/uvl/root/usr/bin/uvlc new file mode 100755 index 0000000..c07cc54 --- /dev/null +++ b/openwrt/packages/luci/libs/uvl/root/usr/bin/uvlc @@ -0,0 +1,22 @@ +#!/usr/bin/lua + + +if arg[1] then + require("luci.util") + require("luci.uvl") + require("luci.fs") + + local uvl = luci.uvl.UVL() + local scheme, err = uvl:get_scheme( arg[1] ) + + if scheme then + luci.fs.writefile( + "%s/bytecode/%s.lua" %{ uvl.schemedir, arg[1] }, + luci.util.get_bytecode(scheme) + ) + else + print("Error:", err:string()) + end +else + print( "Usage: uvlc " ) +end diff --git a/openwrt/packages/luci/libs/uvldoc/Makefile b/openwrt/packages/luci/libs/uvldoc/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/footer.xml b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/footer.xml new file mode 100644 index 0000000..4b97469 --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/footer.xml @@ -0,0 +1,11 @@ + +
+
+generated on <%=require "os".date("%c")%> with LuCI UVLDoc - written by Steven Barth and Jo-Philipp Wich +
+ +
+
 
+ + + \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/header.xml b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/header.xml new file mode 100644 index 0000000..f4a89b5 --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/header.xml @@ -0,0 +1,15 @@ + + + + + + + <% if title then %><%=title%> - <% end %>LuCI UVLDoc + + + + + +
diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/index.xml b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/index.xml new file mode 100644 index 0000000..a905004 --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/index.xml @@ -0,0 +1,12 @@ +<%+header.xml%> +

UCI Documentation

+

Schemes

+ +<% for k, v in luci.util.kspairs(self.schemes) do %> + + + + +<% end %> +
<%=k%><%=self.schemes[k].title%>
+<%+footer.xml%> \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/menu.xml b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/menu.xml new file mode 100644 index 0000000..c0ad3da --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/menu.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/scheme.xml b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/scheme.xml new file mode 100644 index 0000000..f4fe22e --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/scheme.xml @@ -0,0 +1,16 @@ +<%- title = scheme -%> +<%+header.xml%> +

<%=scheme-%> +<%-if package.title then%> - <%=package.title%><%end%>

+
<%=package.description%>
+ +

Sections:

+ +<% for k, v in luci.util.kspairs(package.sections) do %> + + + + +<% end %> +
<%=k%><%=v.title%>
+<%+footer.xml%> \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/section.xml b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/section.xml new file mode 100644 index 0000000..691fde4 --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/section.xml @@ -0,0 +1,198 @@ +<%- title = scheme .. "." .. type -%> +<%+header.xml%> +<% +local table = require "table" + +types = { + list = "List", + variable = "Variable", + lazylist = "Mixed", + enum = "Enumerator", + reference = "Reference" +} + +datatypes = { + boolean = "Boolean", + string = "String", + uint = "Unsigned Integer", + integer = "Integer", + float = "Real Number", + ipaddr = "IP-Address", + ip4addr = "IPv4-Address", + ip6addr = "IPv6-Address", + ip4prefix = "IPv4-Prefix", + ip6prefix = "IPv6-Prefix", + hostname = "Hostname", + host = "Host (Hostname or IP-Address)", + directory = "Filesystem path (to directory)", + file = "Filesystem path (to file)", + macaddr = "MAC-Address", + port = "Port", + portrange = "Single Port or Portrange (First-Last)" +} + +function _parse_ref( r ) + local k, v, h = r:match("([^.]+)%.([^.]+)%.([^.]+)") + if not k then + k, v = r:match("([^.]+)%.([^.]+)") + end + if k then + if h then + return self:_variable_target(k, v, h), true + else + return self:_section_filename(k, v) + end + end +end + +function _parse_dep( r, c, s, o ) + local ref = { } + local vars = { + config = c, + section = s, + option = o + } + + for v in r:gmatch("[^.]+") do + ref[#ref+1] = (v:gsub( "%$(.+)", vars )) + end + + if #ref < 2 then + table.insert(ref, 1, s or '$section') + end + if #ref < 3 then + table.insert(ref, 1, c or '$config') + end + + return self:_variable_target(unpack(ref)) +end + +%> + +

<%=scheme-%> +<%-if package.title then%> - <%=package.title%><%end%>

+

<%=type-%> +<%-if section.title then%> - <%=section.title%><%end%>

+
<%=section.description%>
+ +

Attributes:

+
    +<%- +if section.required then %> +
  • required: A section of this type is required.
  • +<% end +if section.unique then %> +
  • unique: There can be only one section of this type.
  • +<%- else -%> +
  • multiple: There can be more than one section of this type.
  • +<% end +if section.dynamic then %> +
  • dynamic: Sections of this type may contain user-defined options.
  • +<% end +if section.named then %> +
  • named: Sections of this type require a name.
  • +<% end -%> +
+ +<% if section.depends then %> +

Requirements (one of):

+
    + <% for i, d in ipairs(section.depends) do + local nf = false%> +
  • + <% for k2, v in luci.util.kspairs(d) do + local t = _parse_dep(k2, scheme, type) + %> + <% if nf then %>and<% end %> + <%if t then%><%end%><%=k2%><%if t then%><%end%><%if v~=true then%>=<%=v%><%end%> + <% nf = true + end %> +
  • + <% end %> +
+<% end %> + +

Variable Overview:

+ +<% for k, v in luci.util.kspairs(package.variables[type]) do +if v.required then%> + + + + +<% end end +for k, v in luci.util.kspairs(package.variables[type]) do +if not v.required then%> + + + + +<% end end %> +
<%=k%><%=v.title%>
<%=k%><%=v.title%>
+ +

Options:

+<%- +for i=0, 1 do +for k, v in luci.util.kspairs(package.variables[type]) do +if (i==0) == v.required then +%> +
+
+ +

<%=k-%> + <%-if v.title then%> - <%=v.title%><%end%>

+
+
<%=v.description%>
+
Attributes:
+
    + <% if v.required then %> +
  • required
  • + <% end %> +
  • Type: <%=types[v.type] or v.type%>
  • +
  • Datatype: <%=datatypes[v.datatype] or v.datatype%>
  • + <% if v.multival then %> +
  • multiple values: space-separated
  • + <% end %> +
+ <% if v.depends then %> +
Dependencies (one of):
+
    + <% for i, d in ipairs(v.depends) do + local nf = false %> +
  • + <% for k2, v in luci.util.kspairs(d) do + local t = _parse_dep(k2, scheme, type, k) + %> + <% if nf then %>and<% end %> + <%if t then%><%end%><%=k2%><%if t then%><%end%><%if v~=true then%>=<%=v%><%end%> + <% nf = true + end %> +
  • + <% end %> +
+ <% end %> + <% if v.type == "enum" then %> +
Possible Values:
+
    + <% for k, d in pairs(v.values) do %> +
  • <%=k%><%if d then%> (<%=d%>)<%end%>
  • + <% end %> +
+ <% elseif v.type == "reference" then %> +
Value references:
+
    + <% for k, d in ipairs(v.valueof) do %> +
  • + <% local t, x = _parse_ref(d) + if t then %><%=x and "Value of" or "Section of type"%> <% end %> + <%=d%> + <% if t then%><% end %> +
  • + <% end %> +
+ <% end %> +
+ +
+<% end end end -%> +<%+footer.xml%> \ No newline at end of file diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/uvldoc.css b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/uvldoc.css new file mode 100644 index 0000000..32a5e96 --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/proto/xhtml/uvldoc.css @@ -0,0 +1,135 @@ +body { + font-family: sans-serif; + font-size: 0.85em; + color: #101010; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + font-weight: bold; +} + +h1 { + font-size: 1.5em; +} + +h2 { + font-size: 1.4em; +} + +h3 { + font-size: 1.2em; +} + +h4 { + font-size: 1.1em; +} + +h5 { + font-size: 1.0em; +} + +dfn { + font-weight: normal; + font-size: 0.9em; +} + +table { + border-collapse: collapse; +} + +tr, td, th { + border: 1px solid #e0e0ff; + padding: 3px; +} + +th { + background-color: #f0f0ff; + text-align: left; +} + + +hr { + border: none; + background-color: #cccccc; + height: 1px; +} + +ul, li { + margin-top: 0; +} + +div.clear { + clear: both; +} + +div.variable-declaration { + padding-left: 2em; +} + +div.variable-description { + margin-bottom: 1em; +} + +h3.section-variables { + margin-top: 2em; +} + +h4.variable-title { + margin-bottom: 0; +} + +div#menu { + float: left; + background-color: #f0f0ff; + margin: 0; + padding: 0; + border: 1px solid #e0e0ff; + width: 11.5em; +} + +#menu ul { + list-style-type: none; + margin-bottom: 0.5em; + padding-left: 1em; +} +#menu ul li { + margin-left: 0; + +} + +div.menu-title { + background-color: #e0e0ff; + color: #000000; + font-weight: bold; + padding: 2px; +} + +div#content { + margin-top: 0; + padding-top: 0; + margin-left: 12.5em; +} + +div#copy { + margin-top: 2.5em; + font-size: 0.7em; + text-align: center; + font-size: bold; +} + +a:link { + font-weight: bold; + color: #004080; + text-decoration: none; +} + +a:visited { + font-weight:bold; + color: #006699; + text-decoration: none; +} + +a:hover { + text-decoration:underline; +} diff --git a/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/renderer.lua b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/renderer.lua new file mode 100644 index 0000000..d005ba3 --- /dev/null +++ b/openwrt/packages/luci/libs/uvldoc/luasrc/uvldoc/renderer.lua @@ -0,0 +1,124 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ +]]-- + +local io = require "io" +local fs = require "luci.fs" +local uvl = require "luci.uvl" +local util = require "luci.util" +local ltn12 = require "luci.ltn12" +local template = require "luci.template" + +local ipairs, getfenv, pairs, require, unpack = ipairs, getfenv, pairs, require, unpack +local luci = luci + +module "luci.uvldoc.renderer" + + +Generator = util.class() + +function Generator.__init__(self, schemes, output, uvlpath) + self.names = schemes + self.output = output or "doc" + self.schemes = {} + self.uvl = uvl.UVL() + + self.extension = ".xml" + self.additionals = {"uvldoc.css"} + self.sourcedir = util.libpath() .. "/uvldoc/proto/xhtml/" +end + + +function Generator.make(self) + for i, scheme in ipairs(self.names) do + self.schemes[scheme] = self.uvl:get_scheme(scheme) + end + + fs.mkdir(self.output) + + for i, file in ipairs(self.additionals) do + fs.copy(self.sourcedir .. file, self.output .. "/" .. file) + end + + template.compiler_mode = "memory" + template.viewdir = self.sourcedir + template.context.viewns = { + include = function(name) template.Template(name):render(getfenv(2)) end, + pairs = pairs, + ipairs = ipairs, + unpack = unpack, + luci = luci, + require = require + } + + self:_make_index() + + for scheme, package in pairs(self.schemes) do + self:_make_package(scheme) + for type, section in pairs(package.sections) do + self:_make_section(scheme, type) + end + end +end + +function Generator._make_index(self) + local t = template.Template("index.xml") + local sink = ltn12.sink.file( + io.open(self.output .. "/" .. self:_index_filename(), "w") + ) + t:render({self = self, write = sink}) + sink() +end + +function Generator._make_package(self, scheme) + local t = template.Template("scheme.xml") + local sink = ltn12.sink.file( + io.open(self.output .. "/" .. self:_scheme_filename(scheme), "w") + ) + t:render({self = self, package = self.schemes[scheme], scheme = scheme, write = sink}) + sink() +end + +function Generator._make_section(self, scheme, section) + local t = template.Template("section.xml") + local sink = ltn12.sink.file( + io.open(self.output .. "/" .. self:_section_filename(scheme, section), "w") + ) + local pkg = self.schemes[scheme] + t:render({self = self, package = pkg, + scheme = scheme, type=section, section=pkg.sections[section], + write = sink}) + sink() +end + +function Generator._index_filename(self) + return "index%s" % self.extension +end + +function Generator._scheme_filename(self, scheme) + return "scheme.%s%s" % {scheme, self.extension} +end + +function Generator._section_filename(self, scheme, section) + if self.schemes[scheme] and self.schemes[scheme].sections[section] then + return "section.%s.%s%s" % {scheme, section, self.extension} + end +end + +function Generator._variable_target(self, scheme, section, variable) + if self.schemes[scheme] and self.schemes[scheme].variables[section] and + self.schemes[scheme].variables[section][variable] then + return "section.%s.%s%s#variable.%s" % {scheme, section, self.extension, variable} + end +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/web/Makefile b/openwrt/packages/luci/libs/web/Makefile new file mode 100644 index 0000000..f7fac77 --- /dev/null +++ b/openwrt/packages/luci/libs/web/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk diff --git a/openwrt/packages/luci/libs/web/luasrc/cacheloader.lua b/openwrt/packages/luci/libs/web/luasrc/cacheloader.lua new file mode 100644 index 0000000..1cdf534 --- /dev/null +++ b/openwrt/packages/luci/libs/web/luasrc/cacheloader.lua @@ -0,0 +1,23 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: cacheloader.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local config = require "luci.config" +local ccache = require "luci.ccache" + +module "luci.cacheloader" + +if config.ccache and config.ccache.enable == "1" then + ccache.cache_ondemand() +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/web/luasrc/config.lua b/openwrt/packages/luci/libs/web/luasrc/config.lua new file mode 100644 index 0000000..58e182e --- /dev/null +++ b/openwrt/packages/luci/libs/web/luasrc/config.lua @@ -0,0 +1,42 @@ +--[[ +LuCI - Configuration + +Description: +Some LuCI configuration values read from uci file "luci" + + +FileId: +$Id: config.lua 3857 2008-12-05 15:37:39Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local util = require "luci.util" +module("luci.config", + function(m) + if pcall(require, "luci.model.uci") then + local config = util.threadlocal() + setmetatable(m, { + __index = function(tbl, key) + if not config[key] then + config[key] = luci.model.uci.cursor():get_all("luci", key) + end + return config[key] + end + }) + end + end) diff --git a/openwrt/packages/luci/libs/web/luasrc/dispatcher.lua b/openwrt/packages/luci/libs/web/luasrc/dispatcher.lua new file mode 100644 index 0000000..ab5e7a4 --- /dev/null +++ b/openwrt/packages/luci/libs/web/luasrc/dispatcher.lua @@ -0,0 +1,720 @@ +--[[ +LuCI - Dispatcher + +Description: +The request dispatcher and module dispatcher generators + +FileId: +$Id: dispatcher.lua 4189 2009-01-30 15:29:53Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +--- LuCI web dispatcher. +local fs = require "luci.fs" +local sys = require "luci.sys" +local init = require "luci.init" +local util = require "luci.util" +local http = require "luci.http" + +module("luci.dispatcher", package.seeall) +context = util.threadlocal() + +authenticator = {} + +-- Index table +local index = nil + +-- Fastindex +local fi + + +--- Build the URL relative to the server webroot from given virtual path. +-- @param ... Virtual path +-- @return Relative URL +function build_url(...) + local path = {...} + local sn = http.getenv("SCRIPT_NAME") or "" + for k, v in pairs(context.urltoken) do + sn = sn .. "/;" .. k .. "=" .. http.urlencode(v) + end + return sn .. ((#path > 0) and "/" .. table.concat(path, "/") or "") +end + +--- Send a 404 error code and render the "error404" template if available. +-- @param message Custom error message (optional) +-- @return false +function error404(message) + luci.http.status(404, "Not Found") + message = message or "Not Found" + + require("luci.template") + if not luci.util.copcall(luci.template.render, "error404") then + luci.http.prepare_content("text/plain") + luci.http.write(message) + end + return false +end + +--- Send a 500 error code and render the "error500" template if available. +-- @param message Custom error message (optional)# +-- @return false +function error500(message) + luci.http.status(500, "Internal Server Error") + + require("luci.template") + if not luci.util.copcall(luci.template.render, "error500", {message=message}) then + luci.http.prepare_content("text/plain") + luci.http.write(message) + end + return false +end + +function authenticator.htmlauth(validator, accs, default) + local user = luci.http.formvalue("username") + local pass = luci.http.formvalue("password") + + if user and validator(user, pass) then + return user + end + + require("luci.i18n") + require("luci.template") + context.path = {} + luci.template.render("sysauth", {duser=default, fuser=user}) + return false + +end + +--- Dispatch an HTTP request. +-- @param request LuCI HTTP Request object +function httpdispatch(request) + luci.http.context.request = request + context.request = {} + local pathinfo = http.urldecode(request:getenv("PATH_INFO") or "", true) + + for node in pathinfo:gmatch("[^/]+") do + table.insert(context.request, node) + end + + local stat, err = util.copcall(dispatch, context.request) + if not stat then + luci.util.perror(err) + error500(err) + end + + luci.http.close() + + --context._disable_memtrace() +end + +--- Dispatches a LuCI virtual path. +-- @param request Virtual path +function dispatch(request) + --context._disable_memtrace = require "luci.debug".trap_memtrace() + local ctx = context + ctx.path = request + ctx.urltoken = ctx.urltoken or {} + + local conf = require "luci.config" + local lang = conf.main.lang + if lang == "auto" then + local aclang = http.getenv("HTTP_ACCEPT_LANGUAGE") or "" + for lpat in aclang:gmatch("[%w-]+") do + lpat = lpat and lpat:gsub("-", "_") + if conf.languages[lpat] then + lang = lpat + break + end + end + end + require "luci.i18n".setlanguage(lang) + + local c = ctx.tree + local stat + if not c then + c = createtree() + end + + local track = {} + local args = {} + ctx.args = args + ctx.requestargs = ctx.requestargs or args + local n + local t = true + local token = ctx.urltoken + local preq = {} + local freq = {} + + for i, s in ipairs(request) do + local tkey, tval + if t then + tkey, tval = s:match(";(%w+)=(.*)") + end + + if tkey then + token[tkey] = tval + else + t = false + preq[#preq+1] = s + freq[#freq+1] = s + c = c.nodes[s] + n = i + if not c then + break + end + + util.update(track, c) + + if c.leaf then + break + end + end + end + + if c and c.leaf then + for j=n+1, #request do + args[#args+1] = request[j] + freq[#freq+1] = request[j] + end + end + + ctx.requestpath = freq + ctx.path = preq + + if track.i18n then + require("luci.i18n").loadc(track.i18n) + end + + -- Init template engine + if (c and c.index) or not track.notemplate then + local tpl = require("luci.template") + local media = track.mediaurlbase or luci.config.main.mediaurlbase + if not pcall(tpl.Template, "themes/%s/header" % fs.basename(media)) then + media = nil + for name, theme in pairs(luci.config.themes) do + if name:sub(1,1) ~= "." and pcall(tpl.Template, + "themes/%s/header" % fs.basename(theme)) then + media = theme + end + end + assert(media, "No valid theme found") + end + + local viewns = setmetatable({}, {__index=function(table, key) + if key == "controller" then + return build_url() + elseif key == "REQUEST_URI" then + return build_url(unpack(ctx.requestpath)) + else + return rawget(table, key) or _G[key] + end + end}) + tpl.context.viewns = viewns + viewns.write = luci.http.write + viewns.include = function(name) tpl.Template(name):render(getfenv(2)) end + viewns.translate = function(...) return require("luci.i18n").translate(...) end + viewns.striptags = util.striptags + viewns.media = media + viewns.theme = fs.basename(media) + viewns.resource = luci.config.main.resourcebase + end + + track.dependent = (track.dependent ~= false) + assert(not track.dependent or not track.auto, "Access Violation") + + if track.sysauth then + local sauth = require "luci.sauth" + + local authen = type(track.sysauth_authenticator) == "function" + and track.sysauth_authenticator + or authenticator[track.sysauth_authenticator] + + local def = (type(track.sysauth) == "string") and track.sysauth + local accs = def and {track.sysauth} or track.sysauth + local sess = ctx.authsession + local verifytoken = false + if not sess then + sess = luci.http.getcookie("sysauth") + sess = sess and sess:match("^[A-F0-9]+$") + verifytoken = true + end + + local sdat = sauth.read(sess) + local user + + if sdat then + sdat = loadstring(sdat)() + if not verifytoken or ctx.urltoken.stok == sdat.token then + user = sdat.user + end + end + + if not util.contains(accs, user) then + if authen then + ctx.urltoken.stok = nil + local user, sess = authen(luci.sys.user.checkpasswd, accs, def) + if not user or not util.contains(accs, user) then + return + else + local sid = sess or luci.sys.uniqueid(16) + if not sess then + local token = luci.sys.uniqueid(16) + sauth.write(sid, util.get_bytecode({ + user=user, + token=token, + secret=luci.sys.uniqueid(16) + })) + ctx.urltoken.stok = token + end + luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path="..build_url()) + ctx.authsession = sid + end + else + luci.http.status(403, "Forbidden") + return + end + else + ctx.authsession = sess + end + end + + if track.setgroup then + luci.sys.process.setgroup(track.setgroup) + end + + if track.setuser then + luci.sys.process.setuser(track.setuser) + end + + local target = nil + if c then + if type(c.target) == "function" then + target = c.target + elseif type(c.target) == "table" then + target = c.target.target + end + end + + if c and (c.index or type(target) == "function") then + ctx.dispatched = c + ctx.requested = ctx.requested or ctx.dispatched + end + + if c and c.index then + local tpl = require "luci.template" + + if util.copcall(tpl.render, "indexer", {}) then + return true + end + end + + if type(target) == "function" then + util.copcall(function() + local oldenv = getfenv(target) + local module = require(c.module) + local env = setmetatable({}, {__index= + + function(tbl, key) + return rawget(tbl, key) or module[key] or oldenv[key] + end}) + + setfenv(target, env) + end) + + if type(c.target) == "table" then + target(c.target, unpack(args)) + else + target(unpack(args)) + end + else + error404() + end +end + +--- Generate the dispatching index using the best possible strategy. +function createindex() + local path = luci.util.libpath() .. "/controller/" + local suff = ".lua" + + if luci.util.copcall(require, "luci.fastindex") then + createindex_fastindex(path, suff) + else + createindex_plain(path, suff) + end +end + +--- Generate the dispatching index using the fastindex C-indexer. +-- @param path Controller base directory +-- @param suffix Controller file suffix +function createindex_fastindex(path, suffix) + index = {} + + if not fi then + fi = luci.fastindex.new("index") + fi.add(path .. "*" .. suffix) + fi.add(path .. "*/*" .. suffix) + end + fi.scan() + + for k, v in pairs(fi.indexes) do + index[v[2]] = v[1] + end +end + +--- Generate the dispatching index using the native file-cache based strategy. +-- @param path Controller base directory +-- @param suffix Controller file suffix +function createindex_plain(path, suffix) + local controllers = util.combine( + luci.fs.glob(path .. "*" .. suffix) or {}, + luci.fs.glob(path .. "*/*" .. suffix) or {} + ) + + if indexcache then + local cachedate = fs.mtime(indexcache) + if cachedate then + local realdate = 0 + for _, obj in ipairs(controllers) do + local omtime = fs.mtime(path .. "/" .. obj) + realdate = (omtime and omtime > realdate) and omtime or realdate + end + + if cachedate > realdate then + assert( + sys.process.info("uid") == fs.stat(indexcache, "uid") + and fs.stat(indexcache, "mode") == "rw-------", + "Fatal: Indexcache is not sane!" + ) + + index = loadfile(indexcache)() + return index + end + end + end + + index = {} + + for i,c in ipairs(controllers) do + local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".") + local mod = require(module) + local idx = mod.index + + if type(idx) == "function" then + index[module] = idx + end + end + + if indexcache then + fs.writefile(indexcache, util.get_bytecode(index)) + fs.chmod(indexcache, "a-rwx,u+rw") + end +end + +--- Create the dispatching tree from the index. +-- Build the index before if it does not exist yet. +function createtree() + if not index then + createindex() + end + + local ctx = context + local tree = {nodes={}} + local modi = {} + + ctx.treecache = setmetatable({}, {__mode="v"}) + ctx.tree = tree + ctx.modifiers = modi + + -- Load default translation + require "luci.i18n".loadc("default") + + local scope = setmetatable({}, {__index = luci.dispatcher}) + + for k, v in pairs(index) do + scope._NAME = k + setfenv(v, scope) + v() + end + + local function modisort(a,b) + return modi[a].order < modi[b].order + end + + for _, v in util.spairs(modi, modisort) do + scope._NAME = v.module + setfenv(v.func, scope) + v.func() + end + + return tree +end + +--- Register a tree modifier. +-- @param func Modifier function +-- @param order Modifier order value (optional) +function modifier(func, order) + context.modifiers[#context.modifiers+1] = { + func = func, + order = order or 0, + module + = getfenv(2)._NAME + } +end + +--- Clone a node of the dispatching tree to another position. +-- @param path Virtual path destination +-- @param clone Virtual path source +-- @param title Destination node title (optional) +-- @param order Destination node order value (optional) +-- @return Dispatching tree node +function assign(path, clone, title, order) + local obj = node(unpack(path)) + obj.nodes = nil + obj.module = nil + + obj.title = title + obj.order = order + + setmetatable(obj, {__index = _create_node(clone)}) + + return obj +end + +--- Create a new dispatching node and define common parameters. +-- @param path Virtual path +-- @param target Target function to call when dispatched. +-- @param title Destination node title +-- @param order Destination node order value (optional) +-- @return Dispatching tree node +function entry(path, target, title, order) + local c = node(unpack(path)) + + c.target = target + c.title = title + c.order = order + c.module = getfenv(2)._NAME + + return c +end + +--- Fetch or create a new dispatching node. +-- @param ... Virtual path +-- @return Dispatching tree node +function node(...) + local c = _create_node({...}) + + c.module = getfenv(2)._NAME + c.auto = nil + + return c +end + +function _create_node(path, cache) + if #path == 0 then + return context.tree + end + + cache = cache or context.treecache + local name = table.concat(path, ".") + local c = cache[name] + + if not c then + local new = {nodes={}, auto=true, path=util.clone(path)} + local last = table.remove(path) + + c = _create_node(path, cache) + + c.nodes[last] = new + cache[name] = new + + return new + else + return c + end +end + +-- Subdispatchers -- + +--- Create a redirect to another dispatching node. +-- @param ... Virtual path destination +function alias(...) + local req = {...} + return function(...) + for _, r in ipairs({...}) do + req[#req+1] = r + end + + dispatch(req) + end +end + +--- Rewrite the first x path values of the request. +-- @param n Number of path values to replace +-- @param ... Virtual path to replace removed path values with +function rewrite(n, ...) + local req = {...} + return function(...) + local dispatched = util.clone(context.dispatched) + + for i=1,n do + table.remove(dispatched, 1) + end + + for i, r in ipairs(req) do + table.insert(dispatched, i, r) + end + + for _, r in ipairs({...}) do + dispatched[#dispatched+1] = r + end + + dispatch(dispatched) + end +end + + +local function _call(self, ...) + if #self.argv > 0 then + return getfenv()[self.name](unpack(self.argv), ...) + else + return getfenv()[self.name](...) + end +end + +--- Create a function-call dispatching target. +-- @param name Target function of local controller +-- @param ... Additional parameters passed to the function +function call(name, ...) + return {type = "call", argv = {...}, name = name, target = _call} +end + + +local _template = function(self, ...) + require "luci.template".render(self.view) +end + +--- Create a template render dispatching target. +-- @param name Template to be rendered +function template(name) + return {type = "template", view = name, target = _template} +end + + +local function _cbi(self, ...) + local cbi = require "luci.cbi" + local tpl = require "luci.template" + local http = require "luci.http" + + local config = self.config or {} + local maps = cbi.load(self.model, ...) + + local state = nil + + for i, res in ipairs(maps) do + if config.autoapply then + res.autoapply = config.autoapply + end + local cstate = res:parse() + if not state or cstate < state then + state = cstate + end + end + + if config.on_valid_to and state and state > 0 and state < 2 then + http.redirect(config.on_valid_to) + return + end + + if config.on_changed_to and state and state > 1 then + http.redirect(config.on_changed_to) + return + end + + if config.on_success_to and state and state > 0 then + http.redirect(config.on_success_to) + return + end + + if config.state_handler then + if not config.state_handler(state, maps) then + return + end + end + + local pageaction = true + http.header("X-CBI-State", state or 0) + tpl.render("cbi/header", {state = state}) + for i, res in ipairs(maps) do + res:render() + if res.pageaction == false then + pageaction = false + end + end + tpl.render("cbi/footer", {pageaction=pageaction, state = state, autoapply = config.autoapply}) +end + +--- Create a CBI model dispatching target. +-- @param model CBI model to be rendered +function cbi(model, config) + return {type = "cbi", config = config, model = model, target = _cbi} +end + + +local function _arcombine(self, ...) + local argv = {...} + local target = #argv > 0 and self.targets[2] or self.targets[1] + setfenv(target.target, self.env) + target:target(unpack(argv)) +end + +--- Create a combined dispatching target for non argv and argv requests. +-- @param trg1 Overview Target +-- @param trg2 Detail Target +function arcombine(trg1, trg2) + return {type = "arcombine", env = getfenv(), target = _arcombine, targets = {trg1, trg2}} +end + + +local function _form(self, ...) + local cbi = require "luci.cbi" + local tpl = require "luci.template" + local http = require "luci.http" + + local maps = luci.cbi.load(self.model, ...) + local state = nil + + for i, res in ipairs(maps) do + local cstate = res:parse() + if not state or cstate < state then + state = cstate + end + end + + http.header("X-CBI-State", state or 0) + tpl.render("header") + for i, res in ipairs(maps) do + res:render() + end + tpl.render("footer") +end + +--- Create a CBI form model dispatching target. +-- @param model CBI form model tpo be rendered +function form(model) + return {type = "cbi", model = model, target = _form} +end diff --git a/openwrt/packages/luci/libs/web/luasrc/http.lua b/openwrt/packages/luci/libs/web/luasrc/http.lua new file mode 100644 index 0000000..eecedcb --- /dev/null +++ b/openwrt/packages/luci/libs/web/luasrc/http.lua @@ -0,0 +1,293 @@ +--[[ +LuCI - HTTP-Interaction + +Description: +HTTP-Header manipulator and form variable preprocessor + +FileId: +$Id: http.lua 3838 2008-11-29 21:59:06Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local ltn12 = require "luci.ltn12" +local protocol = require "luci.http.protocol" +local util = require "luci.util" +local string = require "string" +local coroutine = require "coroutine" + +local pairs, tostring, error = pairs, tostring, error + +--- LuCI Web Framework high-level HTTP functions. +module "luci.http" + +context = util.threadlocal() + +Request = util.class() +function Request.__init__(self, env, sourcein, sinkerr) + self.input = sourcein + self.error = sinkerr + + + -- File handler + self.filehandler = function() end + + -- HTTP-Message table + self.message = { + env = env, + headers = {}, + params = protocol.urldecode_params(env.QUERY_STRING or ""), + } + + self.parsed_input = false +end + +function Request.formvalue(self, name, noparse) + if not noparse and not self.parsed_input then + self:_parse_input() + end + + if name then + return self.message.params[name] + else + return self.message.params + end +end + +function Request.formvaluetable(self, prefix) + local vals = {} + prefix = prefix and prefix .. "." or "." + + if not self.parsed_input then + self:_parse_input() + end + + local void = self.message.params[nil] + for k, v in pairs(self.message.params) do + if k:find(prefix, 1, true) == 1 then + vals[k:sub(#prefix + 1)] = tostring(v) + end + end + + return vals +end + +function Request.content(self) + if not self.parsed_input then + self:_parse_input() + end + + return self.message.content, self.message.content_length +end + +function Request.getcookie(self, name) + local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";") + local p = ";" .. name .. "=(.-);" + local i, j, value = c:find(p) + return value and urldecode(value) +end + +function Request.getenv(self, name) + if name then + return self.message.env[name] + else + return self.message.env + end +end + +function Request.setfilehandler(self, callback) + self.filehandler = callback +end + +function Request._parse_input(self) + protocol.parse_message_body( + self.input, + self.message, + self.filehandler + ) + self.parsed_input = true +end + +--- Close the HTTP-Connection. +function close() + if not context.eoh then + context.eoh = true + coroutine.yield(3) + end + + if not context.closed then + context.closed = true + coroutine.yield(5) + end +end + +--- Return the request content if the request was of unknown type. +-- @return HTTP request body +-- @return HTTP request body length +function content() + return context.request:content() +end + +--- Get a certain HTTP input value or a table of all input values. +-- @param name Name of the GET or POST variable to fetch +-- @param noparse Don't parse POST data before getting the value +-- @return HTTP input value or table of all input value +function formvalue(name, noparse) + return context.request:formvalue(name, noparse) +end + +--- Get a table of all HTTP input values with a certain prefix. +-- @param prefix Prefix +-- @return Table of all HTTP input values with given prefix +function formvaluetable(prefix) + return context.request:formvaluetable(prefix) +end + +--- Get the value of a certain HTTP-Cookie. +-- @param name Cookie Name +-- @return String containing cookie data +function getcookie(name) + return context.request:getcookie(name) +end + +--- Get the value of a certain HTTP environment variable +-- or the environment table itself. +-- @param name Environment variable +-- @return HTTP environment value or environment table +function getenv(name) + return context.request:getenv(name) +end + +--- Set a handler function for incoming user file uploads. +-- @param callback Handler function +function setfilehandler(callback) + return context.request:setfilehandler(callback) +end + +--- Send a HTTP-Header. +-- @param key Header key +-- @param value Header value +function header(key, value) + if not context.headers then + context.headers = {} + end + context.headers[key:lower()] = value + coroutine.yield(2, key, value) +end + +--- Set the mime type of following content data. +-- @param mime Mimetype of following content +function prepare_content(mime) + if not context.headers or not context.headers["content-type"] then + if mime == "application/xhtml+xml" then + if not getenv("HTTP_ACCEPT") or + not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then + mime = "text/html; charset=UTF-8" + end + header("Vary", "Accept") + end + header("Content-Type", mime) + end +end + +--- Get the RAW HTTP input source +-- @return HTTP LTN12 source +function source() + return context.request.input +end + +--- Set the HTTP status code and status message. +-- @param code Status code +-- @param message Status message +function status(code, message) + code = code or 200 + message = message or "OK" + context.status = code + coroutine.yield(1, code, message) +end + +--- Send a chunk of content data to the client. +-- This function is as a valid LTN12 sink. +-- If the content chunk is nil this function will automatically invoke close. +-- @param content Content chunk +-- @param src_err Error object from source (optional) +-- @see close +function write(content, src_err) + if not content then + if src_err then + error(src_err) + else + close() + end + return true + elseif #content == 0 then + return true + else + if not context.eoh then + if not context.status then + status() + end + if not context.headers or not context.headers["content-type"] then + header("Content-Type", "text/html; charset=utf-8") + end + if not context.headers["cache-control"] then + header("Cache-Control", "no-cache") + header("Expires", "0") + end + + + context.eoh = true + coroutine.yield(3) + end + coroutine.yield(4, content) + return true + end +end + +--- Redirects the client to a new URL and closes the connection. +-- @param url Target URL +function redirect(url) + status(302, "Found") + header("Location", url) + close() +end + +--- Create a querystring out of a table of key - value pairs. +-- @param table Query string source table +-- @return Encoded HTTP query string +function build_querystring(table) + local s="?" + + for k, v in pairs(table) do + s = s .. urlencode(k) .. "=" .. urlencode(v) .. "&" + end + + return s +end + +--- Return the URL-decoded equivalent of a string. +-- @param str URL-encoded string +-- @param no_plus Don't decode + to " " +-- @return URL-decoded string +-- @see urlencode +urldecode = protocol.urldecode + +--- Return the URL-encoded equivalent of a string. +-- @param str Source string +-- @return URL-encoded string +-- @see urldecode +urlencode = protocol.urlencode diff --git a/openwrt/packages/luci/libs/web/luasrc/i18n.lua b/openwrt/packages/luci/libs/web/luasrc/i18n.lua new file mode 100644 index 0000000..b031d82 --- /dev/null +++ b/openwrt/packages/luci/libs/web/luasrc/i18n.lua @@ -0,0 +1,98 @@ +--[[ +LuCI - Internationalisation + +Description: +A very minimalistic but yet effective internationalisation module + +FileId: +$Id: i18n.lua 3652 2008-10-29 19:41:33Z jow $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +--- LuCI translation library. +module("luci.i18n", package.seeall) +require("luci.util") + +table = {} +i18ndir = luci.util.libpath() .. "/i18n/" +loaded = {} +context = luci.util.threadlocal() +default = "en" + +--- Clear the translation table. +function clear() + table = {} +end + +--- Load a translation and copy its data into the translation table. +-- @param file Language file +-- @param lang Two-letter language code +-- @param force Force reload even if already loaded (optional) +-- @return Success status +function load(file, lang, force) + lang = lang and lang:gsub("_", "-") or "" + if force or not loaded[lang] or not loaded[lang][file] then + local f = loadfile(i18ndir .. file .. "." .. lang .. ".lua") + if f then + table[lang] = table[lang] or {} + setfenv(f, table[lang]) + f() + loaded[lang] = loaded[lang] or {} + loaded[lang][file] = true + return true + else + return false + end + else + return true + end +end + +--- Load a translation file using the default translation language. +-- Alternatively load the translation of the fallback language. +-- @param file Language file +-- @param force Force reload even if already loaded (optional) +function loadc(file, force) + load(file, default, force) + return load(file, context.lang, force) +end + +--- Set the context default translation language. +-- @param lang Two-letter language code +function setlanguage(lang) + context.lang = lang:gsub("_", "-") +end + +--- Return the translated value for a specific translation key. +-- @param key Translation key +-- @param def Default translation +-- @return Translated string +function translate(key, def) + return (table[context.lang] and table[context.lang][key]) + or (table[default] and table[default][key]) + or def +end + +--- Return the translated value for a specific translation key and use it as sprintf pattern. +-- @param key Translation key +-- @param default Default translation +-- @param ... Format parameters +-- @return Translated and formatted string +function translatef(key, default, ...) + return translate(key, default):format(...) +end diff --git a/openwrt/packages/luci/libs/web/luasrc/sauth.lua b/openwrt/packages/luci/libs/web/luasrc/sauth.lua new file mode 100644 index 0000000..758934e --- /dev/null +++ b/openwrt/packages/luci/libs/web/luasrc/sauth.lua @@ -0,0 +1,106 @@ +--[[ + +Session authentication +(c) 2008 Steven Barth + +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: sauth.lua 3941 2008-12-23 21:39:38Z jow $ + +]]-- + +--- LuCI session library. +module("luci.sauth", package.seeall) +require("luci.fs") +require("luci.util") +require("luci.sys") +require("luci.config") + + +luci.config.sauth = luci.config.sauth or {} +sessionpath = luci.config.sauth.sessionpath +sessiontime = tonumber(luci.config.sauth.sessiontime) or 15 * 60 + +--- Manually clean up expired sessions. +function clean() + local now = os.time() + local files = luci.fs.dir(sessionpath) + + if not files then + return nil + end + + for i, file in pairs(files) do + local fname = sessionpath .. "/" .. file + local stat = luci.fs.stat(fname) + if stat and stat.type == "regular" and stat.atime + sessiontime < now then + luci.fs.unlink(fname) + end + end +end + +--- Prepare session storage by creating the session directory. +function prepare() + luci.fs.mkdir(sessionpath) + luci.fs.chmod(sessionpath, "a-rwx,u+rwx") + + if not sane() then + error("Security Exception: Session path is not sane!") + end +end + +--- Read a session and return its content. +-- @param id Session identifier +-- @return Session data +function read(id) + if not id then + return + end + if not id:match("^%w+$") then + error("Session ID is not sane!") + end + clean() + if not sane(sessionpath .. "/" .. id) then + return + end + return luci.fs.readfile(sessionpath .. "/" .. id) +end + + +--- Check whether Session environment is sane. +-- @return Boolean status +function sane(file) + return luci.sys.process.info("uid") + == luci.fs.stat(file or sessionpath, "uid") + and luci.fs.stat(file or sessionpath, "mode") + == (file and "rw-------" or "rwx------") +end + + +--- Write session data to a session file. +-- @param id Session identifier +-- @param data Session data +function write(id, data) + if not sane() then + prepare() + end + if not id:match("^%w+$") then + error("Session ID is not sane!") + end + luci.fs.writefile(sessionpath .. "/" .. id, data) + luci.fs.chmod(sessionpath .. "/" .. id, "a-rwx,u+rw") +end + + +--- Kills a session +-- @param id Session identifier +function kill(id) + if not id:match("^%w+$") then + error("Session ID is not sane!") + end + luci.fs.unlink(sessionpath .. "/" .. id) +end \ No newline at end of file diff --git a/openwrt/packages/luci/libs/web/luasrc/template.lua b/openwrt/packages/luci/libs/web/luasrc/template.lua new file mode 100644 index 0000000..df30060 --- /dev/null +++ b/openwrt/packages/luci/libs/web/luasrc/template.lua @@ -0,0 +1,239 @@ +--[[ +LuCI - Template Parser + +Description: +A template parser supporting includes, translations, Lua code blocks +and more. It can be used either as a compiler or as an interpreter. + +FileId: $Id: template.lua 3246 2008-09-12 07:48:36Z Cyrus $ + +License: +Copyright 2008 Steven Barth + +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 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local fs = require"luci.fs" +local sys = require "luci.sys" +local util = require "luci.util" +local table = require "table" +local string = require "string" +local config = require "luci.config" +local coroutine = require "coroutine" + +local tostring, pairs, loadstring = tostring, pairs, loadstring +local setmetatable, loadfile = setmetatable, loadfile +local getfenv, setfenv, rawget = getfenv, setfenv, rawget +local assert, type, error = assert, type, error + +--- LuCI template library. +module "luci.template" + +config.template = config.template or {} + +viewdir = config.template.viewdir or util.libpath() .. "/view" +compiledir = config.template.compiledir or util.libpath() .. "/view" + + +-- Compile modes: +-- memory: Always compile, do not save compiled files, ignore precompiled +-- file: Compile on demand, save compiled files, update precompiled +compiler_mode = config.template.compiler_mode or "memory" + + +-- Define the namespace for template modules +context = util.threadlocal() + +--- Manually compile a given template into an executable Lua function +-- @param template LuCI template +-- @return Lua template function +function compile(template) + local expr = {} + + -- Search all <% %> expressions + local function expr_add(ws1, skip1, command, skip2, ws2) + expr[#expr+1] = command + return ( #skip1 > 0 and "" or ws1 ) .. + "<%" .. tostring(#expr) .. "%>" .. + ( #skip2 > 0 and "" or ws2 ) + end + + -- Save all expressiosn to table "expr" + template = template:gsub("(%s*)<%%(%-?)(.-)(%-?)%%>(%s*)", expr_add) + + local function sanitize(s) + s = "%q" % s + return s:sub(2, #s-1) + end + + -- Escape and sanitize all the template (all non-expressions) + template = sanitize(template) + + -- Template module header/footer declaration + local header = 'write("' + local footer = '")' + + template = header .. template .. footer + + -- Replacements + local r_include = '")\ninclude("%s")\nwrite("' + local r_i18n = '"..translate("%1","%2").."' + local r_i18n2 = '"..translate("%1", "").."' + local r_pexec = '"..(%s or "").."' + local r_exec = '")\n%s\nwrite("' + + -- Parse the expressions + for k,v in pairs(expr) do + local p = v:sub(1, 1) + v = v:gsub("%%", "%%%%") + local re = nil + if p == "+" then + re = r_include:format(sanitize(string.sub(v, 2))) + elseif p == ":" then + if v:find(" ") then + re = sanitize(v):gsub(":(.-) (.*)", r_i18n) + else + re = sanitize(v):gsub(":(.+)", r_i18n2) + end + elseif p == "=" then + re = r_pexec:format(v:sub(2)) + elseif p == "#" then + re = "" + else + re = r_exec:format(v) + end + template = template:gsub("<%%"..tostring(k).."%%>", re) + end + + return loadstring(template) +end + +--- Render a certain template. +-- @param name Template name +-- @param scope Scope to assign to template (optional) +function render(name, scope) + return Template(name):render(scope or getfenv(2)) +end + + +-- Template class +Template = util.class() + +-- Shared template cache to store templates in to avoid unnecessary reloading +Template.cache = setmetatable({}, {__mode = "v"}) + + +-- Constructor - Reads and compiles the template on-demand +function Template.__init__(self, name) + local function _encode_filename(str) + + local function __chrenc( chr ) + return "%%%02x" % string.byte( chr ) + end + + if type(str) == "string" then + str = str:gsub( + "([^a-zA-Z0-9$_%-%.%+!*'(),])", + __chrenc + ) + end + + return str + end + + self.template = self.cache[name] + self.name = name + + -- Create a new namespace for this template + self.viewns = context.viewns + + -- If we have a cached template, skip compiling and loading + if self.template then + return + end + + -- Enforce cache security + local cdir = compiledir .. "/" .. sys.process.info("uid") + + -- Compile and build + local sourcefile = viewdir .. "/" .. name + local compiledfile = cdir .. "/" .. _encode_filename(name) .. ".lua" + local err + + if compiler_mode == "file" then + local tplmt = fs.mtime(sourcefile) or fs.mtime(sourcefile .. ".htm") + local commt = fs.mtime(compiledfile) + + if not fs.mtime(cdir) then + fs.mkdir(cdir, true) + fs.chmod(fs.dirname(cdir), "a+rxw") + end + + assert(tplmt or commt, "No such template: " .. name) + + -- Build if there is no compiled file or if compiled file is outdated + if not commt or (commt and tplmt and commt < tplmt) then + local source + source, err = fs.readfile(sourcefile) or fs.readfile(sourcefile .. ".htm") + + if source then + local compiled, err = compile(source) + + fs.writefile(compiledfile, util.get_bytecode(compiled)) + fs.chmod(compiledfile, "a-rwx,u+rw") + self.template = compiled + end + else + assert( + sys.process.info("uid") == fs.stat(compiledfile, "uid") + and fs.stat(compiledfile, "mode") == "rw-------", + "Fatal: Cachefile is not sane!" + ) + self.template, err = loadfile(compiledfile) + end + + elseif compiler_mode == "memory" then + local source + source, err = fs.readfile(sourcefile) or fs.readfile(sourcefile .. ".htm") + if source then + self.template, err = compile(source) + end + + end + + -- If we have no valid template throw error, otherwise cache the template + if not self.template then + error(err) + else + self.cache[name] = self.template + end +end + + +-- Renders a template +function Template.render(self, scope) + scope = scope or getfenv(2) + + -- Put our predefined objects in the scope of the template + setfenv(self.template, setmetatable({}, {__index = + function(tbl, key) + return rawget(tbl, key) or self.viewns[key] or scope[key] + end})) + + -- Now finally render the thing + local stat, err = util.copcall(self.template) + if not stat then + error("Error in template %s: %s" % {self.name, err}) + end +end diff --git a/openwrt/packages/luci/libs/web/root/etc/config/luci b/openwrt/packages/luci/libs/web/root/etc/config/luci new file mode 100644 index 0000000..7c0ed5b --- /dev/null +++ b/openwrt/packages/luci/libs/web/root/etc/config/luci @@ -0,0 +1,28 @@ +config core main + option lang auto + option mediaurlbase /luci-static/openwrt.org + option resourcebase /luci-static/resources + +config extern flash_keep + option uci "/etc/config/" + option dropbear "/etc/dropbear/" + option openvpn "/etc/openvpn/" + option passwd "/etc/passwd" + option opkg "/etc/opkg.conf" + option firewall "/etc/firewall.user" + option uploads "/lib/uci/upload/" + +config internal languages + +config internal sauth + option sessionpath "/tmp/luci-sessions" + option sessiontime 3600 + +config internal ccache + option enable 1 + +config internal template + option compiler_mode file + option compiledir "/tmp/luci-templatecache" + +config internal themes diff --git a/openwrt/packages/luci/modules/admin-core/Makefile b/openwrt/packages/luci/modules/admin-core/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-core/ipkg/postinst b/openwrt/packages/luci/modules/admin-core/ipkg/postinst new file mode 100755 index 0000000..b0293a7 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/ipkg/postinst @@ -0,0 +1,7 @@ +#!/bin/sh + +[ -n "${IPKG_INSTROOT}" ] || { + /etc/init.d/luci_fixtime enabled || /etc/init.d/luci_fixtime enable + /etc/init.d/luci_ethers enabled || /etc/init.d/luci_ethers enable + /etc/init.d/luci_hosts enabled || /etc/init.d/luci_hosts enable +} diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/tools/webadmin.lua b/openwrt/packages/luci/modules/admin-core/luasrc/tools/webadmin.lua new file mode 100644 index 0000000..ae90c50 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/tools/webadmin.lua @@ -0,0 +1,173 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: webadmin.lua 4169 2009-01-27 17:15:58Z jow $ +]]-- + +module("luci.tools.webadmin", package.seeall) +local uci = require("luci.model.uci") +require("luci.sys") +require("luci.ip") + +function byte_format(byte) + local suff = {"B", "KB", "MB", "GB", "TB"} + for i=1, 5 do + if byte > 1024 and i < 5 then + byte = byte / 1024 + else + return string.format("%.2f %s", byte, suff[i]) + end + end +end + +function date_format(secs) + local suff = {"min", "h", "d"} + local mins = 0 + local hour = 0 + local days = 0 + + secs = math.floor(secs) + if secs > 60 then + mins = math.floor(secs / 60) + secs = secs % 60 + end + + if mins > 60 then + hour = math.floor(mins / 60) + mins = mins % 60 + end + + if hour > 24 then + days = math.floor(hour / 24) + hour = hour % 24 + end + + if days > 0 then + return string.format("%.0fd %02.0fh %02.0fmin %02.0fs", days, hour, mins, secs) + else + return string.format("%02.0fh %02.0fmin %02.0fs", hour, mins, secs) + end +end + +function network_get_addresses(net) + local state = uci.cursor_state() + state:load("network") + local addr = {} + local ipv4 = state:get("network", net, "ipaddr") + local mav4 = state:get("network", net, "netmask") + local ipv6 = state:get("network", net, "ip6addr") + + if ipv4 and #ipv4 > 0 then + if mav4 and #mav4 == 0 then mav4 = nil end + + ipv4 = luci.ip.IPv4(ipv4, mav4) + + if ipv4 then + table.insert(addr, ipv4:string()) + end + end + + if ipv6 then + table.insert(addr, ipv6) + end + + state:foreach("network", "alias", + function (section) + if section.interface == net then + if section.ipaddr and section.netmask then + local ipv4 = luci.ip.IPv4(section.ipaddr, section.netmask) + + if ipv4 then + table.insert(addr, ipv4:string()) + end + end + + if section.ip6addr then + table.insert(addr, section.ip6addr) + end + end + end + ) + + return addr +end + +function cbi_add_networks(field) + uci.cursor():foreach("network", "interface", + function (section) + if section[".name"] ~= "loopback" then + field:value(section[".name"]) + end + end + ) + field.titleref = luci.dispatcher.build_url("admin", "network", "network") +end + +function cbi_add_knownips(field) + for i, dataset in ipairs(luci.sys.net.arptable()) do + field:value(dataset["IP address"]) + end +end + +function network_get_zones(net) + local state = uci.cursor_state() + if not state:load("firewall") then + return nil + end + + local zones = {} + + state:foreach("firewall", "zone", + function (section) + local znet = section.network or section.name + if luci.util.contains(luci.util.split(znet, " "), net) then + table.insert(zones, section.name) + end + end + ) + + return zones +end + +function firewall_find_zone(name) + local find + + luci.model.uci.cursor():foreach("firewall", "zone", + function (section) + if section.name == name then + find = section[".name"] + end + end + ) + + return find +end + +function iface_get_network(iface) + local state = uci.cursor_state() + state:load("network") + local net + + state:foreach("network", "interface", + function (section) + local ifname = state:get( + "network", section[".name"], "ifname" + ) + + if iface == ifname then + net = section[".name"] + end + end + ) + + return net +end diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/view/about.htm b/openwrt/packages/luci/modules/admin-core/luasrc/view/about.htm new file mode 100644 index 0000000..5de651f --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/view/about.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: about.htm 3650 2008-10-29 19:40:40Z jow $ + +-%> +<%+header%> +

<%:about%> LuCI

+

<%:c_lucidesc%>

+ +

<%:c_projecthome%>: luci.freifunk-halle.net

+ +
+

<%:c_leaddev%>

+ +
+ +

<%:c_contributors%>

+ +
+ +

<%:c_thanksto%>

+
    +
  • Mono (Freifunk Halle)
  • +
  • tetzlav (Freifunk Leipzig)
  • +
  • Mickey Knox (Freifunk Hannover)
  • +
+<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/view/error404.htm b/openwrt/packages/luci/modules/admin-core/luasrc/view/error404.htm new file mode 100644 index 0000000..0942341 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/view/error404.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: error404.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

404 Not Found

+

Sorry, the object you requested was not found.

+Unable to dispatch: <%=luci.http.request.env.PATH_INFO%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/view/error500.htm b/openwrt/packages/luci/modules/admin-core/luasrc/view/error500.htm new file mode 100644 index 0000000..bfa2e54 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/view/error500.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: error500.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

500 Internal Server Error

+

Sorry, the server encountered an unexpected error.

+
<%=message%>
+<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/view/footer.htm b/openwrt/packages/luci/modules/admin-core/luasrc/view/footer.htm new file mode 100644 index 0000000..fc29595 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/view/footer.htm @@ -0,0 +1,15 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3655 2008-10-29 19:54:59Z jow $ + +-%> +<% include("themes/" .. theme .. "/footer") %> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/view/header.htm b/openwrt/packages/luci/modules/admin-core/luasrc/view/header.htm new file mode 100644 index 0000000..84c6dc4 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/view/header.htm @@ -0,0 +1,15 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3650 2008-10-29 19:40:40Z jow $ + +-%> +<% include("themes/" .. theme .. "/header") %> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/view/indexer.htm b/openwrt/packages/luci/modules/admin-core/luasrc/view/indexer.htm new file mode 100644 index 0000000..363802b --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/view/indexer.htm @@ -0,0 +1,15 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: indexer.htm 3552 2008-10-10 14:37:53Z Cyrus $ + +-%> +<% include("themes/" .. theme .. "/indexer") %> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-core/luasrc/view/sysauth.htm b/openwrt/packages/luci/modules/admin-core/luasrc/view/sysauth.htm new file mode 100644 index 0000000..0c8cf30 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/luasrc/view/sysauth.htm @@ -0,0 +1,49 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: sysauth.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> +<%+header%> +<% luci.i18n.loadc("sysauth") %> + +
"> +
+

<%:sysauth_head%>

+
+ <%:sysauth_prompt%> + <%- if fuser then %> +
<%:sysauth_failed%>
+
+ <% end -%> +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+ + +
+
+<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-core/root/etc/config/luci_ethers b/openwrt/packages/luci/modules/admin-core/root/etc/config/luci_ethers new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/etc/config/luci_ethers @@ -0,0 +1 @@ + diff --git a/openwrt/packages/luci/modules/admin-core/root/etc/config/luci_hosts b/openwrt/packages/luci/modules/admin-core/root/etc/config/luci_hosts new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/etc/config/luci_hosts @@ -0,0 +1 @@ + diff --git a/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_ethers b/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_ethers new file mode 100755 index 0000000..fb1deb2 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_ethers @@ -0,0 +1,37 @@ +#!/bin/sh /etc/rc.common +START=59 + +apply_lease() { + local cfg="$1" + + config_get macaddr "$cfg" macaddr + config_get ipaddr "$cfg" ipaddr + + [ -n "$macaddr" -a -n "$ipaddr" ] || return 0 + + echo "$macaddr $ipaddr" >> /var/etc/ethers +} + +start() { + if [ ! -L /etc/ethers ]; then + test -f /etc/ethers && mv /etc/ethers /etc/ethers.local + ln -s /var/etc/ethers /etc/ethers + fi + + test -d /var/etc || mkdir -p /var/etc + + echo "# This file is autogenerated, use /etc/ethers.local instead" > /var/etc/ethers + + config_load luci_ethers + config_foreach apply_lease static_lease + + test -f /etc/ethers.local && cat /etc/ethers.local >> /var/etc/ethers + + return 0 +} + +stop() { + test -f /var/etc/ethers && rm -f /var/etc/ethers + + return 0 +} diff --git a/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_fixtime b/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_fixtime new file mode 100755 index 0000000..f300e45 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_fixtime @@ -0,0 +1,11 @@ +#!/bin/sh /etc/rc.common + +START=05 + +start() { + cat <<' EOF' | lua -l luci.fs -l luci.util - + if (os.time() < 1000000000) then + os.execute('date -s ' .. os.date('%m%d%H%M%Y', luci.fs.mtime("/etc/init.d/luci_fixtime"))) + end + EOF +} diff --git a/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_hosts b/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_hosts new file mode 100755 index 0000000..ae94714 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/etc/init.d/luci_hosts @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common +START=59 + +apply_host() { + local cfg="$1" + + config_get hostname "$cfg" hostname + config_get ipaddr "$cfg" ipaddr + + [ -n "$hostname" -a -n "$ipaddr" ] || return 0 + + echo "$ipaddr $hostname" >> /var/etc/hosts +} + +start() { + if [ ! -L /etc/hosts ]; then + test -f /etc/hosts && mv /etc/hosts /etc/hosts.local + ln -s /var/etc/hosts /etc/hosts + fi + + echo "# This file is autogenerated, use /etc/hosts.local instead" > /var/etc/hosts + + test -d /var/etc || mkdir -p /var/etc + test -f /etc/hosts.local && cat /etc/hosts.local >> /var/etc/hosts + + config_load luci_hosts + config_foreach apply_host host + + return 0 +} + +stop() { + test -f /var/etc/hosts && rm -f /var/etc/hosts + + return 0 +} diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dhcp b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dhcp new file mode 100644 index 0000000..86a5a47 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dhcp @@ -0,0 +1,240 @@ +package dhcp + +config package + option title 'Dnsmasq DHCPd configuration' + +config section + option name 'dnsmasq' + option package 'dhcp' + option title 'General Settings' + option unique true + option required true + option dynamic true + +config variable + option name 'domainneeded' + option section 'dhcp.dnsmasq' + option title 'Domain required' + option description "Don't forward DNS-Requests without DNS-Name" + option datatype boolean + +config variable + option name 'authoritative' + option section 'dhcp.dnsmasq' + option title 'Authoritative' + option description 'This is the only DHCP in the local network' + option datatype boolean + +config variable + option name 'boguspriv' + option section 'dhcp.dnsmasq' + option title 'Filter private' + option description "Don't forward reverse lookups for local networks" + option datatype boolean + +config variable + option name 'filterwin2k' + option section 'dhcp.dnsmasq' + option title 'Filter useless' + option description 'Filter useless DNS-queries of Windows-systems' + option datatype boolean + +config variable + option name 'localise_queries' + option section 'dhcp.dnsmasq' + option title 'Localise queries' + option description 'Localises the hostname depending on its subnet' + option datatype boolean + +config variable + option name 'local' + option section 'dhcp.dnsmasq' + option title 'Local Server' + +config variable + option name 'domain' + option section 'dhcp.dnsmasq' + option title 'Local Domain' + +config variable + option name 'expandhosts' + option section 'dhcp.dnsmasq' + option title 'Expand Hosts' + option description 'adds domain names to hostentries in the resolv file' + option datatype boolean + +config variable + option name 'nonegcache' + option section 'dhcp.dnsmasq' + option title "don't cache unknown" + option description 'prevents caching of negative DNS-replies' + option datatype boolean + +config variable + option name 'readethers' + option section 'dhcp.dnsmasq' + option title 'Use /etc/ethers' + option description 'Read /etc/ethers to configure the DHCP-Server' + option datatype boolean + +config variable + option name 'leasefile' + option section 'dhcp.dnsmasq' + option title 'Leasefile' + option description 'file where given DHCP-leases will be stored' + +config variable + option name 'resolvfile' + option section 'dhcp.dnsmasq' + option title 'Resolvfile' + option description 'local DNS file' + +config variable + option name 'nohosts' + option section 'dhcp.dnsmasq' + option title 'Ignore /etc/hosts ' + option datatype boolean + +config variable + option name 'strictorder' + option section 'dhcp.dnsmasq' + option title 'Strict order' + option description 'DNS-Server will be queried in the order of the resolvfile' + option datatype boolean + +config variable + option name 'logqueries' + option section 'dhcp.dnsmasq' + option title 'Log queries' + option datatype boolean + +config variable + option name 'noresolv' + option section 'dhcp.dnsmasq' + option title 'Ignore resolve file' + option datatype boolean + +config variable + option name 'dnsforwardmax' + option section 'dhcp.dnsmasq' + option title 'concurrent queries' + option datatype uint + +config variable + option name 'port' + option section 'dhcp.dnsmasq' + option title 'DNS-Port' + option datatype port + +config variable + option name 'ednspacket_max' + option section 'dhcp.dnsmasq' + option title 'ednspacket_max' + option datatype uint + +config variable + option name 'dhcpleasemax' + option section 'dhcp.dnsmasq' + option title 'max. DHCP -Leases' + option datatype uint + +config variable + option name 'addnhosts' + option section 'dhcp.dnsmasq' + option title 'additional hostfile' + option datatype file + +config variable + option name 'queryport' + option section 'dhcp.dnsmasq' + option title 'query port' + option datatype port + +config variable + option name 'enable_tftp' + option section 'dhcp.dnsmasq' + option title 'Enable builtin TFTP-Server' + option datatype boolean + +config variable + option name 'tftp_root' + option section 'dhcp.dnsmasq' + option title 'TFTP-Server root directory' + option datatype directory + +config variable + option name 'dhcp_boot' + option section 'dhcp.dnsmasq' + option title 'DHCP Boot image' + + +config section + option name 'dhcp' + option package 'dhcp' + option title 'DHCP interface configuration' + option dynamic true + +config variable + option name 'interface' + option section 'dhcp.dhcp' + option title 'Interface' + option required true + option type reference + list valueof network.interface + list valueof network.alias + +config variable + option name 'start' + option section 'dhcp.dhcp' + option title 'Start' + option description 'first address (last octet)' + option datatype uint + +config variable + option name 'limit' + option section 'dhcp.dhcp' + option title 'Limit' + option description 'number of leased addresses -1' + option datatype uint + +config variable + option name 'leasetime' + option section 'dhcp.dhcp' + option title 'Leasetime' + +config variable + option name 'dynamicdhcp' + option section 'dhcp.dhcp' + option title 'Dynamic DHCP ' + option datatype boolean + +config variable + option name 'name' + option section 'dhcp.dhcp' + option title 'Name' + +config variable + option name 'ignore' + option section 'dhcp.dhcp' + option title 'Ignore interface' + option description 'disable DHCP for this interface' + option datatype boolean + +config variable + option name 'netmask' + option section 'dhcp.dhcp' + option title 'IPv4-Netmask' + option datatype ip4addr + +config variable + option name 'force' + option section 'dhcp.dhcp' + option title 'Force' + option datatype boolean + +config variable + option name 'dhcp_option' + option section 'dhcp.dhcp' + option title 'DHCP-Options' + option description 'See "dnsmasq --help dhcp" for a list of available options.' + option type lazylist diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dropbear b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dropbear new file mode 100644 index 0000000..ba490a7 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/dropbear @@ -0,0 +1,24 @@ +package dropbear + +config package + option title 'Dropbear SSHd configuration' + +config section + option name 'dropbear' + option title 'General SSH daemon settings' + option package 'dropbear' + option required true + option unique true + +config variable + option name 'PasswordAuth' + option title 'Permit password authentication' + option section 'dropbear.dropbear' + option datatype 'boolean' + +config variable + option name 'Port' + option title 'Listening port' + option section 'dropbear.dropbear' + option datatype 'integer' + option required true diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/fstab b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/fstab new file mode 100644 index 0000000..58dff58 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/fstab @@ -0,0 +1,54 @@ +package fstab + +config package + option title 'Filesystem configuration' + +config section + option name 'mount' + option title 'Filesystem entry' + option package 'fstab' + +config variable + option name 'device' + option title 'Device node' + option section 'fstab.mount' + +config variable + option name 'enabled' + option title 'Enable this mount point' + option section 'fstab.mount' + option datatype 'boolean' + option required 'true' + +config variable + option name 'fstype' + option title 'Filesystem type' + option section 'fstab.mount' + +config variable + option name 'options' + option title 'Mount options' + option section 'fstab.mount' + +config variable + option name 'target' + option title 'Mount point' + option section 'fstab.mount' + option datatype 'directory' + + +config section + option name 'swap' + option title 'Swap entry' + option package 'fstab' + +config variable + option name 'device' + option title 'Swap file or Partition' + option section 'fstab.swap' + +config variable + option name 'enabled' + option title 'Enable this swap' + option section 'fstab.swap' + option datatype 'boolean' diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/httpd b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/httpd new file mode 100644 index 0000000..8dcf095 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/httpd @@ -0,0 +1,37 @@ +package httpd + +config package + option title 'Busybox HTTPd configuration' + +config section + option name 'httpd' + option title 'General httpd settings' + option package 'httpd' + option required true + +config variable + option name 'home' + option title 'Document root' + option section 'httpd.httpd' + option datatype 'directory' + option required true + +config variable + option name 'port' + option title 'Listening port' + option section 'httpd.httpd' + option datatype 'integer' + option required true + +config variable + option name 'c_file' + option title 'Configuration file' + option section 'httpd.httpd' + option datatype 'file' + +config variable + option name 'realm' + option title 'Authentication Realm' + option description 'Realm shown on login prompt' + option section 'httpd.httpd' + diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/luci_hosts b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/luci_hosts new file mode 100644 index 0000000..e2597f4 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/luci_hosts @@ -0,0 +1,21 @@ +package luci_hosts + +config section + option name 'host' + option title 'Host entry definition' + option package 'luci_hosts' + +config variable + option name 'hostname' + option title 'Hostname' + option section 'luci_hosts.host' + option datatype 'hostname' + option required true + +config variable + option name 'ipaddr' + option title 'IP address' + option section 'luci_hosts.host' + option datatype 'ipaddr' + option required true + diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/network b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/network new file mode 100644 index 0000000..0ea439d --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/network @@ -0,0 +1,495 @@ +package network + +config package + option title 'Network configuration' + +config section + option name 'interface' + option title 'Network interface' + option package 'network' + list depends 'proto=static, ipaddr, netmask' + list depends 'proto=static, ip6addr' + list depends 'proto=pppoe, username, password' + list depends 'proto=pppoa, username, password, encaps, vpi, vci' + list depends 'proto=ppp, device' + list depends 'proto=3g, device' + list depends 'proto=pptp, username, password, server' + list depends 'proto=dhcp' + list depends 'proto=none' + option named 'true' + option required 'true' + +config variable + option name 'ifname' + option title 'Physical interface' + option section 'network.interface' + +config variable + option name 'macaddr' + option title 'Interface MAC address' + option section 'network.interface' + option datatype 'macaddr' + +config variable + option name 'mtu' + option title 'MTU' + option section 'network.interface' + option datatype 'uint' + +config variable + option name 'ipaddr' + option title 'IPv4 host address' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'netmask' + option title 'IPv4 network mask' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'gateway' + option title 'IPv4 gateway' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'bcast' + option title 'IPv4 broadcast address' + option section 'network.interface' + option datatype 'ip4addr' + +config variable + option name 'ip6addr' + option title 'IPv6 address (CIDR)' + option section 'network.interface' + option datatype 'ip6addr' + +config variable + option name 'ip6gw' + option title 'IPv6 gateway' + option section 'network.interface' + option datatype 'ip6addr' + +config variable + option name 'dns' + option title 'DNS server (IPv4 or IPv6)' + option section 'network.interface' + option datatype 'ipaddr' + option multival 'true' + +config variable + option name 'keepalive' + option title 'keep-alive' + option description 'Number of connection failures before reconnect' + option section 'network.interface' + option datatype 'string' + list depends 'proto=pppoe' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + list depends 'proto=pppoa' + +config variable + option name 'demand' + option title 'Dial on-demand' + option description 'Number of seconds to wait before closing the connection due to inactivity' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'username' + option title 'Username' + option section 'network.interface' + option datatype 'string' + list depends 'proto=pppoa' + list depends 'proto=pppoe' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'password' + option title 'Password' + option section 'network.interface' + option datatype 'string' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'encaps' + option title 'PPPoA encapsulation mode' + option section 'network.interface' + option type 'enum' + list depends 'proto=pppoa' + +config enum + option variable 'network.interface.encaps' + option value 'vc' + option title 'VC' + +config enum + option variable 'network.interface.encaps' + option value 'llc' + option title 'LLC' + +config variable + option name 'vpi' + option title 'PPPoA VPI' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=pppoa' + +config variable + option name 'vci' + option title 'PPPoA VCI' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=pppoa' + +config variable + option name 'server' + option title 'PPTP server' + option section 'network.interface' + option datatype 'host' + list depends 'proto=pptp' + +config variable + option name 'device' + option title 'Modem device' + option section 'network.interface' + option datatype 'device' + list depends 'proto=ppp' + list depends 'proto=3g' + +config variable + option name 'defaultroute' + option title 'Replace default route' + option section 'network.interface' + option datatype 'boolean' + list depends 'proto=ppp' + list depends 'proto=pppoa' + list depends 'proto=pppoe' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'peerdns' + option title 'Use peer DNS' + option section 'network.interface' + option datatype 'boolean' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'ipv6' + option title 'Enable IPv6 on PPP link' + option section 'network.interface' + option datatype 'boolean' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'connect' + option title 'PPP connect script' + option section 'network.interface' + option datatype 'file' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'disconnect' + option title 'PPP disconnect script' + option section 'network.interface' + option datatype 'file' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'pppd_options' + option title 'Additional PPP daemon options' + option section 'network.interface' + option datatype 'string' + list depends 'proto=ppp' + list depends 'proto=pppoe' + list depends 'proto=pppoa' + list depends 'proto=pptp' + list depends 'proto=3g' + +config variable + option name 'maxwait' + option title 'Setup wait time' + option description 'Number of seconds to wait for the device to become ready' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=3g' + +config variable + option name 'apn' + option title 'Access point (APN)' + option section 'network.interface' + option datatype 'string' + list depends 'proto=3g' + +config variable + option name 'pincode' + option title 'PIN code' + option section 'network.interface' + option datatype 'uint' + list depends 'proto=3g' + +config variable + option name 'service' + option title 'Service type' + option section 'network.interface' + option type 'enum' + list depends 'proto=3g' + +config enum + option variable 'network.interface.service' + option value 'umts' + option title 'UMTS/GPRS' + +config enum + option variable 'network.interface.service' + option value 'cdma' + option title 'CDMA' + +config enum + option variable 'network.interface.service' + option value 'evdo' + option title 'EV-DO' + +config variable + option name 'proto' + option title 'Protocol' + option section 'network.interface' + option type 'enum' + option required 'true' + +config enum + option variable 'network.interface.proto' + option value 'none' + option title 'Disabled' + +config enum + option variable 'network.interface.proto' + option value 'dhcp' + option title 'Retrieve IP address via DHCP' + option default 'true' + +config enum + option variable 'network.interface.proto' + option value 'pptp' + option title 'Interface is a PPTP tunnel endpoint' + +config enum + option variable 'network.interface.proto' + option value 'static' + option title 'Interface has static network configuration' + +config enum + option variable 'network.interface.proto' + option value 'pppoe' + option title 'Interface is a PPPoE connection' + +config enum + option variable 'network.interface.proto' + option value 'pppoa' + option title 'Interface is a PPPoA connection' + +config enum + option variable 'network.interface.proto' + option value 'ppp' + option title 'Interface is a PPP connection' + +config enum + option variable 'network.interface.proto' + option value '3g' + option title '3G UMTS/GPRS connection' + +config variable + option name 'type' + option title 'Option type' + option section 'network.interface' + option type 'enum' + +config enum + option variable 'network.interface.type' + option value 'bridge' + option title 'This is a bridge interface' + + + +config section + option name 'alias' + option title 'Alias interface definition' + option package 'network' + list depends 'proto=static, ipaddr, netmask' + list depends 'proto=static, ip6addr' + option named 'true' + +config variable + option name 'interface' + option title 'Parent interface' + option section 'network.alias' + option valueof 'network.interface' + option required 'true' + +config variable + option name 'ipaddr' + option title 'IPv4 host address' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'netmask' + option title 'IPv4 network mask' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'gateway' + option title 'IPv4 gateway' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'bcast' + option title 'IPv4 broadcast address' + option section 'network.alias' + option datatype 'ip4addr' + +config variable + option name 'ip6addr' + option title 'IPv6 address (CIDR)' + option section 'network.alias' + option datatype 'ip6addr' + +config variable + option name 'ip6gw' + option title 'IPv6 gateway' + option section 'network.alias' + option datatype 'ip6addr' + +config variable + option name 'dns' + option title 'DNS server (IPv4 or IPv6)' + option section 'network.alias' + option datatype 'ipaddr' + +config variable + option name 'proto' + option title 'Protocol' + option section 'network.alias' + option type 'enum' + option required 'true' + +config enum + option variable 'network.alias.proto' + option value 'static' + option title 'Interface has static network configuration' + + + +config section + option name 'route' + option title 'Static route definition' + option package 'network' + +config variable + option name 'interface' + option title 'Interface' + option section 'network.route' + option valueof 'network.interface' + option required 'true' + +config variable + option name 'target' + option title 'Target IPv4 host or network' + option section 'network.route' + option datatype 'ip4addr' + option required 'true' + +config variable + option name 'netmask' + option title 'Target IPv4 netmask' + option section 'network.route' + option datatype 'ip4addr' + +config variable + option name 'gateway' + option title 'IPv4 gateway' + option section 'network.route' + option datatype 'ip4addr' + +config variable + option name 'metric' + option title 'Metric' + option section 'network.route6' + option datatype 'uint' + + + +config section + option name 'route6' + option title 'Static IPv6 route definition' + option package 'network' + +config variable + option name 'interface' + option title 'Interface' + option section 'network.route6' + option valueof 'network.interface' + option required 'true' + +config variable + option name 'target' + option title 'Target IPv6 host or network (CIDR)' + option section 'network.route6' + option datatype 'ip6addr' + option required 'true' + +config variable + option name 'gateway' + option title 'IPv6 gateway' + option section 'network.route6' + option datatype 'ip6addr' + option required 'false' + +config variable + option name 'metric' + option title 'Metric' + option section 'network.route6' + option datatype 'uint' + + + +config section + option name 'switch' + option title 'Section switch' + option package 'network' + option named 'true' + option dynamic 'true' + option required 'true' diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/system b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/system new file mode 100644 index 0000000..28fee1c --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/system @@ -0,0 +1,103 @@ +package system + +config package + option title 'System configuration' + +config section + option name 'system' + option title 'General system configuration' + option package 'system' + option unique true + option required true + +config variable + option name 'hostname' + option title 'Local hostname' + option section 'system.system' + option datatype 'hostname' + option required true + +config variable + option name 'zonename' + option title 'Option zonename' + option section 'system.system' + +config variable + option name 'timezone' + option title 'Option timezone' + option section 'system.system' + option required true + +config variable + option name 'log_size' + option section 'system.system' + option title 'System log buffer size (kiB)' + option datatype uint + +config variable + option name 'log_ip' + option section 'system.system' + option title 'External system log server' + option datatype ipaddr + +config variable + option name 'conloglevel' + option section 'system.system' + option title 'Log output level' + option description 'Level of log messages on the console' + option datatype integer + +config section + option name 'led' + option package 'system' + option title 'LED Configuration' + +config variable + option name 'name' + option section 'system.led' + option title 'LED Name' + option required true + +config variable + option name 'sysfs' + option section 'system.led' + option title 'LED Device' + option required true + +config variable + option name 'default' + option section 'system.led' + option title 'Default state' + option datatype boolean + +config variable + option name 'trigger' + option section 'system.led' + option title 'Trigger' + option required true + +config variable + option name 'delayon' + option section 'system.led' + option title 'On-State Delay' + option description 'Time (in ms) the LED is on' + list depends 'trigger=timer' + +config variable + option name 'delayoff' + option section 'system.led' + option title 'Off-State Delay' + option description 'Time (in ms) the LED is off' + list depends 'trigger=timer' + +config variable + option name 'dev' + option section 'system.led' + option title 'Device' + list depends 'trigger=netdev' + +config variable + option name 'mode' + option section 'system.led' + option title 'Trigger Mode' + list depends 'trigger=netdev' diff --git a/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/wireless b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/wireless new file mode 100644 index 0000000..85532a1 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/lib/uci/schema/default/wireless @@ -0,0 +1,523 @@ +package wireless + +config package + option title 'Wireless LAN' + +config section + option name 'wifi-device' + option package 'wireless' + option title 'Devices' + option named true + +config variable + option name 'disabled' + option section 'wireless.wifi-device' + option title 'disabled' + option datatype boolean + +config variable + option name 'type' + option section 'wireless.wifi-device' + option title 'Type' + option required true + +config variable + option name 'channel' + option section 'wireless.wifi-device' + option title 'Channel' + +config variable + option name 'hwmode' + option section 'wireless.wifi-device' + option title 'Mode (atheros)' + option type enum + list depends type=atheros + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '' + option title 'auto' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11b' + option title '802.11b' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11g' + option title '802.11g' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11a' + option title '802.11a' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11bg' + option title '802.11b+g' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11gdt' + option title '802.11adt' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value '11adt' + option title '802.11adt' + +config enum + option variable 'wireless.wifi-device.hwmode' + option value 'fh' + option title 'Frequency Hopping' + +config variable + option name 'diversity' + option section 'wireless.wifi-device' + option title 'Diversity (atheros)' + option datatype boolean + list depends type=atheros + +config variable + option name 'txpower' + option section 'wireless.wifi-device' + option title 'Transmit Power' + option description 'dbm' + option datatype uint + +config variable + option name 'txantenna' + option section 'wireless.wifi-device' + option title 'Transmitter Antenna' + option datatype uint + list depends type=atheros + list depends type=broadcom + +config variable + option name 'rxantenna' + option section 'wireless.wifi-device' + option title 'Receiver Antenna' + option datatype uint + list depends type=atheros + list depends type=broadcom + +config variable + option name 'distance' + option section 'wireless.wifi-device' + option title 'Distance Optimization (atheros, broadcom)' + option description 'Distance to farthest network member in meters.' + option datatype uint + list depends type=atheros + list depends type=broadcom + +config variable + option name 'macfilter' + option section 'wireless.wifi-device' + option title 'MAC-Address Filter (broadcom)' + option type enum + list depends type=broadcom + +config enum + option variable 'wireless.wifi-device.macfilter' + option value 'deny' + option title 'Allow listed only' + +config enum + option variable 'wireless.wifi-device.macfilter' + option value 'allow' + option title 'Allow all except listed' + +config variable + option name 'maclist' + option section 'wireless.wifi-device' + option title 'MAC-List (broadcom)' + list depends 'type=broadcom, macfilter=allow' + list depends 'type=broadcom, macfilter=deny' + option type lazylist + option datatype macaddr + +config variable + option name 'frameburst' + option section 'wireless.wifi-device' + option title 'Frame Bursting (broadcom)' + option datatype boolean + list depends 'type=broadcom' + +config variable + option name 'country' + option section 'wireless.wifi-device' + option title 'Country Code (broadcom)' + list depends 'type=broadcom' + +config variable + option name 'maxassoc' + option section 'wireless.wifi-device' + option title 'Connection Limit (broadcom)' + option datatype uint + list depends 'type=broadcom' + + +config section + option name 'wifi-iface' + option package 'wireless' + option title 'Interfaces' + +config variable + option name 'device' + option section 'wireless.wifi-iface' + option title 'Wifi Device' + option valueof 'wireless.wifi-device' + +config variable + option name 'ssid' + option section 'wireless.wifi-iface' + option title 'ESSID' + +config variable + option name 'network' + option section 'wireless.wifi-iface' + option title 'Network' + option description 'Add the Wifi network to physical network' + option type reference + list valueof network.interface + +config variable + option name 'mode' + option section 'wireless.wifi-iface' + option title 'Mode' + option required true + option type enum + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'ap' + option title 'Access Point' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'adhoc' + option title 'Ad-Hoc' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'sta' + option title 'Client' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'monitor' + option title 'Monitor' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'ahdemo' + option title 'Pseudo Ad-Hoc (ahdemo)' + +config enum + option variable 'wireless.wifi-iface.mode' + option value 'wds' + option title 'WDS' + +config variable + option name 'bssid' + option section 'wireless.wifi-iface' + option title 'BSSID' + +config variable + option name 'txpower' + option section 'wireless.wifi-iface' + option title 'Transmit Power' + option description 'dbm' + option datatype uint + +config variable + option name 'frag' + option section 'wireless.wifi-iface' + option title 'Fragmentation Threshold (mac80211, atheros)' + option datatype uint + +config variable + option name 'rts' + option section 'wireless.wifi-iface' + option title 'RTS/CTS Threshold (mac80211, atheros)' + option datatype uint + +config variable + option name 'wds' + option section 'wireless.wifi-iface' + option title 'WDS (atheros)' + option datatype boolean + list depends 'mode=ap' + list depends 'mode=sta' + +config variable + option name 'wdssep' + option section 'wireless.wifi-iface' + option title 'Separate WDS (atheros)' + option datatype boolean + list depends 'wds=1,mode=ap' + +config variable + option name 'doth' + option section 'wireless.wifi-iface' + option title '802.11h (atheros)' + option datatype boolean + +config variable + option name 'hidden' + option section 'wireless.wifi-iface' + option title 'Hide ESSID (atheros, broadcom)' + option datatype boolean + list depends 'mode=ap' + list depends 'mode=adhoc' + list depends 'mode=wds' + +config variable + option name 'isolate' + option section 'wireless.wifi-iface' + option title 'isolate (atheros, broadcom)' + option datatype boolean + list depends 'mode=ap' + +config variable + option name 'bgscan' + option section 'wireless.wifi-iface' + option title 'Background Scan (atheros)' + option datatype boolean + +config variable + option name 'sw_merge' + option section 'wireless.wifi-iface' + option title 'Disable Ad-Hoc HW beacon timer (atheros)' + option datatype boolean + +config variable + option name 'nosbeacon' + option section 'wireless.wifi-iface' + option title 'Disable station HW beacon timer (atheros)' + option datatype boolean + +config variable + option name 'probereq' + option section 'wireless.wifi-iface' + option title 'Disable probe responses (atheros)' + option datatype boolean + +config variable + option name 'macpolicy' + option section 'wireless.wifi-iface' + option title 'MAC-Address Filter (atheros)' + option type enum + +config enum + option variable 'wireless.wifi-iface.macpolicy' + option value 'deny' + option title 'Allow listed only' + +config enum + option variable 'wireless.wifi-iface.macpolicy' + option value 'allow' + option title 'Allow all except listed' + +config variable + option name 'maclist' + option section 'wireless.wifi-iface' + option title 'MAC-List (atheros)' + list depends 'macpolicy=allow' + list depends 'macpolicy=deny' + option type lazylist + option datatype macaddr + +config variable + option name 'rate' + option section 'wireless.wifi-iface' + option title 'Transmission Rate (atheros)' + +config variable + option name 'mcast_rate' + option section 'wireless.wifi-iface' + option title 'Multicast Rate (atheros)' + +config variable + option name 'minrate' + option section 'wireless.wifi-iface' + option title 'Minimum Rate (atheros)' + +config variable + option name 'maxrate' + option section 'wireless.wifi-iface' + option title 'Maximum Rate (atheros)' + +config variable + option name 'compression' + option section 'wireless.wifi-iface' + option title 'Compression (atheros)' + option datatype boolean + +config variable + option name 'bursting' + option section 'wireless.wifi-iface' + option title 'Frame Bursting (atheros)' + option datatype boolean + +config variable + option name 'turbo' + option section 'wireless.wifi-iface' + option title 'Turbo Mode (atheros)' + option datatype boolean + +config variable + option name 'ff' + option section 'wireless.wifi-iface' + option title 'Fast Frames (atheros)' + +config variable + option name 'wmm' + option section 'wireless.wifi-iface' + option title 'WMM Mode (atheros)' + option datatype boolean + +config variable + option name 'xr' + option section 'wireless.wifi-iface' + option title 'XR Support (atheros)' + option datatype boolean + +config variable + option name 'ar' + option section 'wireless.wifi-iface' + option title 'AR Support (atheros)' + option datatype boolean + +config variable + option name 'encryption' + option section 'wireless.wifi-iface' + option title 'Encryption' + option description 'WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP and ad-hoc mode) to be installed.' + option type enum + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'none' + option title 'No Encryption' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'wep' + option title 'WEP' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'psk' + option title 'WPA-PSK' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'psk2' + option title 'WPA2-PSK' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'wpa' + option title 'WPA-EAP' + +config enum + option variable 'wireless.wifi-iface.encryption' + option value 'wpa2i' + option title 'WPA2-EAP' + +config variable + option name 'server' + option section 'wireless.wifi-iface' + option title 'RadiusServer' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=wpa2i,mode=ap' + option datatype host + +config variable + option name 'port' + option section 'wireless.wifi-iface' + option title 'Radius-Port' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=wpa2i,mode=ap' + option datatype port + +config variable + option name 'key' + option section 'wireless.wifi-iface' + option title 'Key' + list depends 'encryption=wep' + list depends 'encryption=psk' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=psk2' + list depends 'encryption=wpa2i,mode=ap' + +config variable + option name 'nasid' + option section 'wireless.wifi-iface' + option title 'NAS ID' + list depends 'encryption=wpa,mode=ap' + list depends 'encryption=wpa2i,mode=ap' + +config variable + option name 'eap_type' + option section 'wireless.wifi-iface' + option title 'EAP-Method' + option type enum + list depends 'encryption=wpa,mode=sta' + list depends 'encryption=wpa2i,mode=sta' + +config enum + option variable 'wireless.wifi-iface.eap_type' + option value 'TLS' + +config enum + option variable 'wireless.wifi-iface.eap_type' + option value 'PEAP' + +config variable + option name 'ca_cert' + option section 'wireless.wifi-iface' + option title 'Path to CA-Certificate' + list depends 'encryption=wpa,mode=sta' + list depends 'encryption=wpa2i,mode=sta' + option datatype file + +config variable + option name 'priv_key' + option section 'wireless.wifi-iface' + option title 'Path to Private Key' + list depends 'mode=sta,encryption=wpa2i,eap_type=TLS' + list depends 'mode=sta,encryption=wpa,eap_type=TLS' + option datatype file + + +config variable + option name 'priv_key_pwd' + option section 'wireless.wifi-iface' + option title 'Password of Private Key' + list depends 'mode=sta,encryption=wpa2i,eap_type=TLS' + list depends 'mode=sta,encryption=wpa,eap_type=TLS' + +config variable + option name 'auth' + option section 'wireless.wifi-iface' + option title 'PEAP-Authentication' + list depends 'mode=sta,encryption=wpa2i,eap_type=PEAP' + list depends 'mode=sta,encryption=wpa,eap_type=PEAP' + +config variable + option name 'identity' + option section 'wireless.wifi-iface' + option title 'PEAP-Identity' + list depends 'mode=sta,encryption=wpa2i,eap_type=PEAP' + list depends 'mode=sta,encryption=wpa,eap_type=PEAP' + +config variable + option name 'password' + option section 'wireless.wifi-iface' + option title 'PEAP-Password' + list depends 'mode=sta,encryption=wpa2i,eap_type=PEAP' + list depends 'mode=sta,encryption=wpa,eap_type=PEAP' diff --git a/openwrt/packages/luci/modules/admin-core/root/sbin/luci-flash b/openwrt/packages/luci/modules/admin-core/root/sbin/luci-flash new file mode 100755 index 0000000..819be40 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-core/root/sbin/luci-flash @@ -0,0 +1,89 @@ +#!/bin/sh +. /etc/functions.sh + +# initialize defaults +RAMFS_COPY_BIN="/usr/bin/awk" # extra programs for temporary ramfs root +RAMFS_COPY_DATA="" # extra data files +export KEEP_PATTERN="" +export VERBOSE=0 + +# parse options +while [ -n "$1" ]; do + case "$1" in + -k) + shift + export SAVE_CONFIG=1 + 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 < + +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' diff --git a/openwrt/packages/luci/modules/admin-full/Makefile b/openwrt/packages/luci/modules/admin-full/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/filebrowser.lua b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/filebrowser.lua new file mode 100644 index 0000000..4c19b46 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/filebrowser.lua @@ -0,0 +1,20 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: filebrowser.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +module("luci.controller.admin.filebrowser", package.seeall) + +function index() + entry( {"admin", "filebrowser"}, template("cbi/filebrowser") ).leaf = true +end diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/index.lua b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/index.lua new file mode 100644 index 0000000..41f423c --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/index.lua @@ -0,0 +1,67 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: index.lua 4041 2009-01-16 12:39:50Z Cyrus $ +]]-- +module("luci.controller.admin.index", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + local root = node() + if not root.target then + root.target = alias("admin") + root.index = true + end + + entry({"about"}, template("about")).i18n = "admin-core" + + local page = node("admin") + page.target = alias("admin", "index") + page.title = i18n("administration", "Administration") + page.order = 10 + page.i18n = "admin-core" + page.sysauth = "root" + page.sysauth_authenticator = "htmlauth" + page.ucidata = true + page.index = true + + local page = node("admin", "index") + page.target = template("admin_index/index") + page.title = i18n("overview", "Übersicht") + page.order = 10 + page.index = true + + local page = node("admin", "index", "luci") + page.target = cbi("admin_index/luci") + page.title = i18n("a_i_ui", "Oberfläche") + page.order = 10 + + entry({"admin", "index", "components"}, call("redir_components"), i18n("luci_components", "LuCI Components"), 20) + entry({"admin", "index", "logout"}, call("action_logout"), i18n("logout"), 90) +end + +function redir_components() + luci.http.redirect(luci.dispatcher.build_url("admin", "system", "packages")..'?update=1&query=luci') +end + +function action_logout() + local dsp = require "luci.dispatcher" + local sauth = require "luci.sauth" + if dsp.context.authsession then + sauth.kill(dsp.context.authsession) + dsp.context.urltoken.stok = nil + end + + luci.http.header("Set-Cookie", "sysauth=; path=" .. dsp.build_url()) + luci.http.redirect(luci.dispatcher.build_url()) +end diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/network.lua b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/network.lua new file mode 100644 index 0000000..6d12abb --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/network.lua @@ -0,0 +1,97 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: network.lua 3995 2009-01-04 15:47:53Z Cyrus $ +]]-- +module("luci.controller.admin.network", package.seeall) + +function index() + require("luci.i18n") + local uci = require("luci.model.uci").cursor() + local i18n = luci.i18n.translate + + local page = node("admin", "network") + page.target = alias("admin", "network", "network") + page.title = i18n("network") + page.order = 50 + page.index = true + + local page = node("admin", "network", "vlan") + page.target = cbi("admin_network/vlan") + page.title = i18n("a_n_switch") + page.order = 20 + + local page = entry({"admin", "network", "wireless"}, arcombine(cbi("admin_network/wireless"), cbi("admin_network/wifi")), i18n("wifi"), 15) + page.i18n = "wifi" + page.leaf = true + page.subindex = true + + uci:foreach("wireless", "wifi-device", + function (section) + local ifc = section[".name"] + entry({"admin", "network", "wireless", ifc}, + true, + ifc:upper()).i18n = "wifi" + end + ) + + local page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), i18n("interfaces", "Schnittstellen"), 10) + page.leaf = true + page.subindex = true + + uci:foreach("network", "interface", + function (section) + local ifc = section[".name"] + if ifc ~= "loopback" then + entry({"admin", "network", "network", ifc}, + true, + ifc:upper()) + end + end + ) + + local page = node("admin", "network", "dhcp") + page.target = cbi("admin_network/dhcp") + page.title = "DHCP" + page.order = 30 + page.subindex = true + + entry( + {"admin", "network", "dhcp", "leases"}, + cbi("admin_network/dhcpleases"), + i18n("dhcp_leases") + ) + + local page = node("admin", "network", "hosts") + page.target = cbi("admin_network/hosts") + page.title = i18n("hostnames", "Hostnames") + page.order = 40 + + local page = node("admin", "network", "routes") + page.target = cbi("admin_network/routes") + page.title = i18n("a_n_routes") + page.order = 50 + page.leaf = true + + entry( + {"admin", "network", "routes", "static"}, + function() end, + i18n("a_n_routes_static") + ) + + entry( + {"admin", "network", "conntrack"}, + form("admin_network/conntrack"), + i18n("a_n_conntrack"), + 60 + ) + +end \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/services.lua b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/services.lua new file mode 100644 index 0000000..6f4fa77 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/services.lua @@ -0,0 +1,54 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: services.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +module("luci.controller.admin.services", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + local page = node("admin", "services", "crontab") + page.target = form("admin_services/crontab") + page.title = i18n("a_s_crontab") + page.order = 50 + + local page = node("admin", "services") + page.target = template("admin_services/index") + page.title = i18n("services", "Dienste") + page.order = 40 + page.index = true + + if luci.fs.access("/etc/config/lucittpd") then + local page = node("admin", "services", "lucittpd") + page.target = cbi("admin_services/lucittpd") + page.title = "LuCIttpd" + page.order = 10 + end + + if luci.fs.access("/etc/config/httpd") then + local page = node("admin", "services", "httpd") + page.target = cbi("admin_services/httpd") + page.title = "Busybox HTTPd" + page.order = 11 + end + + local page = node("admin", "services", "dropbear") + page.target = cbi("admin_services/dropbear") + page.title = "Dropbear SSHd" + page.order = 20 + + local page = node("admin", "services", "dnsmasq") + page.target = cbi("admin_services/dnsmasq") + page.title = "Dnsmasq" + page.order = 30 +end \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/status.lua b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/status.lua new file mode 100644 index 0000000..8133013 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/status.lua @@ -0,0 +1,33 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: status.lua 3792 2008-11-16 22:46:25Z jow $ +]]-- +module("luci.controller.admin.status", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + entry({"admin", "status"}, template("admin_status/index"), i18n("status", "Status"), 20).index = true + entry({"admin", "status", "syslog"}, call("action_syslog"), i18n("syslog", "Systemprotokoll"), 1) + entry({"admin", "status", "dmesg"}, call("action_dmesg"), i18n("dmesg", "Kernelprotokoll"), 2) +end + +function action_syslog() + local syslog = luci.sys.syslog() + luci.template.render("admin_status/syslog", {syslog=syslog}) +end + +function action_dmesg() + local dmesg = luci.sys.dmesg() + luci.template.render("admin_status/dmesg", {dmesg=dmesg}) +end diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/system.lua b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/system.lua new file mode 100644 index 0000000..9d4422d --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/system.lua @@ -0,0 +1,235 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: system.lua 4065 2009-01-17 13:21:50Z Cyrus $ +]]-- +module("luci.controller.admin.system", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + entry({"admin", "system"}, alias("admin", "system", "system"), i18n("system"), 30).index = true + entry({"admin", "system", "system"}, cbi("admin_system/system"), i18n("system"), 1) + entry({"admin", "system", "packages"}, call("action_packages"), i18n("a_s_packages"), 10) + entry({"admin", "system", "packages", "ipkg"}, form("admin_system/ipkg")) + entry({"admin", "system", "passwd"}, form("admin_system/passwd"), i18n("a_s_changepw"), 20) + entry({"admin", "system", "sshkeys"}, form("admin_system/sshkeys"), i18n("a_s_sshkeys"), 30) + entry({"admin", "system", "processes"}, form("admin_system/processes"), i18n("process_head"), 45) + entry({"admin", "system", "fstab"}, cbi("admin_system/fstab"), i18n("a_s_fstab"), 50) + + if luci.fs.isdirectory("/sys/class/leds") then + entry({"admin", "system", "leds"}, cbi("admin_system/leds"), i18n("leds", "LEDs"), 60) + end + + entry({"admin", "system", "backup"}, call("action_backup"), i18n("a_s_backup"), 70) + entry({"admin", "system", "upgrade"}, call("action_upgrade"), i18n("a_s_flash"), 80) + entry({"admin", "system", "reboot"}, call("action_reboot"), i18n("reboot"), 90) +end + +function action_packages() + local ipkg = require("luci.model.ipkg") + local void = nil + local submit = luci.http.formvalue("submit") + + + -- Search query + local query = luci.http.formvalue("query") + query = (query ~= '') and query or nil + + + -- Packets to be installed + local install = submit and luci.http.formvaluetable("install") + + -- Install from URL + local url = luci.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 = submit and luci.http.formvaluetable("remove") + if remove then + for k, v in pairs(remove) do + void, remove[k] = ipkg.remove(k) + end + end + + + -- Update all packets + local update = luci.http.formvalue("update") + if update then + void, update = ipkg.update() + end + + + -- Upgrade all packets + local upgrade = luci.http.formvalue("upgrade") + if upgrade then + void, upgrade = ipkg.upgrade() + end + + + -- Package info + local info = luci.model.ipkg.info(query and "*"..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 + + luci.template.render("admin_system/packages", {pkgs=pkgs, query=query, + install=install, remove=remove, update=update, upgrade=upgrade}) +end + +function action_backup() + local reset_avail = os.execute([[grep '"rootfs_data"' /proc/mtd >/dev/null 2>&1]]) == 0 + local restore_cmd = "gunzip | tar -xC/ >/dev/null 2>&1" + local backup_cmd = "tar -c %s | gzip 2>/dev/null" + + local restore_fpi + luci.http.setfilehandler( + function(meta, chunk, eof) + if not restore_fpi then + restore_fpi = io.popen(restore_cmd, "w") + end + if chunk then + restore_fpi:write(chunk) + end + if eof then + restore_fpi:close() + end + end + ) + + local upload = luci.http.formvalue("archive") + local backup = luci.http.formvalue("backup") + local reset = reset_avail and luci.http.formvalue("reset") + + if upload and #upload > 0 then + luci.template.render("admin_system/applyreboot") + luci.sys.reboot() + elseif backup then + luci.util.perror(backup_cmd:format(_keep_pattern())) + local backup_fpi = io.popen(backup_cmd:format(_keep_pattern()), "r") + luci.http.header('Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % { + luci.sys.hostname(), os.date("%Y-%m-%d")}) + luci.http.prepare_content("application/x-targz") + luci.ltn12.pump.all(luci.ltn12.source.file(backup_fpi), luci.http.write) + elseif reset then + luci.template.render("admin_system/applyreboot") + luci.util.exec("mtd -r erase rootfs_data") + else + luci.template.render("admin_system/backup", {reset_avail = reset_avail}) + end +end + +function action_passwd() + local p1 = luci.http.formvalue("pwd1") + local p2 = luci.http.formvalue("pwd2") + local stat = nil + + if p1 or p2 then + if p1 == p2 then + stat = luci.sys.user.setpasswd("root", p1) + else + stat = 10 + end + end + + luci.template.render("admin_system/passwd", {stat=stat}) +end + +function action_reboot() + local reboot = luci.http.formvalue("reboot") + luci.template.render("admin_system/reboot", {reboot=reboot}) + if reboot then + luci.sys.reboot() + end +end + +function action_upgrade() + require("luci.model.uci") + + local ret + local plat = luci.fs.mtime("/lib/upgrade/platform.sh") + local tmpfile = "/tmp/firmware.img" + local keep_avail = true + + local file + luci.http.setfilehandler( + function(meta, chunk, eof) + if not file then + file = io.open(tmpfile, "w") + end + if chunk then + file:write(chunk) + end + if eof then + file:close() + end + end + ) + + local fname = luci.http.formvalue("image") + local keepcfg = keep_avail and luci.http.formvalue("keepcfg") + + if plat and fname then + ret = function() + return luci.sys.flash(tmpfile, keepcfg and _keep_pattern()) + end + end + + luci.http.prepare_content("text/html") + luci.template.render("admin_system/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail}) +end + +function _keep_pattern() + local kpattern = "" + local files = luci.model.uci.cursor():get_all("luci", "flash_keep") + if files then + kpattern = "" + for k, v in pairs(files) do + if k:sub(1,1) ~= "." and luci.fs.glob(v) then + kpattern = kpattern .. " " .. v + end + end + end + return kpattern +end diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/uci.lua b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/uci.lua new file mode 100644 index 0000000..ddecd9b --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/controller/admin/uci.lua @@ -0,0 +1,90 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: uci.lua 3650 2008-10-29 19:40:40Z jow $ +]]-- +module("luci.controller.admin.uci", package.seeall) + +function index() + local i18n = luci.i18n.translate + local redir = luci.http.formvalue("redir", true) or + luci.dispatcher.build_url(unpack(luci.dispatcher.context.request)) + + entry({"admin", "uci"}, nil, i18n("config")) + entry({"admin", "uci", "changes"}, call("action_changes"), i18n("changes"), 40).query = {redir=redir} + entry({"admin", "uci", "revert"}, call("action_revert"), i18n("revert"), 30).query = {redir=redir} + entry({"admin", "uci", "apply"}, call("action_apply"), i18n("apply"), 20).query = {redir=redir} + entry({"admin", "uci", "saveapply"}, call("action_apply"), i18n("saveapply"), 10).query = {redir=redir} +end + +function convert_changes(changes) + local util = require "luci.util" + + local ret + for r, tbl in pairs(changes) do + for s, os in pairs(tbl) do + for o, v in pairs(os) do + ret = (ret and ret.."\n" or "") .. "%s%s.%s%s%s" % { + v == "" and "-" or "", + r, + s, + o ~= ".type" and "."..o or "", + v ~= "" and "="..util.pcdata(v) or "" + } + end + end + end + return ret +end + +function action_changes() + local changes = convert_changes(luci.model.uci.cursor():changes()) + luci.template.render("admin_uci/changes", {changes=changes}) +end + +function action_apply() + local path = luci.dispatcher.context.path + local uci = luci.model.uci.cursor() + local changes = uci:changes() + local reload = {} + + -- Collect files to be applied and commit changes + for r, tbl in pairs(changes) do + table.insert(reload, r) + if path[#path] ~= "apply" then + uci:load(r) + uci:commit(r) + uci:unload(r) + end + end + + local function _reload() + local cmd = uci:apply(reload, true) + return io.popen(cmd) + end + + luci.template.render("admin_uci/apply", {changes=convert_changes(changes), reload=_reload}) +end + + +function action_revert() + local uci = luci.model.uci.cursor() + local changes = uci:changes() + + -- Collect files to be reverted + for r, tbl in pairs(changes) do + uci:load(r) + uci:revert(r) + uci:unload(r) + end + + luci.template.render("admin_uci/revert", {changes=convert_changes(changes)}) +end diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_index/luci.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_index/luci.lua new file mode 100644 index 0000000..bba0cf3 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_index/luci.lua @@ -0,0 +1,52 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: luci.lua 4038 2009-01-14 23:48:51Z Cyrus $ +]]-- +require("luci.config") +m = Map("luci", translate("webui"), translate("a_i_luci1", + "Hier können Eigenschaften und die Funktionalität der Oberfläche angepasst werden.")) + +-- force reload of global luci config namespace to reflect the changes +function m.commit_handler(self) + package.loaded["luci.config"] = nil + require("luci.config") +end + + +c = m:section(NamedSection, "main", "core", translate("general")) + +l = c:option(ListValue, "lang", translate("language")) +l:value("auto") + +local i18ndir = luci.i18n.i18ndir .. "default." +for k, v in pairs(luci.config.languages) do + if k:sub(1, 1) ~= "." and luci.fs.access(i18ndir .. k:gsub("_", "-") .. ".lua") then + l:value(k, v) + end +end + +t = c:option(ListValue, "mediaurlbase", translate("design")) +for k, v in pairs(luci.config.themes) do + if k:sub(1, 1) ~= "." then + t:value(v, k) + end +end + +u = m:section(NamedSection, "uci_oncommit", "event", translate("a_i_ucicommit"), + translate("a_i_ucicommit1")) +u.dynamic = true + +f = m:section(NamedSection, "flash_keep", "extern", translate("a_i_keepflash"), + translate("a_i_keepflash1")) +f.dynamic = true + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/conntrack.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/conntrack.lua new file mode 100644 index 0000000..4daab8a --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/conntrack.lua @@ -0,0 +1,49 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: conntrack.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +f = SimpleForm("conntrack", translate("a_n_conntrack"), translate("a_n_conntrack_desc")) +f.reset = false +f.submit = false + +t = f:section(Table, luci.sys.net.arptable(), "ARP") +t:option(DummyValue, "IP address", translate("ipaddress")) +t:option(DummyValue, "HW address", translate("macaddress")) +t:option(DummyValue, "Device", translate("interface")) + +t = f:section(Table, luci.sys.net.conntrack() or {}, translate("a_n_conntrack")) +l3 = t:option(DummyValue, "layer3", translate("network")) +function l3.cfgvalue(self, ...) + return DummyValue.cfgvalue(self, ...):upper() +end + + +l4 = t:option(DummyValue, "layer4", translate("protocol")) +function l4.cfgvalue(self, ...) + return DummyValue.cfgvalue(self, ...):upper() +end + +s = t:option(DummyValue, "src", translate("source")) +function s.cfgvalue(self, section) + return "%s:%s" % { self.map:get(section, "src"), + self.map:get(section, "sport") or "*" } +end + +d = t:option(DummyValue, "dst", translate("destination")) +function d.cfgvalue(self, section) + return "%s:%s" % { self.map:get(section, "dst"), + self.map:get(section, "dport") or "*" } +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcp.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcp.lua new file mode 100644 index 0000000..c366f02 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcp.lua @@ -0,0 +1,72 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dhcp.lua 3796 2008-11-18 12:29:25Z Cyrus $ +]]-- +require("luci.tools.webadmin") +require("luci.model.uci") +require("luci.util") + +m = Map("dhcp", "DHCP") + +s = m:section(TypedSection, "dhcp", "") +s.addremove = true +s.anonymous = true + +iface = s:option(ListValue, "interface", translate("interface")) +luci.tools.webadmin.cbi_add_networks(iface) + +local uci = luci.model.uci.cursor() +uci:foreach("network", "interface", + function (section) + if section[".name"] ~= "loopback" then + iface.default = iface.default or section[".name"] + s:depends("interface", section[".name"]) + end + end) + +uci:foreach("network", "alias", + function (section) + iface:value(section[".name"]) + s:depends("interface", section[".name"]) + end) + +s:option(Value, "start", translate("start")).rmempty = true + +s:option(Value, "limit", translate("limit")).rmempty = true + +s:option(Value, "leasetime").rmempty = true + +local dd = s:option(Flag, "dynamicdhcp") +dd.rmempty = false +function dd.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "1" +end + +s:option(Value, "name", translate("name")).optional = true + +ignore = s:option(Flag, "ignore") +ignore.optional = true + +s:option(Value, "netmask", translate("netmask")).optional = true + +s:option(Flag, "force").optional = true + +s:option(DynamicList, "dhcp_option").optional = true + + +for i, n in ipairs(s.children) do + if n ~= iface and n ~= ignore then + n:depends("ignore", "") + end +end + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcpleases.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcpleases.lua new file mode 100644 index 0000000..7a39b85 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/dhcpleases.lua @@ -0,0 +1,61 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dhcpleases.lua 2960 2008-08-26 23:00:44Z Cyrus $ +]]-- +require("luci.sys") +require("luci.tools.webadmin") +m2 = Map("luci_ethers", translate("dhcp_leases")) + +local leasefn, leasefp, leases +luci.model.uci.cursor():foreach("dhcp", "dnsmasq", + function(section) + leasefn = section.leasefile + end +) +local leasefp = leasefn and luci.fs.access(leasefn) and io.lines(leasefn) +if leasefp then + leases = {} + for lease in leasefp do + table.insert(leases, luci.util.split(lease, " ")) + end +end + +if leases then + v = m2:section(Table, leases, translate("dhcp_leases_active")) + ip = v:option(DummyValue, 3, translate("ipaddress")) + + mac = v:option(DummyValue, 2, translate("macaddress")) + + ltime = v:option(DummyValue, 1, translate("dhcp_timeremain")) + function ltime.cfgvalue(self, ...) + local value = DummyValue.cfgvalue(self, ...) + return luci.tools.webadmin.date_format( + os.difftime(tonumber(value), os.time()) + ) + end +end + +s = m2:section(TypedSection, "static_lease", translate("luci_ethers")) +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" + +mac = s:option(Value, "macaddr", translate("macaddress")) +ip = s:option(Value, "ipaddr", translate("ipaddress")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + ip:value(dataset["IP address"]) + mac:value(dataset["HW address"], + dataset["HW address"] .. " (" .. dataset["IP address"] .. ")") +end + + +return m2 diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/hosts.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/hosts.lua new file mode 100644 index 0000000..024625c --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/hosts.lua @@ -0,0 +1,33 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: hosts.lua 3172 2008-09-06 23:29:58Z jow $ +]]-- + +require("luci.sys") +require("luci.util") +m = Map("luci_hosts", translate("hostnames")) + +s = m:section(TypedSection, "host", translate("hostnames_entries")) +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" + +hn = s:option(Value, "hostname", translate("hostnames_hostname")) +ip = s:option(Value, "ipaddr", translate("hostnames_address")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + ip:value( + dataset["IP address"], + "%s (%s)" %{ dataset["IP address"], dataset["HW address"] } + ) +end + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/ifaces.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/ifaces.lua new file mode 100644 index 0000000..ca98216 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/ifaces.lua @@ -0,0 +1,343 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ifaces.lua 4114 2009-01-25 12:16:33Z Cyrus $ +]]-- + +require("luci.tools.webadmin") +arg[1] = arg[1] or "" + +local has_3g = luci.fs.mtime("/usr/bin/gcom") +local has_pptp = luci.fs.mtime("/usr/sbin/pptp") +local has_pppd = luci.fs.mtime("/usr/sbin/pppd") +local has_pppoe = luci.fs.glob("/usr/lib/pppd/*/rp-pppoe.so") +local has_pppoa = luci.fs.glob("/usr/lib/pppd/*/pppoatm.so") + +m = Map("network", translate("interfaces"), translate("a_n_ifaces1")) + +s = m:section(NamedSection, arg[1], "interface") +s.addremove = true + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "network") + +p = s:option(ListValue, "proto", translate("protocol")) +p.override_scheme = true +p.default = "static" +p:value("static", translate("static")) +p:value("dhcp", "DHCP") +if has_pppd then p:value("ppp", "PPP") end +if has_pppoe then p:value("pppoe", "PPPoE") end +if has_pppoa then p:value("pppoa", "PPPoA") end +if has_3g then p:value("3g", "UMTS/3G") end +if has_pptp then p:value("pptp", "PPTP") end +p:value("none", translate("none")) + +if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then + p.description = translate("network_interface_prereq") +end + +br = s:option(Flag, "type", translate("a_n_i_bridge"), translate("a_n_i_bridge1")) +br.enabled = "bridge" +br.rmempty = true + +ifname = s:option(Value, "ifname", translate("interface")) +ifname.rmempty = true +for i,d in ipairs(luci.sys.net.devices()) do + if d ~= "lo" then + ifname:value(d) + end +end + +local zones = luci.tools.webadmin.network_get_zones(arg[1]) +if zones then + if #zones == 0 then + m:chain("firewall") + + fwzone = s:option(Value, "_fwzone", + translate("network_interface_fwzone"), + translate("network_interface_fwzone_desc")) + fwzone.rmempty = true + fwzone:value("", "- " .. translate("none") .. " -") + fwzone:value(arg[1]) + m.uci:load("firewall") + m.uci:foreach("firewall", "zone", + function (section) + fwzone:value(section.name) + end + ) + + function fwzone.write(self, section, value) + local zone = luci.tools.webadmin.firewall_find_zone(value) + local stat + + if not zone then + stat = m.uci:section("firewall", "zone", nil, { + name = value, + network = section + }) + else + local net = m.uci:get("firewall", zone, "network") + net = (net or value) .. " " .. section + stat = m.uci:set("firewall", zone, "network", net) + end + + if stat then + self.render = function() end + end + end + else + fwzone = s:option(DummyValue, "_fwzone", translate("zone")) + fwzone.value = table.concat(zones, ", ") + end + fwzone.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "zones") + m.uci:unload("firewall") +end + +ipaddr = s:option(Value, "ipaddr", translate("ipaddress")) +ipaddr.rmempty = true +ipaddr:depends("proto", "static") + +nm = s:option(Value, "netmask", translate("netmask")) +nm.rmempty = true +nm:depends("proto", "static") +nm:value("255.255.255.0") +nm:value("255.255.0.0") +nm:value("255.0.0.0") + +gw = s:option(Value, "gateway", translate("gateway")) +gw:depends("proto", "static") +gw.rmempty = true + +bcast = s:option(Value, "bcast", translate("broadcast")) +bcast:depends("proto", "static") +bcast.optional = true + +ip6addr = s:option(Value, "ip6addr", translate("ip6address"), translate("cidr6")) +ip6addr.optional = true +ip6addr:depends("proto", "static") + +ip6gw = s:option(Value, "ip6gw", translate("gateway6")) +ip6gw:depends("proto", "static") +ip6gw.optional = true + +dns = s:option(Value, "dns", translate("dnsserver")) +dns.optional = true + +mtu = s:option(Value, "mtu", "MTU") +mtu.optional = true +mtu.isinteger = true + +mac = s:option(Value, "macaddr", translate("macaddress")) +mac.optional = true + + +srv = s:option(Value, "server", translate("network_interface_server")) +srv:depends("proto", "pptp") +srv.rmempty = true + +if has_3g then + service = s:option(ListValue, "service", translate("network_interface_service")) + service:value("", translate("cbi_select")) + service:value("umts", "UMTS/GPRS") + service:value("cdma", "CDMA") + service:value("evdo", "EV-DO") + service:depends("proto", "3g") + service.rmempty = true + + apn = s:option(Value, "apn", translate("network_interface_apn")) + apn:depends("proto", "3g") + + pincode = s:option(Value, "pincode", + translate("network_interface_pincode"), + translate("network_interface_pincode_desc") + ) + pincode:depends("proto", "3g") +end + +if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then + user = s:option(Value, "username", translate("username")) + user.rmempty = true + user:depends("proto", "pptp") + user:depends("proto", "pppoe") + user:depends("proto", "pppoa") + user:depends("proto", "ppp") + user:depends("proto", "3g") + + pass = s:option(Value, "password", translate("password")) + pass.rmempty = true + pass.password = true + pass:depends("proto", "pptp") + pass:depends("proto", "pppoe") + pass:depends("proto", "pppoa") + pass:depends("proto", "ppp") + pass:depends("proto", "3g") + + ka = s:option(Value, "keepalive", + translate("network_interface_keepalive"), + translate("network_interface_keepalive_desc") + ) + ka.optional = true + ka:depends("proto", "pptp") + ka:depends("proto", "pppoe") + ka:depends("proto", "pppoa") + ka:depends("proto", "ppp") + ka:depends("proto", "3g") + + demand = s:option(Value, "demand", + translate("network_interface_demand"), + translate("network_interface_demand_desc") + ) + demand.optional = true + demand:depends("proto", "pptp") + demand:depends("proto", "pppoe") + demand:depends("proto", "pppoa") + demand:depends("proto", "ppp") + demand:depends("proto", "3g") +end + +if has_pppoa then + encaps = s:option(ListValue, "encaps", translate("network_interface_encaps")) + encaps.optional = false + encaps:depends("proto", "pppoa") + encaps:value("", translate("cbi_select")) + encaps:value("vc", "VC") + encaps:value("llc", "LLC") + + vpi = s:option(Value, "vpi", "VPI") + vpi.optional = false + vpi:depends("proto", "pppoa") + + vci = s:option(Value, "vci", "VCI") + vci.optional = false + vci:depends("proto", "pppoa") +end + +if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then + device = s:option(Value, "device", + translate("network_interface_device"), + translate("network_interface_device_desc") + ) + device:depends("proto", "ppp") + device:depends("proto", "3g") + + defaultroute = s:option(Flag, "defaultroute", + translate("network_interface_defaultroute"), + translate("network_interface_defaultroute_desc") + ) + defaultroute:depends("proto", "ppp") + defaultroute:depends("proto", "pppoa") + defaultroute:depends("proto", "pppoe") + defaultroute:depends("proto", "pptp") + defaultroute:depends("proto", "3g") + defaultroute.rmempty = false + function defaultroute.cfgvalue(...) + return ( AbstractValue.cfgvalue(...) or '1' ) + end + + peerdns = s:option(Flag, "peerdns", + translate("network_interface_peerdns"), + translate("network_interface_peerdns_desc") + ) + peerdns:depends("proto", "ppp") + peerdns:depends("proto", "pppoa") + peerdns:depends("proto", "pppoe") + peerdns:depends("proto", "pptp") + peerdns:depends("proto", "3g") + peerdns.rmempty = false + function peerdns.cfgvalue(...) + return ( AbstractValue.cfgvalue(...) or '1' ) + end + + ipv6 = s:option(Flag, "ipv6", translate("network_interface_ipv6") ) + ipv6:depends("proto", "ppp") + ipv6:depends("proto", "pppoa") + ipv6:depends("proto", "pppoe") + ipv6:depends("proto", "pptp") + ipv6:depends("proto", "3g") + + connect = s:option(Value, "connect", + translate("network_interface_connect"), + translate("network_interface_connect_desc") + ) + connect.optional = true + connect:depends("proto", "ppp") + connect:depends("proto", "pppoe") + connect:depends("proto", "pppoa") + connect:depends("proto", "pptp") + connect:depends("proto", "3g") + + disconnect = s:option(Value, "disconnect", + translate("network_interface_disconnect"), + translate("network_interface_disconnect_desc") + ) + disconnect.optional = true + disconnect:depends("proto", "ppp") + disconnect:depends("proto", "pppoe") + disconnect:depends("proto", "pppoa") + disconnect:depends("proto", "pptp") + disconnect:depends("proto", "3g") + + pppd_options = s:option(Value, "pppd_options", + translate("network_interface_pppd_options"), + translate("network_interface_pppd_options_desc") + ) + pppd_options.optional = true + pppd_options:depends("proto", "ppp") + pppd_options:depends("proto", "pppoa") + pppd_options:depends("proto", "pppoe") + pppd_options:depends("proto", "pptp") + pppd_options:depends("proto", "3g") + + maxwait = s:option(Value, "maxwait", + translate("network_interface_maxwait"), + translate("network_interface_maxwait_desc") + ) + maxwait.optional = true + maxwait:depends("proto", "3g") +end + +s2 = m:section(TypedSection, "alias", translate("aliases")) +s2.addremove = true + +s2:depends("interface", arg[1]) +s2.defaults.interface = arg[1] + + +s2.defaults.proto = "static" + +ipaddr = s2:option(Value, "ipaddr", translate("ipaddress")) +ipaddr.rmempty = true + +nm = s2:option(Value, "netmask", translate("netmask")) +nm.rmempty = true +nm:value("255.255.255.0") +nm:value("255.255.0.0") +nm:value("255.0.0.0") + +gw = s2:option(Value, "gateway", translate("gateway")) +gw.rmempty = true + +bcast = s2:option(Value, "bcast", translate("broadcast")) +bcast.optional = true + +ip6addr = s2:option(Value, "ip6addr", translate("ip6address"), translate("cidr6")) +ip6addr.optional = true + +ip6gw = s2:option(Value, "ip6gw", translate("gateway6")) +ip6gw.optional = true + +dns = s2:option(Value, "dns", translate("dnsserver")) +dns.optional = true + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/network.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/network.lua new file mode 100644 index 0000000..89e13a5 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/network.lua @@ -0,0 +1,128 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: network.lua 3650 2008-10-29 19:40:40Z jow $ +]]-- +require("luci.sys") +require("luci.tools.webadmin") + +local netstate = luci.model.uci.cursor_state():get_all("network") +m = Map("network", translate("interfaces")) + +local created +local netstat = luci.sys.net.deviceinfo() + +s = m:section(TypedSection, "interface", "") +s.addremove = true +s.extedit = luci.dispatcher.build_url("admin", "network", "network") .. "/%s" +s.template = "cbi/tblsection" +s.override_scheme = true + +function s.filter(self, section) + return section ~= "loopback" and section +end + +function s.create(self, section) + if TypedSection.create(self, section) then + created = section + else + self.invalid_cts = true + end +end + +function s.parse(self, ...) + TypedSection.parse(self, ...) + if created then + m.uci:save("network") + luci.http.redirect(luci.dispatcher.build_url("admin", "network", "network") + .. "/" .. created) + end +end + +up = s:option(Flag, "up") +function up.cfgvalue(self, section) + return netstate[section] and netstate[section].up or "0" +end + +function up.write(self, section, value) + local call + if value == "1" then + call = "ifup" + elseif value == "0" then + call = "ifdown" + end + os.execute(call .. " " .. section .. " >/dev/null 2>&1") +end + +ifname = s:option(DummyValue, "ifname", translate("device")) +function ifname.cfgvalue(self, section) + return netstate[section] and netstate[section].ifname +end + +ifname.titleref = luci.dispatcher.build_url("admin", "network", "vlan") + + +if luci.model.uci.cursor():load("firewall") then + zone = s:option(DummyValue, "_zone", translate("zone")) + zone.titleref = luci.dispatcher.build_url("admin", "network", "firewall", "zones") + + function zone.cfgvalue(self, section) + local zones = luci.tools.webadmin.network_get_zones(section) + return zones and table.concat(zones, ", ") or "-" + end +end + +hwaddr = s:option(DummyValue, "_hwaddr") +function hwaddr.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") or "" + return luci.fs.readfile("/sys/class/net/" .. ix .. "/address") + or luci.util.exec("ifconfig " .. ix):match(" ([A-F0-9:]+)%s*\n") + or "n/a" + +end + + +ipaddr = s:option(DummyValue, "ipaddr", translate("addresses")) +function ipaddr.cfgvalue(self, section) + local addr = luci.tools.webadmin.network_get_addresses(section) + return table.concat(addr, ", ") +end + +txrx = s:option(DummyValue, "_txrx") + +function txrx.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][1] + rx = rx and luci.tools.webadmin.byte_format(tonumber(rx)) or "-" + + local tx = netstat and netstat[ix] and netstat[ix][9] + tx = tx and luci.tools.webadmin.byte_format(tonumber(tx)) or "-" + + return string.format("%s / %s", tx, rx) +end + +errors = s:option(DummyValue, "_err") + +function errors.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][3] + local tx = netstat and netstat[ix] and netstat[ix][11] + + rx = rx and tostring(rx) or "-" + tx = tx and tostring(tx) or "-" + + return string.format("%s / %s", tx, rx) +end + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua new file mode 100644 index 0000000..73732f8 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/routes.lua @@ -0,0 +1,120 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: routes.lua 3888 2008-12-10 21:46:22Z Cyrus $ +]]-- +require("luci.tools.webadmin") +m = Map("network", translate("a_n_routes"), translate("a_n_routes1")) + +local routes6 = luci.sys.net.routes6() +local bit = require "bit" + +if not arg or not arg[1] then + local routes = luci.sys.net.routes() + + v = m:section(Table, routes, translate("a_n_routes_kernel4")) + + net = v:option(DummyValue, "iface", translate("network")) + function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes[section].device) + or routes[section].device + end + + target = v:option(DummyValue, "target", translate("target")) + function target.cfgvalue(self, section) + return routes[section].dest:network():string() + end + + netmask = v:option(DummyValue, "netmask", translate("netmask")) + function netmask.cfgvalue(self, section) + return routes[section].dest:mask():string() + end + + gateway = v:option(DummyValue, "gateway", translate("gateway")) + function gateway.cfgvalue(self, section) + return routes[section].gateway:string() + end + + metric = v:option(DummyValue, "metric", translate("metric")) + function metric.cfgvalue(self, section) + return routes[section].metric + end + + if routes6 then + v = m:section(Table, routes6, translate("a_n_routes_kernel6")) + + net = v:option(DummyValue, "iface", translate("network")) + function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes6[section].device) + or routes6[section].device + end + + target = v:option(DummyValue, "target", translate("target")) + function target.cfgvalue(self, section) + return routes6[section].dest:string() + end + + gateway = v:option(DummyValue, "gateway", translate("gateway6")) + function gateway.cfgvalue(self, section) + return routes6[section].source:string() + end + + metric = v:option(DummyValue, "metric", translate("metric")) + function metric.cfgvalue(self, section) + local metr = routes6[section].metric + local lower = bit.band(metr, 0xffff) + local higher = bit.rshift(bit.band(metr, 0xffff0000), 16) + return "%04X%04X" % {higher, lower} + end + end +end + + +s = m:section(TypedSection, "route", translate("a_n_routes_static4")) +s.addremove = true +s.anonymous = true + +s.template = "cbi/tblsection" + +iface = s:option(ListValue, "interface", translate("interface")) +luci.tools.webadmin.cbi_add_networks(iface) + +if not arg or not arg[1] then + net.titleref = iface.titleref +end + +s:option(Value, "target", translate("target"), translate("a_n_r_target1")) + +s:option(Value, "netmask", translate("netmask"), translate("a_n_r_netmask1")).rmemepty = true + +s:option(Value, "gateway", translate("gateway")) + +if routes6 then + s = m:section(TypedSection, "route6", translate("a_n_routes_static6")) + s.addremove = true + s.anonymous = true + + s.template = "cbi/tblsection" + + iface = s:option(ListValue, "interface", translate("interface")) + luci.tools.webadmin.cbi_add_networks(iface) + + if not arg or not arg[1] then + net.titleref = iface.titleref + end + + s:option(Value, "target", translate("target"), translate("a_n_r_target6")) + + s:option(Value, "gateway", translate("gateway6")).rmempty = true +end + + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/vlan.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/vlan.lua new file mode 100644 index 0000000..eb14148 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/vlan.lua @@ -0,0 +1,22 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: vlan.lua 2808 2008-08-14 11:49:36Z Cyrus $ +]]-- +m = Map("network", translate("a_n_switch"), translate("a_n_switch1")) + +s = m:section(TypedSection, "switch", "") + +for i = 0, 15 do + s:option(Value, "vlan"..i, "ethX."..i).optional = true +end + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wifi.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wifi.lua new file mode 100644 index 0000000..66fd3b8 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wifi.lua @@ -0,0 +1,373 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: wifi.lua 4224 2009-02-04 19:20:23Z Cyrus $ +]]-- +require("luci.tools.webadmin") +arg[1] = arg[1] or "" + +m = Map("wireless", translate("networks"), translate("a_w_networks1")) + +s = m:section(NamedSection, arg[1], "wifi-device", translate("device") .. " " .. arg[1]) +s.addremove = false + +back = s:option(DummyValue, "_overview", translate("overview")) +back.value = "" +back.titleref = luci.dispatcher.build_url("admin", "network", "wireless") + + +en = s:option(Flag, "disabled", translate("enable")) +en.enabled = "0" +en.disabled = "1" +en.rmempty = false + +function en.cfgvalue(self, section) + return Flag.cfgvalue(self, section) or "0" +end + +s:option(DummyValue, "type", translate("type")) +local hwtype = m:get(arg[1], "type") +-- NanoFoo +local nsantenna = m:get(arg[1], "antenna") + +ch = s:option(Value, "channel", translate("a_w_channel")) +for i=1, 14 do + ch:value(i, i .. " (2.4 GHz)") +end +for i=36, 64, 4 do + ch:value(i, i .. " (5 GHz)") +end +for i=100, 140, 4 do + ch:value(i, i .. " (5 GHz)") +end +ch:value(147, 147 .. " (5 GHz)") +ch:value(151, 151 .. " (5 GHz)") +ch:value(155, 155 .. " (5 GHz)") +ch:value(167, 167 .. " (5 GHz)") + +s:option(Value, "txpower", translate("a_w_txpwr"), "dBm").rmempty = true + + +------------------- MAC80211 Device ------------------ + +if hwtype == "mac80211" then + +end + + +------------------- Madwifi Device ------------------ + +if hwtype == "atheros" then + mode = s:option(ListValue, "hwmode", translate("mode")) + mode:value("", translate("wifi_auto")) + mode:value("11b", "802.11b") + mode:value("11g", "802.11g") + mode:value("11a", "802.11a") + mode:value("11bg", "802.11b+g") + mode:value("11gdt", "802.11adt") + mode:value("11adt", "802.11adt") + mode:value("fh", translate("wifi_fh")) + + s:option(Flag, "diversity", translate("wifi_diversity")).rmempty = false + + if not nsantenna then + s:option(Value, "txantenna", translate("wifi_txantenna")).optional = true + s:option(Value, "rxantenna", translate("wifi_rxantenna")).optional = true + else -- NanoFoo + local ant = s:option(ListValue, "antenna", translate("wifi_txantenna")) + ant:value("auto") + ant:value("vertical") + ant:value("horizontal") + ant:value("external") + end + s:option(Value, "distance", translate("wifi_distance"), + translate("wifi_distance_desc")).optional = true + + --s:option(Flag, "nosbeacon", translate("wifi_nosbeacon")).optional = true +end + + + +------------------- Broadcom Device ------------------ + +if hwtype == "broadcom" then + mp = s:option(ListValue, "macfilter", translate("wifi_macpolicy")) + mp.optional = true + mp:value("") + mp:value("allow", translate("wifi_whitelist")) + mp:value("deny", translate("wifi_blacklist")) + ml = s:option(DynamicList, "maclist", translate("wifi_maclist")) + ml:depends({macfilter="allow"}) + ml:depends({macfilter="deny"}) + + s:option(Value, "txantenna", translate("wifi_txantenna")).optional = true + s:option(Value, "rxantenna", translate("wifi_rxantenna")).optional = true + + s:option(Flag, "frameburst", translate("wifi_bursting")).optional = true + + s:option(Value, "distance", translate("wifi_distance")).optional = true + --s:option(Value, "slottime", translate("wifi_slottime")).optional = true + + s:option(Value, "country", translate("wifi_country")).optional = true + s:option(Value, "maxassoc", translate("wifi_maxassoc")).optional = true +end + + +----------------------- Interface ----------------------- + +s = m:section(TypedSection, "wifi-iface", translate("interfaces")) +s.addremove = true +s.anonymous = true +s:depends("device", arg[1]) +s.defaults.device = arg[1] + +s:option(Value, "ssid", translate("wifi_essid")) + +network = s:option(Value, "network", translate("network"), translate("a_w_network1")) +network.rmempty = true +network:value("") +network.combobox_manual = translate("a_w_netmanual") +luci.tools.webadmin.cbi_add_networks(network) + +function network.write(self, section, value) + if not m.uci:get("network", value) then + -- avoid "value not defined in enum" because network is not known yet + s.override_scheme = true + + m:chain("network") + m.uci:set("network", value, "interface") + Value.write(self, section, value) + else + if m.uci:get("network", value) == "interface" then + Value.write(self, section, value) + end + end +end + + +mode = s:option(ListValue, "mode", translate("mode")) +mode.override_values = true +mode:value("ap", translate("a_w_ap")) +mode:value("adhoc", translate("a_w_adhoc")) +mode:value("sta", translate("a_w_client")) + +bssid = s:option(Value, "bssid", translate("wifi_bssid")) + + +-------------------- MAC80211 Interface ---------------------- + +if hwtype == "mac80211" then + mode:value("ahdemo", translate("a_w_ahdemo")) + mode:value("monitor", translate("a_w_monitor")) + bssid:depends({mode="adhoc"}) + + s:option(Value, "frag", translate("wifi_frag")).optional = true + s:option(Value, "rts", translate("wifi_rts")).optional = true +end + + + +-------------------- Madwifi Interface ---------------------- + +if hwtype == "atheros" then + mode:value("ahdemo", translate("a_w_ahdemo")) + mode:value("monitor", translate("a_w_monitor")) + + bssid:depends({mode="adhoc"}) + bssid:depends({mode="ahdemo"}) + + wds = s:option(Flag, "wds", translate("a_w_wds")) + wds:depends({mode="ap"}) + wds:depends({mode="sta"}) + wds.rmempty = true + wdssep = s:option(Flag, "wdssep", translate("wifi_wdssep")) + wdssep:depends({mode="ap", wds="1"}) + wdssep.optional = true + + s:option(Flag, "doth", "802.11h").optional = true + hidden = s:option(Flag, "hidden", translate("wifi_hidden")) + hidden:depends({mode="ap"}) + hidden:depends({mode="adhoc"}) + hidden:depends({mode="wds"}) + hidden.optional = true + isolate = s:option(Flag, "isolate", translate("wifi_isolate"), + translate("wifi_isolate_desc")) + isolate:depends({mode="ap"}) + isolate.optional = true + s:option(Flag, "bgscan", translate("wifi_bgscan")).optional = true + + mp = s:option(ListValue, "macpolicy", translate("wifi_macpolicy")) + mp.optional = true + mp:value("") + mp:value("deny", translate("wifi_whitelist")) + mp:value("allow", translate("wifi_blacklist")) + ml = s:option(DynamicList, "maclist", translate("wifi_maclist")) + ml:depends({macpolicy="allow"}) + ml:depends({macpolicy="deny"}) + + s:option(Value, "rate", translate("wifi_rate")).optional = true + s:option(Value, "mcast_rate", translate("wifi_mcast_rate")).optional = true + s:option(Value, "frag", translate("wifi_frag")).optional = true + s:option(Value, "rts", translate("wifi_rts")).optional = true + s:option(Value, "minrate", translate("wifi_minrate")).optional = true + s:option(Value, "maxrate", translate("wifi_maxrate")).optional = true + s:option(Flag, "compression", translate("wifi_compression")).optional = true + + s:option(Flag, "bursting", translate("wifi_bursting")).optional = true + s:option(Flag, "turbo", translate("wifi_turbo")).optional = true + s:option(Value, "ff", translate("wifi_ff")).optional = true + + s:option(Flag, "wmm", translate("wifi_wmm")).optional = true + s:option(Flag, "xr", translate("wifi_xr")).optional = true + s:option(Flag, "ar", translate("wifi_ar")).optional = true + + local swm = s:option(Flag, "sw_merge", translate("wifi_nosbeacon")) + swm:depends({mode="adhoc"}) + swm.optional = true + + local nos = s:option(Flag, "nosbeacon", translate("wifi_nosbeacon")) + nos:depends({mode="sta"}) + nos.optional = true + + local probereq = s:option(Flag, "probereq", translate("wifi_noprobereq")) + probereq.optional = true + probereq.enabled = "0" + probereq.disabled = "1" +end + + +-------------------- Broadcom Interface ---------------------- + +if hwtype == "broadcom" then + mode:value("wds", translate("a_w_wds")) + mode:value("monitor", translate("a_w_monitor")) + + hidden = s:option(Flag, "hidden", translate("wifi_hidden")) + hidden:depends({mode="ap"}) + hidden:depends({mode="adhoc"}) + hidden:depends({mode="wds"}) + hidden.optional = true + + isolate = s:option(Flag, "isolate", translate("wifi_isolate"), + translate("wifi_isolate_desc")) + isolate:depends({mode="ap"}) + isolate.optional = true + + bssid:depends({mode="wds"}) + bssid:depends({mode="adhoc"}) +end + + + +------------------- WiFI-Encryption ------------------- + +encr = s:option(ListValue, "encryption", translate("encryption")) +encr.override_values = true +encr:depends({mode="ap"}) +encr:depends({mode="sta"}) +encr:depends({mode="adhoc"}) +encr:depends({mode="ahdemo"}) +encr:depends({mode="wds"}) + +encr:value("none", "No Encryption") +encr:value("wep", "WEP") + +if hwtype == "atheros" or hwtype == "mac80211" then + local supplicant = luci.fs.mtime("/usr/sbin/wpa_supplicant") + local hostapd = luci.fs.mtime("/usr/sbin/hostapd") + + if hostapd and supplicant then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") + encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="sta"}) + encr:value("wpa2i", "WPA2-EAP", {mode="ap"}, {mode="sta"}) + elseif hostapd and not supplicant then + encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="adhoc"}, {mode="ahdemo"}) + encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="adhoc"}, {mode="ahdemo"}) + encr:value("wpa", "WPA-EAP", {mode="ap"}) + encr:value("wpa2i", "WPA2-EAP", {mode="ap"}) + encr.description = translate("wifi_wpareq") + elseif not hostapd and supplicant then + encr:value("psk", "WPA-PSK", {mode="sta"}) + encr:value("psk2", "WPA2-PSK", {mode="sta"}) + encr:value("wpa", "WPA-EAP", {mode="sta"}) + encr:value("wpa2i", "WPA2-EAP", {mode="sta"}) + encr.description = translate("wifi_wpareq") + else + encr.description = translate("wifi_wpareq") + end +elseif hwtype == "broadcom" then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") +end + +encr:depends("mode", "ap") +encr:depends("mode", "sta") +encr:depends("mode", "wds") + +server = s:option(Value, "server", translate("a_w_radiussrv")) +server:depends({mode="ap", encryption="wpa"}) +server:depends({mode="ap", encryption="wpa2i"}) +server.rmempty = true + +port = s:option(Value, "port", translate("a_w_radiusport")) +port:depends({mode="ap", encryption="wpa"}) +port:depends({mode="ap", encryption="wpa2i"}) +port.rmempty = true + +key = s:option(Value, "key", translate("key")) +key:depends("encryption", "wep") +key:depends("encryption", "psk") +key:depends({mode="ap", encryption="wpa"}) +key:depends("encryption", "psk2") +key:depends({mode="ap", encryption="wpa2i"}) +key.rmempty = true + +if hwtype == "atheros" or hwtype == "mac80211" then + nasid = s:option(Value, "nasid", translate("a_w_nasid")) + nasid:depends({mode="ap", encryption="wpa"}) + nasid:depends({mode="ap", encryption="wpa2i"}) + nasid.rmempty = true + + eaptype = s:option(ListValue, "eap_type", translate("a_w_eaptype")) + eaptype:value("TLS") + eaptype:value("PEAP") + eaptype:depends({mode="sta", encryption="wpa"}) + eaptype:depends({mode="sta", encryption="wpa2i"}) + + cacert = s:option(FileUpload, "ca_cert", translate("a_w_cacert")) + cacert:depends({mode="sta", encryption="wpa"}) + cacert:depends({mode="sta", encryption="wpa2i"}) + + privkey = s:option(FileUpload, "priv_key", translate("a_w_tlsprivkey")) + privkey:depends({mode="sta", eap_type="TLS", encryption="wpa2i"}) + privkey:depends({mode="sta", eap_type="TLS", encryption="wpa"}) + + privkeypwd = s:option(Value, "priv_key_pwd", translate("a_w_tlsprivkeypwd")) + privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa2i"}) + privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa"}) + + + auth = s:option(Value, "auth", translate("a_w_peapauth")) + auth:depends({mode="sta", eap_type="PEAP", encryption="wpa2i"}) + auth:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) + + identity = s:option(Value, "identity", translate("a_w_peapidentity")) + identity:depends({mode="sta", eap_type="PEAP", encryption="wpa2i"}) + identity:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) + + password = s:option(Value, "password", translate("a_w_peappassword")) + password:depends({mode="sta", eap_type="PEAP", encryption="wpa2i"}) + password:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) +end + + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wireless.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wireless.lua new file mode 100644 index 0000000..198d410 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_network/wireless.lua @@ -0,0 +1,134 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: wireless.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +require("luci.sys") +require("luci.tools.webadmin") + +local wireless = luci.model.uci.cursor_state():get_all("wireless") +local wifidata = luci.sys.wifi.getiwconfig() +local ifaces = {} + +for k, v in pairs(wireless) do + if v[".type"] == "wifi-iface" then + table.insert(ifaces, v) + end +end + + +m = SimpleForm("wireless", translate("wifi")) + +s = m:section(Table, ifaces, translate("networks")) + +function s.extedit(self, section) + local device = self.map:get(section, "device") or "" + return luci.dispatcher.build_url(unpack(luci.dispatcher.context.requested.path)) .. "/" .. device +end + +link = s:option(DummyValue, "_link", translate("link")) +function link.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Link Quality"] or "-" +end + +essid = s:option(DummyValue, "ssid", "ESSID") + +bssid = s:option(DummyValue, "_bsiid", "BSSID") +function bssid.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return (wifidata[ifname] and (wifidata[ifname].Cell + or wifidata[ifname]["Access Point"])) or "-" +end + +channel = s:option(DummyValue, "channel", translate("channel")) +function channel.cfgvalue(self, section) + return wireless[self.map:get(section, "device")].channel +end + +protocol = s:option(DummyValue, "_mode", translate("protocol")) +function protocol.cfgvalue(self, section) + local mode = wireless[self.map:get(section, "device")].mode + return mode and "802." .. mode +end + +mode = s:option(DummyValue, "mode", translate("mode")) +encryption = s:option(DummyValue, "encryption", translate("iwscan_encr")) + +power = s:option(DummyValue, "_power", translate("power")) +function power.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Tx-Power"] or "-" +end + +scan = s:option(Button, "_scan", translate("scan")) +scan.inputstyle = "find" + +function scan.cfgvalue(self, section) + return self.map:get(section, "ifname") or false +end + +t2 = m:section(Table, {}, translate("iwscan"), translate("iwscan1")) + +function scan.write(self, section) + t2.render = t2._render + local ifname = self.map:get(section, "ifname") + luci.util.update(t2.data, luci.sys.wifi.iwscan(ifname)) +end + +t2._render = t2.render +t2.render = function() end + +t2:option(DummyValue, "Quality", translate("iwscan_link")) +essid = t2:option(DummyValue, "ESSID", "ESSID") +function essid.cfgvalue(self, section) + return luci.util.pcdata(self.map:get(section, "ESSID")) +end + +t2:option(DummyValue, "Address", "BSSID") +t2:option(DummyValue, "Mode", translate("mode")) +chan = t2:option(DummyValue, "channel", translate("channel")) +function chan.cfgvalue(self, section) + return self.map:get(section, "Channel") + or self.map:get(section, "Frequency") + or "-" +end + +t2:option(DummyValue, "Encryption key", translate("iwscan_encr")) + +t2:option(DummyValue, "Signal level", translate("iwscan_signal")) + +t2:option(DummyValue, "Noise level", translate("iwscan_noise")) + + +s2 = m:section(SimpleSection, translate("a_w_create")) +create = s2:option(ListValue, "create", translate("device")) +create:value("", translate("cbi_select")) +for k, v in pairs(wireless) do + if v[".type"] == "wifi-device" then + create:value(k) + end +end + +function create.write(self, section, value) + local uci = luci.model.uci.cursor() + uci:load("wireless") + uci:section("wireless", "wifi-iface", nil, {device=value}) + uci:save("wireless") + luci.http.redirect(luci.dispatcher.build_url(unpack(luci.dispatcher.context.requested.path)) .. "/" .. value) +end + +function create.cbid(self, section) + return "priv.cbid.create" +end + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/crontab.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/crontab.lua new file mode 100644 index 0000000..5be5fd1 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/crontab.lua @@ -0,0 +1,35 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: crontab.lua 4106 2009-01-20 11:33:33Z Cyrus $ +]]-- +local cronfile = "/etc/crontabs/root" + +f = SimpleForm("crontab", translate("a_s_crontab"), translate("a_s_crontab1")) + +t = f:field(TextValue, "crons") +t.rmempty = true +t.rows = 10 +function t.cfgvalue() + return luci.fs.readfile(cronfile) or "" +end + +function f.handle(self, state, data) + if state == FORM_VALID then + if data.crons then + luci.fs.writefile(cronfile, data.crons:gsub("\r\n", "\n")) + end + end + return true +end + +return f diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dnsmasq.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dnsmasq.lua new file mode 100644 index 0000000..afdf075 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dnsmasq.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dnsmasq.lua 3595 2008-10-17 16:20:01Z Cyrus $ +]]-- +m = Map("dhcp", "Dnsmasq") + +s = m:section(TypedSection, "dnsmasq", translate("settings")) +s.anonymous = true + +s:option(Flag, "domainneeded") +s:option(Flag, "authoritative") +s:option(Flag, "boguspriv") +s:option(Flag, "filterwin2k") +s:option(Flag, "localise_queries") +s:option(Value, "local") +s:option(Value, "domain") +s:option(Flag, "expandhosts") +s:option(Flag, "nonegcache") +s:option(Flag, "readethers") +s:option(Value, "leasefile") +s:option(Value, "resolvfile") +s:option(Flag, "nohosts").optional = true +s:option(Flag, "strictorder").optional = true +s:option(Flag, "logqueries").optional = true +s:option(Flag, "noresolv").optional = true +s:option(Value, "dnsforwardmax").optional = true +s:option(Value, "port").optional = true +s:option(Value, "ednspacket_max").optional = true +s:option(Value, "dhcpleasemax").optional = true +s:option(Value, "addnhosts").optional = true +s:option(Value, "queryport").optional = true +s:option(Flag, "enable_tftp").optional = true +s:option(Value, "tftp_root").optional = true +s:option(Value, "dhcp_boot").optional = true + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dropbear.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dropbear.lua new file mode 100644 index 0000000..30f7325 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/dropbear.lua @@ -0,0 +1,27 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: dropbear.lua 4150 2009-01-26 02:10:02Z jow $ +]]-- +m = Map("dropbear", "Dropbear SSHd", translate("a_srv_dropbear1")) + +s = m:section(TypedSection, "dropbear", "") +s.anonymous = true + +port = s:option(Value, "Port", translate("port")) +port.isinteger = true + +pwauth = s:option(Flag, "PasswordAuth", translate("a_srv_d_pwauth"), translate("a_srv_d_pwauth1")) +pwauth.enabled = 'on' +pwauth.disabled = 'off' +pwauth.rmempty = false + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/httpd.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/httpd.lua new file mode 100644 index 0000000..5541959 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/httpd.lua @@ -0,0 +1,31 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: httpd.lua 3402 2008-09-23 17:29:05Z jow $ +]]-- +m = Map("httpd", "Busybox HTTPd", translate("a_srv_http1")) + +s = m:section(TypedSection, "httpd", "") +s.anonymous = true +s.addremove = true + +port = s:option(Value, "port", translate("port")) +port.isinteger = true + +s:option(Value, "home", translate("a_srv_http_root")) + +config = s:option(Value, "c_file", translate("configfile"), translate("a_srv_http_config1")) +config.rmempty = true + +realm = s:option(Value, "realm", translate("a_srv_http_authrealm"), translate("a_srv_http_authrealm1")) +realm.rmempty = true + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/lucittpd.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/lucittpd.lua new file mode 100644 index 0000000..3599f59 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_services/lucittpd.lua @@ -0,0 +1,25 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: lucittpd.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +m = Map("lucittpd", "LuCIttpd", translate("a_srv_lucittpd")) + +s = m:section(NamedSection, "lucittpd", "lucittpd", "") + +s:option(Value, "port", translate("port")) +s:option(Value, "root", translate("a_srv_http_root")) +s:option(Value, "path", translate("a_srv_http_path")) +s:option(Flag, "keepalive", translate("a_srv_http_keepalive")) +s:option(Value, "timeout", translate("a_srv_http_timeout")) + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/buttons.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/buttons.lua new file mode 100644 index 0000000..d32f8fa --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/buttons.lua @@ -0,0 +1,31 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: buttons.lua 2880 2008-08-17 23:47:38Z jow $ +]]-- +m = Map("system", translate("buttons"), translate("buttons_desc")) + +s = m:section(TypedSection, "button", "") +s.anonymous = true +s.addremove = true + +s:option(Value, "button") + +act = s:option(ListValue, "action") +act:value("released") + +s:option(Value, "handler") + +min = s:option(Value, "min") +min.rmempty = true + +max = s:option(Value, "max") +max.rmempty = true diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/fstab.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/fstab.lua new file mode 100644 index 0000000..30409a4 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/fstab.lua @@ -0,0 +1,86 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: fstab.lua 3329 2008-09-16 02:01:05Z jow $ +]]-- +require("luci.tools.webadmin") + +local fs = require "luci.fs" +local devices = {} +luci.util.update(devices, fs.glob("/dev/sd*") or {}) +luci.util.update(devices, fs.glob("/dev/hd*") or {}) +luci.util.update(devices, fs.glob("/dev/scd*") or {}) +luci.util.update(devices, fs.glob("/dev/mmc*") or {}) + +local size = {} +for i, dev in ipairs(devices) do + local s = tonumber((luci.fs.readfile("/sys/class/block/%s/size" % dev:sub(6)))) + size[dev] = s and math.floor(s / 2048) +end + + +m = Map("fstab", translate("a_s_fstab")) + +local mounts = luci.sys.mounts() + +v = m:section(Table, mounts, translate("a_s_fstab_active")) + +fs = v:option(DummyValue, "fs", translate("filesystem")) + +mp = v:option(DummyValue, "mountpoint", translate("a_s_fstab_mountpoint")) + +avail = v:option(DummyValue, "avail", translate("a_s_fstab_avail")) +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("a_s_fstab_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 + + + +mount = m:section(TypedSection, "mount", translate("a_s_fstab_mountpoints"), translate("a_s_fstab_mountpoints1")) +mount.anonymous = true +mount.addremove = true +mount.template = "cbi/tblsection" + +mount:option(Flag, "enabled", translate("enable")) +dev = mount:option(Value, "device", translate("device"), translate("a_s_fstab_device1")) +for i, d in ipairs(devices) do + dev:value(d, size[d] and "%s (%s MB)" % {d, size[d]}) +end + +mount:option(Value, "target", translate("a_s_fstab_mountpoint")) +mount:option(Value, "fstype", translate("filesystem"), translate("a_s_fstab_fs1")) +mount:option(Value, "options", translate("options"), translatef("manpage", "siehe '%s' manpage", "mount")) + + +swap = m:section(TypedSection, "swap", "SWAP", translate("a_s_fstab_swap1")) +swap.anonymous = true +swap.addremove = true +swap.template = "cbi/tblsection" + +swap:option(Flag, "enabled", translate("enable")) +dev = swap:option(Value, "device", translate("device"), translate("a_s_fstab_device1")) +for i, d in ipairs(devices) do + dev:value(d, size[d] and "%s (%s MB)" % {d, size[d]}) +end + +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/ipkg.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/ipkg.lua new file mode 100644 index 0000000..f941efc --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/ipkg.lua @@ -0,0 +1,35 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ipkg.lua 4106 2009-01-20 11:33:33Z Cyrus $ +]]-- +local ipkgfile = "/etc/opkg.conf" + +f = SimpleForm("ipkgconf", translate("a_s_p_ipkg")) + +t = f:field(TextValue, "lines") +t.rows = 10 +function t.cfgvalue() + return luci.fs.readfile(ipkgfile) or "" +end + +function t.write(self, section, data) + return luci.fs.writefile(ipkgfile, data:gsub("\r\n", "\n")) +end + +f:append(Template("admin_system/ipkg")) + +function f.handle(self, state, data) + return true +end + +return f diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/leds.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/leds.lua new file mode 100644 index 0000000..b6a911f --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/leds.lua @@ -0,0 +1,86 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: leds.lua 2880 2008-08-17 23:47:38Z jow $ +]]-- +m = Map("system", translate("leds"), translate("leds_desc")) + +local sysfs_path = "/sys/class/leds/" +local leds = {} + +if luci.fs.access(sysfs_path) then + for k, v in pairs(luci.fs.dir(sysfs_path)) do + if v ~= "." and v ~= ".." then + table.insert(leds, v) + end + end +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") + + +sysfs = s:option(ListValue, "sysfs") +for k, v in ipairs(leds) do + sysfs:value(v) +end + +s:option(Flag, "default").rmempty = true + + +trigger = s:option(ListValue, "trigger") + +local triggers = luci.fs.readfile(sysfs_path .. leds[1] .. "/trigger") +for t in triggers:gmatch("[%w-]+") do + trigger:value(t, translate("system_led_trigger_" .. t:gsub("-", ""))) +end + + +delayon = s:option(Value, "delayon") +delayon:depends("trigger", "timer") + +delayoff = s:option(Value, "delayoff") +delayoff:depends("trigger", "timer") + + +dev = s:option(ListValue, "dev") +dev.rmempty = true +dev:value("") +dev:depends("trigger", "netdev") +for k, v in pairs(luci.sys.net.devices()) do + if v ~= "lo" then + dev:value(v) + end +end + + +mode = s:option(MultiValue, "mode") +mode.rmempty = true +mode:depends("trigger", "netdev") +mode:value("link", translate("system_led_mode_link")) +mode:value("tx", translate("system_led_mode_tx")) +mode:value("rx", translate("system_led_mode_rx")) + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/passwd.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/passwd.lua new file mode 100644 index 0000000..f078dd5 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/passwd.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: passwd.lua 3864 2008-12-07 13:44:25Z Cyrus $ +]]-- +f = SimpleForm("password", translate("a_s_changepw"), translate("a_s_changepw1")) + +pw1 = f:field(Value, "pw1", translate("password")) +pw1.password = true +pw1.rmempty = false + +pw2 = f:field(Value, "pw2", translate("confirmation")) +pw2.password = true +pw2.rmempty = false + +function pw2.validate(self, value, section) + return pw1:formvalue(section) == value and value +end + +function f.handle(self, state, data) + if state == FORM_VALID then + local stat = luci.sys.user.setpasswd("root", data.pw1) == 0 + + if stat then + f.message = translate("a_s_changepw_changed") + else + f.errmessage = translate("unknownerror") + end + + data.pw1 = nil + data.pw2 = nil + end + return true +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/processes.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/processes.lua new file mode 100644 index 0000000..8aa2be8 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/processes.lua @@ -0,0 +1,44 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: processes.lua 2880 2008-08-17 23:47:38Z jow $ +]]-- +f = SimpleForm("processes", translate("process_head"), translate("process_descr")) +f.reset = false +f.submit = false + +t = f:section(Table, luci.sys.process.list()) +t:option(DummyValue, "PID", translate("process_pid")) +t:option(DummyValue, "USER", translate("process_owner")) +t:option(DummyValue, "COMMAND", translate("process_command")) +t:option(DummyValue, "%CPU", translate("process_cpu")) +t:option(DummyValue, "%MEM", translate("process_mem")) + +hup = t:option(Button, "_hup", translate("process_hup")) +hup.inputstyle = "reload" +function hup.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 1) +end + +term = t:option(Button, "_term", translate("process_term")) +term.inputstyle = "remove" +function term.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 15) +end + +kill = t:option(Button, "_kill", translate("process_kill")) +kill.inputstyle = "reset" +function kill.write(self, section) + null, self.tag_error[section] = luci.sys.process.signal(section, 9) +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/sshkeys.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/sshkeys.lua new file mode 100644 index 0000000..bae8116 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/sshkeys.lua @@ -0,0 +1,35 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: sshkeys.lua 4106 2009-01-20 11:33:33Z Cyrus $ +]]-- +local keyfile = "/etc/dropbear/authorized_keys" + +f = SimpleForm("sshkeys", translate("a_s_sshkeys"), translate("a_s_sshkeys1")) + +t = f:field(TextValue, "keys") +t.rmempty = true +t.rows = 10 +function t.cfgvalue() + return luci.fs.readfile(keyfile) or "" +end + +function f.handle(self, state, data) + if state == FORM_VALID then + if data.keys then + luci.fs.writefile(keyfile, data.keys:gsub("\r\n", "\n")) + end + end + return true +end + +return f diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/system.lua b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/system.lua new file mode 100644 index 0000000..b3a01f3 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/model/cbi/admin_system/system.lua @@ -0,0 +1,73 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: system.lua 3736 2008-11-06 23:10:43Z jow $ +]]-- + +require("luci.sys") +require("luci.sys.zoneinfo") +require("luci.tools.webadmin") + +m = Map("system", translate("system"), translate("a_s_desc")) + +s = m:section(TypedSection, "system", "") +s.anonymous = true + +local system, model, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo() +local uptime = luci.sys.uptime() + +s:option(DummyValue, "_system", translate("system")).value = system +s:option(DummyValue, "_cpu", translate("m_i_processor")).value = model + +local load1, load5, load15 = luci.sys.loadavg() +s:option(DummyValue, "_la", translate("load")).value = + string.format("%.2f, %.2f, %.2f", load1, load5, load15) + +s:option(DummyValue, "_memtotal", translate("m_i_memory")).value = + string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)", + tonumber(memtotal) / 1024, + 100 * memcached / memtotal, + translate("mem_cached") or "", + 100 * membuffers / memtotal, + translate("mem_buffered") or "", + 100 * memfree / memtotal, + translate("mem_free") or "") + +s:option(DummyValue, "_systime", translate("m_i_systemtime")).value = + os.date("%c") + +s:option(DummyValue, "_uptime", translate("m_i_uptime")).value = + luci.tools.webadmin.date_format(tonumber(uptime)) + +s:option(Value, "hostname", translate("hostname")) + +tz = s:option(ListValue, "zonename", translate("timezone")) +tz:value("UTC") + +for i, zone in ipairs(luci.sys.zoneinfo.TZ) do + tz:value(zone[1]) +end + +function tz.write(self, section, value) + local function lookup_zone(title) + for _, zone in ipairs(luci.sys.zoneinfo.TZ) do + if zone[1] == title then return zone[2] end + end + end + + AbstractValue.write(self, section, value) + self.map.uci:set("system", section, "timezone", lookup_zone(value) or "GMT0") +end + +s:option(Value, "log_size", nil, "kiB").optional = true +s:option(Value, "log_ip").optional = true +s:option(Value, "conloglevel").optional = true +return m diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_index/index.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_index/index.htm new file mode 100644 index 0000000..2f935ee --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_index/index.htm @@ -0,0 +1,24 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:a_i_i_hello%>

+

<%:a_i_i_admin1%>

+

<%:a_i_i_admin2%>
+<%:a_i_i_admin3%>

+

<%:a_i_i_admin4%>

+

<%:a_i_i_admin5%>

+

<%:a_i_i_admin6%>

+

<%:a_i_i_team%>

+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_services/index.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_services/index.htm new file mode 100644 index 0000000..a892d13 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_services/index.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:services%>

+

<%:a_srv_services1%>

+

<%:a_srv_services2%>

+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/dmesg.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/dmesg.htm new file mode 100644 index 0000000..4fa8673 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/dmesg.htm @@ -0,0 +1,20 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: syslog.htm 3622 2008-10-23 16:05:55Z jow $ + +-%> +<%+header%> +

<%:dmesg%>

+
+ +
+<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/index.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/index.htm new file mode 100644 index 0000000..4a3d938 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/index.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:status%>

+

<%:a_st_i_status1%>

+

<%:a_st_i_status2%>

+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/syslog.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/syslog.htm new file mode 100644 index 0000000..1da1c84 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_status/syslog.htm @@ -0,0 +1,20 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: syslog.htm 3792 2008-11-16 22:46:25Z jow $ + +-%> +<%+header%> +

<%:syslog%>

+
+ +
+<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/applyreboot.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/applyreboot.htm new file mode 100644 index 0000000..73cf4a7 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/applyreboot.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: applyreboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+
+

<% if msg then %><%=msg%><% else %><%:a_s_applyreboot1%><% end %>

+

<%:a_s_reboot_running%>

+ +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/backup.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/backup.htm new file mode 100644 index 0000000..3162e73 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/backup.htm @@ -0,0 +1,40 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: backup.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_backup%>

+

<%:a_s_backup1%>

+
+
+ +
+ +
+ +
+
<%:a_s_backup_archive%>:
+
+ +
+
+ +
+
+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/ipkg.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/ipkg.htm new file mode 100644 index 0000000..2ebebfd --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/ipkg.htm @@ -0,0 +1,18 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: ipkg.htm 2819 2008-08-14 17:16:56Z Cyrus $ + +-%> +
    +
  • <%:a_s_p_ipkg_pkglists%>: src Name URL
  • +
  • <%:a_s_p_ipkg_targets%>: dest Name Pfad
  • +
diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/packages.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/packages.htm new file mode 100644 index 0000000..de71a68 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/packages.htm @@ -0,0 +1,98 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: packages.htm 4065 2009-01-17 13:21:50Z Cyrus $ + +-%> +<%- +local rowcnt = 1 +function rowstyle() + rowcnt = rowcnt + 1 + return (rowcnt % 2) + 1 +end +-%> +<%+header%> +

<%:system%>

+

<%:a_s_packages%>

+ +
+ +<% if install or remove or update or upgrade then %> +
<%:status%>:
+<% if update then %> + <%:a_s_packages_update%>: <% if update == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=update%>)<% end %>
+<% end %> +<% if upgrade then%> + <%:a_s_packages_upgrade%>: <% if upgrade == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=upgrade%>)<% end %>
+<% end %> +<% if install then for k,v in pairs(install) do %> + <%:a_s_packages_install%> '<%=k%>': <% if v == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=v%>)<% end %>
+<% end end %> +<% if remove then for k,v in pairs(remove) do %> + <%:a_s_packages_remove%> '<%=k%>': <% if v == 0 then %><%:ok%><% else %><%:error%> (<%:code%> <%=v%>)<% end %>
+<% end end %> +
+
+<% end %> + +
+
+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+ + + + + + + + + + <% for k, pkg in pairs(pkgs) do %> + + + + + + + + <% end %> +
<%:a_s_packages_name%><%:version%><%:install%><%:delete%><%:descr%>
<%=luci.util.pcdata(pkg.Package)%><%=luci.util.pcdata(pkg.Version)%><% if not pkg.Status or not pkg.Status.installed then %><% else %><%:installed%><% end %><% if pkg.Status and pkg.Status.installed then %><% else %><%:notinstalled%><% end %><%=luci.util.pcdata(pkg.Description)%>
+ +
+ +
+ +
+
+
+
+<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/reboot.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/reboot.htm new file mode 100644 index 0000000..115a918 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/reboot.htm @@ -0,0 +1,33 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: reboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:reboot%>

+

<%:a_s_reboot1%>

+<%- +local c = require("luci.model.uci").cursor():changes() +if c and next(c) then +-%> +

<%:a_s_reboot_u%>

+<%- +end +if not reboot then +-%> +

<%:a_s_reboot_do%>

+<%- else -%> +

<%:a_s_reboot_running%>

+ +<%- end -%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/upgrade.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/upgrade.htm new file mode 100644 index 0000000..080aa07 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_system/upgrade.htm @@ -0,0 +1,52 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upgrade.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_flash%>

+

<%:a_s_flash_upgrade1%>

+
+<% if sysupgrade and not ret then %> +
+
<%:a_s_flash_fwimage%>:
+
+ +
+
+ <% if keep_avail then -%> + + <%:a_s_flash_keepcfg%> + <% end -%> +
+
+ +
+
+<% elseif ret then %> +

<%:a_s_flash_received%>

+

<%:a_s_flash_inprogress%>

+ + + <% %> + <% local ret = ret() + if ret == 0 then %> +
<%:a_s_flash_flashed%>
+ <% else %> +
<%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)
+ <% end %> +<% else %> +
<%:a_s_flash_notimplemented%>
+<% end %> +<%+footer%> +<% if ret == 0 then luci.sys.reboot() end %> diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/apply.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/apply.htm new file mode 100644 index 0000000..ac2dd38 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/apply.htm @@ -0,0 +1,42 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: apply.htm 3871 2008-12-07 21:27:52Z jow $ + +-%> +<%+header%> + +

<%:config%>

+

<%:uci_applied%>:

+ +
+ <%=(changes or "-")%> +
+ +
+
    <%- + local fp = reload() + local line = fp:read() + while line do + write("
  • " .. luci.util.pcdata(line) .. "
  • \n") + line = fp:read() + end + fp:close() + -%>
+
+ +
+
"> + +
+
+ +<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/changes.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/changes.htm new file mode 100644 index 0000000..3e6339b --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/changes.htm @@ -0,0 +1,45 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: changes.htm 3871 2008-12-07 21:27:52Z jow $ + +-%> + +<%+header%> + +

<%:config%>

+

<%:changes%>:

+ +
+ <%=changes%> +
+ +
+
+
"> + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/revert.htm b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/revert.htm new file mode 100644 index 0000000..7f58c2a --- /dev/null +++ b/openwrt/packages/luci/modules/admin-full/luasrc/view/admin_uci/revert.htm @@ -0,0 +1,31 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: revert.htm 3871 2008-12-07 21:27:52Z jow $ + +-%> + +<%+header%> + +

<%:config%>

+

<%:uci_reverted%>:

+ +
+ <%=(changes or "-")%> +
+ +
+
"> + +
+
+ +<%+footer%> diff --git a/openwrt/packages/luci/modules/admin-mini/Makefile b/openwrt/packages/luci/modules/admin-mini/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/index.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/index.lua new file mode 100644 index 0000000..686d148 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/index.lua @@ -0,0 +1,53 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +module("luci.controller.mini.index", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + local root = node() + if not root.lock then + root.target = alias("mini") + root.index = true + end + + entry({"about"}, template("about")).i18n = "admin-core" + + --[[ + local page = entry({"mini"}, alias("mini", "index"), i18n("essentials", "Essentials"), 10) + page.i18n = "admin-core" + page.sysauth = "root" + page.sysauth_authenticator = "htmlauth" + page.index = true + ]]-- + --entry({"mini", "index"}, alias("mini", "index", "index"), i18n("overview"), 10).index = true + --entry({"mini", "index", "index"}, form("mini/index"), i18n("general"), 1).ignoreindex = true + --entry({"system", "luci"}, cbi("mini/luci", {autoapply=true}), i18n("settings"), 10) + --entry({"mini", "index", "logout"}, call("action_logout"), i18n("logout")) +end + +function action_logout() + local dsp = require "luci.dispatcher" + local sauth = require "luci.sauth" + if dsp.context.authsession then + sauth.kill(dsp.context.authsession) + dsp.context.urltoken.stok = nil + end + + luci.http.header("Set-Cookie", "sysauth=; path=" .. dsp.build_url()) + luci.http.redirect(luci.dispatcher.build_url()) +end diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/network.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/network.lua new file mode 100644 index 0000000..054b1ed --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/network.lua @@ -0,0 +1,26 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: network.lua 3674 2008-10-31 09:35:53Z Cyrus $ +]]-- + +module("luci.controller.mini.network", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + + -- entry({"network"}, alias("mini", "network", "index"), i18n("network"), 20).index = true + entry({"network"}, cbi("mini/network", {autoapply=true}), i18n("network"), 1) + entry({"wifi"}, cbi("mini/wifi", {autoapply=true}), i18n("wifi"), 10).i18n="wifi" + -- entry({"network", "dhcp"}, cbi("mini/dhcp", {autoapply=true}), "DHCP", 20) +end diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/system.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/system.lua new file mode 100644 index 0000000..17b6309 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/controller/mini/system.lua @@ -0,0 +1,130 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: system.lua 3743 2008-11-09 20:09:31Z Cyrus $ +]]-- + +module("luci.controller.mini.system", package.seeall) + +function index() + luci.i18n.loadc("admin-core") + local i18n = luci.i18n.translate + +--[[ entry({"system"}, alias("mini", "system", "index"), i18n("system"), 40).index = true + entry({"system", "index"}, cbi("mini/system", {autoapply=true}), i18n("general"), 1) + entry({"system", "passwd"}, form("mini/passwd"), i18n("a_s_changepw"), 10) + entry({"system", "backup"}, call("action_backup"), i18n("a_s_backup"), 80) + entry({"system", "upgrade"}, call("action_upgrade"), i18n("a_s_flash"), 90) + entry({"system", "reboot"}, call("action_reboot"), i18n("reboot"), 100) +]]-- + +end + +function action_backup() + local reset_avail = os.execute([[grep '"rootfs_data"' /proc/mtd >/dev/null 2>&1]]) == 0 + local restore_cmd = "gunzip | tar -xC/ >/dev/null 2>&1" + local backup_cmd = "tar -c %s | gzip 2>/dev/null" + + local restore_fpi + luci.http.setfilehandler( + function(meta, chunk, eof) + if not restore_fpi then + restore_fpi = io.popen(restore_cmd, "w") + end + if chunk then + restore_fpi:write(chunk) + end + if eof then + restore_fpi:close() + end + end + ) + + local upload = luci.http.formvalue("archive") + local backup = luci.http.formvalue("backup") + local reset = reset_avail and luci.http.formvalue("reset") + + if upload and #upload > 0 then + luci.template.render("mini/applyreboot") + luci.sys.reboot() + elseif backup then + luci.util.perror(backup_cmd:format(_keep_pattern())) + local backup_fpi = io.popen(backup_cmd:format(_keep_pattern()), "r") + luci.http.header('Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % { + luci.sys.hostname(), os.date("%Y-%m-%d")}) + luci.http.prepare_content("application/x-targz") + luci.ltn12.pump.all(luci.ltn12.source.file(backup_fpi), luci.http.write) + elseif reset then + luci.template.render("mini/applyreboot") + luci.util.exec("mtd -r erase rootfs_data") + else + luci.template.render("mini/backup", {reset_avail = reset_avail}) + end +end + +function action_reboot() + local reboot = luci.http.formvalue("reboot") + luci.template.render("mini/reboot", {reboot=reboot}) + if reboot then + luci.sys.reboot() + end +end + +function action_upgrade() + require("luci.model.uci") + + local ret = nil + local plat = luci.fs.mtime("/lib/upgrade/platform.sh") + local tmpfile = "/tmp/firmware.img" + local keep_avail = true + + local file + luci.http.setfilehandler( + function(meta, chunk, eof) + if not file then + file = io.open(tmpfile, "w") + end + if chunk then + file:write(chunk) + end + if eof then + file:close() + end + end + ) + + local fname = luci.http.formvalue("image") + local keepcfg = keep_avail and luci.http.formvalue("keepcfg") + + if plat and fname then + ret = function() + return luci.sys.flash(tmpfile, keepcfg and _keep_pattern()) + end + end + + luci.http.prepare_content("text/html") + luci.template.render("mini/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail}) +end + +function _keep_pattern() + local kpattern = "" + local files = luci.model.uci.cursor():get_all("luci", "flash_keep") + if files then + kpattern = "" + for k, v in pairs(files) do + if k:sub(1,1) ~= "." and luci.fs.glob(v) then + kpattern = kpattern .. " " .. v + end + end + end + return kpattern +end diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/dhcp.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/dhcp.lua new file mode 100644 index 0000000..56b4ede --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/dhcp.lua @@ -0,0 +1,105 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: dhcp.lua 3675 2008-10-31 09:36:00Z Cyrus $ +]]-- +require("luci.model.uci") +require("luci.sys") +require("luci.tools.webadmin") + +m = Map("dhcp", "DHCP") + +s = m:section(TypedSection, "dhcp", "DHCP-Server") +s.anonymous = true +s.addremove = false +s.dynamic = false + +s:depends("interface", "lan") + +enable = s:option(ListValue, "ignore", translate("enable"), "") +enable:value(0, translate("enable")) +enable:value(1, translate("disable")) + +start = s:option(Value, "start", translate("m_n_d_firstaddress")) +start.rmempty = true +start:depends("ignore", "0") + + +limit = s:option(Value, "limit", translate("m_n_d_numleases"), "") +limit:depends("ignore", "0") + +function limit.cfgvalue(self, section) + local value = Value.cfgvalue(self, section) + + if value then + return tonumber(value) + 1 + end +end + +function limit.write(self, section, value) + value = tonumber(value) - 1 + return Value.write(self, section, value) +end + +limit.rmempty = true + +time = s:option(Value, "leasetime") +time:depends("ignore", "0") +time.rmempty = true + + + +m2 = Map("luci_ethers", translate("dhcp_leases")) + +local leasefn, leasefp, leases +luci.model.uci.cursor():foreach("dhcp", "dnsmasq", + function(section) + leasefn = section.leasefile + end +) +local leasefp = leasefn and luci.fs.access(leasefn) and io.lines(leasefn) +if leasefp then + leases = {} + for lease in leasefp do + table.insert(leases, luci.util.split(lease, " ")) + end +end + +if leases then + v = m2:section(Table, leases, translate("dhcp_leases_active")) + ip = v:option(DummyValue, 3, translate("ipaddress")) + + mac = v:option(DummyValue, 2, translate("macaddress")) + + ltime = v:option(DummyValue, 1, translate("dhcp_timeremain")) + function ltime.cfgvalue(self, ...) + local value = DummyValue.cfgvalue(self, ...) + return luci.tools.webadmin.date_format( + os.difftime(tonumber(value), os.time()) + ) + end +end + +s = m2:section(TypedSection, "static_lease", translate("luci_ethers")) +s.addremove = true +s.anonymous = true +s.template = "cbi/tblsection" + +mac = s:option(Value, "macaddr", translate("macaddress")) +ip = s:option(Value, "ipaddr", translate("ipaddress")) +for i, dataset in ipairs(luci.sys.net.arptable()) do + ip:value(dataset["IP address"]) + mac:value(dataset["HW address"], + dataset["HW address"] .. " (" .. dataset["IP address"] .. ")") +end + +return m, m2 \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/index.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/index.lua new file mode 100644 index 0000000..34e3555 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/index.lua @@ -0,0 +1,14 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: index.lua 2891 2008-08-18 08:43:48Z Cyrus $ +]]-- +return Template("mini/index") diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/luci.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/luci.lua new file mode 100644 index 0000000..627f6de --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/luci.lua @@ -0,0 +1,37 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: luci.lua 4038 2009-01-14 23:48:51Z Cyrus $ +]]-- +require("luci.config") +m = Map("luci", translate("webui"), translate("a_i_luci1")) + +-- force reload of global luci config namespace to reflect the changes +function m.commit_handler(self) + package.loaded["luci.config"] = nil + require("luci.config") +end + + +c = m:section(NamedSection, "main", "core", translate("general")) + +l = c:option(ListValue, "lang", translate("language")) +l:value("auto") + +local i18ndir = luci.i18n.i18ndir .. "default." +for k, v in pairs(luci.config.languages) do + if k:sub(1, 1) ~= "." and luci.fs.access(i18ndir .. k:gsub("_", "-") .. ".lua") then + l:value(k, v) + end +end + +return m diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/network.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/network.lua new file mode 100644 index 0000000..3cbc86c --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/network.lua @@ -0,0 +1,196 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: network.lua 4171 2009-01-27 20:50:28Z Cyrus $ +]]-- + +require("luci.tools.webadmin") +require("luci.sys") +require("luci.fs") + +local has_pptp = luci.fs.mtime("/usr/sbin/pptp") +local has_pppoe = luci.fs.glob("/usr/lib/pppd/*/rp-pppoe.so") + +local network = luci.model.uci.cursor_state():get_all("network") + +local netstat = luci.sys.net.deviceinfo() +local ifaces = {} + +for k, v in pairs(network) do + if v[".type"] == "interface" and k ~= "loopback" then + table.insert(ifaces, v) + end +end + +m = Map("network", translate("network")) +s = m:section(Table, ifaces, translate("status")) +s.parse = function() end + +s:option(DummyValue, ".name", translate("network")) + +hwaddr = s:option(DummyValue, "_hwaddr", + translate("network_interface_hwaddr"), translate("network_interface_hwaddr_desc")) +function hwaddr.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") or "" + return luci.fs.readfile("/sys/class/net/" .. ix .. "/address") + or luci.util.exec("ifconfig " .. ix):match(" ([A-F0-9:]+)%s*\n") + or "n/a" +end + + +s:option(DummyValue, "ipaddr", translate("ipaddress")) + +s:option(DummyValue, "netmask", translate("netmask")) + + +txrx = s:option(DummyValue, "_txrx", + translate("network_interface_txrx"), translate("network_interface_txrx_desc")) + +function txrx.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][1] + rx = rx and luci.tools.webadmin.byte_format(tonumber(rx)) or "-" + + local tx = netstat and netstat[ix] and netstat[ix][9] + tx = tx and luci.tools.webadmin.byte_format(tonumber(tx)) or "-" + + return string.format("%s / %s", tx, rx) +end + +errors = s:option(DummyValue, "_err", + translate("network_interface_err"), translate("network_interface_err_desc")) + +function errors.cfgvalue(self, section) + local ix = self.map:get(section, "ifname") + + local rx = netstat and netstat[ix] and netstat[ix][3] + local tx = netstat and netstat[ix] and netstat[ix][11] + + rx = rx and tostring(rx) or "-" + tx = tx and tostring(tx) or "-" + + return string.format("%s / %s", tx, rx) +end + + + +s = m:section(NamedSection, "lan", "interface", translate("m_n_local")) +s.addremove = false +s:option(Value, "ipaddr", translate("ipaddress")) + +nm = s:option(Value, "netmask", translate("netmask")) +nm:value("255.255.255.0") +nm:value("255.255.0.0") +nm:value("255.0.0.0") + +gw = s:option(Value, "gateway", translate("gateway") .. translate("cbi_optional")) +gw.rmempty = true +dns = s:option(Value, "dns", translate("dnsserver") .. translate("cbi_optional")) +dns.rmempty = true + + +s = m:section(NamedSection, "wan", "interface", translate("m_n_inet")) +s.addremove = false +p = s:option(ListValue, "proto", translate("protocol")) +p.override_values = true +p:value("none", "disabled") +p:value("static", translate("manual", "manual")) +p:value("dhcp", translate("automatic", "automatic")) +if has_pppoe then p:value("pppoe", "PPPoE") end +if has_pptp then p:value("pptp", "PPTP") end + +function p.write(self, section, value) + -- Always set defaultroute to PPP and use remote dns + -- Overwrite a bad variable behaviour in OpenWrt + if value == "pptp" or value == "pppoe" then + self.map:set(section, "peerdns", "1") + self.map:set(section, "defaultroute", "1") + end + return ListValue.write(self, section, value) +end + +if not ( has_pppoe and has_pptp ) then + p.description = translate("network_interface_prereq_mini") +end + + +ip = s:option(Value, "ipaddr", translate("ipaddress")) +ip:depends("proto", "static") + +nm = s:option(Value, "netmask", translate("netmask")) +nm:depends("proto", "static") + +gw = s:option(Value, "gateway", translate("gateway")) +gw:depends("proto", "static") +gw.rmempty = true + +dns = s:option(Value, "dns", translate("dnsserver")) +dns:depends("proto", "static") +dns.rmempty = true + +usr = s:option(Value, "username", translate("username")) +usr:depends("proto", "pppoe") +usr:depends("proto", "pptp") + +pwd = s:option(Value, "password", translate("password")) +pwd.password = true +pwd:depends("proto", "pppoe") +pwd:depends("proto", "pptp") + + +-- Allow user to set MSS correction here if the UCI firewall is installed +-- This cures some cancer for providers with pre-war routers +if luci.fs.access("/etc/config/firewall") then + mssfix = s:option(Flag, "_mssfix", + translate("m_n_mssfix"), translate("m_n_mssfix_desc")) + mssfix.rmempty = false + + function mssfix.cfgvalue(self) + local value + m.uci:foreach("firewall", "forwarding", function(s) + if s.src == "lan" and s.dest == "wan" then + value = s.mtu_fix + end + end) + return value + end + + function mssfix.write(self, section, value) + m.uci:foreach("firewall", "forwarding", function(s) + if s.src == "lan" and s.dest == "wan" then + m.uci:set("firewall", s[".name"], "mtu_fix", value) + m:chain("firewall") + end + end) + end +end + +kea = s:option(Flag, "keepalive", translate("m_n_keepalive")) +kea:depends("proto", "pppoe") +kea:depends("proto", "pptp") +kea.rmempty = true +kea.enabled = "10" + + +cod = s:option(Value, "demand", translate("m_n_dialondemand"), "s") +cod:depends("proto", "pppoe") +cod:depends("proto", "pptp") +cod.rmempty = true + +srv = s:option(Value, "server", translate("m_n_pptp_server")) +srv:depends("proto", "pptp") +srv.rmempty = true + + + +return m diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/passwd.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/passwd.lua new file mode 100644 index 0000000..f078dd5 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/passwd.lua @@ -0,0 +1,45 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: passwd.lua 3864 2008-12-07 13:44:25Z Cyrus $ +]]-- +f = SimpleForm("password", translate("a_s_changepw"), translate("a_s_changepw1")) + +pw1 = f:field(Value, "pw1", translate("password")) +pw1.password = true +pw1.rmempty = false + +pw2 = f:field(Value, "pw2", translate("confirmation")) +pw2.password = true +pw2.rmempty = false + +function pw2.validate(self, value, section) + return pw1:formvalue(section) == value and value +end + +function f.handle(self, state, data) + if state == FORM_VALID then + local stat = luci.sys.user.setpasswd("root", data.pw1) == 0 + + if stat then + f.message = translate("a_s_changepw_changed") + else + f.errmessage = translate("unknownerror") + end + + data.pw1 = nil + data.pw2 = nil + end + return true +end + +return f \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/system.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/system.lua new file mode 100644 index 0000000..6ab7d0d --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/system.lua @@ -0,0 +1,55 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: system.lua 3736 2008-11-06 23:10:43Z jow $ +]]-- + +require("luci.sys") +require("luci.sys.zoneinfo") +require("luci.tools.webadmin") + + +m = Map("system", translate("system"), translate("a_s_desc")) + +s = m:section(TypedSection, "system", "") +s.anonymous = true + + + +local system, model, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo() +local uptime = luci.sys.uptime() + +s:option(DummyValue, "_system", translate("system")).value = system +s:option(DummyValue, "_cpu", translate("m_i_processor")).value = model + +local load1, load5, load15 = luci.sys.loadavg() +s:option(DummyValue, "_la", translate("load")).value = + string.format("%.2f, %.2f, %.2f", load1, load5, load15) + +s:option(DummyValue, "_memtotal", translate("m_i_memory")).value = + string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)", + tonumber(memtotal) / 1024, + 100 * memcached / memtotal, + translate("mem_cached") or "", + 100 * membuffers / memtotal, + translate("mem_buffered") or "", + 100 * memfree / memtotal, + translate("mem_free") or "") + +s:option(DummyValue, "_systime", translate("m_i_systemtime")).value = + os.date("%c") + +s:option(DummyValue, "_uptime", translate("m_i_uptime")).value = + luci.tools.webadmin.date_format(tonumber(uptime)) + +s:option(DummyValue, "hostname", translate("hostname")) + +return m diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/wifi.lua b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/wifi.lua new file mode 100644 index 0000000..a182fcb --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/model/cbi/mini/wifi.lua @@ -0,0 +1,277 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: wifi.lua 4223 2009-02-04 19:20:17Z Cyrus $ +]]-- + +-- Data init -- + +local uci = luci.model.uci.cursor() +if not uci:get("network", "wan") then + uci:section("network", "interface", "wan", {proto="none", ifname=" "}) + uci:save("network") + uci:commit("network") +end + +local wlcursor = luci.model.uci.cursor_state() +local wireless = wlcursor:get_all("wireless") +local wifidata = luci.sys.wifi.getiwconfig() +local wifidevs = {} +local ifaces = {} + +for k, v in pairs(wireless) do + if v[".type"] == "wifi-iface" then + table.insert(ifaces, v) + end +end + +wlcursor:foreach("wireless", "wifi-device", + function(section) + table.insert(wifidevs, section[".name"]) + end) + + +-- Main Map -- + +m = Map("wireless", translate("wifi"), translate("a_w_devices1")) +m:chain("network") + + +-- Status Table -- +s = m:section(Table, ifaces, translate("networks")) + +link = s:option(DummyValue, "_link", translate("link")) +function link.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Link Quality"] or "-" +end + +essid = s:option(DummyValue, "ssid", "ESSID") + +bssid = s:option(DummyValue, "_bsiid", "BSSID") +function bssid.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return (wifidata[ifname] and (wifidata[ifname].Cell + or wifidata[ifname]["Access Point"])) or "-" +end + +channel = s:option(DummyValue, "channel", translate("channel")) +function channel.cfgvalue(self, section) + return wireless[self.map:get(section, "device")].channel +end + +protocol = s:option(DummyValue, "_mode", translate("protocol")) +function protocol.cfgvalue(self, section) + local mode = wireless[self.map:get(section, "device")].mode + return mode and "802." .. mode +end + +mode = s:option(DummyValue, "mode", translate("mode")) +encryption = s:option(DummyValue, "encryption", translate("iwscan_encr")) + +power = s:option(DummyValue, "_power", translate("power")) +function power.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Tx-Power"] or "-" +end + +scan = s:option(Button, "_scan", translate("scan")) +scan.inputstyle = "find" + +function scan.cfgvalue(self, section) + return self.map:get(section, "ifname") or false +end + +-- WLAN-Scan-Table -- + +t2 = m:section(Table, {}, translate("iwscan"), translate("iwscan1")) + +function scan.write(self, section) + m.autoapply = false + t2.render = t2._render + local ifname = self.map:get(section, "ifname") + luci.util.update(t2.data, luci.sys.wifi.iwscan(ifname)) +end + +t2._render = t2.render +t2.render = function() end + +t2:option(DummyValue, "Quality", translate("iwscan_link")) +essid = t2:option(DummyValue, "ESSID", "ESSID") +function essid.cfgvalue(self, section) + return self.map:get(section, "ESSID") +end + +t2:option(DummyValue, "Address", "BSSID") +t2:option(DummyValue, "Mode", translate("mode")) +chan = t2:option(DummyValue, "channel", translate("channel")) +function chan.cfgvalue(self, section) + return self.map:get(section, "Channel") + or self.map:get(section, "Frequency") + or "-" +end + +t2:option(DummyValue, "Encryption key", translate("iwscan_encr")) + +t2:option(DummyValue, "Signal level", translate("iwscan_signal")) + +t2:option(DummyValue, "Noise level", translate("iwscan_noise")) + + + +if #wifidevs < 1 then + return m +end + +-- Config Section -- + +s = m:section(NamedSection, wifidevs[1], "wifi-device", translate("devices")) +s.addremove = false + +local hwtype = m:get(wifidevs[1], "type") + +if hwtype == "atheros" then + mode = s:option(ListValue, "hwmode", translate("mode")) + mode.override_values = true + mode:value("", "auto") + mode:value("11b", "802.11b") + mode:value("11g", "802.11g") + mode:value("11a", "802.11a") + mode:value("11bg", "802.11b+g") + mode.rmempty = true +end + + +ch = s:option(Value, "channel", translate("a_w_channel")) +for i=1, 14 do + ch:value(i, i .. " (2.4 GHz)") +end + + +s = m:section(TypedSection, "wifi-iface", translate("m_n_local")) +s.anonymous = true +s.addremove = false + +s:option(Value, "ssid", translate("a_w_netid")) + +bssid = s:option(Value, "bssid", translate("wifi_bssid")) + +local devs = {} +luci.model.uci.cursor():foreach("wireless", "wifi-device", + function (section) + table.insert(devs, section[".name"]) + end) + +if #devs > 1 then + device = s:option(DummyValue, "device", translate("device")) +else + s.defaults.device = devs[1] +end + +encr = s:option(ListValue, "encryption", translate("encryption")) +encr.override_values = true +encr:value("none", "No Encryption") +encr:value("wep", "WEP") + +if hwtype == "atheros" or hwtype == "mac80211" then + local supplicant = luci.fs.mtime("/usr/sbin/wpa_supplicant") + local hostapd = luci.fs.mtime("/usr/sbin/hostapd") + + if hostapd and supplicant then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") + encr:value("wpa", "WPA-Radius", {mode="ap"}) + encr:value("wpa2i", "WPA2-Radius", {mode="ap"}) + elseif hostapd and not supplicant then + encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="adhoc"}) + encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="adhoc"}) + encr:value("wpa", "WPA-Radius", {mode="ap"}) + encr:value("wpa2i", "WPA2-Radius", {mode="ap"}) + encr.description = translate("wifi_wpareq") + elseif not hostapd and supplicant then + encr:value("psk", "WPA-PSK", {mode="sta"}) + encr:value("psk2", "WPA2-PSK", {mode="sta"}) + encr.description = translate("wifi_wpareq") + else + encr.description = translate("wifi_wpareq") + end +elseif hwtype == "broadcom" then + encr:value("psk", "WPA-PSK") + encr:value("psk2", "WPA2-PSK") +end + +key = s:option(Value, "key", translate("key")) +key:depends("encryption", "wep") +key:depends("encryption", "psk") +key:depends("encryption", "wpa") +key:depends("encryption", "psk2") +key:depends("encryption", "wpa2i") +key.rmempty = true +key.description = translate('wifi_keyreq') + +function key:validate(value, section) + function string.tohex(x) + local hex = '' + for c in x:gmatch('(.)') do hex = hex .. string.format("%02x", c:byte()) end + return hex + end + + function string.hexcheck(x) + return #(x:match('%x*')) == #x and x + end + + if encr:formvalue(section) == 'wep' then + if #value == 5 or #value == 13 then + return value:tohex() + elseif #value == 10 or #value == 26 then + return value:hexcheck() + else + return nil + end + elseif encr:formvalue(section) == 'psk' or encr:formvalue(section) == 'psk2' then + return #value == 64 and value:hexcheck() + else + return value + end +end + +server = s:option(Value, "server", translate("a_w_radiussrv")) +server:depends("encryption", "wpa") +server:depends("encryption", "wpa2i") +server.rmempty = true + +port = s:option(Value, "port", translate("a_w_radiusport")) +port:depends("encryption", "wpa") +port:depends("encryption", "wpa2i") +port.rmempty = true + + +if hwtype == "atheros" or hwtype == "broadcom" then + iso = s:option(Flag, "isolate", translate("a_w_apisolation"), translate("a_w_apisolation1")) + iso.rmempty = true + iso:depends("mode", "ap") + + hide = s:option(Flag, "hidden", translate("a_w_hideessid")) + hide.rmempty = true + hide:depends("mode", "ap") +end + +if hwtype == "mac80211" or hwtype == "atheros" then + bssid:depends({mode="adhoc"}) +end + +if hwtype == "broadcom" then + bssid:depends({mode="wds"}) +end + + +return m diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/applyreboot.htm b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/applyreboot.htm new file mode 100644 index 0000000..73cf4a7 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/applyreboot.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: applyreboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+
+

<% if msg then %><%=msg%><% else %><%:a_s_applyreboot1%><% end %>

+

<%:a_s_reboot_running%>

+ +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/backup.htm b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/backup.htm new file mode 100644 index 0000000..3162e73 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/backup.htm @@ -0,0 +1,40 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: backup.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_backup%>

+

<%:a_s_backup1%>

+
+
+ +
+ +
+ +
+
<%:a_s_backup_archive%>:
+
+ +
+
+ +
+
+<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/index.htm b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/index.htm new file mode 100644 index 0000000..d7c5bd3 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/index.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 4069 2009-01-17 13:26:07Z Cyrus $ + +-%> +

<%:a_i_i_hello%>

+

<%:a_i_i_admin1%>

+

<%:a_i_i_admin2%>
+<%:a_i_i_admin3%>

+

<%:a_i_i_admin5%>

+

<%:a_i_i_admin6%>

+

<%:a_i_i_team%>

diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/reboot.htm b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/reboot.htm new file mode 100644 index 0000000..f5e3304 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/reboot.htm @@ -0,0 +1,33 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: reboot.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:reboot%>

+

<%:a_s_reboot1%>

+<%- +local c = require("luci.model.uci").cursor():changes() +if c and next(c) then +-%> +

<%:a_s_reboot_u%>

+<%- +end +if not reboot then +-%> +

<%:a_s_reboot_do%>

+<%- else -%> +

<%:a_s_reboot_running%>

+ +<%- end -%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/upgrade.htm b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/upgrade.htm new file mode 100644 index 0000000..080aa07 --- /dev/null +++ b/openwrt/packages/luci/modules/admin-mini/luasrc/view/mini/upgrade.htm @@ -0,0 +1,52 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: upgrade.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +

<%:system%>

+

<%:a_s_flash%>

+

<%:a_s_flash_upgrade1%>

+
+<% if sysupgrade and not ret then %> +
+
<%:a_s_flash_fwimage%>:
+
+ +
+
+ <% if keep_avail then -%> + + <%:a_s_flash_keepcfg%> + <% end -%> +
+
+ +
+
+<% elseif ret then %> +

<%:a_s_flash_received%>

+

<%:a_s_flash_inprogress%>

+ + + <% %> + <% local ret = ret() + if ret == 0 then %> +
<%:a_s_flash_flashed%>
+ <% else %> +
<%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)
+ <% end %> +<% else %> +
<%:a_s_flash_notimplemented%>
+<% end %> +<%+footer%> +<% if ret == 0 then luci.sys.reboot() end %> diff --git a/openwrt/packages/luci/modules/freifunk/Makefile b/openwrt/packages/luci/modules/freifunk/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/modules/freifunk/ipkg/postinst b/openwrt/packages/luci/modules/freifunk/ipkg/postinst new file mode 100755 index 0000000..90e28ef --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/ipkg/postinst @@ -0,0 +1,5 @@ +#!/bin/sh + +[ -n "${IPKG_INSTROOT}" ] || { + /etc/init.d/freifunk enabled || /etc/init.d/freifunk enable +} diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/controller/freifunk/freifunk.lua b/openwrt/packages/luci/modules/freifunk/luasrc/controller/freifunk/freifunk.lua new file mode 100644 index 0000000..5bd7821 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/controller/freifunk/freifunk.lua @@ -0,0 +1,192 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: freifunk.lua 4152 2009-01-26 10:21:20Z Cyrus $ +]]-- +module("luci.controller.freifunk.freifunk", package.seeall) + +function index() + local i18n = luci.i18n.translate + + local page = node() + page.lock = true + page.target = alias("freifunk") + page.subindex = true + page.index = false + + local page = node("freifunk") + page.title = "Freifunk" + page.target = alias("freifunk", "index") + page.order = 5 + page.setuser = "nobody" + page.setgroup = "nogroup" + page.i18n = "freifunk" + page.index = true + + local page = node("freifunk", "index") + page.target = template("freifunk/index") + page.title = "Übersicht" + page.order = 10 + page.indexignore = true + + local page = node("freifunk", "index", "contact") + page.target = template("freifunk/contact") + page.title = "Kontakt" + + + local page = node("freifunk", "status") + page.target = form("freifunk/public_status") + page.title = "Status" + page.order = 20 + page.i18n = "admin-core" + page.setuser = false + page.setgroup = false + + entry({"freifunk", "status.json"}, call("jsonstatus")) + + assign({"freifunk", "olsr"}, {"admin", "status", "olsr"}, "OLSR", 30) + + if luci.fs.access("/etc/config/luci_statistics") then + assign({"freifunk", "graph"}, {"admin", "statistics", "graph"}, i18n("stat_statistics", "Statistiken"), 40) + end + + assign({"mini", "freifunk"}, {"admin", "freifunk"}, "Freifunk", 15) + entry({"admin", "freifunk"}, alias("admin", "freifunk", "index"), "Freifunk", 15) + local page = node("admin", "freifunk", "index") + page.target = cbi("freifunk/freifunk") + page.title = "Freifunk" + page.order = 30 + + local page = node("admin", "freifunk", "contact") + page.target = cbi("freifunk/contact") + page.title = "Kontakt" + page.order = 40 +end + +local function fetch_olsrd() + local sys = require "luci.sys" + local util = require "luci.util" + local table = require "table" + local rawdata = sys.httpget("http://127.0.0.1:2006/") + + if #rawdata == 0 then + if luci.fs.access("/proc/net/ipv6_route", "r") then + rawdata = sys.httpget("http://[::1]:2006/") + if #rawdata == 0 then + return nil + end + else + return nil + end + end + + local data = {} + + local tables = util.split(util.trim(rawdata), "\r?\n\r?\n", nil, true) + + + for i, tbl in ipairs(tables) do + local lines = util.split(tbl, "\r?\n", nil, true) + local name = table.remove(lines, 1):sub(8) + local keys = util.split(table.remove(lines, 1), "\t") + local split = #keys - 1 + + data[name] = {} + + for j, line in ipairs(lines) do + local fields = util.split(line, "\t", split) + data[name][j] = {} + for k, key in pairs(keys) do + data[name][j][key] = fields[k] + end + + if data[name][j].Linkcost then + data[name][j].LinkQuality, + data[name][j].NLQ, + data[name][j].ETX = + data[name][j].Linkcost:match("([%w.]+)/([%w.]+)[%s]+([%w.]+)") + end + end + end + + return data +end + +function jsonstatus() + local root = {} + local sys = require "luci.sys" + local uci = require "luci.model.uci" + local util = require "luci.util" + local http = require "luci.http" + local json = require "luci.json" + local ltn12 = require "luci.ltn12" + local version = require "luci.version" + local webadmin = require "luci.tools.webadmin" + + local cursor = uci.cursor_state() + + local ffzone = webadmin.firewall_find_zone("freifunk") + local ffznet = ffzone and cursor:get("firewall", ffzone, "network") + local ffwifs = ffznet and util.split(ffznet, " ") or {} + + + root.protocol = 1 + + root.system = { + uptime = {sys.uptime()}, + loadavg = {sys.loadavg()}, + sysinfo = {sys.sysinfo()}, + hostname = sys.hostname() + } + + root.firmware = { + luciname=version.luciname, + luciversion=version.luciversion, + distname=version.distname, + distversion=version.distversion + } + + root.freifunk = {} + cursor:foreach("freifunk", "public", function(s) + root.freifunk[s[".name"]] = s + end) + + cursor:foreach("system", "system", function(s) + root.geo = { + latitude = s.latitude, + longitude = s.longitude + } + end) + + root.network = {} + root.wireless = {devices = {}, interfaces = {}, status = {}} + local wifs = root.wireless.interfaces + local wifidata = luci.sys.wifi.getiwconfig() or {} + local netdata = luci.sys.net.deviceinfo() or {} + + for _, vif in ipairs(ffwifs) do + root.network[vif] = cursor:get_all("network", vif) + root.wireless.devices[vif] = cursor:get_all("wireless", vif) + cursor:foreach("wireless", "wifi-iface", function(s) + if s.device == vif and s.network == vif then + wifs[#wifs+1] = s + if s.ifname then + root.wireless.status[s.ifname] = wifidata[s.ifname] + end + end + end) + end + + root.olsrd = fetch_olsrd() + + http.prepare_content("application/json") + ltn12.pump.all(json.Encoder(root):source(), http.write) +end diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.lua b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.lua new file mode 100644 index 0000000..27382b3 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.lua @@ -0,0 +1,21 @@ +ff_hellonet = 'Hallo und willkommen im Netz von' +ff_public1 = 'Wir sind eine Initiative zur Schaffung eines freien, offenen und unabhängigen Funknetzwerks auf WLAN-Basis.' +ff_public2 = 'Dies ist der Zugangspunkt ' +ff_public3 = 'Er wird betrieben von ' +ff_public4 = 'Weitere Informationen zur globalen Freifunkinitiative findest du unter' +ff_public5 = 'Hast du Interesse an diesem Projekt, dann wende dich an deine lokale Gemeinschaft' +ff_public6 = 'Der Internetzugang über das experimentelle Freifunknetz ist an technische und organisatorische Bedingungen geknüpft und deshalb möglicherweise nicht (immer) gewährleistet.' +ff_location = 'Standort' +ff_mail = 'E-Mail' +ff_mail1 = 'Bitte unbedingt angeben!' +ff_nickname = 'Pseudonym' +ff_name = 'Name' +ff_node = 'Knoten' +ff_note = 'Notiz' +ff_phone = 'Telefon' +ff_ram = 'Hauptspeicher' +ff_free = 'Frei' +ff_buffers = 'Buffers' +ff_cached = 'Cached' +ff_total = 'Gesamt' +ff_geocoord = 'Geokoordinaten' diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.xml b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.xml new file mode 100644 index 0000000..426454d --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.de.xml @@ -0,0 +1,28 @@ + + + + +Hallo und willkommen im Netz von +Wir sind eine Initiative zur Schaffung eines freien, offenen und unabhängigen Funknetzwerks auf WLAN-Basis. +Dies ist der Zugangspunkt +Er wird betrieben von +Weitere Informationen zur globalen Freifunkinitiative findest du unter +Hast du Interesse an diesem Projekt, dann wende dich an deine lokale Gemeinschaft +Der Internetzugang über das experimentelle Freifunknetz ist an technische und organisatorische Bedingungen geknüpft und deshalb möglicherweise nicht (immer) gewährleistet. + +Standort +E-Mail +Bitte unbedingt angeben! +Pseudonym +Name +Knoten +Notiz +Telefon +Hauptspeicher +Frei +Buffers +Cached +Gesamt +Geokoordinaten + + diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.lua b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.lua new file mode 100644 index 0000000..cf3ae4d --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.lua @@ -0,0 +1,21 @@ +ff_hellonet = 'Hello and welcome in the network of' +ff_public1 = 'We are an initiative to establish a free, independent and open wireless mesh network.' +ff_public2 = 'This is the access point' +ff_public3 = 'It is operated by' +ff_public4 = 'You can find further information about the global Freifunk initiative at' +ff_public5 = 'If you are interested in our project then contact the local community' +ff_public6 = 'Internet access depends on technical and organisational conditions and may or may not work for you.' +ff_location = 'Location' +ff_mail = 'E-Mail' +ff_mail1 = 'You really should provide your address here!' +ff_nickname = 'Nickname' +ff_name = 'Realname' +ff_node = 'Node' +ff_note = 'Notice' +ff_phone = 'Phone' +ff_ram = 'Memory' +ff_free = 'Free' +ff_buffers = 'Buffers' +ff_cached = 'Cached' +ff_total = 'Total' +ff_geocoord = 'Coordinates' diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.xml b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.xml new file mode 100644 index 0000000..ce519ad --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/i18n/freifunk.en.xml @@ -0,0 +1,28 @@ + + + + +Hello and welcome in the network of +We are an initiative to establish a free, independent and open wireless mesh network. +This is the access point +It is operated by +You can find further information about the global Freifunk initiative at +If you are interested in our project then contact the local community +Internet access depends on technical and organisational conditions and may or may not work for you. + +Location +E-Mail +You really should provide your address here! +Nickname +Realname +Node +Notice +Phone +Memory +Free +Buffers +Cached +Total +Coordinates + + diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/contact.lua b/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/contact.lua new file mode 100644 index 0000000..5dd8835 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/contact.lua @@ -0,0 +1,34 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: contact.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +luci.i18n.loadc("freifunk") + +m = Map("freifunk", translate("contact"), translate("contact1")) + +c = m:section(NamedSection, "contact", "public", "") + +c:option(Value, "nickname", translate("ff_nickname")) +c:option(Value, "name", translate("ff_name")) +c:option(Value, "mail", translate("ff_mail"), translate("ff_mail1")) +c:option(Value, "phone", translate("ff_phone")) +c:option(Value, "location", translate("ff_location")) +c:option(Value, "note", translate("ff_note")) + +m2 = Map("system", translate("geo")) + +s = m2:section(TypedSection, "system", "") +s:option(Value, "latitude", translate("latitude", "Breite")).rmempty = true +s:option(Value, "longitude", translate("longitude", "Länge")).rmempty = true + +return m, m2 diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/freifunk.lua b/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/freifunk.lua new file mode 100644 index 0000000..fa789d9 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/freifunk.lua @@ -0,0 +1,24 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth + +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: freifunk.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- +m = Map("freifunk", "Freifunk") + +c = m:section(NamedSection, "community", "public", "Gemeinschaft", [[Dies sind die Grundeinstellungen +für die lokale Freifunkgemeinschaft. Diese Werte wirken sich NICHT auf die Konfiguration +des Routers aus, sondern definieren nur die Vorgaben für den Freifunkassistenten.]]) +c:option(Value, "name", "Gemeinschaft") +c:option(Value, "homepage", "Webseite") +c:option(Value, "ssid", "ESSID") +c:option(Value, "prefix", "Netzprefix") + +return m \ No newline at end of file diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua b/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua new file mode 100644 index 0000000..8180bfe --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/model/cbi/freifunk/public_status.lua @@ -0,0 +1,216 @@ +require "luci.sys" +require "luci.tools.webadmin" + +local bit = require "bit" +local uci = luci.model.uci.cursor_state() + +local ffzone = luci.tools.webadmin.firewall_find_zone("freifunk") +local ffznet = ffzone and uci:get("firewall", ffzone, "network") +local ffwifs = ffznet and luci.util.split(ffznet, " ") or {} + +-- System -- + +f = SimpleForm("system", "System") +f.submit = false +f.reset = false +local system, model, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo() +local uptime = luci.sys.uptime() + +f:field(DummyValue, "_system", translate("system")).value = system +f:field(DummyValue, "_cpu", translate("m_i_processor")).value = model + +local load1, load5, load15 = luci.sys.loadavg() +f:field(DummyValue, "_la", translate("load")).value = +string.format("%.2f, %.2f, %.2f", load1, load5, load15) + +f:field(DummyValue, "_memtotal", translate("m_i_memory")).value = +string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)", + tonumber(memtotal) / 1024, + 100 * memcached / memtotal, + translate("mem_cached") or "", + 100 * membuffers / memtotal, + translate("mem_buffered") or "", + 100 * memfree / memtotal, + translate("mem_free") or "") + +f:field(DummyValue, "_systime", translate("m_i_systemtime")).value = +os.date("%c") + +f:field(DummyValue, "_uptime", translate("m_i_uptime")).value = +luci.tools.webadmin.date_format(tonumber(uptime)) + + +-- Wireless -- + +local wireless = uci:get_all("wireless") +local wifidata = luci.sys.wifi.getiwconfig() +local ifaces = {} + +for k, v in pairs(wireless) do + if v[".type"] == "wifi-iface" and ( + luci.util.contains(ffwifs, v.device) or + ( #ffwifs == 0 and (not v.encryption or v.encryption == "none") ) ) + then + table.insert(ifaces, v) + end +end + + +m = SimpleForm("wireless", "Freifunk WLAN") +m.submit = false +m.reset = false + +s = m:section(Table, ifaces, translate("networks")) + +link = s:option(DummyValue, "_link", translate("link")) +function link.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Link Quality"] or "-" +end + +essid = s:option(DummyValue, "ssid", "ESSID") + +bssid = s:option(DummyValue, "_bsiid", "BSSID") +function bssid.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return (wifidata[ifname] and (wifidata[ifname].Cell + or wifidata[ifname]["Access Point"])) or "-" +end + +channel = s:option(DummyValue, "channel", translate("channel")) + function channel.cfgvalue(self, section) + return wireless[self.map:get(section, "device")].channel +end + +protocol = s:option(DummyValue, "_mode", translate("protocol")) +function protocol.cfgvalue(self, section) + local mode = wireless[self.map:get(section, "device")].mode + return mode and "802." .. mode +end + +mode = s:option(DummyValue, "mode", translate("mode")) +encryption = s:option(DummyValue, "encryption", translate("iwscan_encr")) + +power = s:option(DummyValue, "_power", translate("power")) +function power.cfgvalue(self, section) + local ifname = self.map:get(section, "ifname") + return wifidata[ifname] and wifidata[ifname]["Tx-Power"] or "-" +end + +scan = s:option(Button, "_scan", translate("scan")) +scan.inputstyle = "find" + +function scan.cfgvalue(self, section) + return self.map:get(section, "ifname") or false +end + +t2 = m:section(Table, {}, translate("iwscan"), translate("iwscan1")) + +function scan.write(self, section) + t2.render = t2._render + local ifname = self.map:get(section, "ifname") + luci.util.update(t2.data, luci.sys.wifi.iwscan(ifname)) +end + +t2._render = t2.render +t2.render = function() end + +t2:option(DummyValue, "Quality", translate("iwscan_link")) +essid = t2:option(DummyValue, "ESSID", "ESSID") +function essid.cfgvalue(self, section) + return luci.util.pcdata(self.map:get(section, "ESSID")) +end + +t2:option(DummyValue, "Address", "BSSID") +t2:option(DummyValue, "Mode", translate("mode")) +chan = t2:option(DummyValue, "channel", translate("channel")) +function chan.cfgvalue(self, section) + return self.map:get(section, "Channel") + or self.map:get(section, "Frequency") + or "-" +end + +t2:option(DummyValue, "Encryption key", translate("iwscan_encr")) + +t2:option(DummyValue, "Signal level", translate("iwscan_signal")) + +t2:option(DummyValue, "Noise level", translate("iwscan_noise")) + + +-- Routes -- +r = SimpleForm("routes", "Standardrouten") +r.submit = false +r.reset = false + +local routes = {} +for i, route in ipairs(luci.sys.net.routes()) do + if route.dest:prefix() == 0 then + routes[#routes+1] = route + end +end + +v = r:section(Table, routes) + +net = v:option(DummyValue, "iface", translate("network")) +function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes[section].device) + or routes[section].device +end + +target = v:option(DummyValue, "target", translate("target")) +function target.cfgvalue(self, section) + return routes[section].dest:network():string() +end + +netmask = v:option(DummyValue, "netmask", translate("netmask")) +function netmask.cfgvalue(self, section) + return routes[section].dest:mask():string() +end + +gateway = v:option(DummyValue, "gateway", translate("gateway")) +function gateway.cfgvalue(self, section) + return routes[section].gateway:string() +end + +metric = v:option(DummyValue, "metric", translate("metric")) +function metric.cfgvalue(self, section) + return routes[section].metric +end + + +local routes6 = {} +for i, route in ipairs(luci.sys.net.routes6() or {}) do + if route.dest:prefix() == 0 then + routes6[#routes6+1] = route + end +end + +if #routes6 > 0 then + v6 = r:section(Table, routes6) + + net = v6:option(DummyValue, "iface", translate("network")) + function net.cfgvalue(self, section) + return luci.tools.webadmin.iface_get_network(routes[section].device) + or routes6[section].device + end + + target = v6:option(DummyValue, "target", translate("target")) + function target.cfgvalue(self, section) + return routes6[section].dest:string() + end + + gateway = v6:option(DummyValue, "gateway6", translate("gateway6")) + function gateway.cfgvalue(self, section) + return routes6[section].source:string() + end + + metric = v6:option(DummyValue, "metric", translate("metric")) + function metric.cfgvalue(self, section) + local metr = routes6[section].metric + local lower = bit.band(metr, 0xffff) + local higher = bit.rshift(bit.band(metr, 0xffff0000), 16) + return "%04X%04X" % {higher, lower} + end +end + +return f, m, r diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/contact.htm b/openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/contact.htm new file mode 100644 index 0000000..c83cd58 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/contact.htm @@ -0,0 +1,27 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: contact.htm 3646 2008-10-29 18:54:56Z jow $ + +-%> +<%+header%> +<% local contact = luci.model.uci.cursor():get_all("freifunk", "contact") %> +

<%:contact%>

+ + + + + + + + +
<%:ff_nickname%>:<%=contact.nickname%>
<%:ff_name%>:<%=contact.name%>
<%:ff_mail%>:<%=contact.mail%>
<%:ff_phone%>:<%=contact.phone%>
<%:ff_location%>:<%=contact.location%>
<%:ff_geocoord%>:<%=contact.geo%>
<%:ff_note%>:<%=contact.note%>
+<%+footer%> diff --git a/openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/index.htm b/openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/index.htm new file mode 100644 index 0000000..9f9aff9 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/luasrc/view/freifunk/index.htm @@ -0,0 +1,24 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: index.htm 3941 2008-12-23 21:39:38Z jow $ + +-%> +<%+header%> +<% local ff = luci.model.uci.cursor():get_all("freifunk") %> +

<%:ff_hellonet%> <%=ff.community.name or 'Freifunk Deutschland'%>!

+

<%:ff_public1%>
+<%:ff_public2%> <%=luci.sys.hostname()%>. <%:ff_public3%> +"> <%=ff.contact.nickname%>.

+

<%:ff_public4%> Freifunk.net.
+<%:ff_public5%> <%=ff.community.name or 'Freifunk'%>.

+

<%:ff_note%>: <%:ff_public6%>

+<%+footer%> diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk new file mode 100644 index 0000000..862c86d --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk @@ -0,0 +1,126 @@ +config settings wizard +config public contact + option nickname '' + option name '' + option mail '' + option phone '' + option location '' + option note '' + +config public community + option name 'Freifunk' + option homepage 'http://freifunk.net' + +config fw_rule icmp + option src freifunk + option target ACCEPT + option proto icmp + +config fw_rule http + option src freifunk + option target ACCEPT + option proto tcp + option dest_port 80 + +config fw_rule https + option src freifunk + option target ACCEPT + option proto tcp + option dest_port 443 + +config fw_rule ssh + option src freifunk + option target ACCEPT + option proto tcp + option dest_port 22 + +config fw_rule olsr + option src freifunk + option target ACCEPT + option proto udp + option dest_port 698 + +config fw_forwarding lan + option src lan + option dest freifunk + +config fw_forwarding fffwd + option src freifunk + option dest freifunk + + +config defaults wifi_device + option channel 1 + option diversity 1 + option disabled 0 + option txpower 10 + + +config defaults wifi_iface + option mode adhoc + option bssid 02:CA:FF:EE:BA:BE + option sw_merge 1 + + +config defaults interface + option netmask 255.0.0.0 + option dns "88.198.178.18 141.54.1.1 212.204.49.83 208.67.220.220 208.67.222.222" + + +config defaults alias + option netmask 255.255.255.0 + + +config defaults dhcp + option leasetime 30m + + +config defaults olsr_interface + option HelloInterval 6.0 + option HelloValidityTime 108.0 + option TcInterval 4.0 + option TcValidityTime 324.0 + option MidInterval 18.0 + option MidValidityTime 324.0 + option HnaInterval 18.0 + option HnaValidityTime 108.0 + + +config community leipzig + option name "Freifunk Leipzig" + option homepage http://leipzig.freifunk.net + option ssid "leipzig.freifunk.net" + option prefix "104.61" + +config community halle + option name "Freifunk Halle" + option homepage http://halle.freifunk.net + option ssid "halle.freifunk.net" + option prefix "104.62" + +config community l59 + option name "Freifunk L59" + option homepage http://freifunk.net + option ssid "start.freifunk.net" + option prefix "104.59" + +config community berlin + option name "Freifunk Berlin" + option homepage http://berlin.freifunk.net + option ssid "olsr.freifunk.net" + option prefix "104" + option external freifunk_berlin + +config community hannover + option name "Freifunk Hannover" + option homepage http://hannover.freifunk.net + option ssid "hannover.freifunk.net" + option prefix "10.2" + option external freifunk_hannover + +config community augsburg + option name "Freifunk Augsburg" + option homepage http://augsburg.freifunk.net + option ssid "augsburg.freifunk.net" + option prefix "191.161" + option external freifunk_augsburg diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_augsburg b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_augsburg new file mode 100644 index 0000000..f68600c --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_augsburg @@ -0,0 +1,2 @@ +config defaults interface + option netmask 255.255.0.0 \ No newline at end of file diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_berlin b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_berlin new file mode 100644 index 0000000..65bde76 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_berlin @@ -0,0 +1,2 @@ +config defaults wifi_device + option channel 10 \ No newline at end of file diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_hannover b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_hannover new file mode 100644 index 0000000..f797a93 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/config/freifunk_hannover @@ -0,0 +1,5 @@ +config defaults wifi_iface + option bssid CA:FF:EE:CA:FF:EE + +config defaults interface + option netmask 255.255.0.0 \ No newline at end of file diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/firewall.freifunk b/openwrt/packages/luci/modules/freifunk/root/etc/firewall.freifunk new file mode 100644 index 0000000..3a33127 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/firewall.freifunk @@ -0,0 +1,53 @@ +#!/bin/sh +# Freifunk Firewall addons +# $Id: firewall.freifunk 4140 2009-01-25 19:38:41Z jow $ + + +# +# Apply advanced settings +# +apply_advanced() { + local tcp_ecn + local tcp_window_scaling + local accept_redirects + local accept_source_route + + config_get_bool tcp_ecn $1 tcp_ecn 1 + config_get_bool tcp_window_scaling $1 tcp_window_scaling 1 + config_get_bool accept_redirects $1 accept_redirects 0 + config_get_bool accept_source_route $1 accept_source_route 0 + + logger -t firewall.freifunk "tcp_ecn is $tcp_ecn" + logger -t firewall.freifunk "tcp_window_scaling is $tcp_window_scaling" + logger -t firewall.freifunk "accept_redirects is $accept_redirects" + logger -t firewall.freifunk "accept_source_route is $accept_source_route" + + sysctl -w net.ipv4.tcp_ecn=$tcp_ecn >/dev/null + sysctl -w net.ipv4.tcp_window_scaling=$tcp_window_scaling >/dev/null + + for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do + echo $accept_redirects > $f + done + + for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do + echo $accept_source_route > $f + done +} + +config_foreach apply_advanced advanced + + +# +# Apply fixes for masquerading rules +# +apply_nat_fix() { + local up + local ifname + config_get up $1 up + [ -n "$up" ] || return 0 + (ACTION="ifup" INTERFACE="$1" . /etc/hotplug.d/iface/22-firewall-nat-fix ) +} + +uci_set_state firewall core loaded 1 +config_foreach fw_addif interface +config_foreach apply_nat_fix interface diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/hotplug.d/iface/22-firewall-nat-fix b/openwrt/packages/luci/modules/freifunk/root/etc/hotplug.d/iface/22-firewall-nat-fix new file mode 100644 index 0000000..634f432 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/hotplug.d/iface/22-firewall-nat-fix @@ -0,0 +1,61 @@ +. /lib/firewall/uci_firewall.sh +unset ZONE +config_get ifname $INTERFACE ifname +[ "$ifname" == "lo" ] && exit 0 + +load_zones() { + local name + local network + config_get name $1 name + config_get network $1 network + [ -z "$network" ] && network=$name + for n in $network; do + [ "$n" = "$INTERFACE" ] && ZONE="$ZONE $name" + done +} + +config_foreach load_zones zone + +[ -z "$ZONE" ] && exit 0 + +natfix_addr_add() { + local network=$1 + local iface=$2 + + config_get parent "$1" interface + [ "$network" != "$INTERFACE" -a "$parent" != "$INTERFACE" ] && return 0 + + config_get ipaddr "$network" ipaddr + [ -n "$ipaddr" ] || return 0 + config_get netmask "$network" netmask + [ -n "$netmask" ] || return 0 + eval "$(ipcalc.sh $ipaddr $netmask)" + + logger -t firewall.freifunk "adding nat rule for $iface($NETWORK/$PREFIX)" + iptables -t nat -A "natfix_$iface" -s "$NETWORK/$PREFIX" -d "$NETWORK/$PREFIX" -j ACCEPT +} + +[ ifup = "$ACTION" ] && { + iptables -t nat -N "natfix_$ifname" + natfix_addr_add "$INTERFACE" "$ifname" + config_foreach natfix_addr_add alias "$ifname" + + for z in $ZONE; do + local loaded + config_get loaded core loaded + [ -n "$loaded" ] && { + logger -t firewall.freifunk "applying nat rules on zone $z" + iptables -t nat -I "zone_${z}_nat" 1 -o "$ifname" -j "natfix_$ifname" + } + done +} + +[ ifdown = "$ACTION" ] && { + for z in $ZONE; do + local up + config_get up $z up + iptables -t nat -D "zone_${z}_nat" -o "$ifname" -j "natfix_$ifname" 2>/dev/null + done + iptables -t nat -F "natfix_$ifname" 2>/dev/null + iptables -t nat -X "natfix_$ifname" 2>/dev/null +} diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/init.d/freifunk b/openwrt/packages/luci/modules/freifunk/root/etc/init.d/freifunk new file mode 100755 index 0000000..60c0eb5 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/init.d/freifunk @@ -0,0 +1,24 @@ +#!/bin/sh /etc/rc.common +# Freifunk Init +# $Id: freifunk 4214 2009-01-31 17:32:35Z jow $ + +START=99 + +boot() { + grep -q 'killall -HUP dnsmasq' /etc/crontabs/root || { + echo "*/5 * * * * killall -HUP dnsmasq" >> /etc/crontabs/root + } + + grep -q '/usr/sbin/ff_olsr_test_gw' /etc/crontabs/root || { + echo "* * * * * /usr/sbin/ff_olsr_test_gw" >> /etc/crontabs/root + } + + [ -f /etc/rc.local ] && . /etc/rc.local + [ -d /etc/rc.local.d ] && { + for file in /etc/rc.local.d/*; do + test -f "$file" && . "$file" + done + } + + killall -HUP crond 2>/dev/null || /etc/init.d/cron start +} diff --git a/openwrt/packages/luci/modules/freifunk/root/etc/rc.local b/openwrt/packages/luci/modules/freifunk/root/etc/rc.local new file mode 100644 index 0000000..58e44e4 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/etc/rc.local @@ -0,0 +1,2 @@ +# /etc/rc.local +# Only executed on boot, put your custom startup commands here diff --git a/openwrt/packages/luci/modules/freifunk/root/usr/sbin/ff_olsr_test_gw b/openwrt/packages/luci/modules/freifunk/root/usr/sbin/ff_olsr_test_gw new file mode 100755 index 0000000..5c47b49 --- /dev/null +++ b/openwrt/packages/luci/modules/freifunk/root/usr/sbin/ff_olsr_test_gw @@ -0,0 +1,41 @@ +#!/usr/bin/lua +local STRICT = true -- Only delete metric 0 routes +local PINGCMD = "ping -q -I%s -c3 -w3 '%s' >/dev/null 2>&1" +local PINGTRG = {"google.de", "www.de.debian.org", "eu.kernel.org", "freifunk.net"} +local ROUTECMD = "route del default gw '%s' >/dev/null 2>&1" +local THRESHOLD = 3 -- Maximum number of failed tests before dropping the route + +local sys = require "luci.sys" +local uci = require "luci.model.uci".cursor_state() +local ucisec = "ff_olsr_test_gw" +local section = nil + +uci:foreach("olsrd", "LoadPlugin", function(s) + if s.library == "olsrd_dyn_gw_plain.so.0.4" and s.ignore ~= "1" then + section = s[".name"] + end +end) + +local droute = sys.net.defaultroute() +if section and droute then -- dyn_gw is enabled and we have a defaultroute, test it + local state = false + + for _, host in ipairs(PINGTRG) do + state = state or (sys.call(PINGCMD % {droute.device, host}) == 0) + end + + if not state and (not STRICT or tonumber(droute.metric) == 0) then + local count = tonumber(uci:get("olsrd", ucisec, "noinet_count")) + if not THRESHOLD or (count and count >= THRESHOLD) then + sys.call(ROUTECMD % droute.gateway:string()) + else + if not count then + uci:set("olsrd", ucisec, "state") + end + uci:set("olsrd", ucisec, "noinet_count", (count or 0) + 1) + uci:save("olsrd") + end + else + uci:revert("olsrd", ucisec) + end +end diff --git a/openwrt/packages/luci/modules/rpc/Makefile b/openwrt/packages/luci/modules/rpc/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/modules/rpc/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/modules/rpc/luasrc/controller/rpc.lua b/openwrt/packages/luci/modules/rpc/luasrc/controller/rpc.lua new file mode 100644 index 0000000..a1d1b89 --- /dev/null +++ b/openwrt/packages/luci/modules/rpc/luasrc/controller/rpc.lua @@ -0,0 +1,179 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: rpc.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local require = require +local pairs = pairs +local print = print +local pcall = pcall +local table = table + +module "luci.controller.rpc" + +function index() + local function authenticator(validator, accs) + local auth = luci.http.formvalue("auth", true) + if auth then + local sdat = luci.sauth.read(auth) + user = loadstring(sdat)().user + if user and luci.util.contains(accs, user) then + return user, auth + end + end + luci.http.status(403, "Forbidden") + end + + local rpc = node("rpc") + rpc.sysauth = "root" + rpc.sysauth_authenticator = authenticator + rpc.notemplate = true + + entry({"rpc", "uci"}, call("rpc_uci")) + entry({"rpc", "uvl"}, call("rpc_uvl")) + entry({"rpc", "fs"}, call("rpc_fs")) + entry({"rpc", "sys"}, call("rpc_sys")) + entry({"rpc", "ipkg"}, call("rpc_ipkg")) + entry({"rpc", "auth"}, call("rpc_auth")).sysauth = false +end + +function rpc_auth() + local jsonrpc = require "luci.jsonrpc" + local sauth = require "luci.sauth" + local http = require "luci.http" + local sys = require "luci.sys" + local ltn12 = require "luci.ltn12" + local util = require "luci.util" + + local loginstat + + local server = {} + server.challenge = function(user, pass) + local sid, token, secret + + if sys.user.checkpasswd(user, pass) then + sid = sys.uniqueid(16) + token = sys.uniqueid(16) + secret = sys.uniqueid(16) + + http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") + sauth.write(sid, util.get_bytecode({ + user=user, + token=token, + secret=secret + })) + end + + return sid and {sid=sid, token=token, secret=secret} + end + + server.login = function(...) + local challenge = server.challenge(...) + return challenge and challenge.sid + end + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(server, http.source()), http.write) +end + +function rpc_uci() + if not pcall(require, "luci.model.uci") then + luci.http.status(404, "Not Found") + return nil + end + local uci = require "luci.jsonrpcbind.uci" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(uci, http.source()), http.write) +end + +function rpc_uvl() + if not pcall(require, "luci.uvl") then + luci.http.status(404, "Not Found") + return nil + end + local uvl = require "luci.jsonrpcbind.uvl" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(uvl, http.source()), http.write) +end + +function rpc_fs() + local util = require "luci.util" + local io = require "io" + local fs2 = util.clone(require "luci.fs") + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + function fs2.readfile(filename) + local stat, mime = pcall(require, "mime") + if not stat then + error("Base64 support not available. Please install LuaSocket.") + end + + local fp = io.open(filename) + if not fp then + return nil + end + + local output = {} + local sink = ltn12.sink.table(output) + local source = ltn12.source.chain(ltn12.source.file(fp), mime.encode("base64")) + return ltn12.pump.all(source, sink) and table.concat(output) + end + + function fs2.writefile(filename, data) + local stat, mime = pcall(require, "mime") + if not stat then + error("Base64 support not available. Please install LuaSocket.") + end + + local file = io.open(filename, "w") + local sink = file and ltn12.sink.chain(mime.decode("base64"), ltn12.sink.file(file)) + return sink and ltn12.pump.all(ltn12.source.string(data), sink) or false + end + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(fs2, http.source()), http.write) +end + +function rpc_sys() + local sys = require "luci.sys" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(sys, http.source()), http.write) +end + +function rpc_ipkg() + if not pcall(require, "luci.model.ipkg") then + luci.http.status(404, "Not Found") + return nil + end + local ipkg = require "luci.model.ipkg" + local jsonrpc = require "luci.jsonrpc" + local http = require "luci.http" + local ltn12 = require "luci.ltn12" + + http.prepare_content("application/json") + ltn12.pump.all(jsonrpc.handle(ipkg, http.source()), http.write) +end diff --git a/openwrt/packages/luci/modules/rpc/luasrc/jsonrpc.lua b/openwrt/packages/luci/modules/rpc/luasrc/jsonrpc.lua new file mode 100644 index 0000000..177383d --- /dev/null +++ b/openwrt/packages/luci/modules/rpc/luasrc/jsonrpc.lua @@ -0,0 +1,94 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: jsonrpc.lua 3000 2008-08-29 12:27:54Z Cyrus $ +]]-- + +module("luci.jsonrpc", package.seeall) +require "luci.json" + +function resolve(mod, method) + local path = luci.util.split(method, ".") + + for j=1, #path-1 do + if not type(mod) == "table" then + break + end + mod = rawget(mod, path[j]) + if not mod then + break + end + end + mod = type(mod) == "table" and rawget(mod, path[#path]) or nil + if type(mod) == "function" then + return mod + end +end + +function handle(tbl, rawsource, ...) + local decoder = luci.json.Decoder() + local stat = luci.ltn12.pump.all(rawsource, decoder:sink()) + local json = decoder:get() + local response + local success = false + + if stat then + if type(json.method) == "string" + and (not json.params or type(json.params) == "table") then + local method = resolve(tbl, json.method) + if method then + response = reply(json.jsonrpc, json.id, + proxy(method, unpack(json.params or {}))) + else + response = reply(json.jsonrpc, json.id, + nil, {code=-32601, message="Method not found."}) + end + else + response = reply(json.jsonrpc, json.id, + nil, {code=-32600, message="Invalid request."}) + end + else + response = reply("2.0", nil, + nil, {code=-32700, message="Parse error."}) + end + + return luci.json.Encoder(response, ...):source() +end + +function reply(jsonrpc, id, res, err) + require "luci.json" + id = id or luci.json.null + + -- 1.0 compatibility + if jsonrpc ~= "2.0" then + jsonrpc = nil + res = res or luci.json.null + err = err or luci.json.null + end + + return {id=id, result=res, error=err, jsonrpc=jsonrpc} +end + +function proxy(method, ...) + local res = {luci.util.copcall(method, ...)} + local stat = table.remove(res, 1) + + if not stat then + return nil, {code=-32602, message="Invalid params.", data=table.remove(res, 1)} + else + if #res <= 1 then + return res[1] or luci.json.null + else + return res + end + end +end diff --git a/openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uci.lua b/openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uci.lua new file mode 100644 index 0000000..7cd7f8e --- /dev/null +++ b/openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uci.lua @@ -0,0 +1,94 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: uci.lua 3132 2008-09-05 19:27:19Z Cyrus $ +]]-- + +local uci = require "luci.model.uci".cursor() +local ucis = require "luci.model.uci".cursor_state() +local table = require "table" + + +module "luci.jsonrpcbind.uci" +_M, _PACKAGE, _NAME = nil, nil, nil + +function add(config, ...) + uci:load(config) + local stat = uci:add(config, ...) + return uci:save(config) and stat +end + +function apply(config) + return uci:apply(config) +end + +function changes(...) + return uci:changes(...) +end + +function commit(config) + return uci:load(config) and uci:commit(config) +end + +function delete(config, ...) + uci:load(config) + return uci:delete(config, ...) and uci:save(config) +end + +function delete_all(config, ...) + uci:load(config) + return uci:delete_all(config, ...) and uci:save(config) +end + +function foreach(config, stype) + uci:load(config) + local sections = {} + + return uci:foreach(config, stype, function(section) + table.insert(sections, section) + end) and sections +end + +function get(config, ...) + uci:load(config) + return uci:get(config, ...) +end + +function get_all(config, ...) + uci:load(config) + return uci:get_all(config, ...) +end + +function get_state(config, ...) + ucis:load(config) + return ucis:get(config, ...) +end + +function revert(config) + return uci:load(config) and uci:revert(config) +end + +function section(config, ...) + uci:load(config) + return uci:section(config, ...) and uci:save(config) +end + +function set(config, ...) + uci:load(config) + return uci:set(config, ...) and uci:save(config) +end + +function tset(config, ...) + uci:load(config) + return uci:tset(config, ...) and uci:save(config) +end + diff --git a/openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uvl.lua b/openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uvl.lua new file mode 100644 index 0000000..b06c3e2 --- /dev/null +++ b/openwrt/packages/luci/modules/rpc/luasrc/jsonrpcbind/uvl.lua @@ -0,0 +1,41 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: uvl.lua 3941 2008-12-23 21:39:38Z jow $ +]]-- + +local uvl = require "luci.uvl".UVL() +local table = require "table" + +module "luci.jsonrpcbind.uvl" +_M, _PACKAGE, _NAME = nil, nil, nil + + +function get_scheme(...) + return uvl:get_scheme(...) +end + +function validate(...) + return {uvl:validate(...)} +end + +function validate_config(...) + return {uvl:validate_config(...)} +end + +function validate_section(...) + return {uvl:validate_section(...)} +end + +function validate_option(...) + return {uvl:validate_option(...)} +end \ No newline at end of file diff --git a/openwrt/packages/luci/themes/base/Makefile b/openwrt/packages/luci/themes/base/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/base/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/Dropdowns.js b/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/Dropdowns.js new file mode 100644 index 0000000..ff2f0e6 --- /dev/null +++ b/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/Dropdowns.js @@ -0,0 +1,120 @@ +/* +Copyright (C) 2008 Alina Friedrichsen + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +function initDropdowns() { + var aSelects = XHTML1.getElementsByTagName("select"); + var isIE6 = false /*@cc_on || @_jscript_version < 5.7 @*/; + + function showPlaceholder(sel) { + if( ! sel._ph ) { + var box = sel.getBoundingClientRect(); + sel._dm = sel.currentStyle.display; + sel._ph = document.createElement('input'); + sel.parentNode.insertBefore(sel._ph, sel); + sel._ph.style.width = ( box.right - box.left ) + 'px'; + sel._ph.style.height = ( box.bottom - box.top ) + 'px'; + sel._ph.style.margin = sel.currentStyle.margin; + } + + sel._ph.value = sel.options[sel.selectedIndex].text; + sel._ph.style.display = sel._dm; + sel.style.display = 'none'; + } + + function hidePlaceholder(sel) { + if( sel._ph ) sel._ph.style.display = 'none'; + sel.style.display = sel._dm; + } + + function hideSelects() { + for(var i = 0; i < aSelects.length; i++) { + showPlaceholder(aSelects[i]); + } + } + + function showSelects() { + for(var i = 0; i < aSelects.length; i++) { + hidePlaceholder(aSelects[i]); + } + } + + function onmouseover(evt) { + XHTML1.addClass(evt.currentTarget, "over"); + if( isIE6 ) hideSelects(); + } + + function onmouseout(evt) { + XHTML1.removeClass(evt.currentTarget, "over"); + if( isIE6 ) showSelects(); + } + + function onfocus(evt) { + for(var element = evt.currentTarget; element; element = element.parentNode) { + if(XHTML1.isElement(element, "li")) { + XHTML1.addClass(element, "focus"); + } + } + if( isIE6 ) hideSelects(); + } + + function onblur(evt) { + for(var element = evt.currentTarget; element; element = element.parentNode) { + if(XHTML1.isElement(element, "li")) { + XHTML1.removeClass(element, "focus"); + } + } + if( isIE6 ) showSelects(); + } + + if(document.all) { + var liElements = XHTML1.getElementsByTagName("li"); + for(var i = 0; i < liElements.length; i++) { + var li = liElements[i]; + for(var element = li.parentNode; element; element = element.parentNode) { + if(XHTML1.isElement(element, "ul") && XHTML1.containsClass(element, "dropdowns")) { + XHTML1.addEventListener(li, "mouseover", onmouseover); + XHTML1.addEventListener(li, "mouseout", onmouseout); + break; + } + } + } + } + + var aElements = XHTML1.getElementsByTagName("a"); + for(var i = 0; i < aElements.length; i++) { + var a = aElements[i]; + for(var element = a.parentNode; element; element = element.parentNode) { + if(XHTML1.isElement(element, "ul") && XHTML1.containsClass(element, "dropdowns")) { + XHTML1.addEventListener(a, "focus", onfocus); + XHTML1.addEventListener(a, "blur", onblur); + break; + } + } + } +} + +if(XHTML1.isDOMSupported()) { + XHTML1.addEventListener(window, "load", initDropdowns); +} diff --git a/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/VarType.js b/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/VarType.js new file mode 100644 index 0000000..d466810 --- /dev/null +++ b/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/VarType.js @@ -0,0 +1,91 @@ +/* +Copyright (C) 2008 Alina Friedrichsen + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +function VarType() { +} + +VarType.isNull = function(obj) { + if(typeof obj == "undefined") return true; + if(typeof obj == "object" && (!obj)) return true; + return false; +}; + +VarType.toFloat = function(value) { + value = Number(value); + return value; +}; + +VarType.toDecimal = function(value) { + value = Number(value); + if(!isFinite(value)) value = 0.0; + return value; +}; + +VarType.toInt = function(value) { + value = Number(value); + if(!isFinite(value)) value = 0.0; + value = Math.floor(value); + return value; +}; + +VarType.toUInt = function(value) { + value = Number(value); + if(!isFinite(value)) value = 0.0; + else if(value < 0.0) value = 0.0; + value = Math.floor(value); + return value; +}; + +VarType.toStr = function(value) { + if(VarType.isNull(value)) value = ""; + value = String(value); + return value; +}; + +VarType.toBool = function(value) { + value = Boolean(value); + return value; +}; + +VarType.needObject = function(obj) { + if(typeof obj != "object" || (!obj)) throw new TypeError(); +}; + +VarType.needInstanceOf = function(obj, type) { + if(!(obj instanceof type)) throw new TypeError(); +}; + +VarType.needFunction = function(obj) { + if(typeof obj != "function") throw new TypeError(); +}; + +VarType.needNode = function(obj, type) { + VarType.needObject(obj); + if(VarType.isNull(obj.nodeType)) throw new TypeError(); + if(!VarType.isNull(type)) { + type = VarType.toInt(type); + if(obj.nodeType != type) throw new TypeError(); + } +}; diff --git a/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/XHTML1.js b/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/XHTML1.js new file mode 100644 index 0000000..a7d4f7d --- /dev/null +++ b/openwrt/packages/luci/themes/base/htdocs/luci-static/resources/XHTML1.js @@ -0,0 +1,271 @@ +/* +Copyright (C) 2007, 2008 Alina Friedrichsen + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +var XMLNS_XMLNS = "http://www.w3.org/2000/xmlns/"; +var XMLNS_XML = "http://www.w3.org/XML/1998/namespace"; +var XMLNS_XHTML = "http://www.w3.org/1999/xhtml"; + +function W3CDOM_Event(currentTarget) { + VarType.needObject(currentTarget); + this.currentTarget = currentTarget; + this.preventDefault = function() { window.event.returnValue = false; }; + return this; +} + +function XHTML1() { +} + +XHTML1.isDOMSupported = function() { + if(!document.getElementById) return false; + if(!(window.addEventListener || window.attachEvent)) return false; + return true; +}; + +XHTML1.isXHTML = function() { + if(document.documentElement.nodeName == "HTML") return false; + return true; +}; + +XHTML1.addEventListener = function(target, type, listener) { + VarType.needObject(target); + type = VarType.toStr(type); + VarType.needFunction(listener); + + if(target.addEventListener) { + target.addEventListener(type, listener, false); + } + else if(target.attachEvent) { + target.attachEvent("on" + type, function() { listener(new W3CDOM_Event(target)); } ); + } +}; + +XHTML1.createElement = function(tagName) { + tagName = VarType.toStr(tagName); + + if(XHTML1.isXHTML()) { + return document.createElementNS(XMLNS_XHTML, tagName.toLowerCase()); + } + + return document.createElement(tagName.toUpperCase()); +}; + +XHTML1.getElementsByTagName = function(tagName) { + tagName = VarType.toStr(tagName); + + if(XHTML1.isXHTML()) { + return document.getElementsByTagNameNS(XMLNS_XHTML, tagName.toLowerCase()); + } + + return document.getElementsByTagName(tagName.toUpperCase()); +}; + +XHTML1.isElement = function(node, tagName) { + VarType.needNode(node); + tagName = VarType.toStr(tagName); + + if(node.nodeType == 1) { + if(XHTML1.isXHTML()) { + if(node.namespaceURI == XMLNS_XHTML) { + if(node.localName == tagName.toLowerCase()) return true; + } + } else { + if(node.nodeName == tagName.toUpperCase()) return true; + } + } + + return false; +}; + +XHTML1.getAttribute = function(element, name) { + VarType.needNode(element, 1); + name = VarType.toStr(name); + + name = name.toLowerCase(); + + if(XHTML1.isXHTML()) { + return element.getAttributeNS(null, name); + } + + if(name == "class") { + return element.className; + } + + return element.getAttribute(name); +}; + +XHTML1.setAttribute = function(element, name, value) { + VarType.needNode(element, 1); + name = VarType.toStr(name); + value = VarType.toStr(value); + + name = name.toLowerCase(); + + if(XHTML1.isXHTML()) { + element.setAttributeNS(null, name, value); + return; + } + + if(name == "class") { + element.className = value; + return; + } + + element.setAttribute(name, value); +}; + +XHTML1.removeAttribute = function(element, name) { + VarType.needNode(element, 1); + name = VarType.toStr(name); + + name = name.toLowerCase(); + + if(XHTML1.isXHTML()) { + element.removeAttributeNS(null, name); + return; + } + + if(name == "class") { + element.className = ""; + return; + } + + element.removeAttribute(name); +}; + +XHTML1.containsClass = function(element, className) { + VarType.needNode(element, 1); + className = VarType.toStr(className).replace(/^\s+/g, "").replace(/\s+$/g, ""); + + var classString = XHTML1.getAttribute(element, "class").replace(/\s+/g, " ").replace(/^\s+/g, "").replace(/\s+$/g, ""); + var classArray = classString.split(" "); + for(var i = 0; i < classArray.length; i++) { + if(classArray[i] == className) return true; + } + + return false; +}; + +XHTML1.addClass = function(element, className) { + VarType.needNode(element, 1); + className = VarType.toStr(className).replace(/^\s+/g, "").replace(/\s+$/g, ""); + + var classString = XHTML1.getAttribute(element, "class").replace(/\s+/g, " ").replace(/^\s+/g, "").replace(/\s+$/g, ""); + var classArray = classString.split(" "); + classString = ""; + for(var i = 0; i < classArray.length; i++) { + if(classArray[i] != className) { + if(classString == "") classString = classArray[i]; + else classString += " " + classArray[i]; + } + } + + if(classString == "") classString = className; + else classString += " " + className; + + XHTML1.setAttribute(element, "class", classString); +}; + +XHTML1.removeClass = function(element, className) { + VarType.needNode(element, 1); + className = VarType.toStr(className).replace(/^\s+/g, "").replace(/\s+$/g, ""); + + var classString = XHTML1.getAttribute(element, "class").replace(/\s+/g, " ").replace(/^\s+/g, "").replace(/\s+$/g, ""); + var classArray = classString.split(" "); + classString = ""; + for(var i = 0; i < classArray.length; i++) { + if(classArray[i] != className) { + if(classString == "") classString = classArray[i]; + else classString += " " + classArray[i]; + } + } + + XHTML1.setAttribute(element, "class", classString); +}; + +XHTML1.removeAllChildren = function(node) { + VarType.needNode(node); + + while(node.lastChild) { + node.removeChild(node.lastChild); + } +}; + +XHTML1.getTextContent = function(node) { + VarType.needNode(node); + + if(typeof node.textContent != "undefined") { + return node.textContent; + } + + switch(node.nodeType) { + case 1: + case 2: + case 5: + case 6: + case 11: + var textContent = ""; + for(node = node.firstChild; node; node = node.nextSibling) { + if(node.nodeType == 7) continue; + if(node.nodeType == 8) continue; + textContent += VarType.toStr(XHTML1.getTextContent(node)); + } + return textContent; + case 3: + case 4: + case 7: + case 8: + return node.nodeValue; + } + + return null; +}; + +XHTML1.setTextContent = function(node, value) { + VarType.needNode(node); + value = VarType.toStr(value); + + if(typeof node.textContent != "undefined") { + node.textContent = value; + } + + switch(node.nodeType) { + case 1: + case 2: + case 5: + case 6: + case 11: + XHTML1.removeAllChildren(node); + if(value != "") { + node.appendChild(document.createTextNode(value)); + } + break; + case 3: + case 4: + case 7: + case 8: + node.nodeValue = value; + break; + } +}; diff --git a/openwrt/packages/luci/themes/fledermaus/Makefile b/openwrt/packages/luci/themes/fledermaus/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/fledermaus/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/cascade.css b/openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/cascade.css new file mode 100644 index 0000000..f9adade --- /dev/null +++ b/openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/cascade.css @@ -0,0 +1,626 @@ +* { + margin: 0; + padding: 0; +} + +body { + background-color: #e5e6ec; + color: #ffffff; + font-family: Verdana, Arial, sans-serif; + font-size: 100%; + line-height: 100%; +} + +code { + font-family: monospace; + white-space: pre; +} + +div#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red !important; + font-weight: bold; +} + +.clear { + clear: both; + height: 1px; +} + +.hidden { + display: none; +} + +.error { + color: #ff0000; +} + +#header { + min-height: 98px; + background-image: url(logo.png); + background-repeat: no-repeat; + background-position: left center; + background-color: #000000; + text-align: center; + border-bottom: 1px solid #dc0067; +} + +#header2 { + min-height: 98px; + background-image: url(fledermaus.png); + background-repeat: no-repeat; + background-position: right center; +} + +#header3 { + font-size: 2.6em; + font-family: serif; + color: #FFCB05; + letter-spacing: 0.35em; + font-weight: bold; + line-height: 1.4em; +} + +#header4 { + font-size: 1.25em; + line-height: 1.2em; + letter-spacing: 0.2em; + color: white; +} + +.pathbar { + display: none; +} + +.menubar { + width: 100%; + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +.mainmenu { + float: left; + width: auto; + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +.mainmenu div { + float: left; +} + +.mainmenu li { + white-space: nowrap; +} + +.mainmenu div ul { + display: none; + position: absolute; + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + list-style-type: none; +} + +.mainmenu ul li:hover > ul, +.mainmenu div:hover > ul { + display: block; +} + +.mainmenu ul li > ul { + left: 100%; + margin-top: -1.8em; + border-width: 1px; +} + +.modemenu a, +.mainmenu a { + display: block; + padding: 0.5em; + color: #ffffff; + text-decoration: none; + font-size: 80%; +} + +.mainmenu .active a, +.modemenu .active a { + color: #ffff00; + font-weight: bold; +} + +.mainmenu li:hover > span > a, +.mainmenu div:hover > a { + font-weight: bold; +} + +.modemenu a:hover, +.modemenu a:focus, +.mainmenu a:hover, +.mainmenu a:focus { + color: #ffff00; + font-weight: bold; +} + +.mainmenu div.preactive > a { + color: #ffff00; + font-weight: bold; +} + +.modemenu ul { + width: auto; + background: #000000; + color: #ffffff; + list-style-type: none; +} + +.modemenu li { + float: right; +} + +#maincontent { + clear: both; + width: 90%; + margin: 0 auto; + padding: 0.5em; + background: #f8f9fe; + color: #000000; + font-size: 80%; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #f2f3f9; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +input[type=submit], +input[type=reset], +input[type=image], +label { + cursor: pointer; +} + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #f2f3f9; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { + background: #f5f5f5; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +.cbi-rowstyle-1 { + background-color: #eeeeff; +} + +.cbi-rowstyle-2 { + +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; +} + +div.cbi-value:last-child { + border: none; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin: 0.25em 0 0.25em 40%; +} + +div.cbi-value-description { + font-size: 90%; +} + +div.cbi-value-field > div.cbi-value-description { + display: none; +} + +div.cbi-value:hover div.cbi-value-field > div.cbi-value-description { + display: block; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + margin: 0.5em 0; + padding: 0 0.25em; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border: 1px dotted #bbbbbb; + padding-bottom: 0; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #FF0000; +} + +td.cbi-value-error { + border-color: red !important; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red !important; + background-color: #FFCCCC; +} + +.cbi-section-error { + color: red; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +ul.cbi-apply { + font-size: 90%; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a { + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #FF0000; + background-color: #FFFFFF; + padding: 0.5em; +} + +#memorybar { + width:200px; + height:8px; + border:1px solid #bbb; + background-color:red +} + +#memfree, #membuffers, #memcached { + float:right; + border:1px solid #bbb; + height:6px; +} + +#memfree { + background-color:green; +} + +#membuffers { + background-color:yellow; +} + +#memcached { + background-color:orange; +} + + +/* obligatory IE6 Voodoo Code */ +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.mainmenu div.hover ul, +* html div.mainmenu div li.hover ul, +* html div.mainmenu div li li.hover ul, +* html div.mainmenu div li li li.hover ul, +* html div.mainmenu div li li li li.hover ul { + display: block !important; + margin-left: 3em; +} + +* html div.mainmenu div.hover ul { + margin-left: 0; +} + +* html div.mainmenu .hover ul ul, +* html div.mainmenu .hover ul ul ul, +* html div.mainmenu .hover ul ul ul ul, +* html div.mainmenu .hover ul ul ul ul ul { + display: none !important; +} + +* html div.mainmenu li { + height: 1em !important; + width: 10em !important; +} + +* html .mainmenu { + height: 1.8em; +} + +* html div.cbi-value-description { + margin-left: 40%; +} diff --git a/openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/fledermaus.png b/openwrt/packages/luci/themes/fledermaus/htdocs/luci-static/fledermaus/fledermaus.png new file mode 100644 index 0000000000000000000000000000000000000000..852e9d0c08adec21b5bef5a968383522aecd0ccd GIT binary patch literal 7321 zcmWkz2RxK-96wTaMi(bDr29)&viBzIWRJ@3L#9ltlyKu?2~>IM}A0-@E?R5b*jNbpvqxB`B&+%)e7A0(cJ z8p;s#5ZfyFgVJ5o+!F$!zV`1;0!jT00|&{yv~<otw48keqS6@%eTil`q?(pUytpVZAiI+#g59sW$< zfN}jt$wyCB?@aY61?RTew4CADN=)C9CozRZ<#=hvf8n7BHJ^oCC6y8nLu0^I! zl;H?*1xPD;GSlXHVHzdqw^$F;Mnz*|cF2~b9=>Py{1+Z2v)M~aOUpjAOyo2*_I?Zt zZ|2n^c{N$*>dq#?s5Ww^)?#DtVWD2SrG-Umooj$&aPWM7fYpR%YQc^N8wO&F@pxYL z7b|jna#9<^D)D@CZOy-pSL?vX%WJkAnc7@g3E54xt$L@*O`;Xg6~+BaGJNZ#(p5$< zd4M^TOLBLuwBme~)vZ|sX>KxT%{K_H$pX27!gos~oo!$?=bDx}Iy#!hR{z>S=!mil z*>EbVFw&%?q{`-Int^Ki@S8@)YJ$ls;%Q+8NQy3cSu78Y%DbF*@F*@VMk`$T`HF_Z zaZh)5H>bO4uf`l3CIyB6;r3~<-)^ixxBvX?gi}A?@S^|VEO@3aZeYoPKe6)5m$#nF zL$8f`E1qWl!W$cD>a!SYnPH26bk)Bl`7SG~SGq zYhJi(DWU**`m-zI07@06K-uMfFgnV}tJOJ_E(5;T)6-K43Zg`BP=T{CX9`@J zg}YlbR||l3gUf>&4T$*w}&23VBwl0&5KmxQex*(BY$YP|^)AqhHs z3dW`5su+*TfP?3n@o(=r4P{xB=ZrkfnsQO5ClgE4?e=)jMX@M()i*u9y&pQIMts`I6Xyko=EUV1uNw=pN&cf2!c7t0P$)YgyAX~;Jz%{Joi z5T^O85W<1Nw-aT3GssbRdW^_`5Ogi|JD-tp7@@J!l{He86f)r#$3?Ln#3_r#@bK_l z5StdxHkSqW^57`^Eyy`-!s&My3`ReHaekmMJ~Fc72gxZZS=rp|38Q9q-<*|FMZA?n zrPzRquwg(s5Kt1xr7KGG|852Wg+Q>xcR3WHT*43rOjW?I?#Kn1;L}6X9C%bp+(gz( zvi3%sq&AiaI?f^cnyD@Dep4-w+tR{LO-=1f{4N1X{Yz4vJMPui2}S5D7R@Aw1~fJH z#9T2dhoYpUlPD{R>gr@;iEPFao0kCA&)zUU4&1qp@lZB4CQ7t-So&gHgHFVMzxe7l zP~BWpU(Xz)e(AP;1{ubKCh?ocV3sEvX3;NW4s79Do8IO~*_ij5M_Ne^0EfafO3K11Jfb5yQYJss$C&gDU9zfLq zn3d>-dE&BH2E=sjMOjFxhx9{^$1t%Ra{guBU_U-dy!T4kiHi;V-L>j~O*S_- z&wCda7d2E7-JPAJ($dnPO?kCKOG-ZQBCUfdyFSdR#PfE0(5N8*S6JcHa!1-vPi6TN zshF6VS#+4y7yu51X+VR3D*UCsckiC*=LK3G5>38@^OO05R-TQG4FPCvZEc5`u36G$ zKoDddjocrVS;Hi5DAB)K_A_ZfqtV=T_EW!~$J7p~2jN+ci0VQ90!D4M~4G!)3 zpRMlf>?GEwEmSn$roDRg`E>0wT&AABzGrD^DQHJf6&M?vs--2XrTxMIi)ilb7*%;L zJQOc!W?>PEOf6IAzVw0(BhRD7Xjp6{CLwXqS6p1YRG-FkQTjZuwY9Y?Jw1JPcUSa| zxb9f@or>nrr6mV|Kv+15HSU7RovSAmF9|3FOZF*}0WV`s zMe}a|51ABv#g{no=d-J^}f8+<=}5yiGh!9MY;5*t*LU-K4IrZU%qBMjn;Z z?rjbJKQ*(UVm$Ac`ubdxQovVW=hYC4ejFv^{D4qurrs|5xmzcPsq2oJRlIxB43CPg zb5%G!C1NiQ(}#$r)0%1GuE&xX4?sM{MpSjK_lk5mmL#tN&W?~oAq1F2q@}44P@5TX zml?1z?rh}X6f-?9hHRyNjcS234>pCr;9_mZ#6hAQ3ETAabb|(G(BJ)&t+orxRWE;c zFR#CcGeM4oiSl1S&@Sxg$%+#buh;c{T=&axlH#Kv1t@@0UGA-Z9~O2QTz;T>*hM^r z{J0f+e#@@7BuWxx0}H2I+~mh+vDC4}(eiT1+iw+idnH;Y2!1uJR zY;7%YQFO9@cO*`YjEvy^EH78U^H$f_XOq7>HtDBJhjCG4A#dD+icEU2)jTiWI*|-H zmwmZ88ws{p;O<=#2!PdC}rq~D8{4hA_rbu93w zcdg{Gb}byCb7+FCy*-)4oYyr%!*tzuXFjd?PvrTA|M4$cDo%780EH;qoeTs`6Vh)B+_0w5Wv2 z8kb$d4Wdv*<^?#RGD0{Ton32J8 zKcP<%`b}tKp-sW>>oZ`1zGY`;FZfuSitAp>fpf=ca;57LE$dvqp4`nkz(}G7eh|D( z4&YIpFJc|c30~wslDMegG%7keI#1l)KakLXMZl@Zloa_Bm8H|exhNK7U#?GvoIBvw zt^2g<=lx4($Hs^^yM*OU_!F;s`}j~Z3q9)A58h2U3+2+xH(Y&KQ&Y2ZO9vt_5W4Jl zCi8Or5a;RXnVFKB8YQIU#Oh@o(qK|5@*T1i>LnfI_UjfDpA$^iPbETqM6$)Nw(KL&(EAl`+hP~O9=-b6~zgARi zwb9VhZm@E2IR5g|9pi8jyWvuGT}_D%V}@UB)X>ntv1pEoW#AiPQw#dYqE@|bK!hbE zBGhv`qK557DV6BWn8j&So~HJQ(U9SQAQu}c=NsCH#g&v`<%xs$gdUgQZ*f+iuCj}0 z2CaKrO!uV4Ui9m&gublOQfkm34i1+?xw4v?SPS(t9gUl~D4vSlpeIujqrqoVhHn2l zJw4T*fT(91z#$Ntu2%&}nFsl!PT>&|Z4d~6EF+msgo8QnuU7&C_C|-TAz#@hn8`X6 zM!nO+q(}Sn$B;>;E;H&iQ}$vXN=nMwb@L5%WOGXRbKuJQ`gBRj$tkbz4jj9gdg3oe z)q%bwS0cv>G7!UILOsaHi9qZr$qgp4$hn!e5f- zTnxjQqd^x=@!oU zN*fg+Eb*WbEn_N}oQ=E@xDb&8pKSClZER>b^kT!9E71pzQm-_k{9CT#yg_sNjW-(j zVAy@2*0`YNnwo2zr;FrOm6h#JeCWw^cy4PkHa0eznI=V9Qh6YtHxv3QPgSv#b8|7{ zAOV1JtxG3| zu1ok6sYcS$?&9K;D-gy=vfEL=mLKHD?+>fc*?4#`07jrE0|uv4OxHI9BMu{>v_#|6)tOV@<1Jqj3ezRq;f#p~Uc2x^Z*2MtTk#6l>^pH;H zL(`<_Tmjh&O;8>a`>37oP5RBhWrzX+qMbR@%oBT&E1hk;G z*m>53OfA|Gc115!KE`#XPDJm!xAhyDp3o_BG~A zb$|Z+F&oOgG;0F`QZ4*fD_OkdzFgoSd17mJ8TF-OpBu z2(F)U(FSL^L`b1(1nm*Nxlx&3!@O5{^EAS3)skHC5FJC6HL@xUkl{BIR%1ugvlf@M1rU7lJ0s|R<`nNXkIy#h` zb?pX{?t3?U?}o# z(AYTfKi`#hQ~69M*B2#A{Y#=Mxo@SftJ%Osk_SlIcMlH_$shTz<~vxusk$1G&9 zfTN>hRtdj>z<;nOfLY(zz%&cT09Zdbq}*(>7wtpke=s!&ax!NEQ5#GE0F4GL zlU^@+CYQ7Q>sxf&Q75&~pw*og@`u!OAs1&s0M!>QCZ&<(eJ7)>)YJY_7!&6gz;#3G};DV-Hm>@8*g3lmv z#Od%&?Wz8J9}{Ea=y)ZbHyZ#Pm`Pb|O+0rdwx;c2vC;YZ@4keKY?IQTsjREOx}W5@ z&IC|Kjwo4`kgxni)-$B?_~$h>rQMZeZ|2s2diP3kY!^}X;jDm=5a3yEK()@1OsRh! zmYbNj6T5OzvA&JDJ;O-SNacmTdy=; z)g2R-lzjL4HHoyyIsV(XZ{&}H_Qs!`uW^t-Hoq=s=mS@$`0Q!!DVTg%no+$jH~NqR z?{%zM&k`It`9Yc`TmYxCEBi0vuAm@y+V^S>T0e^PlHAUZsV-hazyoKswSnPVu0=V} z^`v_Mi=rw2<|JQZoAt)T{!Q@y*+@-PCrpI3q$I~ofIE2r8E*5=2G-i#&;YaYx{Y7sqaZ6X=Pvn7Pe-;~I)4RrVERfwi(bfL39-!%y27@%OaMgYi z6H^Hgc4X?Oj0|-^EP}~)RESg=O2c=31>ce#SP~Kvd{^_6g+)YOTM1$orTykCUT>gK zsB>V1n|wBB{oJI}GlGwnlJ%`0@IXJi#F!CcAsX;&6h)0NB)i{m{9; z=AteHETtSWwa1xTlypf+iT*>MJuovslVw7**Vt$3b_VZZ|M97$*9tv2${5+*2v5?xLCG`kP%7OyWJ)H8;QB5 z;4O9Km0tA-muMo*6xEdF4F0!=7pLf;MO^PI%51UF#qt~Lis0)2 z{6RrMl7WZ9QQx=&WRePy0CC;VDq6y|^GUHpV4?W{92Duv!1xEulwH}CUB%Nt*UB8$ zRs?PQ2jRqc3wJx$ItOGhV>||HqwYKvd1sZUHYOIc^E@wrk5?VDxEhFB_S4Dbi?Yo_ zPFM44edeOr_>$14qA8*K^$rSeM*sHPeg6Mg$zG3AjTOfz_C9xUp~1v*Iw{AQuv8Kn z*Ds=SK-8q~>gp;B&T)51oIF9nz9a66QK%yl4nxNUSY&9^n$G( zc$cVJzQ4)2f^XAX)iggK}KAv*fpSgDJT8NyKlvE+| zMm-pw#mvpkwJ~9K5`cY->$TfZ3t9q0wjY50;_#SQY(-!9Xt)jAsMrP`a&@Y%oW4Kr z7(@411f857m5rOfU^} zo1bq9$p4-u5n_b+Sg49vH#XjLskLZ1AUwV}zFvAFv(_Q0-Nx5p_V2R_e8Mxv1c zvhBZS&(FX0husLrfL9byb#l550Fd%%s9In`OaMx?ClqotuuACHY+E_}_w->goR;-m zGEv(VZBojtGj{rKS`~-~4d1j)oL%1j*>wqkUg+PFLM~1gF3yj9CPy_MKVEobjZ?U^ zh`dWo$QNbDK3WlYq4QO__9Ir@L;oZcBV>ls7eA}SBWp73Jiv)U;gY2`*U%i zZb9r6H%~hF3=F{$crsv>z)aYjsjpB-9thGyeAI_Vt35(M`QB$wqZF@RZw|Nl7w15u z3d|yU9~6!~)K@t3y4d@r)%I7bEiR6M03Ipj4h#(7)^9pGIhBI2hdnqrz!sPIH$1A~ z{EsQxvPd9n_w{^$_VCH*!I@^fYIUVh>rM~rZ8S4ai<4fa3<@k4*VJP#TMqAMC0nNa zLC?+m3z(E@QYT!{RXQ2i#>Jn_^)^W zEjSq&K@^o(RE#^z0qt)>&qthR_`7~j9gL34cEV;@Z?3EyItnH~P)FpE3XAC`6#Me2 zt0Xxvu7&J}F+Vz7z|DBJ6w0n{^z3iUgehkam%{tQtpw{;aCE40&9Rz zGp-fDtG4fb)1Cau&L-TzaR&mYh1an_P6wxI02Tqy0t;;4tLqvLw_&FcZs53mfyuyl zptKtvp+FTd7pSy-Z&O!HxH@1MdOX*}nIDM<>|fgc~^SVBlfk=uS?x1rQ*&lk@x+@JrkGR<(EF4kg^camNCW z0lT+j*n7Zpz(;Je2G#&;F~Z#sD8yJ0g}@-pW;n1N&-fDfsqK6J-HtIkj&K9Vy#crt zBam!J0)GeQ1M_X)ThYPiIlx%pblUcoGys!q-<#9cXKZ)j29BE#%m&VBg;argz>T)= zt?XhRjs|YW*vzfrUf`;>Y=r|EKX94td&yM8s=*V7Bpa<~5b_mn zS>3PygCiGB-P#rW)Y=pB**$-<3O4|&wNb~FET8#N8o&7%^Ke|u6khi|T zxfr|juo#kOfzxf@YhtRl)ICduhXkG|u)dqT|I$al>ki)P23@*uLtgSRREMj`_>yIn zuch&wk8vi3#ti?9?R%p$8?EkOGz%^wUa-}`xlMuxzBvg6q*VMl4!vKoRcot znlkqs;2IHYY)=aopk$f%xQd*Q=)ELp%G|F~c0-7wHW>BHX}n_Xn3+fX zy;o8tTw1)W@~=I?UldA~RsN?ScS=&8T3LF@A!%K+FSo2EllRo5{t4y5;$@Zp(L=n&qPW_-5#e=9lFu-Hd=5bP+Fu(pZt$th^K8rZmrbys#bUu}Y_ZrPl?02mOwzt4H8X505(#H5I# z(DYk-LUSuHu4g7T15;8rtB#mhh{_eJ`kN!F=QZ>IUv0u+AIw@SBDX0r?UQ4!C`jvy z)865s^U?Lf4IDSqIXEqb^rdveJ88+y2p^QZH*0QJ^VDf<*mR#jW5b4xm!+D*&F!5C zY9aj19gflmj{7}Kz+^OVAlp*f1%cykW?M@8$e1bSr~X)7Hfe7}&X=T~%Jzyp|6=lJWsI@7SBxbD-9CxuKtx>e@1QlprTs zmNh?yc87tg&IirhLt4a|Lk!F++|XZs19%ZQ%=W$Cr@MD;K$MjL@C;A}%ur<^kh5h| z?qAw5?{|AK=pE7ZS+jLpC{mG6!}^19!2N;aww4W!MpeZqpfU@^ zG={#_*ww<}j+@u6!S5b@DDX58Jx=A% zlvhpfB#Z4rlW+saJrfuJ+#F3R7Kx$5czf7TmXw#17$-9b)|tJkLdIA@>2(R z+%>s@3IH zOwkcxf991Ls1Q^hrK-ZoXpbxJ9FzK^FfnVRqAw?t$+77Kw(ot7DIPh!#ptRE2bCx2 z;nDyR84L1kM)R0RVpwSb{{*}oL(m>`Xm?t!eG6k~j}4DG0U*d95gCI>W_i;>;JAqK z>w#{oVTeLa#l*hANVSqp!VRN-nTiHx|9Zv3B-LtT=KK&75nGC>l=%Qyi3urYVh-hr z`_dc2*SR`^HV5PGnj4Ylfqu0|PCPM#ZUs?mT6tnMCfeVjI~nhSmENraK{V zTD!>hz4aDmw~Kb+$`cn-o~WQaaTMi=QpywG2Yv`_%%FUg4SnM5(#+Q=g{EcT;ANFx zqxz6q^4kpU{e-yPxIFPDDxGtcw;_qqwn)_46Y@c(D0){$jar;==Yv_Z;)R=ur^e@? zGMDDX9o1~jJ%f>p;tJ#9g!|8d<2L#ER#I<9IlSh`iD#wJ)B*d&M$0PRo{Q+st#Ex0 zRl<8&hQ5I!bD$Bl@GXmNmf141XirG0z0iRzq)0fCzvA%V(`Y^d1qpb$RLdR77iC z$m3qIvk$47hG;f-eKJX_gyC;|&agMvQJz@O5!K%^a#4L2g=oTuhfnOMs@DrTHKT_2 z_Lw1W+P=4jknyz`7cM)hDt1HVb5yPcZUClWB~J?1zgUEYbx+20pBp%Clg2b|>UAfu zTLJst9X9QU35tB3mA7y9oPY`HM7IlwA=&{vP7n#0K9sF+br zzcm-5RoSYi4ayT6fq!o|g9f)_jQvbk*#d3@P6jySqu+f~J9yIRn$*R$Ws`j1UEuRp zvmYZD)$`_vvE*)j3phA}qL92TPx93G(VRK2&8H%3OWo4tC!}tQmsY-^!Ud}O0LTf%J0i_tVh5*S5~wYqavXMW zTU&XqDVub*qF1Y>XAZ2Mk#4VFh$*^@!cFNJ8w+EG#U&EE5_bb}!IQ@W$89=>TC&W0 z9JmAYMkF$_7LD?RkLb@ayMIfFUd@v7mQG0qObMwzgvw>WfCXU<(OK>ZRwiFVMx{U)aUO-PUGH@SMJtVV#mrf zD{wBpLzG7luF9y*Jpf~3#RY(_&0M~uru5?8m|gjp^rE=#Kzqve1IO);NvT|_aL-Oz zwr~61W{mqASJTyHuzhbUrnn^22}$8J;J$FvI2CxS*!N~yR`Lg`9KSKS`-&RJbr+AC z*4e|-O{lde_r1uwP)#t+jxtYAOqH7p69$?Q2{I(Z-`v z2V+uB_rp$nR4Oc2S^_+7`(E6x-lb^6A-^raVB7c7!+SgDA-~WZnhOjJ!+qV3UFvvh z;JB{>t8Cx9Fx#N6!Y*~NI&j>BfVY6#Y~PD2{p@n=QlA6}9CtWIo5rP|vgvLFj#~-1 zZ6MvbKV}g)?pc@`+@IOL_flIY>nH-p9f7fNU&2(~{9}KHC2-txF+qr_w(s2?Nz?@h zpEC=XX8Yb9yUYiK0>>Q&{0Va`=nC8SzKA7mCqh?u8s-?l*|zV!kk+?reEKT%sb>Q} zz%2Urbmoh3VRg^1Fvp}m#1#GgZw&3O@zJ)xagW24?jMACZJ!0I(vR=AGQJeE)}04z z0&ZxlR_rpL8w?!x6pYz)5+-)~A|^|lGTy($6vP#US23p6p%4?pcoKN3o#p@O&;Q5& zP-gggj|5J@R7a+~pnjONOls#|jXC}DS_e!2v+=M)f8zE30SPdqmS-GahyVZp07*qo IM6N<$g0fW6u>b%7 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/fledermaus/ipkg/postinst b/openwrt/packages/luci/themes/fledermaus/ipkg/postinst new file mode 100755 index 0000000..1951df5 --- /dev/null +++ b/openwrt/packages/luci/themes/fledermaus/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-theme-fledermaus ) && rm -f /etc/uci-defaults/luci-theme-fledermaus +} diff --git a/openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/footer.htm b/openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/footer.htm new file mode 100644 index 0000000..09eff44 --- /dev/null +++ b/openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/footer.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 4185 2009-01-30 14:00:35Z jow $ + +-%> +
+
+
+
+ + + + diff --git a/openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm b/openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm new file mode 100644 index 0000000..194245f --- /dev/null +++ b/openwrt/packages/luci/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm @@ -0,0 +1,180 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3655 2008-10-29 19:54:59Z jow $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("text/html") + +-%> + + + + + + + <% if node and node.css then %><% end %> + + + <%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + +
+<%:path%>: <% +local c = tree +local url = controller +for k,v in pairs(request) do + if c.nodes and c.nodes[v] then + c = c.nodes[v] + url = url .. "/" .. v + %><%=c.title or v%> <% if k ~= #request then %>» <% end + end +end +%> +
+ + +
+
    <% + for k,node in pairs(tree.nodes) do + if node.title and not node.hidden then %> + class="active"<%end%>><%=node.title%> +<% end + end%> +
+
+ + <% + if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end + %> + + <% end %> + +
+ +
diff --git a/openwrt/packages/luci/themes/fledermaus/root/etc/uci-defaults/luci-theme-fledermaus b/openwrt/packages/luci/themes/fledermaus/root/etc/uci-defaults/luci-theme-fledermaus new file mode 100755 index 0000000..83e472b --- /dev/null +++ b/openwrt/packages/luci/themes/fledermaus/root/etc/uci-defaults/luci-theme-fledermaus @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.themes.Fledermaus=/luci-static/fledermaus + commit luci +EOF + diff --git a/openwrt/packages/luci/themes/freifunk-bno/Makefile b/openwrt/packages/luci/themes/freifunk-bno/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk-bno/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/cascade.css b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/cascade.css new file mode 100644 index 0000000..3507777 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/cascade.css @@ -0,0 +1,726 @@ +* { + margin: 0; + padding: 0; +} + +body { + background-color: #ffffff; + color: #ffffff; + font-family: Verdana, Arial, sans-serif; + font-size: 100%; + line-height: 100%; + background-image: url(images/main-back.png); + background-repeat: repeat-x; + background-position: left bottom; + } +#all { + margin: 0px; + padding: 0px; + min-height: 800px; +} + +code { + font-family: monospace; + white-space: pre; +} + +a:link, a:visited { + color:#000000; + font-weight:bold; + text-decoration:none; + } +a:hover { + color:#333333; + font-weight:bold; + } + +/* Custom*/ + #wrapper +{ + width: 95%; + color: #333333; + margin-left: auto; + margin-right: auto; +/* background-image: url(images/corner-left.gif); */ +/* background-repeat: no-repeat; */ +/* background-position: left bottom; */ + background-color: #FffdF4; + min-width: 710px; + min-height: 710px; +} +#main { + clear: both; + width: 100%; + margin: 0; + padding: 0; + color: #333333; +/* background-image: url(images/corner-right.gif); */ +/* background-repeat: no-repeat; */ +/* background-position: right bottom; */ + min-height: 710px; +} + +div#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red !important; + font-weight: bold; +} + +.clear { + clear: both; + height: 1px; +} + +.hidden { + display: none; +} + +.error { + color: #ff0000; +} + +#header +{ + padding: 0px; + height: 100px; +} +#headerleft +{ + height: 100px; + background-color: #FFFfff; + background-image: url(images/header-left.gif); + background-repeat: no-repeat; + background-position: left top; +} +#headerright +{ + height: 100px; + background-color: #FFfffF; + + margin-left: 5px; + background-image: url(images/header-right.gif); + background-repeat: no-repeat; + background-position: right top; +} + +#headerback +{ + margin-right: 5px; + height: 100px; + background-color: #FFfffF; + background-image: url(images/header-back.gif); + background-repeat: repeat-x; + background-position: left top; +} +#schriftzug { + font-size : 1.5em; + text-align:left; + margin-bottom: 7px; + margin-top: 7px; + float:left; + width: 450px; +} + +#schriftzug a:hover{ + background-color:transparent; +} +#logo{ + margin-top: 5px; + float:right; + width: 115px; +} + +.pathbar { + display: none; +} + +.menubar { + width: 100%; + min-height: 1.8em; + background: #ffffff; + color: #000000; + border-top:0.4em solid #DC0067; +} + +.mainmenu { + float: left; + width: auto; + min-height: 1.8em; + background: #ffffff; + color: #000000; +} +.modemenu li { + border-top:0.3em solid #DC0067; + margin-left: 0.3em; + margin-top: -0.3em; +} +.mainmenu div { + float: left; + border-top:0.3em solid #DC0067; + margin-right: 0.3em; + margin-top: -0.3em; +} +.mainmenu div.preactive { + border-top: 0.3em solid #FFCB05; + margin-top: -0.2em; +} + +.mainmenu li { + white-space: nowrap; +} + +.mainmenu div ul { + display: none; + position: absolute; + background: #ffffff; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + list-style-type: none; +} + +.mainmenu ul li:hover > ul, +.mainmenu div:hover > ul { + display: block; +} + +.mainmenu ul li > ul { + left: 100%; + margin-top: -1.8em; + border-width: 1px; +} + +.modemenu a, +.mainmenu a { + display: block; + padding: 0.2em; + color: #000000; + text-decoration: none; + font-size: 70%; + font-weight: bold; +} + + +.modemenu .active a { + color: #000000; + font-weight: bold; + border-top:0.3em solid #FFCB05; + margin-top: -0.2em; +} +.mainmenu .active a{ + color: #000000; + font-weight: bold; + border-top:0.2em solid #FFCB05; +} +.mainmenu li > span:active { + background-color: #FFE990; +} + +.mainmenu li:hover > span > a, +.mainmenu div:hover > a { +color: #ffffff; +background-color: #FFCB05; +} + + +.modemenu a:focus, +.mainmenu a:focus { + color: #000000; +} + +.mainmenu a:hover, +.modemenu a:hover { +color: #ffffff; +background-color: #FFCB05; +} + +.mainmenu div.preactive > a { + color: #DC0067; + font-weight: bold; +} +.mainmenu div.preactive > a:hover, +.mainmenu div.preactive > a:focus { + color: #ffffff; + font-weight: bold; +} + +.modemenu ul { + width: auto; + background: #000000; + color: #ffffff; + list-style-type: none; +} + +.modemenu li { + float: right; + +} + +#maincontent { + clear: both; + width: 98%; + margin: 0 auto; + padding: 0.5em; + background: #FFF4BE; + color: #000000; + font-size: 80%; + border-top:1px solid #D2A800; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #D2A800; + background-color: #FFE990; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +input[type=submit], +input[type=reset], +input[type=image], +label { + cursor: pointer; +} + +select, +input, +textarea { + background: #FffdF4; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #FFF4BE; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { +background-color: #FFCB05; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { +background-color: #FFE990; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +.cbi-rowstyle-1 { + background-color: #FFF4BE; +} + +.cbi-rowstyle-2 { +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #FFCB05; +} + +div.cbi-value:hover { + background: #FFF4BE; +} + +div.cbi-value:last-child { + border: none; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin: 0.25em 0 0.25em 40%; +} + +div.cbi-value-description { + font-size: 90%; +} + +div.cbi-value-field > div.cbi-value-description { + display: none; +} + +div.cbi-value:hover div.cbi-value-field > div.cbi-value-description { + display: block; + color: #ffffff; + background-color: #FFCB05; +} + +option:active, +option:before, +option:after, +option:focus, +option:hover { + color: #ffffff; + background-color: #EEBA00; + background: url(images/bgoption.png); +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + margin: 0.5em 0; + padding: 0 0.25em; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border: 1px dotted #FFCB05; + padding-bottom: 0; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #FF0000; +} + +td.cbi-value-error { + border-color: red !important; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red !important; + background-color: #FFCCCC; +} + +.cbi-section-error { + color: red; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +ul.cbi-apply { + font-size: 90%; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a { + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #FF0000; + background-color: #FFFFFF; + padding: 0.5em; +} + +#memorybar { + width:200px; + height:8px; + border:1px solid #bbb; + background-color:red +} + +#memfree, #membuffers, #memcached { + float:right; + border:1px solid #bbb; + height:6px; +} + +#memfree { + background-color:green; +} + +#membuffers { + background-color:yellow; +} + +#memcached { + background-color:orange; +} + + +/* obligatory IE6 Voodoo Code */ +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.mainmenu div.hover ul, +* html div.mainmenu div li.hover ul, +* html div.mainmenu div li li.hover ul, +* html div.mainmenu div li li li.hover ul, +* html div.mainmenu div li li li li.hover ul { + display: block !important; + margin-left: 3em; +} + +* html div.mainmenu div.hover ul { + margin-left: 0; +} + +* html div.mainmenu .hover ul ul, +* html div.mainmenu .hover ul ul ul, +* html div.mainmenu .hover ul ul ul ul, +* html div.mainmenu .hover ul ul ul ul ul { + display: none !important; +} + +* html div.mainmenu li { + height: 1em !important; + width: 10em !important; +} + +* html .mainmenu { + height: 1.8em; +} + +* html div.cbi-value-description { + margin-left: 40%; +} diff --git a/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/bgoption.png b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/bgoption.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd1e2f34787b200eb425e42fb98c75b039163e2 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaOClDyqr82*Fc zg1yTp14TFsJR*yMv=#_6DqH@!17xt5c>21s-{2Gz=HriQFMb9T;`MZK4B@z*T(N!D bLwg3cy-YKE&k4N(N-%i3`njxgN@xNAizFlF literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/favicon.ico b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7247cfac5fe279cf3e12c965f53483196bfb0e2f GIT binary patch literal 5310 zcmeHJd2AGA6n}uYe@I#)M*vMg2#O-0f)-FIh+q(ng4H&}NJygr4G0#oh0<*)Edo`b z6iWb+044>R6hb106t=XbT-CN%OS^OJebMf2ce|avW_;6GrrVuqHT-FIc4qVDeQ$o> zo8P+zU=aQ$OaS~J17#xtMgzbUyif)6@e=fpc7y`lUuE9%751GY^f^H10)yvPp!bY7 zXmXv8h8g|T!Iw-MfY=O_1TJpzEs)haT+x<~CX-iu8-XkYW(P3adrp*5$OM8nge6Q% zga7Co7U^~X!P?}fD!Zc%vVeO1V`|z;Ds?(NH=P-`k4c$KEto_sG1w)uf+uttKq7CF zMp0-z-}Ma;89<1ur)}PaT3gm`TlO^l?LF@OqYT@D&I9UJzN`6+_pH}fY;+epI|~jt za)4Y1T769)$K+eoAMX4L+O`1o>j+ax*t1>dYV8V0X2%v-aS8o&>3Ws-J^rU=wWbUw z8ovHd;jlIMGl7JI#Hlq730V}*u5ut(815K-cSGPnvUwzB^oDvP5@Qp6n_b(U^{PHv zBg)qcUEcvI#}`+RSUiQg$SWM0Wj?;hDn~%gXDtpg6jWTgSLVgE%mhkt6_uK;*M*_ z(KBXh19ar2q8~J}LC`QzNy48D+@awjF|>;53@UiSySev96B|YeuYj-!ekRS1<&P!# zK@z=gnK2qxlmlT7E@p3czc=TI9_i5#iz!(sWiR@Pn zSxNO~sHA$4r7f;dOPdsuq%PC>;bg&KgcZTDWnp`nl13WJeR6-`5((G(IxlX4%HK)3 zJyYRZI+ZMV*lERni1-PcNar=b+#W6w{o>=2?C3bp!d~rGAh9uGK8yJIKrbCb+OD%Q zb4+U{mVD9wtMssHoq|0;NxjQb%bM=6Efrn33-+|lK+buMXs=W7f1kmP2@}gdl5>GL zY4s}N7n$6W-gKAs+In)bQOEHL`GA(6G~0y~s-&T+=frSd&|;-aAkjhyLC`>U+;Fq^ zJPQ7chLs(@7w($iA_bS}m+Q@VD+7oqE*^K^2`k_PdA`v4FFm$lowFwOL4U}o=Uv<~ zX!{a~qjM}sezYa84Z$I8`FvZnGDfc5?W)@|kPjzPY*0ZJ0ge6Vb71En)e z*e(iydUJRi|3FYG9yow%cJ_-OXbCPFOKcg6Gp6jLmQ68(s9Ou>W-ZLSZug_&3%!iTHI)D>L<|pTK0N@GXAc?I#nr!b&3Ur z{l9G4Ks=Z7-WBP3wkdYdxOBm)Z3_4sQjCkIl0QD|2{=X->6Mh{-m#C(AU}GXIK9Ni zTYJNS4O64;kjzk^e8F7CIlJBZ6X>y_;b$1~+-X*5^3qd{$2~Y?am=lMl3w^0^_ZF{ znrN)q;xwQ1@jQQPtKk3N6RY3gmWBYgfjy9 z%u>-SC(-Xtr{J*mfY-C;2MgRJ_n&BAHJHeFzEA)8<7bb(S)sDzyI^!M0WgPg7fiN% z;iSLsVU?;7DmUC7Mprii;Woy`NRFnc!Re1fABzIV98MzKt8kd$t-U!ie35M=WZ*ne zM2=D73@uNy;|KZPXN2i#x*ehSMv=SWm?z}#jeg97;w`U9Xyv4$)s|=i4lgFv^gzGM+9>UGb xQE>^Gst_zl41wwwZqP!WAC%7Xx^(4+t>|f78D}8QK%9X%191l84E$dh_y^c+g?9h| literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/header-back.gif b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/header-back.gif new file mode 100644 index 0000000000000000000000000000000000000000..21fe02b1e9af89e64fea086b438e20e68b391927 GIT binary patch literal 127 zcmZ?wbhEHbWMxQU*v!E2|NsA=KYzY?^XA5l8~@KR?A^O}&YU?-O-*@ud5MXM3>ZN1 zCku-R!+!=HkPOHS1{R$OCp=g0wRnAY_x}WqzLd;)8LQUic&i!oocWx1+ijk>jr||{ P#sCQoF-DIR76xkomfbH1 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/header-left.gif b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/header-left.gif new file mode 100644 index 0000000000000000000000000000000000000000..a3258ccb6d2f6809c591cdcf5694b6d9557c0feb GIT binary patch literal 293 zcmZ?wbhEHbWMxQUxXQrr|Ns9#fByXb{rlIiUq65T{Qmv>=g*%%eE9JG{rh+C-o1JA z=EaK_PoF-0`0(M~yLWHiym{lsjk9OZ{y)QT^ytweM~)mgaA51!ty{KiS+Qcp!i5Vb zO`0@u;>7m$_J)Rr($dnBl9G&!3P#h)xJA`Jf-bU>DX{KUZKkR+M{QLX+`uh6$`T6(v_x1Jl^z`)e^YifV z@b2#J?Ck96>FMa`=;h_*$$O;Js L%*+7K&p`k?3O3Jl literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/logo.gif b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff00d6ddb8051a28a4430977069e240b8a0a741b GIT binary patch literal 2415 zcmV-#36Sb0Nep)b8~ai%d_rlGwy@6rKP3+{O{;o zo#i!6_3zgI;A{G_5K~iA;xB`YjEw1Cb^p;I^|#de(Z98|wciw6`PS$E_}%fH#M{%b z;wMz|i6mxbX6tIE_2r~{dwciy_xk9b{qXjgnVIKLfZr8#zP`TUCw}vmbojoV?B>ko z=H^ODO7HLQqm4TM+Dz+OJM^s1_s8D<&l>r(Gymw4>S2}t|Nq6s#pz5!@|&RM-^Ty+ z%lqK%%*@Q>Jd523Vy>>PT3TA~i@Dyl8TOw&goK3UL2&0tS?q9x>R3?x;?bFznc*Q< z-QC^o;HhS2X3og8?R&87W?SiHqu?KT=1i3T)in0L%tAs!@}kH3^xFUKt^ebD|M}(T zKuG-N@a%J}{`dO-@w@SVDgD3-@0^tGd28^LzupdJ_Lv?2{rBT4U--`A?sszg;MLp# zXzgb;`SaQIueJ8Q*xd+g{p5!rC|J+yo5D={Dvfm4V!bm_qSW5Q2j%!C^>o^ynBcTEMi)VQ~NrsN8_0bb-KR z7bKGUx!?z!m>KR`I7HIrTn4z3LWqE;;pm(*3-)07 zfLH^!8E$r*x$!N?fHCewU~_>aL$#}tBA{)0L5PeeI4ErFcA(qDHwnHZNRYz{Ow{fS zvZXeqlx(y)Bsf@r1%o@};Ji#gbJTP4Qd4&INJ(Hf)C_&9e0*mG-iiwxV%|CH?$-lz ztr$Qf(heMn59TG{#aQr=pa48SB*DQGF`Xa~I4=+}5-Xl$uv$d!P%*$CHTf_Bfe0R0 zpb68(gxxn#loEn#o>)){3h#(<$3-Wo@kJSEy&)nzVkohLd^Ncflq42-(uIUBlz<@r z9x&~Ygn97Tu_HWha1cgJQ+`u|Bt$gEiBv8;FxfzM{PDyS?V&Y8mhX(QzydJ^362OU z4G~J6(B)u59%4YJ0h=r_!A49;y#wY06cz#-5o1Et#us_!Pz0dv6!GH#ci@58J0c+2 zmLUwJWI>)~_>dGhhv`5lu!sA zFXov*4NxVJ1tM7xH_!wb0LDoSP<>G?v66&0h(SsY zqyS8Kt>=y&p9Bk!59>mAYXpO2fMftrF?rDi3oP}Hxt*X3PaMRN@PnN11i&T#ix!88 zmT4C)umid7`05F>G0Gsr9amt{8&oL;U{!2rVF6PZ9c1KA8?Ef>%^PN1IshJM8T2VM zI-vCdObE~P&a<9m0nZGz!9=MyI*cR$3#Bv)PZ9LWu(CT1eA2+yGF)&RS|XIf0uT>D z$3;vRm;etLA|q16s_&R^B}{5S_scSpAOW2ia=>K99DTl1Mkm9vB!d|-fjkgo%t#XN z#xN~lfOqfsV1yxAmrl`g5Yrw!43wf5N3g+00|P>pgbXI;38o{G zzz7`%Fj>(A-tQ2x(!2vu{Eh|-2oV!~Xbt&@Bn0P)M|Ip};l(>Tc)*SS!IHnDgaa}C z5oyK*AUPLWP?j;aJ6rSv!9~==140@x*$iC^T*_Lcz|jUhB(56>5F9s*;=gxz!BkwB z5f%oRwo_LJ>gBd!Yv=AVm z8)ATo(&%!48}MOQQ2HO2ev!QwYUm<3APoS$LA;Cf?He@kgAAVX!f&t-GQz{4>n`#K zG9*9`Mks(79(0q76sj9wh(QM~GQuk6zAhVLFfTV5!ixUDEPs5P~a$39B4N(Mg$fK0AAzV zLKe|NfKk0;m=~GaFaJe|ZHX@jopK~R0`P!=7$+t{kf=AH;VwapAX(fXf=3790t~%F znisi(Ou2EbYz^X8Cq?NN)(MUhpz|FwItnT6Su8_P7^f$_*V50WE%nsYDM|D?%JfYY)gu zHzWy_`*r0GV67sZBw;5`i~vcFYykiiYYDW7m6-WU<*mBZBAjvqfCSJ%36eSxHGI>U zZoF2JJfVjReFF%>h%7i{Hq8lYQ$-f-1PJ!S)d7+rs>HlQJuw)e3ArK)ZGQcWpZ zbB+vf0BT1w&Gg|SaD8@08v5aOsgBH@@^DCk-4_i3;%wksb hD?l)cN7F(Tg_SflMzDxRJOUb&ummPFG3G!306PKJT{Qpz literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/main-back.png b/openwrt/packages/luci/themes/freifunk-bno/htdocs/luci-static/freifunk-bno/images/main-back.png new file mode 100644 index 0000000000000000000000000000000000000000..34aca44e01c12fa9f63dcce8d5c6fa529133f7b2 GIT binary patch literal 404 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 +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3464 2008-09-29 19:10:51Z jow $ + +-%> +
+
+ + + + +
+
+ + + + + + + diff --git a/openwrt/packages/luci/themes/freifunk-bno/luasrc/view/themes/freifunk-bno/header.htm b/openwrt/packages/luci/themes/freifunk-bno/luasrc/view/themes/freifunk-bno/header.htm new file mode 100644 index 0000000..8ea3058 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk-bno/luasrc/view/themes/freifunk-bno/header.htm @@ -0,0 +1,196 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3529 2008-10-07 13:10:24Z jow $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("text/html") + +-%> + + + + + + + <% if node and node.css then %><% end %> + + + + <%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + +
+
+ +
+
+ + + + +
+<%:path%>: <% +local c = tree +local url = controller +for k,v in pairs(request) do + if c.nodes and c.nodes[v] then + c = c.nodes[v] + url = url .. "/" .. v + %><%=c.title or v%> <% if k ~= #request then %>» <% end + end +end +%> +
+ + +
+
    <% + for k,node in pairs(tree.nodes) do + if node.title and not node.hidden then %> + class="active"<%end%>><%=node.title%> +<% end + end%> +
+
+ + <% + if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end + %> + + <% end %> + +
+
+
diff --git a/openwrt/packages/luci/themes/freifunk-bno/root/etc/uci-defaults/luci-theme-freifunk-bno b/openwrt/packages/luci/themes/freifunk-bno/root/etc/uci-defaults/luci-theme-freifunk-bno new file mode 100755 index 0000000..e5fb8a1 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk-bno/root/etc/uci-defaults/luci-theme-freifunk-bno @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.themes.Freifunk_BNO=/luci-static/freifunk-bno + commit luci +EOF + diff --git a/openwrt/packages/luci/themes/freifunk/Makefile b/openwrt/packages/luci/themes/freifunk/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/cascade.css b/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/cascade.css new file mode 100644 index 0000000..3507777 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/cascade.css @@ -0,0 +1,726 @@ +* { + margin: 0; + padding: 0; +} + +body { + background-color: #ffffff; + color: #ffffff; + font-family: Verdana, Arial, sans-serif; + font-size: 100%; + line-height: 100%; + background-image: url(images/main-back.png); + background-repeat: repeat-x; + background-position: left bottom; + } +#all { + margin: 0px; + padding: 0px; + min-height: 800px; +} + +code { + font-family: monospace; + white-space: pre; +} + +a:link, a:visited { + color:#000000; + font-weight:bold; + text-decoration:none; + } +a:hover { + color:#333333; + font-weight:bold; + } + +/* Custom*/ + #wrapper +{ + width: 95%; + color: #333333; + margin-left: auto; + margin-right: auto; +/* background-image: url(images/corner-left.gif); */ +/* background-repeat: no-repeat; */ +/* background-position: left bottom; */ + background-color: #FffdF4; + min-width: 710px; + min-height: 710px; +} +#main { + clear: both; + width: 100%; + margin: 0; + padding: 0; + color: #333333; +/* background-image: url(images/corner-right.gif); */ +/* background-repeat: no-repeat; */ +/* background-position: right bottom; */ + min-height: 710px; +} + +div#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red !important; + font-weight: bold; +} + +.clear { + clear: both; + height: 1px; +} + +.hidden { + display: none; +} + +.error { + color: #ff0000; +} + +#header +{ + padding: 0px; + height: 100px; +} +#headerleft +{ + height: 100px; + background-color: #FFFfff; + background-image: url(images/header-left.gif); + background-repeat: no-repeat; + background-position: left top; +} +#headerright +{ + height: 100px; + background-color: #FFfffF; + + margin-left: 5px; + background-image: url(images/header-right.gif); + background-repeat: no-repeat; + background-position: right top; +} + +#headerback +{ + margin-right: 5px; + height: 100px; + background-color: #FFfffF; + background-image: url(images/header-back.gif); + background-repeat: repeat-x; + background-position: left top; +} +#schriftzug { + font-size : 1.5em; + text-align:left; + margin-bottom: 7px; + margin-top: 7px; + float:left; + width: 450px; +} + +#schriftzug a:hover{ + background-color:transparent; +} +#logo{ + margin-top: 5px; + float:right; + width: 115px; +} + +.pathbar { + display: none; +} + +.menubar { + width: 100%; + min-height: 1.8em; + background: #ffffff; + color: #000000; + border-top:0.4em solid #DC0067; +} + +.mainmenu { + float: left; + width: auto; + min-height: 1.8em; + background: #ffffff; + color: #000000; +} +.modemenu li { + border-top:0.3em solid #DC0067; + margin-left: 0.3em; + margin-top: -0.3em; +} +.mainmenu div { + float: left; + border-top:0.3em solid #DC0067; + margin-right: 0.3em; + margin-top: -0.3em; +} +.mainmenu div.preactive { + border-top: 0.3em solid #FFCB05; + margin-top: -0.2em; +} + +.mainmenu li { + white-space: nowrap; +} + +.mainmenu div ul { + display: none; + position: absolute; + background: #ffffff; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + list-style-type: none; +} + +.mainmenu ul li:hover > ul, +.mainmenu div:hover > ul { + display: block; +} + +.mainmenu ul li > ul { + left: 100%; + margin-top: -1.8em; + border-width: 1px; +} + +.modemenu a, +.mainmenu a { + display: block; + padding: 0.2em; + color: #000000; + text-decoration: none; + font-size: 70%; + font-weight: bold; +} + + +.modemenu .active a { + color: #000000; + font-weight: bold; + border-top:0.3em solid #FFCB05; + margin-top: -0.2em; +} +.mainmenu .active a{ + color: #000000; + font-weight: bold; + border-top:0.2em solid #FFCB05; +} +.mainmenu li > span:active { + background-color: #FFE990; +} + +.mainmenu li:hover > span > a, +.mainmenu div:hover > a { +color: #ffffff; +background-color: #FFCB05; +} + + +.modemenu a:focus, +.mainmenu a:focus { + color: #000000; +} + +.mainmenu a:hover, +.modemenu a:hover { +color: #ffffff; +background-color: #FFCB05; +} + +.mainmenu div.preactive > a { + color: #DC0067; + font-weight: bold; +} +.mainmenu div.preactive > a:hover, +.mainmenu div.preactive > a:focus { + color: #ffffff; + font-weight: bold; +} + +.modemenu ul { + width: auto; + background: #000000; + color: #ffffff; + list-style-type: none; +} + +.modemenu li { + float: right; + +} + +#maincontent { + clear: both; + width: 98%; + margin: 0 auto; + padding: 0.5em; + background: #FFF4BE; + color: #000000; + font-size: 80%; + border-top:1px solid #D2A800; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #D2A800; + background-color: #FFE990; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +input[type=submit], +input[type=reset], +input[type=image], +label { + cursor: pointer; +} + +select, +input, +textarea { + background: #FffdF4; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #FFF4BE; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { +background-color: #FFCB05; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { +background-color: #FFE990; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +.cbi-rowstyle-1 { + background-color: #FFF4BE; +} + +.cbi-rowstyle-2 { +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #FFCB05; +} + +div.cbi-value:hover { + background: #FFF4BE; +} + +div.cbi-value:last-child { + border: none; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin: 0.25em 0 0.25em 40%; +} + +div.cbi-value-description { + font-size: 90%; +} + +div.cbi-value-field > div.cbi-value-description { + display: none; +} + +div.cbi-value:hover div.cbi-value-field > div.cbi-value-description { + display: block; + color: #ffffff; + background-color: #FFCB05; +} + +option:active, +option:before, +option:after, +option:focus, +option:hover { + color: #ffffff; + background-color: #EEBA00; + background: url(images/bgoption.png); +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + margin: 0.5em 0; + padding: 0 0.25em; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border: 1px dotted #FFCB05; + padding-bottom: 0; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #FF0000; +} + +td.cbi-value-error { + border-color: red !important; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red !important; + background-color: #FFCCCC; +} + +.cbi-section-error { + color: red; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +ul.cbi-apply { + font-size: 90%; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a { + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #FF0000; + background-color: #FFFFFF; + padding: 0.5em; +} + +#memorybar { + width:200px; + height:8px; + border:1px solid #bbb; + background-color:red +} + +#memfree, #membuffers, #memcached { + float:right; + border:1px solid #bbb; + height:6px; +} + +#memfree { + background-color:green; +} + +#membuffers { + background-color:yellow; +} + +#memcached { + background-color:orange; +} + + +/* obligatory IE6 Voodoo Code */ +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.mainmenu div.hover ul, +* html div.mainmenu div li.hover ul, +* html div.mainmenu div li li.hover ul, +* html div.mainmenu div li li li.hover ul, +* html div.mainmenu div li li li li.hover ul { + display: block !important; + margin-left: 3em; +} + +* html div.mainmenu div.hover ul { + margin-left: 0; +} + +* html div.mainmenu .hover ul ul, +* html div.mainmenu .hover ul ul ul, +* html div.mainmenu .hover ul ul ul ul, +* html div.mainmenu .hover ul ul ul ul ul { + display: none !important; +} + +* html div.mainmenu li { + height: 1em !important; + width: 10em !important; +} + +* html .mainmenu { + height: 1.8em; +} + +* html div.cbi-value-description { + margin-left: 40%; +} diff --git a/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/bgoption.png b/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/bgoption.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd1e2f34787b200eb425e42fb98c75b039163e2 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}K#X;^)4C~IxyaaOClDyqr82*Fc zg1yTp14TFsJR*yMv=#_6DqH@!17xt5c>21s-{2Gz=HriQFMb9T;`MZK4B@z*T(N!D bLwg3cy-YKE&k4N(N-%i3`njxgN@xNAizFlF literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/favicon.ico b/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f785830ff77a700ac1dbf153a11f638f32481171 GIT binary patch literal 4286 zcmeI0d2Ccw6o=0U6l@SdA_`?0cBpnGExS`F`x<0Xs31~6N;@qeDp9Z{7SM>4 z9ykpb;V(D@AAlF`g>bz{<3wa$fYH#rmi%43_l4(RXz-i-{s2xbDtWK2HFuKtC7^gC z`R>kqKD5s1V#p8qP^Pc4t;x zX$H^7&so9|#}a>bEY9cHsKN`D7gG|7vkP+N zApNzl5LUngl9@5^WFY3$9aZ(9L9ef`MUPlJQg&7=-qGk)fCC4hBUs`g#|FMrVcFeFqrDw{i_q%` zIuEk-IPrTk2b{E&UDfsRITW46ARDI=4>|+Jd(T>4>k{>VP|U3vPouWRlD8hC3(8%I zzc}NNFAwTTcNc7e4|^0lo7vMg6SJ@rQ!)zOUJ$C`4cJ&PeOOr(a*dOVo#W_~K_xio zt;N3lzZ&$vfoB}_r`D#=jXTz+_g7W*lYVk`Nd8779CngMynNB}+W77#?s4dk2-@3+ z9rd-O^mSJZxn|gy02kTA&&g}k%(Rm_hns`)`8;*T2V!R?`L91@&1GZ#vFIEL^S_Pp zBFKlu)J2QoD=%7ZTVFJK+P^+f1?rbE)W*}ZQ;*-#@3TsaKjI`)JHz9Db)rTtqyAe5 z>i=Wpl>hmV2CJdZJkHF7?6dN3Sx|g{>JEO{p#gf|0$?BW1Y#T+n0@8%dGg)K;QGW5BS#iLXiJrcm>q60ycHF`h8ld zvllqG_`Lp9Tq!%NEYrgta>me6-x~vCLH71Q$iJSw*`I~PFqyj0KF5RVbrned4{(F} ziE^o&+7m;|tnb#!z*&<|!PyC*{R!@&>`#OwSOc=R9>V==datK?JP)$5-DtxIc`?}N|?Zsf1_d`o1HgLFTFHt;Oy zuC0;97yEXd;Cx%2TDNL$GE{?XOoiG$ZuPEwscxme5p=g^z#Q;^eCcjbtO=lRx@Wq9 z{Dtmd^)VOR%3q}K3(%8)aR5{c>glSJX`u5t9aQ7$mEv6p>3qRB8Y0=g-8tp)Oqfmm z9kvXnfa>yL$OY}wB?$Rm$5=h!cKzH;PG@2ZsE38@-{@J4jB;}`d;j%YEOwW`m+%{0 z0QI%+;dK}aQ4rC7q`%4Q=IS!=e`Ua__2X}1p6?3n?p1zk*zUa5^Z3o>DVp!fFY*`7 zFW6p`R=|HIfV-f;-E8T0|JzIb{@pJ+e!t7{pLaP${1!Mx`MjCSLEovchR!u>=Q!r6 IZN1 zCku-R!+!=HkPOHS1{R$OCp=g0wRnAY_x}WqzLd;)8LQUic&i!oocWx1+ijk>jr||{ P#sCQoF-DIR76xkomfbH1 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/header-left.gif b/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/header-left.gif new file mode 100644 index 0000000000000000000000000000000000000000..a3258ccb6d2f6809c591cdcf5694b6d9557c0feb GIT binary patch literal 293 zcmZ?wbhEHbWMxQUxXQrr|Ns9#fByXb{rlIiUq65T{Qmv>=g*%%eE9JG{rh+C-o1JA z=EaK_PoF-0`0(M~yLWHiym{lsjk9OZ{y)QT^ytweM~)mgaA51!ty{KiS+Qcp!i5Vb zO`0@u;>7m$_J)Rr($dnBl9G&!3P#h)xJA`Jf-bU>DX{KUZKkR+M{QLX+`uh6$`T6(v_x1Jl^z`)e^YifV z@b2#J?Ck96>FMa`=;h_*$$O;Js L%*+7K&p`k?3O3Jl literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/logo.png b/openwrt/packages/luci/themes/freifunk/htdocs/luci-static/freifunk/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0beeb2fad1c99c2477c00b5ab5214f9a82769797 GIT binary patch literal 6400 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 Z`v1Ohi~S#mD^>si002ovPDHLkV1fesfFl3^ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/freifunk/ipkg/postinst b/openwrt/packages/luci/themes/freifunk/ipkg/postinst new file mode 100755 index 0000000..f5d35c9 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-theme-freifunk ) && rm -f /etc/uci-defaults/luci-theme-freifunk +} diff --git a/openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/footer.htm b/openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/footer.htm new file mode 100644 index 0000000..c8c630e --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/footer.htm @@ -0,0 +1,29 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 3464 2008-09-29 19:10:51Z jow $ + +-%> +
+
+
+ + + +
+
+ + + + + + + diff --git a/openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/header.htm b/openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/header.htm new file mode 100644 index 0000000..13e35fa --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk/luasrc/view/themes/freifunk/header.htm @@ -0,0 +1,196 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 3529 2008-10-07 13:10:24Z jow $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("text/html") + +-%> + + + + + + + <% if node and node.css then %><% end %> + + + + <%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + +
+
+ +
+
+ + + + +
+<%:path%>: <% +local c = tree +local url = controller +for k,v in pairs(request) do + if c.nodes and c.nodes[v] then + c = c.nodes[v] + url = url .. "/" .. v + %><%=c.title or v%> <% if k ~= #request then %>» <% end + end +end +%> +
+ + +
+
    <% + for k,node in pairs(tree.nodes) do + if node.title and not node.hidden then %> + class="active"<%end%>><%=node.title%> +<% end + end%> +
+
+ + <% + if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end + %> + + <% end %> + +
+
+
diff --git a/openwrt/packages/luci/themes/freifunk/root/etc/uci-defaults/luci-theme-freifunk b/openwrt/packages/luci/themes/freifunk/root/etc/uci-defaults/luci-theme-freifunk new file mode 100755 index 0000000..eb038f0 --- /dev/null +++ b/openwrt/packages/luci/themes/freifunk/root/etc/uci-defaults/luci-theme-freifunk @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.themes.Freifunk=/luci-static/freifunk + commit luci +EOF + diff --git a/openwrt/packages/luci/themes/openwrt-light/Makefile b/openwrt/packages/luci/themes/openwrt-light/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/cascade.css b/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/cascade.css new file mode 100644 index 0000000..a26e662 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/cascade.css @@ -0,0 +1,790 @@ +@charset "utf-8"; + +@media all { + +html, +body { + background-color: #4a6b7c; + color: #ffffff; +} + +body { + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + background-color: #557788; + color: #ffffff; + text-align: right; + padding: 0.5em; +} + +#header h1 { + display: inline; +} + +#header p { + display: inline; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +ul.dropdowns { + float: left; + margin: 0; + padding: 0; + width: auto; + list-style: none; +} + +html>body ul.dropdowns { + position: relative; +} + +ul.dropdowns li, +ul.dropdowns ul { + margin: 0; + padding: 0; + list-style: none; +} + +ul.dropdowns li { + float: left; + position: relative; + white-space: nowrap; +} + +ul.dropdowns li ul { + position: absolute; + z-index: 1000; + top: auto; + min-width: 10em; +} + +ul.dropdowns li li { + float: none; + position: relative; +} + +ul.dropdowns li a { + display: block; +} + +ul.dropdowns ul li ul { + top: 0; +} + +ul.dropdowns li ul, +ul.dropdowns li.over ul ul, +ul.dropdowns li.focus ul ul, +ul.dropdowns li:hover ul ul, +ul.dropdowns li.over ul ul ul, +ul.dropdowns li.focus ul ul ul, +ul.dropdowns li:hover ul ul ul, +ul.dropdowns li.over ul ul ul ul, +ul.dropdowns li.focus ul ul ul ul, +ul.dropdowns li:hover ul ul ul ul { + left: -3000px; +} + +ul.dropdowns li.over ul, +ul.dropdowns li.focus ul, +ul.dropdowns li:hover ul { + left: 0; +} + +ul.dropdowns ul li.over ul, +ul.dropdowns ul li.focus ul, +ul.dropdowns ul li:hover ul, +ul.dropdowns ul ul li.over ul, +ul.dropdowns ul ul li.focus ul, +ul.dropdowns ul ul li:hover ul, +ul.dropdowns ul ul ul li.over ul, +ul.dropdowns ul ul ul li.focus ul, +ul.dropdowns ul ul ul li:hover ul { + left: 100%; +} + +#menubar { + position: relative; + width: 100%; + background: #000000; + color: #ffffff; +} + +#menubar .warning { + color: red; + background-color: #557788; +} + +#menubar ul.dropdowns { + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +#menubar ul.dropdowns li ul { + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; +} + +#menubar ul.dropdowns ul li ul { + border-width: 1px; +} + +html #menubar a:link, +html #menubar a:visited { + position: relative; + display: block; + padding: 0.5em; + background: #000000; + color: #ffffff; + text-decoration: none; + font-size: 80%; + font-weight: normal; +} + + +html #menubar a:link:hover, +html #menubar a:visited:hover, +html #menubar a:link:active, +html #menubar a:visited:active, +#menubar a:link:focus, +#menubar a:visited:focus { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.active, +html #menubar a:visited.active, +html #menubar a:link.preactive, +html #menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.warning, +html #menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +#menubar ul.dropdowns li.over>a, +#menubar ul.dropdowns li.focus>a, +#menubar ul.dropdowns li:hover>a { + font-weight: bold; +} + +.lang_de #submenu_mini_system { min-width: 13.3em; } +* html .lang_de #submenu_mini_system { width: 13.3em; } + +.lang_pt-br #submenu_mini_network { min-width: 14em; } +* html .lang_pt-br #submenu_mini_network { width: 14em; } + +.lang_pt-br #submenu_mini_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_mini_system { width: 11.5em; } + +.lang_ru #submenu_mini_system { min-width: 18em; } +* html .lang_ru #submenu_mini_system { width: 18em; } + +.lang_pt-br #submenu_admin_index { min-width: 11em; } +* html .lang_pt-br #submenu_admin_index { width: 11em; } + +.lang_ru #submenu_admin_index { min-width: 15.5em; } +* html .lang_ru #submenu_admin_index { width: 15.5em; } + +.lang_ru #submenu_admin_status { min-width: 10.5em; } +* html .lang_ru #submenu_admin_status { width: 10.5em; } + +.lang_de #submenu_admin_system { min-width: 13.3em; } +* html .lang_de #submenu_admin_system { width: 13.3em; } + +.lang_fr #submenu_admin_system { min-width: 14.5em; } +* html .lang_fr #submenu_admin_system { width: 14.5em; } + +.lang_pt-br #submenu_admin_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_admin_system { width: 11.5em; } + +.lang_ru #submenu_admin_system { min-width: 18em; } +* html .lang_ru #submenu_admin_system { width: 18em; } + +#submenu_admin_services_chillispot { min-width: 15.5em; } +* html #submenu_admin_services_chillispot { width: 15.5em; } + +#submenu_admin_services_coovachilli { min-width: 15em; } +* html #submenu_admin_services_coovachilli { width: 15em; } + +.lang_ru #submenu_admin_network_routes { min-width: 15.3em; } +* html .lang_ru #submenu_admin_network_routes { width: 15.3em; } + +#submenu_admin_network_firewall { min-width: 14em; } +* html #submenu_admin_network_firewall { width: 14em; } + +.lang_de #submenu_admin_network_firewall { min-width: 16.5em; } +* html .lang_de #submenu_admin_network_firewall { width: 16.5em; } + +.lang_pt-br #submenu_admin_network_firewall { min-width: 15em; } +* html .lang_pt-br #submenu_admin_network_firewall { width: 15em; } + +#modemenu { + width: auto; + background: #000000; + color: #ffffff; + list-style: none; + margin-right: 1px; +} + +#modemenu li { + float: right; + list-style: none; +} + +#savemenu { + float: right; + margin-right: 2em; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + font-size: 80%; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + text-decoration: none !important; + font-weight: bold !important; + color: #555555 !important; + margin: 0.25em !important; + font-size: 100% !important; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table td, +table th { + color: #000000; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { + color: #000000; +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; + line-height: 1.8em; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; + vertical-align: top; +} + +div.cbi-tblsection-create { + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-create .cbi-button { + margin: 0.25em; +} + +input.cbi-section-create-name { + margin-right: -0.25em; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + +} diff --git a/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie6.css b/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie6.css new file mode 100644 index 0000000..1c95185 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie6.css @@ -0,0 +1,77 @@ +/* obligatory IE6 Voodoo Code */ + +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div#menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html ul.dropdowns li ul { + width: 10em; +} + +* html ul.dropdowns li li { + clear: both; + float: left; +} + +* html ul.dropdowns li li { + width: 100%; +} + +* html ul.dropdowns li li a { + height: 1%; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.cbi-value-description { + width: auto !important; +} + +* html div.cbi-value-field { + margin-left: 0 !important; + width: 100% !important; +} + +* html .cbi-input-text, +* html .cbi-input-user, +* html .cbi-input-select, +* html .cbi-input-password { + width: 50% !important; +} + +* html .cbi-input-user, +* html .cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; +} + +* html .cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +* html table.cbi-section-table td .cbi-input-text, +* html table.cbi-section-table td .cbi-input-select { + width: 100% !important; +} + +* html div.cbi-page-actions { + text-align: right !important; +} + +* html div.cbi-value-field input, +* html div.cbi-value-field select { + font-size: 90% !important; +} diff --git a/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie7.css b/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie7.css new file mode 100644 index 0000000..67ed9fb --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/htdocs/luci-static/openwrt-light/ie7.css @@ -0,0 +1,20 @@ +div.cbi-value-field { + margin-left: 0 !important; +} + +.cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +table.cbi-section-table td .cbi-input-text, +table.cbi-section-table td .cbi-input-select { + width: 95% !important; +} + +.cbi-input-user, +.cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; + width: 18.5em !important; +} diff --git a/openwrt/packages/luci/themes/openwrt-light/ipkg/postinst b/openwrt/packages/luci/themes/openwrt-light/ipkg/postinst new file mode 100755 index 0000000..85db6c6 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-theme-openwrtlight ) && rm -f /etc/uci-defaults/luci-theme-openwrtlight +} diff --git a/openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/footer.htm b/openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/footer.htm new file mode 100644 index 0000000..98d48ad --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/footer.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 4185 2009-01-30 14:00:35Z jow $ + +-%> +
+
+ +

Powered by <%= luci.__appname__ .. " (v" .. luci.__version__ .. ")" %>

+ + + diff --git a/openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/header.htm b/openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/header.htm new file mode 100644 index 0000000..4e53f99 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/luasrc/view/themes/openwrt-light/header.htm @@ -0,0 +1,163 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 4079 2009-01-17 17:59:11Z Cyrus $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + + +<% if node and node.css then %> +<% end -%> + + + +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + + + +
diff --git a/openwrt/packages/luci/themes/openwrt-light/root/etc/uci-defaults/luci-theme-openwrtlight b/openwrt/packages/luci/themes/openwrt-light/root/etc/uci-defaults/luci-theme-openwrtlight new file mode 100755 index 0000000..c2322a4 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt-light/root/etc/uci-defaults/luci-theme-openwrtlight @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.themes.OpenWrt_Light=/luci-static/openwrt-light + commit luci +EOF + diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/Makefile b/openwrt/packages/luci/themes/openwrt.org-oxygen/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/bg.jpg b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dece957dfd82acae201397ebb04f7b3be93a5fd8 GIT binary patch literal 40537 zcmeFZc{r49|36Np&GyV~7o(a=qNE`^X|dgwJIa=b2}!bNiP5bh>yXM$i%2F*D>V^= zDaKy3C}t)kg)w9s{Lb^5QQgny`5wRHa~$8}_xtDRzRh)A=kk8P-mmv^o-=b@v-ozg zkLO>eh9-tQyu7?T#^67m#Sc9Dc$P0)2LA{DR)GKcR`c<#Si!e;)vA@N1=b1(@UP|P z7Zm#AUxGp?A%6aUiT?{FA}S^(CLk;!DK0Achp3n+6vDe4%vr&=hL3NJs35PiP z;tL+s>ScDTmo4Yr$g>Q^yBx*4SjQvF!^^WA{?E&^^pAJh@)avrt>#+;x}E>U%d?DU z#flZnmapO$;$Owb%ftJ}vgIg|6?_L>R<7D$pyGGq{sU3*jen<=fJs27-1q@E_+49$?FV z{`Y_E_~-EDCaTVR4y#JE@u{XBXy!E++#JCxs_H1V4_p`o?6KZ=U_zBoP@=6(w8LCN zHJNj*nrh;_5A>Nh?-6ZlkKp;M-Isfe5afk3_Z@g)Z6X1rNvQIvB1a$qj1)u^@K~Gk zK~+#H@~6tjH^FPZ2}lAm9Z?1W28TKhfEHv#TZgSG%3M`~?=RSIqU!il5)ixz!GQor zt{@(W#TVGnCaQ|`n%nXkaPR?4z)qyq0Ahh!fx(-A#12~shGQUv0!=r8syGUuIlvTE zM?O`=41^Y7+0o7XUrwx*-mxr`|I4!I%T?zTu2<$qWg1srSGaL=R(e^cF>I=eK35Pm z%To|FaIPRa{)^}O8#ntv>p6v+fma_wh9Em!M)&Rc3#tWpP>>NpXf}X~kOSZ&T`T@_ z-e+)#V;x``u?29&C-}=W!Oe*C0L=(R+#x_$Ds(6x_)}HAickz_0HdI%pa@_h#9{(m z2zp_UNInr*sGOgs2lmEH?BkTlvMLY zFBD59D)6n(cL(QD2@O}GQreL7i$7bEE^gRL^)y!CH-@ikkXJs8%I)>}qHuijL*&&8 zD{ZxQ@4@trWGivdkkro+d4VG)1-7p>#F-ixkHC@ISCTFwBDO>A8x)XNPw*<+XaGhT z?M=P{0dYWFxCNC3J0R0dp&kPc2+nwT{>5r7(vA#)1C9KX5iEZonzclKNkfcG=74~b zF*l4y9wOEwLpc+~Ie?)|BY#f&Z?+zU*8K5X0|zVuGjQu~EJ1*4p+N@5NV9C$PaP>e z`P&f&I3)fuHxO{}@0Q9oLL_@TICv1n2nNU~u=L8W7RY@RhrFbVhH+7 zOF{D+a1I&=#7<5uA=Yvu>L+a=x_&$V&FP2_gB3WI1akuF7aDFPMS-~>zBePpLlb3d zQ(SJF-X}I(-6k+0edrE$>95Vx>N@rJzxLav=XFN0?TKmiAzJJ*)K+`&vJn$v|eBak6%@Rtd@fBjh{08j^W&zoKaamF3n!JRJb1VY{Lom6~OCSK>KLJ1smnN8E0W(}y zfkF;nfadmsWDfHGAOJxRhARGhEad-AX$@CjDV1-+^g~4FlO9ot{9wag-$TwmmBxI0 zKju=Scn!ip?Laydq?biaL?y4~?|hxVEQ%S0deS2%kuQ4gFDG9EWU6RV-}UF~LEi)@ zoIsQaoNZwI8k`0x@LYe6*$XCjXlF�HIdk{QH!GEIfw_#6OH=f|-eH_iR-*mS1r; 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/cascade.css b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/cascade.css new file mode 100644 index 0000000..8aea909 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/cascade.css @@ -0,0 +1,803 @@ +@charset "utf-8"; + +@media all { + +html, +body { + background-color: #4a6b7c; + background-image: url(bg.jpg); + background-position: bottom center; + background-attachment: fixed; + background-repeat: repeat-x; + color: #ffffff; +} + +body { + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + min-height: 98px; + background-image: url(header.png); + background-repeat: no-repeat; + background-position: left center; + background-color: #557788; + color: #ffffff; + text-align: right; +} + +#header h1 { + padding: 1em 1em 0 1em; +} + +#header p { + padding: 0 1em 1em 1em; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +ul.dropdowns { + float: left; + margin: 0; + padding: 0; + width: auto; + list-style: none; +} + +html>body ul.dropdowns { + position: relative; +} + +ul.dropdowns li, +ul.dropdowns ul { + margin: 0; + padding: 0; + list-style: none; +} + +ul.dropdowns li { + float: left; + position: relative; + white-space: nowrap; +} + +ul.dropdowns li ul { + position: absolute; + z-index: 1000; + top: auto; + min-width: 10em; +} + +ul.dropdowns li li { + float: none; + position: relative; +} + +ul.dropdowns li a { + display: block; +} + +ul.dropdowns ul li ul { + top: 0; +} + +ul.dropdowns li ul, +ul.dropdowns li.over ul ul, +ul.dropdowns li.focus ul ul, +ul.dropdowns li:hover ul ul, +ul.dropdowns li.over ul ul ul, +ul.dropdowns li.focus ul ul ul, +ul.dropdowns li:hover ul ul ul, +ul.dropdowns li.over ul ul ul ul, +ul.dropdowns li.focus ul ul ul ul, +ul.dropdowns li:hover ul ul ul ul { + left: -3000px; +} + +ul.dropdowns li.over ul, +ul.dropdowns li.focus ul, +ul.dropdowns li:hover ul { + left: 0; +} + +ul.dropdowns ul li.over ul, +ul.dropdowns ul li.focus ul, +ul.dropdowns ul li:hover ul, +ul.dropdowns ul ul li.over ul, +ul.dropdowns ul ul li.focus ul, +ul.dropdowns ul ul li:hover ul, +ul.dropdowns ul ul ul li.over ul, +ul.dropdowns ul ul ul li.focus ul, +ul.dropdowns ul ul ul li:hover ul { + left: 100%; +} + +#menubar { + position: relative; + width: 100%; + background: #000000; + color: #ffffff; +} + +#menubar .warning { + color: red; + background-color: #557788; +} + +#menubar ul.dropdowns { + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +#menubar ul.dropdowns li ul { + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; +} + +#menubar ul.dropdowns ul li ul { + border-width: 1px; +} + +html #menubar a:link, +html #menubar a:visited { + position: relative; + display: block; + padding: 0.5em; + background: #000000; + color: #ffffff; + text-decoration: none; + font-size: 80%; + font-weight: normal; +} + + +html #menubar a:link:hover, +html #menubar a:visited:hover, +html #menubar a:link:active, +html #menubar a:visited:active, +#menubar a:link:focus, +#menubar a:visited:focus { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.active, +html #menubar a:visited.active, +html #menubar a:link.preactive, +html #menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.warning, +html #menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +#menubar ul.dropdowns li.over>a, +#menubar ul.dropdowns li.focus>a, +#menubar ul.dropdowns li:hover>a { + font-weight: bold; +} + +.lang_de #submenu_mini_system { min-width: 13.3em; } +* html .lang_de #submenu_mini_system { width: 13.3em; } + +.lang_pt-br #submenu_mini_network { min-width: 14em; } +* html .lang_pt-br #submenu_mini_network { width: 14em; } + +.lang_pt-br #submenu_mini_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_mini_system { width: 11.5em; } + +.lang_ru #submenu_mini_system { min-width: 18em; } +* html .lang_ru #submenu_mini_system { width: 18em; } + +.lang_pt-br #submenu_admin_index { min-width: 11em; } +* html .lang_pt-br #submenu_admin_index { width: 11em; } + +.lang_ru #submenu_admin_index { min-width: 15.5em; } +* html .lang_ru #submenu_admin_index { width: 15.5em; } + +.lang_ru #submenu_admin_status { min-width: 10.5em; } +* html .lang_ru #submenu_admin_status { width: 10.5em; } + +.lang_de #submenu_admin_system { min-width: 13.3em; } +* html .lang_de #submenu_admin_system { width: 13.3em; } + +.lang_fr #submenu_admin_system { min-width: 14.5em; } +* html .lang_fr #submenu_admin_system { width: 14.5em; } + +.lang_pt-br #submenu_admin_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_admin_system { width: 11.5em; } + +.lang_ru #submenu_admin_system { min-width: 18em; } +* html .lang_ru #submenu_admin_system { width: 18em; } + +#submenu_admin_services_chillispot { min-width: 15.5em; } +* html #submenu_admin_services_chillispot { width: 15.5em; } + +#submenu_admin_services_coovachilli { min-width: 15em; } +* html #submenu_admin_services_coovachilli { width: 15em; } + +.lang_ru #submenu_admin_network_routes { min-width: 15.3em; } +* html .lang_ru #submenu_admin_network_routes { width: 15.3em; } + +#submenu_admin_network_firewall { min-width: 14em; } +* html #submenu_admin_network_firewall { width: 14em; } + +.lang_de #submenu_admin_network_firewall { min-width: 16.5em; } +* html .lang_de #submenu_admin_network_firewall { width: 16.5em; } + +.lang_pt-br #submenu_admin_network_firewall { min-width: 15em; } +* html .lang_pt-br #submenu_admin_network_firewall { width: 15em; } + +#modemenu { + width: auto; + background: #000000; + color: #ffffff; + list-style: none; + margin-right: 1px; +} + +#modemenu li { + float: right; + list-style: none; +} + +#savemenu { + float: right; + margin-right: 2em; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + font-size: 80%; +} + +#maincontent h2 { + font-size: 150%; + font-family: Trebuchet MS, Verdana, sans-serif; + font-weight: bold; + margin: 0.25em 0 0.7em 0; + border-bottom: 1px solid; + padding-top: 10px; + padding-bottom: 4px; +} + +#maincontent h3 { + margin: 0.5em 0 1.1em 0; + font-size: 125%; + font-weight: bold; + font-style: italic; + font-family: Trebuchet MS, Verdana, sans-serif; + color: #27408B; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + text-decoration: none !important; + font-weight: bold !important; + color: #555555 !important; + margin: 0.25em !important; + font-size: 100% !important; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table td, +table th { + color: #000000; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { + color: #000000; +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; + line-height: 1.8em; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; + vertical-align: top; +} + +div.cbi-tblsection-create { + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-create .cbi-button { + margin: 0.25em; +} + +input.cbi-section-create-name { + margin-right: -0.25em; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + +} diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/dashboard.css b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/dashboard.css new file mode 100644 index 0000000..ba9691e --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/dashboard.css @@ -0,0 +1,99 @@ +@charset "utf-8"; + +@media all { + +div.dashicon { + float: left; +} + +div.dashicon a { + background-image: url(icons/default.png); + background-repeat: no-repeat; + background-position: top; + display: block; + width: 70px; + padding-top: 70px; + color: #000000; + text-decoration: none; + text-align: center; + margin: 2em; + font-weight: bold; +} + +div.di_network a { + background-image: url(icons/network.png); +} + +div.di_luci a { + background-image: url(icons/desktop.png); +} + +div.di_index a { + background-image: url(icons/overview.png); +} + +div.di_logout a { + background-image: url(icons/logout.png); +} + +div.di_freifunk a { + background-image: url(icons/freifunk.png); +} + +div.di_status a { + background-image: url(icons/status.png); +} + +div.di_system a { + background-image: url(icons/system.png); +} + +div.di_syslog a { + background-image: url(icons/shell.png); +} + +div.di_ntpc a { + background-image: url(icons/datetime.png); +} + +div.di_leds a { + background-image: url(icons/lightbulb.png); +} + +div.di_reboot a { + background-image: url(icons/restart.png); +} + +div.di_passwd a { + background-image: url(icons/login.png); +} + +div.di_statistics a { + background-image: url(icons/stats.png); +} + +div.di_packages a { + background-image: url(icons/package.png); +} + +div.di_sshkeys a { + background-image: url(icons/key.png); +} + +div.di_upgrade a { + background-image: url(icons/flash.png); +} + +div.di_services a { + background-image: url(icons/worker.png); +} + +div.di_backup a { + background-image: url(icons/switch.png); +} + +div.di_fstab a { + background-image: url(icons/harddisk.png); +} + +} \ No newline at end of file diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/header.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/header.png new file mode 100644 index 0000000000000000000000000000000000000000..5a7c9a10d99fa7b005f8ea3cec34fed279cf4d53 GIT binary patch literal 33244 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 W3tk86V&WM90000 + Copyright (C) 2007 Johann Ollivier Lapeyre + Copyright (C) 2007 Kenneth Wimer + Copyright (C) 2007 Nuno Fernades Pinheiro + Copyright (C) 2007 Riccardo Iaconelli + Copyright (C) 2007 David Miller + +and others + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library. If not, see . + +Clarification: + + The GNU Lesser General Public License or LGPL is written for + software libraries in the first place. We expressly want the LGPL to + be valid for this artwork library too. + + KDE Oxygen theme icons is a special kind of software library, it is an + artwork library, it's elements can be used in a Graphical User Interface, or + GUI. + + Source code, for this library means: + - where they exist, SVG; + - otherwise, if applicable, the multi-layered formats xcf or psd, or + otherwise png. + + The LGPL in some sections obliges you to make the files carry + notices. With images this is in some cases impossible or hardly useful. + + With this library a notice is placed at a prominent place in the directory + containing the elements. You may follow this practice. + + The exception in section 5 of the GNU Lesser General Public License covers + the use of elements of this art library in a GUI. + + kde-artists [at] kde.org diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/datetime.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/datetime.png new file mode 100644 index 0000000000000000000000000000000000000000..641653c07025465c8b090a2eff56f1557a26e88c GIT binary patch literal 5250 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 IM6N<$g51#QkpKVy literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/default.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/default.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe97ae308fdf6b431eb3e92eb95851589a9df07 GIT binary patch literal 5022 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 oEsqiaLPi}MG{G#OQ4v=$ ztez1BBdaK|3WnVU1PMzN5g3p-43l$D=TKdBKVR2Ob<+Zu@SmmZuivXzkLvgRzWm;3 z!$0|T3;^I50LK702EZ`@jsb8CfT`~;eLHOT+)!TCh;SqZNs>qqtxS?kl4S|vKiRw& zeTXrLxe(((x@8aME&FB%Mn_|aFMf+gCz7N7-6HEgm2Pc{jP9j{ z7(SreiW|qAd){FISiQU9Dz&hX9H@{yYI=Pp>E;}3)lwD{NRe{pSkKLlIb@h)7V~K` zM?~LhEs!j5V1mPs`BM_VWOmbN8w&f94viDG?mU2PYd8JN=@i~ z-CTx1Q%m|e%yk|P0K>F9vX4SF1zV^N%}q^6c{)ML?`|=7C`NPn74I@~!7#^+9Bs&9 z7?!$oak=-oK%l9n4i(#WBAG~9f+9&ri~@$9RwDqvJkG%8Zw{b--xhd0UPK1}I$QGD z*P($xwsu&Iw=Di# z0YAgfhn|KcUnwO|5rd!41f)WlN7Jv@V$x8sB z$RH;CGEp?epW_(KfS>&+_c|!_Sp$MWi43M&e&lp3DW*AOdwxY?SBpW_f~eTM1vNDd zFp?3-dIB<1pe;Z$G^Dg7BrO3g#rs%3^rrg517P!%K(>1TUBee^ci_Yl2V8CsHtwyp zR8&G%Jj@M$)+MB8N=me3jLZtgEGFeFGvJ3(Wvj)JiU*-5V`MJMCB@k%k)aqF(}F>i zZ7M@7krMAwWE&g~J7m=b$y9wPI+-GA1i;~ehWKFt;QR;_TOp-x$M@)q9gR99q_aK6 zWdN{3Qx=o$EeVjVzR6q`CM1U{2?=TOs34sTk~zVwo=PGVi^CA_v6-r_nE%oRI|bBG zRf+xkn*e($Y-)Nv4!aB&0Z?SgRQnV(GOim*nhmwVPyj_eJOGiVJ+RAu&a?A(Ns3Bx zKvwJk5jLeK`n<_ZaZL?Lu}QGexBv|x8DvP1o?@GTO){X#ln^8&IVG;?TwFVoZh+5Z zw`BTS$<*K{IS1!t&t& zkR-JThLR7B_Kp-^o`~W25(E2d8$k{_$jH_LOZ8242Tau#U@7hPOmah^lvJlfXo#xo zv`wmXT!WsI1hwA-D(Cv^8nAoU0W-X1CuNGlciC-}KFG8kqt8DLBYr**1^M|A(d0FoplM*}EXlNm)Ue((uyjJ?Q*w?1*8qJffyVI@>%jJ3RhFcz^U zw(TT#lzWVBqOb~LNpyKjCr>fpI66n!| z>Zpft%P2c`>{T#lMZ{z`gDaD1(H@-gcR+@;YHCq9I1&lD;i49>suW>Na)Nb80?DKm z-zii?{C<>C>YApRQs;W?KR7xE$w_%RMMdhSqbqPHaP1`naN>#mVdosxrotuwkkQ!K zh)tWm#p1<(-@kF=MmGTaj{<_rb?Y*5iv!mC)56fN;WTSH(>vMktVc zGGZsQ4&js9QFcgiB!dmmqfL+zM$dl5IO)W(f_aDCAzFpt{^_Mxu;|NWD6eWo&7O6S z8hUa=JM%dJ#A7L;0=7sPc1`80`Sn;%WB^>D=-kZ5g!77am*h0z?2 z5GW_fA+!*-5~x1m1*ky^Y;p`I_3vf=tN@KbrxTz+1n}mU65t}(i+EHz?+wciBtcK*0>iM zHOsE};45@Mb;VKN+=jMbj2dR;_w5%|oGPD(V$$&iaghbq*EgV;bqk+ydK!Qm#tg$V zGd`pF_<`Ua8Gzd3xbAtk-+ue(Z#RAW)%^Jjsygz34h_JM0+5ycYpMF=+gtgzPKMg`C-UOii!gl0I1E@fRvSJq#5`zFONe%7hNecLhvIA%~3rCD6qTGT&d#m*B0S- z*TrZ)DhBlLhqs@)4Yxl!8|95*A%yN-OHfeU8SeZ}XbL9bj~GbOG~A3zUZWL0y$+H6 zwP!}2Hkr+o_+T#W@$-W`L7qFM~`lJ z=b1Zk#}n_NJnVx%u}GL zv$1XaE<|?5QOvP?suypCtj{&rh^xP<50)R9CBy=zg2ITnIA~`@D=AV-A$m4p)wR|753e)XEA3N(#awLWg z8-|4oKSxzn4O)KyAQVI-5`mMxW9QDD@x_Z5zaERl$^b;NqJYB9Puc0|ka#BhfGn7X zAhg%=Y!s7Z!0dBe%+aXc4UGXPtOgw#7fq=p8A3H?h4GLdkyt9d{~#A&=7Kc{L{oU^ z_qPfVUYvR#CO`Ks*6a#$Tw{_X!Q(3wPEgZ6iEj@in3F^y+1XM%zXHG>Qj}z50nk>y3Q3<2 zK)NzxJQa(RfUFW#Co&?`2#XMV1g7*=jJ zR@tk=>-FFtJ9pv1C;o)#kKIS9y78N)|a8SC5BMK4#`;r4KyKNKH~W1bHHB>ApWD}u)P=9Nz?G+(+?w$0vUhRFOY}^P+r-9iPv9>J-c_|jTx_tbhlG+XZnCX zSh;cq=6|sgO<|`<<*6=afzv4R4VxuKbF+nP-Ge`rGSJ-6 zf=D>ZAupYqWNm4iN9SxakHD=2(_%c$yks(;?-Hib;%_07ny3JK9aoAs-+U7jCQM*P z*IR&~Q>t{tbbLFpcJ(53F1Ep4NT*GWQ`7)_UPd3k6U}WZ;<_w;Qa1~!!verK2t#%W zCXMWR!0HppNGM9?n?;c#nR6uzYO6}hNTgs5nO_$3c`g-&K8Cks3_-^ESS$i95y5Ta z&cm-RJ_pag@H}q3X*_1mn8~m=0P$EHRn^s)J$n{BP6ZB@(yA&!k#rQ=Qw*0HioFq3 zP#{&UZbXxc`L_e9BOZ*HnV_}Jm67radum~r2?fGdPJryX!Qx*Mt&qKx34#TeA|$UO z-%It4N2%5UBw|r<$Z_xZi!kcKbMW%ZFQdAq3azcp7<>6xeE8v93}%YUY!Fvpa~)>S znTH228;*F*3jC!kL`P0A;Dgs0#Bs%8(1ZzshZ>+9Q3FhrNVydsQBR9obX9X_{1FdYh!`9w@qcMsh;8fTwzDyC1LjssQu5sgHd#gnxTB!D4xcyKE_JgAS%es--u`(;?P!Rv7l6dmDk z2tF5JBxL;d+R@zI>5XaAoX_l3d(H@q88Zg&e7F#|-ZKTSKKlqRJMC+z z_QkCFPC{vEXPlla$A)+}csh53torDuBx+U|#f?#vl^Y_XjMpClfRbV#B@%-tubW6O zEB5U~<(AKYOb?!0AzDmkJb>_o9S5JC8s97=qyd)tb0&|`qFtBx~jSL3CHUBnzkbqGzo zVB{dwSMG!oKf=+N>?{G@B<#EBEZ0tWBD_pUJ05d(npjt4@NrY%b1nA{!k$iT>xur;kIs=f_J^XkuH=B>Bh65;K! z$EJY#z1rI#%0KWO=8@&Gd>wI9k_` zAww{0)-3Sgf_eQjP;3$!>KjpCSI^wuhesZH1Qit(EO?${Xv~)0%w@pZy)w@3uj9H= zKtDU+QwRe2)Ke+}JqLY?zQVhA0gHav1gY^?CtJ1=DuhW!4giLh)LN_e%!oJbIU(BC zpjK~qM_Qt3!e&)fwJi9*bs0yRpk8#*MMKHh09J9LjdPXLsiTyr_9DxBa_SVg-ERG*mtXy$sV)AOE`3ffcewIm z?SDu?61iLQ&$Tg-;oyxqwJKmiA_9rXXZT&c}+n^mv z=f2^TY%>l%Jq8=um6R2IM_}HD@PaFb#V@ugP`xEUBDflPy#mk*u11kO7xJ*US5ff( zD=KcC_zo5Th-L2w@U^n6#0^6nRAy~$8${mATHD|3XQ~=Lh-vv?=5v4{_lP&|c0Tso zUtK+N#M$@Gn?Jvrd-Ba=$Byay!2N&l+_*4p;`FeKQIL_>v&R zTwLPp857{XZ8qirh-Pew$-1P-F)IPG0BBd|;x3)JBa@G&`eq~(NvmYGw#ssu=b#p< zQ#^@^(ovUOa1Re6Hazm^W3TgB_^V~h2fp;;3-@1g$t8}Gk`fFbJ{(JyEZz9(8#7<# zN%bbRpjQibk#sU_rPUqlF*;79WxJ0BsCWO|4Q=m+W4iu3MZa<22&jyFsM}DE($ga_ zyu;zcYVL7W5tdZa}+lA*XHXI6dfeMR&olEZ07_g>x5P}?Yq zq72*5EuKh*#x%Elnf>3c8PlI?-+AlSE&oX=e#LhNYinyNs;a6k9X)#VX@xwxTD5A` z_kVo)k55r!*75fn2|`MMnO#GeX|`2bioXj|)CAxA-J;D#f(jhDU&HOE^6W(mfgscq zggA81Dag~efgmVk>ABDDhx4-Ocu@clu3mzz)k_Qv-9a4z2W7RIqo$?{#|B=G)hh2a?n+()$h@k7x3c#HY zwYe3osZ=8X*G~aJiqtS~-n?1k#*KUMth3HqvT)(T2)C;}TefT|f8m7}rZM|l4ho8t z#Q*IwNDK)5GuHT7^#@nuGY`8Xg#W20D9OM7c^g<}ATS z&n&<~0RE#7fVH4qUw{4e91^7s)jXQ2GTX#a_{|t;-|l)Wdgueh?rp=(%(>*xH{)-g ztQXAhBE_gIm0kb<002ovPDHLkV1ix{C~5!z literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/flash.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/flash.png new file mode 100644 index 0000000000000000000000000000000000000000..7e9dc7861d1158a272920e0ca5c5e9bf0bcf969a GIT binary patch literal 5065 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/key.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/key.png new file mode 100644 index 0000000000000000000000000000000000000000..1ebfaa43a42d4834cdcbde4716e37c09a55e8126 GIT binary patch literal 4129 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/lightbulb.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/lightbulb.png new file mode 100644 index 0000000000000000000000000000000000000000..3a6755bc3c404c33fa5980c62865ae5f3f4b1134 GIT binary patch literal 5550 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/login.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/login.png new file mode 100644 index 0000000000000000000000000000000000000000..8e881ba3b391eb6460206e8694a24325ef3a769d GIT binary patch literal 2918 zcmV-s3z_tZP))5xvchtv{H}~@jpa)oD!r+k>J1~mnc%CNL+FuLP>J~KS#}*xjscte(Jq-})p{7*C1VZ%c z=WHDSAOJYQ5LF{F7m6_eJ%5q_ZrBUkE*R}Xw&^;N76T2I=2MOB^z|4b`gK?`0EAp? z05Q&)V#w5A5kla55O^&JgAO%F!d^-$z+P=F{;ExbWwDUgbD}*AnZ0)G6&HWc?Et5omNXm zTm90iLJRUdjCHTzv?vmA z0=`=GmEx zcmN|KBas(S1R%`tT-_J#NoXhB@F5`^5K_r9I8hyx8zh}HB;eSwWAOO#V+?c#!Sg(t z95F*jQ}WvLq~YOV0zpXtfkGs(tfNxOeIX)PG&brxGc!YFl8D%}elnoFe*n5G<9d_;C zL(2xxY7-@$I>>mn%^{T%^2CRMT5W5m${;Z}NULBTS_mce=E2C$c>xar$c6w87vKmS zSuu@d#sx|)69Ayn1Yk`LX%{=Yj7a%k9du~X)Dl21RSq9M9K9g<%*XAd0=IA9hJk?r z6$(3QVM~0{jr3hO@_yAD4!(R~j81 zjco+y=jW9d$VB@As%fSrX~roBkx(csxX^>(zkrd>bG;EE74QT!J#Kn|erI>Fy#YN- z8^Mh90ulr{yk!Gan_%*K5}P5%wgGCuZW|z7lK?Xiid5j4;@@huVnu%RtmwH|mBh&g zfMo+{Zl*CzKmzo!k{noOnsJS~1W6b+;O5Pnl9Em|2A32~uS+^rIYAp>i?Ln>!}6*+ z7iS+F-{4kyJQ|sXz=tNke*QFZ}FpEeKl`5IpF9&7~)b$$Uj-w^?=7kGUyG z4;CS}cQ3Z35CGK|gy9A)8^E_&1#};pU>Z_`d%;N$f(U&ON;lMH`}LP9>uc6qWJOGa z;xJtO0dO<;e3q6ThjF3L|CnV1k}`r2TLN5Q=^U_B=Gm_+ET*;2(nX7DO>{+zHn~;m zVA+7pt~sIIAkz{MPZF3L=ashoR!6@@?z+aJ&N?X%z?fkJnB|%w={O+yq&qHh}aN-x3GCvqhjm)yH|kG>In1^_QWx^?Ro0YG~Td3bvA z1xP;+j*X2;#`F0+k^D5bTrSheuavyy00#cqaRv--+A0PiZi9Mb0T0oH4 z(`W7UGKG%74xc}N{+npj9^k!I>{~?_S37s^Tno04wrm8iUcEYkD>RLhn#M`JhWAcm zGZE=*5viakPdwS@f28BYxYB=V3&4!| zq-GQKI|v{MLZkrOYjESn4e732B$*>10Yz=pCk!wTVE_L8Ff}!W>VSP*7bPZ*YVicL zVFZTM#7YRF50BS3B&~0hF*c~Jw>|IYAH4tV9|1r}guL>8DnJZVn@R4KD_1`CJnsXq z)&ADco(e>+p{?GFAVx1W6L2aZBl7wCWxE27eEfIZlMHuX4 zP?rY_g;K6qD&$av2k~uj7F}VcSS)47#$Fj2du43AhKwyOFRxb1y3g*acu0fR{G?7w&>pTMh37 Qz5oCK07*qoM6N<$f<{9 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/logout.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..9f44fd0ef916610a15efbdf654beecced4e429ca GIT binary patch literal 3577 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/network.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/network.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8033452536c47cc213b637991c5847df7a9abf GIT binary patch literal 6602 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 IM6N<$g0J|yl>h($ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/overview.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..0f3edc162668a0943be97cd0ef27e7c020660950 GIT binary patch literal 4553 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/services.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/services.png new file mode 100644 index 0000000000000000000000000000000000000000..54e17dd09f1f2dee8d619edcbd8326390852ac57 GIT binary patch literal 4630 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 M07*qoM6N<$f}0eNO#lD@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/shell.png b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/icons/shell.png new file mode 100644 index 0000000000000000000000000000000000000000..8e2f3c17f81528ba01f5e9691bd00e2d3fba3ebf GIT binary patch literal 2110 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 M07*qoM6N<$f}0eNO#lD@ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie6.css b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie6.css new file mode 100644 index 0000000..1c95185 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie6.css @@ -0,0 +1,77 @@ +/* obligatory IE6 Voodoo Code */ + +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div#menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html ul.dropdowns li ul { + width: 10em; +} + +* html ul.dropdowns li li { + clear: both; + float: left; +} + +* html ul.dropdowns li li { + width: 100%; +} + +* html ul.dropdowns li li a { + height: 1%; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.cbi-value-description { + width: auto !important; +} + +* html div.cbi-value-field { + margin-left: 0 !important; + width: 100% !important; +} + +* html .cbi-input-text, +* html .cbi-input-user, +* html .cbi-input-select, +* html .cbi-input-password { + width: 50% !important; +} + +* html .cbi-input-user, +* html .cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; +} + +* html .cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +* html table.cbi-section-table td .cbi-input-text, +* html table.cbi-section-table td .cbi-input-select { + width: 100% !important; +} + +* html div.cbi-page-actions { + text-align: right !important; +} + +* html div.cbi-value-field input, +* html div.cbi-value-field select { + font-size: 90% !important; +} diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie7.css b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie7.css new file mode 100644 index 0000000..67ed9fb --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/htdocs/luci-static/openwrt.org-oxygen/ie7.css @@ -0,0 +1,20 @@ +div.cbi-value-field { + margin-left: 0 !important; +} + +.cbi-section legend { + background-color: #ffffff; + color: #555555; +} + +table.cbi-section-table td .cbi-input-text, +table.cbi-section-table td .cbi-input-select { + width: 95% !important; +} + +.cbi-input-user, +.cbi-input-password { + text-indent: 0 !important; + padding-left: 1.5em !important; + width: 18.5em !important; +} diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/ipkg/postinst b/openwrt/packages/luci/themes/openwrt.org-oxygen/ipkg/postinst new file mode 100755 index 0000000..e2a497b --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-theme-openwrt-oxygen ) && rm -f /etc/uci-defaults/luci-theme-openwrt-oxygen +} diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/dashboard.htm b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/dashboard.htm new file mode 100644 index 0000000..1e05575 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/dashboard.htm @@ -0,0 +1,46 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<% + local node = luci.dispatcher.context.requested + if node.nodes then +%> + +
+<% +end +%> \ No newline at end of file diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/footer.htm b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/footer.htm new file mode 100644 index 0000000..8df68b1 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/footer.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +
+
+ +

Powered by <%= luci.__appname__ .. " (v" .. luci.__version__ .. ")" %>

+ + + diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/header.htm b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/header.htm new file mode 100644 index 0000000..fe18214 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/header.htm @@ -0,0 +1,166 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local disp = node +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + + + +<% if node and node.css then %> +<% end -%> + + + +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + + + +
+<% if disp and disp.subindex then %><%+themes/openwrt.org-oxygen/dashboard%><% end %> diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/indexer.htm b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/indexer.htm new file mode 100644 index 0000000..8ba29e0 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/luasrc/view/themes/openwrt.org-oxygen/indexer.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<%+header%> +<%+themes/openwrt.org-oxygen/dashboard%> +<%+footer%> diff --git a/openwrt/packages/luci/themes/openwrt.org-oxygen/root/etc/uci-defaults/luci-theme-openwrt-oxygen b/openwrt/packages/luci/themes/openwrt.org-oxygen/root/etc/uci-defaults/luci-theme-openwrt-oxygen new file mode 100755 index 0000000..6fc593f --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org-oxygen/root/etc/uci-defaults/luci-theme-openwrt-oxygen @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.themes.OpenWrtOxygen=/luci-static/openwrt.org-oxygen + commit luci +EOF + diff --git a/openwrt/packages/luci/themes/openwrt.org/Makefile b/openwrt/packages/luci/themes/openwrt.org/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/bg.jpg b/openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dece957dfd82acae201397ebb04f7b3be93a5fd8 GIT binary patch literal 40537 zcmeFZc{r49|36Np&GyV~7o(a=qNE`^X|dgwJIa=b2}!bNiP5bh>yXM$i%2F*D>V^= zDaKy3C}t)kg)w9s{Lb^5QQgny`5wRHa~$8}_xtDRzRh)A=kk8P-mmv^o-=b@v-ozg zkLO>eh9-tQyu7?T#^67m#Sc9Dc$P0)2LA{DR)GKcR`c<#Si!e;)vA@N1=b1(@UP|P z7Zm#AUxGp?A%6aUiT?{FA}S^(CLk;!DK0Achp3n+6vDe4%vr&=hL3NJs35PiP z;tL+s>ScDTmo4Yr$g>Q^yBx*4SjQvF!^^WA{?E&^^pAJh@)avrt>#+;x}E>U%d?DU z#flZnmapO$;$Owb%ftJ}vgIg|6?_L>R<7D$pyGGq{sU3*jen<=fJs27-1q@E_+49$?FV z{`Y_E_~-EDCaTVR4y#JE@u{XBXy!E++#JCxs_H1V4_p`o?6KZ=U_zBoP@=6(w8LCN zHJNj*nrh;_5A>Nh?-6ZlkKp;M-Isfe5afk3_Z@g)Z6X1rNvQIvB1a$qj1)u^@K~Gk zK~+#H@~6tjH^FPZ2}lAm9Z?1W28TKhfEHv#TZgSG%3M`~?=RSIqU!il5)ixz!GQor zt{@(W#TVGnCaQ|`n%nXkaPR?4z)qyq0Ahh!fx(-A#12~shGQUv0!=r8syGUuIlvTE zM?O`=41^Y7+0o7XUrwx*-mxr`|I4!I%T?zTu2<$qWg1srSGaL=R(e^cF>I=eK35Pm z%To|FaIPRa{)^}O8#ntv>p6v+fma_wh9Em!M)&Rc3#tWpP>>NpXf}X~kOSZ&T`T@_ z-e+)#V;x``u?29&C-}=W!Oe*C0L=(R+#x_$Ds(6x_)}HAickz_0HdI%pa@_h#9{(m z2zp_UNInr*sGOgs2lmEH?BkTlvMLY zFBD59D)6n(cL(QD2@O}GQreL7i$7bEE^gRL^)y!CH-@ikkXJs8%I)>}qHuijL*&&8 zD{ZxQ@4@trWGivdkkro+d4VG)1-7p>#F-ixkHC@ISCTFwBDO>A8x)XNPw*<+XaGhT z?M=P{0dYWFxCNC3J0R0dp&kPc2+nwT{>5r7(vA#)1C9KX5iEZonzclKNkfcG=74~b zF*l4y9wOEwLpc+~Ie?)|BY#f&Z?+zU*8K5X0|zVuGjQu~EJ1*4p+N@5NV9C$PaP>e z`P&f&I3)fuHxO{}@0Q9oLL_@TICv1n2nNU~u=L8W7RY@RhrFbVhH+7 zOF{D+a1I&=#7<5uA=Yvu>L+a=x_&$V&FP2_gB3WI1akuF7aDFPMS-~>zBePpLlb3d zQ(SJF-X}I(-6k+0edrE$>95Vx>N@rJzxLav=XFN0?TKmiAzJJ*)K+`&vJn$v|eBak6%@Rtd@fBjh{08j^W&zoKaamF3n!JRJb1VY{Lom6~OCSK>KLJ1smnN8E0W(}y zfkF;nfadmsWDfHGAOJxRhARGhEad-AX$@CjDV1-+^g~4FlO9ot{9wag-$TwmmBxI0 zKju=Scn!ip?Laydq?biaL?y4~?|hxVEQ%S0deS2%kuQ4gFDG9EWU6RV-}UF~LEi)@ zoIsQaoNZwI8k`0x@LYe6*$XCjXlF�HIdk{QH!GEIfw_#6OH=f|-eH_iR-*mS1r; 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/cascade.css b/openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/cascade.css new file mode 100644 index 0000000..90081a6 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/cascade.css @@ -0,0 +1,804 @@ +@charset "utf-8"; + +@media all { + +html { + min-height: 100%; + height: auto; +} + +body { + color: #ffffff; + background-color: #4a6b7c; + background-image: url(bg.jpg); + background-position: bottom center; + background-repeat: repeat-x; + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; + padding-bottom: 1.5em; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + min-height: 98px; + background-image: url(header.png); + background-repeat: no-repeat; + background-position: left center; + background-color: #557788; + color: #ffffff; + text-align: right; +} + +#header h1 { + padding: 1em 1em 0 1em; +} + +#header p { + padding: 0 1em 1em 1em; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +ul.dropdowns { + float: left; + margin: 0; + padding: 0; + width: auto; + list-style: none; +} + +html>body ul.dropdowns { + position: relative; +} + +ul.dropdowns li, +ul.dropdowns ul { + margin: 0; + padding: 0; + list-style: none; +} + +ul.dropdowns li { + float: left; + position: relative; + white-space: nowrap; +} + +ul.dropdowns li ul { + position: absolute; + z-index: 1000; + top: auto; + min-width: 10em; +} + +ul.dropdowns li li { + float: none; + position: relative; +} + +ul.dropdowns li a { + display: block; +} + +ul.dropdowns ul li ul { + top: 0; +} + +ul.dropdowns li ul, +ul.dropdowns li.over ul ul, +ul.dropdowns li.focus ul ul, +ul.dropdowns li:hover ul ul, +ul.dropdowns li.over ul ul ul, +ul.dropdowns li.focus ul ul ul, +ul.dropdowns li:hover ul ul ul, +ul.dropdowns li.over ul ul ul ul, +ul.dropdowns li.focus ul ul ul ul, +ul.dropdowns li:hover ul ul ul ul { + left: -3000px; +} + +ul.dropdowns li.over ul, +ul.dropdowns li.focus ul, +ul.dropdowns li:hover ul { + left: 0; +} + +ul.dropdowns ul li.over ul, +ul.dropdowns ul li.focus ul, +ul.dropdowns ul li:hover ul, +ul.dropdowns ul ul li.over ul, +ul.dropdowns ul ul li.focus ul, +ul.dropdowns ul ul li:hover ul, +ul.dropdowns ul ul ul li.over ul, +ul.dropdowns ul ul ul li.focus ul, +ul.dropdowns ul ul ul li:hover ul { + left: 100%; +} + +#menubar { + position: relative; + width: 100%; + background: #000000; + color: #ffffff; +} + +#menubar .warning { + color: red; + background-color: #557788; +} + +#menubar ul.dropdowns { + min-height: 1.8em; + background: #000000; + color: #ffffff; +} + +#menubar ul.dropdowns li ul { + background: #000000; + color: #ffffff; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; +} + +#menubar ul.dropdowns ul li ul { + border-width: 1px; +} + +html #menubar a:link, +html #menubar a:visited { + position: relative; + display: block; + padding: 0.5em; + background: #000000; + color: #ffffff; + text-decoration: none; + font-size: 80%; + font-weight: normal; +} + + +html #menubar a:link:hover, +html #menubar a:visited:hover, +html #menubar a:link:active, +html #menubar a:visited:active, +#menubar a:link:focus, +#menubar a:visited:focus { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.active, +html #menubar a:visited.active, +html #menubar a:link.preactive, +html #menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html #menubar a:link.warning, +html #menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +#menubar ul.dropdowns li.over>a, +#menubar ul.dropdowns li.focus>a, +#menubar ul.dropdowns li:hover>a { + font-weight: bold; +} + +.lang_de #submenu_mini_system { min-width: 13.3em; } +* html .lang_de #submenu_mini_system { width: 13.3em; } + +.lang_pt-br #submenu_mini_network { min-width: 14em; } +* html .lang_pt-br #submenu_mini_network { width: 14em; } + +.lang_pt-br #submenu_mini_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_mini_system { width: 11.5em; } + +.lang_ru #submenu_mini_system { min-width: 18em; } +* html .lang_ru #submenu_mini_system { width: 18em; } + +.lang_pt-br #submenu_admin_index { min-width: 11em; } +* html .lang_pt-br #submenu_admin_index { width: 11em; } + +.lang_ru #submenu_admin_index { min-width: 15.5em; } +* html .lang_ru #submenu_admin_index { width: 15.5em; } + +.lang_ru #submenu_admin_status { min-width: 10.5em; } +* html .lang_ru #submenu_admin_status { width: 10.5em; } + +.lang_de #submenu_admin_system { min-width: 13.3em; } +* html .lang_de #submenu_admin_system { width: 13.3em; } + +.lang_fr #submenu_admin_system { min-width: 14.5em; } +* html .lang_fr #submenu_admin_system { width: 14.5em; } + +.lang_pt-br #submenu_admin_system { min-width: 11.5em; } +* html .lang_pt-br #submenu_admin_system { width: 11.5em; } + +.lang_ru #submenu_admin_system { min-width: 18em; } +* html .lang_ru #submenu_admin_system { width: 18em; } + +#submenu_admin_services_chillispot { min-width: 15.5em; } +* html #submenu_admin_services_chillispot { width: 15.5em; } + +#submenu_admin_services_coovachilli { min-width: 15em; } +* html #submenu_admin_services_coovachilli { width: 15em; } + +.lang_ru #submenu_admin_network_routes { min-width: 15.3em; } +* html .lang_ru #submenu_admin_network_routes { width: 15.3em; } + +#submenu_admin_network_firewall { min-width: 14em; } +* html #submenu_admin_network_firewall { width: 14em; } + +.lang_de #submenu_admin_network_firewall { min-width: 16.5em; } +* html .lang_de #submenu_admin_network_firewall { width: 16.5em; } + +.lang_pt-br #submenu_admin_network_firewall { min-width: 15em; } +* html .lang_pt-br #submenu_admin_network_firewall { width: 15em; } + +#modemenu { + width: auto; + background: #000000; + color: #ffffff; + list-style: none; + margin-right: 1px; +} + +#modemenu li { + float: right; + list-style: none; +} + +#savemenu { + float: right; + margin-right: 2em; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + color: #000000; + border-width: 0 1px 1px 1px; + border-style: solid; + border-color: #444444; + font-size: 80%; +} + +#maincontent h2 { + font-size: 150%; + font-family: Trebuchet MS, Verdana, sans-serif; + font-weight: bold; + margin: 0.25em 0 0.7em 0; + border-bottom: 1px solid; + padding-top: 10px; + padding-bottom: 4px; +} + +#maincontent h3 { + margin: 0.5em 0 1.1em 0; + font-size: 125%; + font-weight: bold; + font-style: italic; + font-family: Trebuchet MS, Verdana, sans-serif; + color: #27408B; +} + +#maincontent p { + margin-bottom: 1em; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + text-decoration: none !important; + font-weight: bold !important; + color: #555555 !important; + margin: 0.25em !important; + font-size: 100% !important; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + text-indent: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table td, +table th { + color: #000000; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { + color: #000000; +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; + line-height: 1.8em; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; + vertical-align: top; +} + +div.cbi-tblsection-create { + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-create .cbi-button { + margin: 0.25em; +} + +input.cbi-section-create-name { + margin-right: -0.25em; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #666666; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + +} diff --git a/openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/header.png b/openwrt/packages/luci/themes/openwrt.org/htdocs/luci-static/openwrt.org/header.png new file mode 100644 index 0000000000000000000000000000000000000000..5a7c9a10d99fa7b005f8ea3cec34fed279cf4d53 GIT binary patch literal 33244 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 W3tk86V&WM90000 +Copyright 2008 Jo-Philipp Wich + +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: footer.htm 4185 2009-01-30 14:00:35Z jow $ + +-%> +
+
+ +

Powered by <%= luci.__appname__ .. " (v" .. luci.__version__ .. ")" %>

+ + + diff --git a/openwrt/packages/luci/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm b/openwrt/packages/luci/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm new file mode 100644 index 0000000..657d5e8 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm @@ -0,0 +1,163 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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: header.htm 4079 2009-01-17 17:59:11Z Cyrus $ + +-%> +<% +require("luci.sys") +local load1, load5, load15 = luci.sys.loadavg() +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched +local hostname = luci.sys.hostname() + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + + +<% if node and node.css then %> +<% end -%> + + + +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + + + + + + + +
diff --git a/openwrt/packages/luci/themes/openwrt.org/root/etc/uci-defaults/luci-theme-openwrt b/openwrt/packages/luci/themes/openwrt.org/root/etc/uci-defaults/luci-theme-openwrt new file mode 100755 index 0000000..d8dea04 --- /dev/null +++ b/openwrt/packages/luci/themes/openwrt.org/root/etc/uci-defaults/luci-theme-openwrt @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.themes.OpenWrt=/luci-static/openwrt.org + commit luci +EOF + diff --git a/openwrt/packages/luci/themes/oxygen/Makefile b/openwrt/packages/luci/themes/oxygen/Makefile new file mode 100644 index 0000000..81a96f6 --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/Makefile @@ -0,0 +1,2 @@ +include ../../build/config.mk +include ../../build/module.mk \ No newline at end of file diff --git a/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/cascade.css b/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/cascade.css new file mode 100644 index 0000000..c1b19f7 --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/cascade.css @@ -0,0 +1,660 @@ +@charset "utf-8"; + +@media all { + +html, body { + height: 100%; +} + +body { + font-family: Verdana, Arial, sans-serif; + font-size: 101%; + line-height: 100%; + background: #dddddd; +} + +div#screen { + min-height: 100%; +} + +* { + margin: 0; + padding: 0; +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.warning { + color: red; + background-color: white; + font-weight: bold; +} + +.clear { + clear: both; +} + +.skiplink, +.navigation, +.hidden { + position: absolute; + left: -1000px; + top: -1000px; + width: 0px; + height: 0px; + overflow: hidden; + display: inline; +} + +.error { + color: #ff0000; + background-color: white; +} + +#header { + min-height: 98px; + background-image: url(flukso.png); + background-repeat: no-repeat; + background-position: 12% center; + background-color: #dddddd; + color: #ffffff; + text-align: right; +} + +#header h1 { + padding: 1em 1em 0 1em; +} + +#header p { + padding: 0 1em 1em 1em; +} + +#header h1, +#header p { + font-size: 70%; + font-weight: normal; + line-height: 160%; + text-align: right; +} + +.menubar { + background: #000000; + background: rgba(100, 100, 100, 0.8); + color: #ffffff; + width: 80%; + font-size: 0.8em; + + margin: 0.5em auto; + + padding: 0.4em; + padding-left: 0.5em; + padding-right: 0.5em; + + border-radius: 0.8em; + -khtml-border-radius: 0.8em; + -moz-border-radius: 0.8em; + -webkit-border-radius:0.8em; + -opera-border-radius: 0.8em; +} + +.menubar .warning { + color: red; + background-color: #557788; +} + +html .menubar a:link, +html .menubar a:visited { + color: #ffffff; + text-decoration: none; + font-weight: bold; +} + +html .menubar a.menulink { + margin-left: 1em; +} + + +html .menubar a:link:hover, +html .menubar a:visited:hover, +html .menubar a:link:active, +html .menubar a:visited:active, +.menubar a:link:focus, +.menubar a:visited:focus { +} + +html .menubar a:link.active, +html .menubar a:visited.active, +html .menubar a:link.preactive, +html .menubar a:visited.preactive { + background: #000000; + color: #ffff00; + font-weight: bold; +} + +html .menubar a:link.warning, +html .menubar a:visited.warning { + background: #000000; + color: red; + font-weight: bold; +} + +.lang_de #submenu_admin_uci { + width: 12em; +} + +.lang_ru #submenu_admin_uci { + width: 11.5em; +} + +#maincontent { + clear: both; + width: 80%; + margin: 0 auto; + padding: 0.5em; + background: #f5f5f5; + background: rgba(245, 245, 245, 0.9); + color: #000000; + border-width: 1px solid #444444; + font-size: 80%; + + border-radius: 1em; + -khtml-border-radius: 1em; + -moz-border-radius: 1em; + -webkit-border-radius: 1em; + -opera-border-radius: 1em; +} + +#maincontent h2 { + margin: 0.25em 0 0.5em 0; + font-size: 150%; + font-weight: normal; +} + +#maincontent h3 { + margin: 0.5em 0; + font-size: 120%; + font-weight: normal; + text-decoration: underline; +} + +#maincontent p { + margin-bottom: 1em; +} + +textarea#syslog { + width: 98%; + min-height: 500px; + border: 3px solid #cccccc; + padding: 5px; + font-family: monospace; +} + +.cbi-section { + margin-bottom: 0.5em; + padding: 0.5em 1em; + border: 1px dotted #555555; + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #000000; +} + +.cbi-section legend { + font-size: 110%; + font-weight: bold; + height: 1em; + padding: 0 0.25em; + background-color: transparent; + color: #555555; +} + +*+html .cbi-section legend { + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #555555; +} + +* html .cbi-section legend { + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #555555; +} + +.cbi-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.cbi-section h3 { + height: 1.5em; + font-size: 90%; + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.8); + color: #555555; +} + +.cbi-section-descr { + margin-bottom: 0.5em; + font-size: 95%; +} + +.cbi-title-ref { + color: inherit; + text-decoration: none; + padding-right: 18px; + background: url('../resources/cbi/link.gif') no-repeat scroll right center; + background-color: inherit; +} + +ul.cbi-apply { + font-size: 90%; +} + +input[type=submit], +input[type=reset], +input[type=image] { + cursor: pointer; +} + + +select, +input, +textarea { + background: #eeeeee; + color: #000000; + border-width: 1px; + border-color: #000000; +} + +input[type=image] { + border: none; +} + +input:focus, +input:hover, +select:focus, +select:hover, +textarea:focus, +textarea:hover { + background-color: #ffffff; + color: #000000; +} + +select, +input[type=text], +input[type=password] { + width: 20em; +} + +td select, +td input[type=text], +td input[type=password] { + width: 99%; +} + +input.cbi-input-user { + background: url('../resources/cbi/user.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-password { + background: url('../resources/cbi/key.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-find { + background: url('../resources/cbi/find.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-reload { + background: url('../resources/cbi/reload.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; +} + +input.cbi-input-add, +input.cbi-button-add { + background: url('../resources/cbi/add.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-fieldadd, +input.cbi-button-fieldadd { + background: url(../resources/cbi/fieldadd.gif) no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-reset, +input.cbi-button-reset { + background: url('../resources/cbi/reset.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-save, +input.cbi-button-save { + background: url('../resources/cbi/save.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-apply, +input.cbi-button-apply { + background: url('../resources/cbi/apply.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +input.cbi-input-remove, +div.cbi-section-remove input { + background: url('../resources/cbi/remove.gif') no-repeat scroll 1px center; + background-color: inherit; + color: #000000; + padding-left: 17px; + padding-right: 1px; +} + +div.cbi-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +form > div > input[type=submit], +form > div > input[type=reset] { + float: right; + margin-left: 0.5em; +} + +table.smalltext { + background: #f5f5f5; + color: #000000; + border-top: 1px solid #666666; + border-right: 1px solid #666666; + border-bottom: 1px solid #666666; + font-size: 90%; + width: 80%; + margin-left: auto; + margin-right: auto; + border-collapse: collapse; +} + +table.smalltext tr:hover td { + background-color: #bbddee; + color: #000000; +} + +table.smalltext tr th { + padding: 0 0.25em; + border-left: 1px solid #666666; + text-align: left; +} + +table.smalltext tr td { + padding: 0 0.25em; + border-top: 1px solid #666666; + border-left: 1px solid #666666; +} + +table.cbi-section-table .cbi-rowstyle-1, +table.cbi-section-table .cbi-rowstyle-1 * { + background-color: #eeeeff; + color: #000000; +} + +.cbi-section .cbi-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.cbi-rowstyle-2 { +} + +div.cbi-value { + clear: left; + vertical-align: middle; + padding-left: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-value:hover { + background: #f8f8f8; + color: #000000; +} + +.cbi-value-title { + float: left; + width: 40%; +} + +div.cbi-value-field { + width: 58%; + margin-left: 40%; + padding: 0.25em 0; +} + +div.cbi-value-description { + font-size: 90%; + display: inline; +} + +div.cbi-section-create { + clear: left; + white-space: nowrap; +} + +div.cbi-map-descr { + margin-bottom: 1em; +} + +div.cbi-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.cbi-section-remove { + float: right; +} + +.cbi-section-node { + clear: both; + border-top: 1px dotted #bbbbbb; + border-left: 1px dotted #bbbbbb; + border-right: 1px dotted #bbbbbb; + border-bottom: none; + padding-bottom: 0; +} + +.cbi-section-node table div { + padding-bottom: 0; + border-bottom: none; +} + +.cbi-section-node div.cbi-section-table-row { + margin: 0.25em; +} + +table.cbi-section-table { + width: 100%; + font-size: 95%; +} + +table.cbi-section-table th, +table.cbi-section-table td { + text-align: center; +} + +tr.cbi-section-table-descr th { + font-weight: normal; + font-size: 90%; +} + +td.cbi-section-table-optionals { + text-align: left !important; + padding-top: 1em; +} + +.cbi-value-helpicon img { + vertical-align: bottom; +} + +div.cbi-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +td.cbi-value-error { + border-color: red; +} + +.cbi-value-error input, +.cbi-value-error select { + color: red; + background-color: #ffcccc; +} + +.cbi-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.right { + text-align: right; +} + +.luci { + position: fixed; + bottom: 0; + left: 0; + text-align: right; + color: #ffffff; +} + +.luci a:link, +.luci a:visited { + background-color: transparent; + color: #ffffff; + text-decoration: none; + font-size: 70%; +} + +.inline { + display: inline; +} + +.error500 { + white-space: normal; + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +#memorybar { + width: 200px; + height: 8px; + border: 1px solid #bbb; + color: black; + background-color: red; +} + +#memfree, #membuffers, #memcached { + float: right; + border: 1px solid #bbb; + height: 6px; +} + +#memfree { + background-color: green; + color: black; +} + +#membuffers { + background-color: yellow; + color: black; +} + +#memcached { + background-color: #ffa500; + color: black; +} + + +/* obligatory IE6 Voodoo Code */ + +* html body { + padding-left: 50% !important; +} + +* html div#header { + margin-left: -100% !important; +} + +* html div.menubar { + margin-left: -100% !important; + width: 200% !important; +} + +* html div#maincontent { + margin-left: -80% !important; + width: 160% !important; +} + +* html div.cbi-value-description { + margin-left: 40%; +} + +} diff --git a/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/dashboard.css b/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/dashboard.css new file mode 100644 index 0000000..b8b3097 --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/dashboard.css @@ -0,0 +1,31 @@ +@charset "utf-8"; + +@media all { + +div.dashicon { + float: left; +} + +div.dashicon a { + background-image: url(icons/default.png); + background-repeat: no-repeat; + background-position: top; + display: block; + width: 70px; + padding-top: 70px; + color: #000000; + text-decoration: none; + text-align: center; + margin: 2em; + font-weight: bold; +} + +div.di_network a { + background-image: url(icons/network.png); +} + +div.di_wifi a { + background-image: url(icons/wifi.png); +} + +} diff --git a/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/flukso.png b/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/flukso.png new file mode 100644 index 0000000000000000000000000000000000000000..1e419fef373f2715647cb843f9296432406023fa GIT binary patch literal 1612 zcmV-S2DABzP)cdlMnjE&%zPrkr6y*L&_s3jru7Cu3tom!C*K7 zi-o~pu`n2F(e_{earTimwyWP6?r)`7d&}qX~P02^AG_!MSbm`VwU}8x>)j`>zuBu(`SLoa~4?UkxwyRT{_~r55)18zZ?4npl zOU>tnKg*QMY{b*m>wSVhNBqr!I;Hz2!I*_1$U6q zLq%D4=loKL-3@f-Pc}Rd+Fr;Nz))L6|rkBl> z528^8^j!``8ip``(8$G2$KU`b&D~zF>8aoqO+KW|jZVpsE}=HMe5!+$?CiVZj{92D^Nn!%fpp7E8=ZKUAR+ML1UOqREF^ zW^d7KPXJ&kJZexC*G6+xl|3+t6&Hwz1a_y+puzTj?*x= zPKT|xjX*wt1}>ruI^*^FA=svj2>>^d0m8!Ou|^>0a4!q6^6{01+HGrLk=DMLVzIad zdKMUk{iF$d0mn^$zY^GY3D{AlUM++A1CjC*k+M0R06+?-(jFL$+FK6!D3;A3MK1Rckyb3Nh~uO2^lng{JQmTy*zfVPZpoB@F;2Y zjiSY4Rx^)69RX|M5wRW*m(k=H>D_l#9)<=UnVQGs?L0t7hhW0OBQ1E$Gmk0{JSML? zvA*-9DUgW; + Copyright (C) 2007 Johann Ollivier Lapeyre + Copyright (C) 2007 Kenneth Wimer + Copyright (C) 2007 Nuno Fernades Pinheiro + Copyright (C) 2007 Riccardo Iaconelli + Copyright (C) 2007 David Miller + +and others + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library. If not, see . + +Clarification: + + The GNU Lesser General Public License or LGPL is written for + software libraries in the first place. We expressly want the LGPL to + be valid for this artwork library too. + + KDE Oxygen theme icons is a special kind of software library, it is an + artwork library, it's elements can be used in a Graphical User Interface, or + GUI. + + Source code, for this library means: + - where they exist, SVG; + - otherwise, if applicable, the multi-layered formats xcf or psd, or + otherwise png. + + The LGPL in some sections obliges you to make the files carry + notices. With images this is in some cases impossible or hardly useful. + + With this library a notice is placed at a prominent place in the directory + containing the elements. You may follow this practice. + + The exception in section 5 of the GNU Lesser General Public License covers + the use of elements of this art library in a GUI. + + kde-artists [at] kde.org diff --git a/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/icons/network.png b/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/icons/network.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8033452536c47cc213b637991c5847df7a9abf GIT binary patch literal 6602 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 IM6N<$g0J|yl>h($ literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/icons/wifi.png b/openwrt/packages/luci/themes/oxygen/htdocs/luci-static/oxygen/icons/wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..7c17e8d0871faf17e1874fc86f7e8cab5d2fecb4 GIT binary patch literal 7109 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 literal 0 HcmV?d00001 diff --git a/openwrt/packages/luci/themes/oxygen/ipkg/postinst b/openwrt/packages/luci/themes/oxygen/ipkg/postinst new file mode 100755 index 0000000..6eb778f --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/ipkg/postinst @@ -0,0 +1,4 @@ +#!/bin/sh +[ -n "${IPKG_INSTROOT}" ] || { + ( . /etc/uci-defaults/luci-theme-oxygen ) && rm -f /etc/uci-defaults/luci-theme-oxygen +} diff --git a/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/dashboard.htm b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/dashboard.htm new file mode 100644 index 0000000..1e05575 --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/dashboard.htm @@ -0,0 +1,46 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<% + local node = luci.dispatcher.context.requested + if node.nodes then +%> +
+<%- + for k, v in luci.util.spairs(node.nodes, function (a,b) + return (node.nodes[a].order or 100) < (node.nodes[b].order or 100) + end) do + if v.title and #v.title > 0 and not v.ignoreindex and (v.index or v.target) then + local csscl = "dashicon di_%s" % (v.style or k) + local iconl = v.icon + local pref = luci.util.clone(luci.dispatcher.context.request) + pref[#pref+1] = k + local target = luci.dispatcher.build_url(unpack(pref)) +%> + +<% + end + end +-%> +
+
+<% +end +%> \ No newline at end of file diff --git a/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/footer.htm b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/footer.htm new file mode 100644 index 0000000..293a49c --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/footer.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +
+
+ +

Powered by LuCI

+ +
+ + diff --git a/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/header.htm b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/header.htm new file mode 100644 index 0000000..fa86096 --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/header.htm @@ -0,0 +1,129 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<% +local hostname = require("luci.sys").hostname() +local crequest = luci.dispatcher.context.request +local request = require("luci.dispatcher").context.path +local category = request[1] +local tree = luci.dispatcher.node() +local cattree = category and luci.dispatcher.node(category) +local node = luci.dispatcher.context.dispatched + +local c = tree +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 + +require("luci.i18n").loadc("default") +require("luci.http").prepare_content("application/xhtml+xml") + +-%> + + + + + + + + + +<% if node and node.css then %> +<% end -%> +<%=striptags( hostname .. ( (node and node.title) and ' - ' .. node.title or '')) %> - LuCI + + +
+ + + +<%- +local function ucimenu(prefix, node) + if not node.nodes or node.hidden then + return false + end + local index = {} + local count = 0 + for k, n in pairs(node.nodes) do + if n.title and n.target then + table.insert(index, {name=k, order=n.order or 100}) + count = count + 1 + end + end + + table.sort(index, function(a, b) return a.order < b.order end) + + if count > 0 then + for j, v in pairs(index) do + if #v.name > 0 then + local nnode = node.nodes[v.name] + local href = controller .. prefix .. v.name .. "/" + href = (nnode.query) and href .. luci.http.build_querystring(nnode.query) or href +%> + > <%=nnode.title%> +<%- + end + end +%> + +<% + end +end +%> + + + +<% +if tree.nodes[category] and tree.nodes[category].ucidata then + local ucic = 0 + for i, j in pairs(require("luci.model.uci").cursor():changes()) do + for k, l in pairs(j) do + for m, n in pairs(l) do + ucic = ucic + 1; + end + end + end +-%> +<% if ucic > 0 then %> +<% end %> +<% end %> + + + +
+<% if node.subindex then %><%+themes/oxygen/dashboard%><% end %> diff --git a/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/indexer.htm b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/indexer.htm new file mode 100644 index 0000000..6e290dd --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/luasrc/view/themes/oxygen/indexer.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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$ + +-%> +<%+header%> +<%+themes/oxygen/dashboard%> +<%+footer%> \ No newline at end of file diff --git a/openwrt/packages/luci/themes/oxygen/root/etc/uci-defaults/luci-theme-oxygen b/openwrt/packages/luci/themes/oxygen/root/etc/uci-defaults/luci-theme-oxygen new file mode 100755 index 0000000..f4b504b --- /dev/null +++ b/openwrt/packages/luci/themes/oxygen/root/etc/uci-defaults/luci-theme-oxygen @@ -0,0 +1,6 @@ +#!/bin/sh +uci batch <<-EOF + set luci.themes.Oxygen=/luci-static/oxygen + commit luci +EOF + diff --git a/openwrt/packages/ntpclient/Makefile b/openwrt/packages/ntpclient/Makefile new file mode 100644 index 0000000..4808408 --- /dev/null +++ b/openwrt/packages/ntpclient/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=ntpclient +PKG_VERSION:=2007_365 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://doolittle.icarus.com/ntpclient/ +PKG_MD5SUM:=cb98711f11769cdd22fc592844cef414 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-2007 + +include $(INCLUDE_DIR)/package.mk + +define Package/ntpclient + SUBMENU:=Time Synchronization + SECTION:=net + CATEGORY:=Network + TITLE:=NTP (Network Time Protocol) client + URL:=http://doolittle.icarus.com/ntpclient/ + DEPENDS:=+librt +endef + +define Package/ntpclient/description + NTP client for setting system time from NTP servers. +endef + +MAKE_FLAGS += \ + all adjtimex + +define Package/ntpclient/install + $(INSTALL_DIR) $(1)/etc/hotplug.d/iface + $(INSTALL_DATA) ./files/ntpclient.hotplug $(1)/etc/hotplug.d/iface/20-ntpclient + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/ntpclient.config $(1)/etc/config/ntpclient + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ntpclient $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/adjtimex $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/rate.awk $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,ntpclient)) diff --git a/openwrt/packages/ntpclient/files/ntpclient.config b/openwrt/packages/ntpclient/files/ntpclient.config new file mode 100644 index 0000000..1b56f1b --- /dev/null +++ b/openwrt/packages/ntpclient/files/ntpclient.config @@ -0,0 +1,22 @@ +config ntpserver + option hostname '0.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '1.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '2.openwrt.pool.ntp.org' + option port '123' + +config ntpserver + option hostname '3.openwrt.pool.ntp.org' + option port '123' + +config ntpdrift + option freq '0' + +config ntpclient + option interval 60 + #option count 10 diff --git a/openwrt/packages/ntpclient/files/ntpclient.hotplug b/openwrt/packages/ntpclient/files/ntpclient.hotplug new file mode 100644 index 0000000..29f17c1 --- /dev/null +++ b/openwrt/packages/ntpclient/files/ntpclient.hotplug @@ -0,0 +1,64 @@ +#!/bin/sh +# Copyright (C) 2006 OpenWrt.org + +. /etc/functions.sh + +unset SERVER +unset PORT +unset INTERVAL +unset COUNT +NTPC=`which ntpclient` + +check_server() { + local hostname + local port + [ -n "$SERVER" ] && return + config_get hostname $1 hostname + config_get port $1 port + [ -z "$hostname" ] && return + $NTPC -c 1 -p ${port:-123} -h $hostname > /dev/null && { SERVER=$hostname; PORT=${port:-123}; } +} + +set_drift() { + config_get freq $1 freq + [ -n "$freq" ] && adjtimex -f $freq >/dev/null +} + +start_ntpclient() { + config_foreach set_drift ntpdrift + config_foreach check_server ntpserver + [ -z "$SERVER" ] && exit 0 + logger starting ntpclient + $NTPC ${COUNT:+-c $COUNT} ${INTERVAL:+-i $INTERVAL} -s -l -D -p $PORT -h $SERVER 2> /dev/null +} + +stop_ntpclient() { + logger stopping ntpclient + killall ntpclient +} + +load_settings() { + local interval + local count + local iface + + config_get interval $1 interval + config_get count $1 count + + [ -n "$count" ] && COUNT=$count + [ -n "$interval" ] && INTERVAL=$interval +} + +config_load ntpclient +config_foreach load_settings ntpclient + +NTP_RUNNING=`ps | grep $NTPC | grep -v grep` + +case "${ACTION:-ifup}" in + ifup) + [ -z "$NTP_RUNNING" ] && start_ntpclient + ;; + ifdown) + [ -n "$NTP_RUNNING" ] && stop_ntpclient + ;; +esac diff --git a/openwrt/packages/ntpclient/patches/100-daemon.patch b/openwrt/packages/ntpclient/patches/100-daemon.patch new file mode 100644 index 0000000..0ff8d5e --- /dev/null +++ b/openwrt/packages/ntpclient/patches/100-daemon.patch @@ -0,0 +1,24 @@ +Index: ntpclient-2007/ntpclient.c +=================================================================== +--- ntpclient-2007.orig/ntpclient.c 2008-08-12 03:11:34.000000000 +0200 ++++ ntpclient-2007/ntpclient.c 2008-08-12 03:11:36.000000000 +0200 +@@ -614,7 +614,7 @@ + ntpc.cross_check=1; + + for (;;) { +- c = getopt( argc, argv, "c:" DEBUG_OPTION "f:g:h:i:lp:q:" REPLAY_OPTION "st"); ++ c = getopt( argc, argv, "c:" DEBUG_OPTION "f:g:h:i:lp:q:" REPLAY_OPTION "stD"); + if (c == EOF) break; + switch (c) { + case 'c': +@@ -663,6 +663,10 @@ + (ntpc.cross_check)=0; + break; + ++ case 'D': ++ daemon(); ++ break; ++ + default: + usage(argv[0]); + exit(1); diff --git a/openwrt/packages/xyssl/Makefile b/openwrt/packages/xyssl/Makefile new file mode 100644 index 0000000..3e3676b --- /dev/null +++ b/openwrt/packages/xyssl/Makefile @@ -0,0 +1,79 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# $Id: Makefile 12228 2008-08-06 22:43:15Z nbd $ + +include $(TOPDIR)/rules.mk + +PKG_NAME:=xyssl +PKG_VERSION:=0.9 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)_$(PKG_VERSION).orig.tar.gz +PKG_SOURCE_URL:=http://ftp.de.debian.org/debian/pool/main/x/xyssl +PKG_MD5SUM:=3f0695831aa874cb77e3790755d6b570 + +include $(INCLUDE_DIR)/package.mk + +define Package/xyssl/Default + TITLE:=Embedded SSL + URL:=http://xyssl.org/ +endef + +define Package/libxyssl/Default/description + The aim of the XySSL project is to provide a quality, open-source + cryptographic library written in C and targeted at embedded systems. +endef + +define Package/libxyssl +$(call Package/xyssl/Default) + SECTION:=libs + CATEGORY:=Libraries + TITLE+= (library) +endef + +define Package/xyssl-progs +$(call Package/xyssl/Default) + SECTION:=utils + CATEGORY:=Utilities + DEPENDS:=+libxyssl + TITLE+= (programs) +endef + +define Build/Configure +endef + +TARGET_CFLAGS += $(FPIC) + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ + OFLAGS="$(TARGET_CFLAGS)" \ + all + $(MAKE) -C $(PKG_BUILD_DIR) \ + DESTDIR="$(PKG_INSTALL_DIR)/usr" \ + install +endef + +define Build/InstallDev + mkdir -p $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/xyssl $(1)/usr/include/ + mkdir -p $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libxyssl.{a,so} $(1)/usr/lib/ +endef + +define Package/libxyssl/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/libxyssl.so $(1)/usr/lib/ +endef + +define Package/xyssl-progs/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/xyssl_* $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,libxyssl)) +$(eval $(call BuildPackage,xyssl-progs)) diff --git a/openwrt/packages/xyssl/patches/100-shared.patch b/openwrt/packages/xyssl/patches/100-shared.patch new file mode 100644 index 0000000..e787dbb --- /dev/null +++ b/openwrt/packages/xyssl/patches/100-shared.patch @@ -0,0 +1,12 @@ +diff -urN xyssl-0.8.orig/library/Makefile xyssl-0.8/library/Makefile +--- xyssl-0.8.orig/library/Makefile 2007-10-20 20:29:26.000000000 +0200 ++++ xyssl-0.8/library/Makefile 2007-10-20 20:30:41.000000000 +0200 +@@ -28,7 +28,7 @@ + + .SILENT: + +-all: static ++all: static shared + + static: libxyssl.a + diff --git a/openwrt/packages/xyssl/patches/110-make.patch b/openwrt/packages/xyssl/patches/110-make.patch new file mode 100644 index 0000000..bbbdcdf --- /dev/null +++ b/openwrt/packages/xyssl/patches/110-make.patch @@ -0,0 +1,13 @@ +--- xyssl-0.9/Makefile.orig 2008-03-16 15:14:56.000000000 +0100 ++++ xyssl-0.9/Makefile 2008-08-06 17:11:20.000000000 +0200 +@@ -5,8 +5,8 @@ + .SILENT: + + all: +- cd library && make all && cd .. +- cd programs && make all && cd .. ++ cd library && $(MAKE) all && cd .. ++ cd programs && $(MAKE) all && cd .. + + install: + mkdir -p $(DESTDIR)/include/xyssl diff --git a/openwrt/patches/100.disable.console.patch b/openwrt/patches/100.disable.console.patch new file mode 100644 index 0000000..1c67ddf --- /dev/null +++ b/openwrt/patches/100.disable.console.patch @@ -0,0 +1,13 @@ +Index: config-2.6.26 +=================================================================== +--- config-2.6.26 (revision 16491) ++++ config-2.6.26 (working copy) +@@ -1359,7 +1359,7 @@ + # CONFIG_SENSORS_W83L785TS is not set + # CONFIG_SENSORS_W83L786NG is not set + CONFIG_SERIAL_8250=y +-CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_CONSOLE is not set + CONFIG_SERIAL_8250_CS=m + CONFIG_SERIAL_8250_NR_UARTS=2 + # CONFIG_SERIAL_8250_PCI is not set