Browse Source

treewide: convert all LuCI-based packages to gluon-web

Matthias Schiffer 7 years ago
parent
commit
31d3f08f25
100 changed files with 1289 additions and 2791 deletions
  1. 1 1
      Makefile
  2. 29 39
      docs/dev/configmode.rst
  3. 38 35
      docs/dev/i18n.rst
  4. 1 1
      docs/dev/upgrade.rst
  5. 1 1
      docs/features/private-wlan.rst
  6. 3 3
      docs/features/roles.rst
  7. 1 1
      docs/features/wired-mesh.rst
  8. 4 4
      docs/site-example/site.mk
  9. 4 4
      docs/user/site.rst
  10. 1 5
      package/gluon-config-mode-autoupdater/Makefile
  11. 7 18
      package/gluon-config-mode-autoupdater/luasrc/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua
  12. 22 30
      package/gluon-config-mode-contact-info/luasrc/lib/gluon/config-mode/wizard/0500-contact-info.lua
  13. 2 2
      package/gluon-config-mode-core/Makefile
  14. 22 0
      package/gluon-config-mode-core/files/lib/gluon/web/view/gluon/config-mode/reboot.html
  15. 11 0
      package/gluon-config-mode-core/files/lib/gluon/web/view/gluon/config-mode/welcome.html
  16. 0 53
      package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/cbi/config-mode.htm
  17. 0 17
      package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/config-mode/reboot.htm
  18. 7 13
      package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/reboot/0900-msg-reboot.lua
  19. 2 0
      package/gluon-config-mode-core/luasrc/lib/gluon/web/controller/gluon-config-mode/index.lua
  20. 64 0
      package/gluon-config-mode-core/luasrc/lib/gluon/web/model/gluon-config-mode/wizard.lua
  21. 0 93
      package/gluon-config-mode-core/luasrc/usr/lib/lua/luci/controller/gluon-config-mode/index.lua
  22. 0 42
      package/gluon-config-mode-core/luasrc/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua
  23. 52 63
      package/gluon-config-mode-geo-location/luasrc/lib/gluon/config-mode/wizard/0400-geo-location.lua
  24. 9 16
      package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua
  25. 19 24
      package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua
  26. 46 63
      package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua
  27. 0 20
      package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_reboot.htm
  28. 0 39
      package/gluon-luci-admin/luasrc/usr/lib/lua/luci/controller/admin/index.lua
  29. 0 139
      package/gluon-luci-admin/luasrc/usr/lib/lua/luci/controller/admin/upgrade.lua
  30. 0 87
      package/gluon-luci-admin/luasrc/usr/lib/lua/luci/model/cbi/admin/remote.lua
  31. 0 19
      package/gluon-luci-autoupdater/luasrc/usr/lib/lua/luci/controller/admin/autoupdater.lua
  32. 0 32
      package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/view/gluon/cbi/mesh-vpn-fastd-mode.htm
  33. 0 5
      package/gluon-luci-mesh-vpn-fastd/luasrc/usr/lib/lua/luci/controller/admin/mesh_vpn_fastd.lua
  34. 0 40
      package/gluon-luci-mesh-vpn-fastd/luasrc/usr/lib/lua/luci/model/cbi/admin/mesh_vpn_fastd.lua
  35. 0 5
      package/gluon-luci-node-role/luasrc/usr/lib/lua/luci/controller/admin/noderole.lua
  36. 0 33
      package/gluon-luci-node-role/luasrc/usr/lib/lua/luci/model/cbi/admin/noderole.lua
  37. 0 19
      package/gluon-luci-portconfig/luasrc/usr/lib/lua/luci/controller/admin/portconfig.lua
  38. 0 167
      package/gluon-luci-portconfig/luasrc/usr/lib/lua/luci/model/cbi/admin/portconfig.lua
  39. 0 5
      package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/controller/admin/privatewifi.lua
  40. 0 67
      package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua
  41. 0 6
      package/gluon-luci-theme/files/etc/uci-defaults/luci-theme-gluon
  42. 0 19
      package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/footer.htm
  43. 0 171
      package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm
  44. 0 0
      package/gluon-luci-theme/files/www/luci-static/gluon/cascade.css
  45. 0 28
      package/gluon-luci-theme/luasrc/usr/lib/lua/gluon/luci.lua
  46. 0 1029
      package/gluon-luci-theme/sass/cascade.scss
  47. 0 5
      package/gluon-luci-wifi-config/luasrc/usr/lib/lua/luci/controller/admin/wifi-config.lua
  48. 0 169
      package/gluon-luci-wifi-config/luasrc/usr/lib/lua/luci/model/cbi/admin/wifi-config.lua
  49. 1 1
      package/gluon-setup-mode/Makefile
  50. 1 3
      package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S15gluon-setup-mode
  51. 1 1
      package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50uhttpd
  52. 0 10
      package/gluon-setup-mode/files/lib/gluon/setup-mode/www/index.html
  53. 0 1
      package/gluon-setup-mode/files/lib/gluon/setup-mode/www/luci-static
  54. 0 5
      package/gluon-setup-mode/luasrc/lib/gluon/setup-mode/www/cgi-bin/luci
  55. 7 7
      package/gluon-web-admin/Makefile
  56. 12 13
      package/gluon-web-admin/files/lib/gluon/web/view/admin/info.html
  57. 12 17
      package/gluon-web-admin/files/lib/gluon/web/view/admin/upgrade.html
  58. 6 13
      package/gluon-web-admin/files/lib/gluon/web/view/admin/upgrade_confirm.html
  59. 5 0
      package/gluon-web-admin/files/lib/gluon/web/view/admin/upgrade_reboot.html
  60. 24 6
      package/gluon-web-admin/i18n/de.po
  61. 24 6
      package/gluon-web-admin/i18n/fr.po
  62. 24 6
      package/gluon-web-admin/i18n/gluon-web-admin.pot
  63. 9 0
      package/gluon-web-admin/luasrc/lib/gluon/web/controller/admin/index.lua
  64. 139 0
      package/gluon-web-admin/luasrc/lib/gluon/web/controller/admin/upgrade.lua
  65. 109 0
      package/gluon-web-admin/luasrc/lib/gluon/web/model/admin/remote.lua
  66. 8 8
      package/gluon-web-autoupdater/Makefile
  67. 4 1
      package/gluon-web-autoupdater/i18n/de.po
  68. 4 1
      package/gluon-web-autoupdater/i18n/fr.po
  69. 3 0
      package/gluon-web-autoupdater/i18n/gluon-web-autoupdater.pot
  70. 1 0
      package/gluon-web-autoupdater/luasrc/lib/gluon/web/controller/admin/autoupdater.lua
  71. 10 17
      package/gluon-web-autoupdater/luasrc/lib/gluon/web/model/admin/autoupdater.lua
  72. 7 7
      package/gluon-web-mesh-vpn-fastd/Makefile
  73. 0 0
      package/gluon-web-mesh-vpn-fastd/check_site.lua
  74. 32 0
      package/gluon-web-mesh-vpn-fastd/files/lib/gluon/web/view/gluon/model/mesh-vpn-fastd.html
  75. 2 2
      package/gluon-web-mesh-vpn-fastd/i18n/de.po
  76. 0 0
      package/gluon-web-mesh-vpn-fastd/i18n/fr.po
  77. 0 0
      package/gluon-web-mesh-vpn-fastd/i18n/gluon-web-mesh-vpn-fastd.pot
  78. 1 0
      package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/web/controller/admin/mesh_vpn_fastd.lua
  79. 38 0
      package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/web/model/admin/mesh_vpn_fastd.lua
  80. 8 8
      package/gluon-web-network/Makefile
  81. 21 0
      package/gluon-web-network/i18n/de.po
  82. 21 0
      package/gluon-web-network/i18n/fr.po
  83. 21 0
      package/gluon-web-network/i18n/gluon-web-network.pot
  84. 1 0
      package/gluon-web-network/luasrc/lib/gluon/web/controller/admin/network.lua
  85. 143 0
      package/gluon-web-network/luasrc/lib/gluon/web/model/admin/network.lua
  86. 8 8
      package/gluon-web-node-role/Makefile
  87. 0 0
      package/gluon-web-node-role/check_site.lua
  88. 0 0
      package/gluon-web-node-role/i18n/de.po
  89. 0 0
      package/gluon-web-node-role/i18n/fr.po
  90. 0 0
      package/gluon-web-node-role/i18n/gluon-web-node-role.pot
  91. 1 0
      package/gluon-web-node-role/luasrc/lib/gluon/web/controller/admin/noderole.lua
  92. 28 0
      package/gluon-web-node-role/luasrc/lib/gluon/web/model/admin/noderole.lua
  93. 7 7
      package/gluon-web-private-wifi/Makefile
  94. 6 0
      package/gluon-web-private-wifi/i18n/de.po
  95. 6 0
      package/gluon-web-private-wifi/i18n/fr.po
  96. 6 0
      package/gluon-web-private-wifi/i18n/gluon-web-private-wifi.pot
  97. 1 0
      package/gluon-web-private-wifi/luasrc/lib/gluon/web/controller/admin/privatewifi.lua
  98. 54 0
      package/gluon-web-private-wifi/luasrc/lib/gluon/web/model/admin/privatewifi.lua
  99. 5 11
      package/gluon-web-theme/Makefile
  100. 122 0
      package/gluon-web-theme/files/lib/gluon/web/view/themes/gluon/layout.html

+ 1 - 1
Makefile

@@ -99,7 +99,7 @@ config: FORCE
 		&& scripts/target_config.sh generic \
 		&& GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/target_config.sh '$(GLUON_TARGET)' \
 		$(foreach pkg,$(GLUON_PACKAGES_YES),&& echo 'CONFIG_PACKAGE_$(pkg)=y') \
-		$(foreach lang,$(GLUON_LANGS),&& echo 'CONFIG_LUCI_LANG_$(lang)=y') \
+		$(foreach lang,$(GLUON_LANGS),&& echo 'CONFIG_GLUON_WEB_LANG_$(lang)=y') \
 		&& echo 'CONFIG_GLUON_RELEASE="$(GLUON_RELEASE)"' \
 		&& echo 'CONFIG_GLUON_SITEDIR="$(GLUON_SITEDIR)"' \
 		&& echo 'CONFIG_GLUON_BRANCH="$(GLUON_BRANCH)"' \

+ 29 - 39
docs/dev/configmode.rst

@@ -1,7 +1,8 @@
 Config Mode
 ===========
 
-As of 2014.4 `gluon-config-mode` consists of several modules.
+The `Config Mode` consists of several modules that provide a range of different
+condiguration options:
 
 gluon-config-mode-core
     This modules provides the core functionality for the config mode.
@@ -22,20 +23,13 @@ gluon-config-mode-geo-location
 gluon-config-mode-contact-info
     Adds a field where the user can provide contact information.
 
-In order to get a config mode close to the one found in 2014.3.x you may add
-these modules to your `site.mk`:
-gluon-config-mode-hostname,
-gluon-config-mode-autoupdater,
-gluon-config-mode-mesh-vpn,
-gluon-config-mode-geo-location,
-gluon-config-mode-contact-info
 
-Writing Config Mode Modules
+Writing Config Mode modules
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Config mode modules are located at `/lib/gluon/config-mode/wizard` and
-`/lib/gluon/config-mode/reboot`. Modules are named like `0000-name.lua` and
-are executed in lexical order. If you take the standard set of modules, the
+Config mode modules are located at ``/lib/gluon/config-mode/wizard`` and
+``/lib/gluon/config-mode/reboot``. Modules are named like ``0000-name.lua`` and
+are executed in lexical order. In the standard package set, the
 order is, for wizard modules:
 
   - 0050-autoupdater-info
@@ -44,49 +38,45 @@ order is, for wizard modules:
   - 0400-geo-location
   - 0500-contact-info
 
-While for reboot modules it is:
+The reboot module order is:
 
   - 0100-mesh-vpn
   - 0900-msg-reboot
 
+All modules are run in the gluon-web model context and have access to the same
+variables as "full" gluon-web modules.
+
 Wizards
 -------
 
-Wizard modules return a UCI section. A simple module capable of changing the
-hostname might look like this::
+Wizard modules must return a function that is provided with the wizard form and an
+UCI cursor. The function can create configuration sections in the form:
 
-  local cbi = require "luci.cbi"
-  local uci = luci.model.uci.cursor()
+.. code-block:: lua
 
-  local M = {}
-
-  function M.section(form)
-    local s = form:section(cbi.SimpleSection, nil, nil)
-    local o = s:option(cbi.Value, "_hostname", "Hostname")
-    o.value = uci:get_first("system", "system", "hostname")
-    o.rmempty = false
+  return function(form, uci)
+    local s = form:section(Section)
+    local o = s:option(Value, "hostname", "Hostname")
+    o.default = uci:get_first("system", "system", "hostname")
     o.datatype = "hostname"
-  end
 
-  function M.handle(data)
-    uci:set("system", uci:get_first("system", "system"), "hostname", data._hostname)
-    uci:save("system")
-    uci:commit("system")
+    function o:write(data)
+      uci:set("system", uci:get_first("system", "system"), "hostname", data)
+    end
+
+    return {'system'}
   end
 
-  return M
+The function may return a table of UCI packages to commit after the individual
+fields' `write` methods have been executed. This is done to avoid committing the
+packages repeatedly when multiple wizard modules modify the same package.
 
 Reboot page
 -----------
 
-Reboot modules return a function that will be called when the page is to be
-rendered or nil (i.e. the module is skipped)::
+Reboot modules are simply executed when the reboot page is
+rendered:
 
-  if no_hello_world_today then
-    return nil
-  else
-    return function ()
-      luci.template.render_string("Hello World!")
-    end
-  end
+.. code-block:: lua
 
+  renderer.render_string("Hello World!")

+ 38 - 35
docs/dev/i18n.rst

@@ -10,53 +10,56 @@ General guidelines
   nice-to-have, but not required. If you don't know a language well, rather leave the translation
   blank, so it is obvious that there is no proper translation yet.
 * Existing expert mode packages should be made translatable as soon as possible.
-* The "message IDs" (which are the arguments to the ``translate`` function) should be the
+* The "message IDs" (which are the arguments to the *translate* function) should be the
   English texts.
 
-i18n support in LuCI
---------------------
+i18n support in Gluon
+---------------------
 
-Internationalization support can be found in the ``luci.i18n`` package.
-Strings are translated using the ``i18n.translate`` and ``i18n.translatef`` functions
-(``translate`` for static strings, ``translatef`` for printf-like formatted string).
+Internationalization support is available in all components (models, view and
+contrllers) of *gluon-web*-based packages. Strings are translated using the *translate*
+and *translatef* functions (*translate* for static strings, *translatef*
+for printf-like formatted string); in views, the special tags ``<%:...%>`` can
+be used to translate the contained string.
 
-Example from the ``gluon-config-mode-geo-location`` package::
+Example from the *gluon-config-mode-geo-location* package:
 
-  local i18n = require "luci.i18n"
-  o = s:option(cbi.Flag, "_location", i18n.translate("Show node on the map"))
+.. code-block:: lua
+
+  local share_location = s:option(Flag, "location", translate("Show node on the map"))
 
 Adding translation templates to Gluon packages
 ----------------------------------------------
 
 The i18n support is based on the standard gettext system. For each translatable package,
-a translation template with extension ``.pot`` can be created using the ``i18n-scan.pl``
-script from the LuCI repository::
+a translation template with extension ``.pot`` can be created using the *i18n-scan.pl*
+script in the ``contrib`` directory:
+
+.. code-block:: sh
 
-  cd package/gluon-config-mode-geo-location
+  cd package/gluon-web-mesh-vpn-fastd
   mkdir i18n
   cd i18n
-  ../../../packages/luci/build/i18n-scan.pl ../files > gluon-config-mode-geo-location.pot
+  ../../../contrib/i18n-scan.pl ../files ../luasrc > gluon-web-mesh-vpn-fastd.pot
 
-The entries in the template can be reordered after the generation if desirable. Lots of standard
-translations like "Cancel" are already available in the LuCI base translation file (see
-``packages/luci/po/templates/base.pot``) and can be removed from the template.
+The same command can be run again to update the template.
 
-In addition, some additions to the Makefile must be made. Instead of OpenWrt's default ``package.mk``,
-the Gluon version ``$(GLUONDIR)/include/package.mk`` must be used. The i18n files must be installed
+In addition, some additions to the Makefile must be made. Instead of LEDE's default *package.mk*,
+the Gluon version (``../gluon.mk`` for core packages) must be used. The i18n files must be installed
 and PKG_CONFIG_DEPENDS must be added::
 
   ...
-  include $(GLUONDIR)/include/package.mk
+  include ../gluon.mk
 
   PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
   ...
   define Build/Compile
-    $(call GluonBuildI18N,gluon-config-mode-geo-location,i18n)
+    $(call GluonBuildI18N,gluon-web-mesh-vpn-fastd,i18n)
   endef
 
-  define Package/gluon-config-mode-geo-location/install
+  define Package/gluon-web-mesh-vpn-fastd/install
     ...
-    $(call GluonInstallI18N,gluon-config-mode-geo-location,$(1))
+    $(call GluonInstallI18N,gluon-web-mesh-vpn-fastd,$(1))
   endef
   ...
 
@@ -64,29 +67,29 @@ and PKG_CONFIG_DEPENDS must be added::
 Adding translations
 -------------------
 
-A new translation file for a template can be added using the ``msginit`` command::
+A new translation file for a template can be added using the *msginit* command:
+
+.. code-block:: sh
 
-  cd package/gluon-config-mode-geo-location/i18n
+  cd package/gluon-web-mesh-vpn-fastd/i18n
   msginit -l de
 
-This will create the file ``de.po`` in which the translations can be added.
+This will create the file *de.po* in which the translations can be added.
 
-The translation file can be updated to a new template version using the ``msgmerge`` command::
+The translation file can be updated to a new template version using the *msgmerge* command:
 
-  msgmerge -U de.po gluon-config-mode-geo-location.pot
+.. code-block:: sh
+
+  msgmerge -U de.po gluon-web-mesh-vpn-fastd.pot
 
 After the merge, the translation file should be checked for "fuzzy matched" entries where
 the original English texts have changed. All entries from the translation file should be
-translated in the ``.po`` file (or removed from it, so the original English texts are displayed
+translated in the *.po* file (or removed from it, so the original English texts are displayed
 instead).
 
 Adding support for new languages
 --------------------------------
 
-A list of all languages supported by LuCI can be found in the ``packages/luci/luci.mk`` file after
-Gluon's dependencies have been downloaded using ``make update``. Adding translations for these
-languages is straightforward using the ``msginit`` command.
-
-For other languages, support must be added to LuCI first, which constitutes completely translating
-the ``base.pot``. Please contact the upstream LuCI maintainers at https://github.com/openwrt/luci/
-if you'd like to do this.
+A list of all languages supported by *gluon-web* can be found in ``package/gluon.mk``.
+New languages just need to be added to *GLUON_SUPPORTED_LANGS*, after a human-readable
+language name has been defined in the same file.

+ 1 - 1
docs/dev/upgrade.rst

@@ -16,7 +16,7 @@ Best practices
 --------------
 
 * Most upgrade scripts are written in Lua. This allows using lots of helper functions provided
-  by LuCi and Gluon, e.g. to access the site configuration or edit UCI configuration files.
+  by Gluon, e.g. to access the site configuration or edit UCI configuration files.
 
 * Whenever possible, scripts shouldn't check if they are running for the first time, but just edit configuration
   files to achive a valid configuration (without overwriting configuration changes made by the user where desirable).

+ 1 - 1
docs/features/private-wlan.rst

@@ -4,7 +4,7 @@ Private WLAN
 It is possible to set up a private WLAN that bridges the WAN port and is seperated from the mesh network.
 Please note that you should not enable ``mesh_on_wan`` simultaneously.
 
-The private WLAN can be enabled through the config mode if the package ``gluon-luci-private-wifi`` is installed.
+The private WLAN can be enabled through the config mode if the package ``gluon-web-private-wifi`` is installed.
 You may also enable a private WLAN using the command line::
 
   uci set wireless.wan_radio0=wifi-iface

+ 3 - 3
docs/features/roles.rst

@@ -18,13 +18,13 @@ For this the section ``roles`` in ``site.conf`` is needed::
     },
   },
 
-The strings to display in the LuCI interface are configured per language in the
+The strings to display in the web interface are configured per language in the
 ``i18n/en.po``, ``i18n/de.po``, etc. files of the site repository using message IDs like
-``gluon-luci-node-role:role:node`` and ``gluon-luci-node-role:role:backbone``.
+``gluon-web-node-role:role:node`` and ``gluon-web-node-role:role:backbone``.
 
 The value of ``default`` is the role every node will initially own. This value should be part of ``list`` as well.
 If you want node owners to change the defined roles via config-mode you can add the package
-``gluon-luci-node-role`` to your ``site.mk``.
+``gluon-web-node-role`` to your ``site.mk``.
 
 The role is saved in ``gluon-node-info.system.role``. To change the role using command line do::
 

+ 1 - 1
docs/features/wired-mesh.rst

@@ -19,7 +19,7 @@ Configuration
 ~~~~~~~~~~~~~
 
 Both Mesh-on-WAN and Mesh-on-LAN can be configured on the "Network" page
-of the *Advanced settings* (if the package ``gluon-luci-portconfig`` is installed).
+of the *Advanced settings* (if the package ``gluon-web-network`` is installed).
 
 It is also possible to enable Mesh-on-WAN and Mesh-on-LAN by default by
 adding ``mesh_on_wan = true`` and ``mesh_on_lan = true`` to ``site.conf``.

+ 4 - 4
docs/site-example/site.mk

@@ -15,10 +15,10 @@ GLUON_SITE_PACKAGES := \
 	gluon-config-mode-mesh-vpn \
 	gluon-ebtables-filter-multicast \
 	gluon-ebtables-filter-ra-dhcp \
-	gluon-luci-admin \
-	gluon-luci-autoupdater \
-	gluon-luci-portconfig \
-	gluon-luci-wifi-config \
+	gluon-web-admin \
+	gluon-web-autoupdater \
+	gluon-web-network \
+	gluon-web-wifi-config \
 	gluon-mesh-batman-adv-15 \
 	gluon-mesh-vpn-fastd \
 	gluon-radvd \

+ 4 - 4
docs/user/site.rst

@@ -182,7 +182,7 @@ fastd_mesh_vpn
     with the list from the site configuration. Setting `configurable` to `true` will allow the user to
     add the method ``null`` to the beginning of the method list or remove ``null`` from it,
     and make this change survive updates. Setting `configurable` is necessary for the
-    package `gluon-luci-mesh-vpn-fastd`, which adds a UI for this configuration.
+    package `gluon-web-mesh-vpn-fastd`, which adds a UI for this configuration.
 
     In any case, the ``null`` method should always be the first method in the list
     if it is supported at all. You should only set `configurable` to `true` if the
@@ -288,11 +288,11 @@ roles \: optional
     the community which roles to define. See the section below as an example.
     ``default`` takes the default role which is set initially. This value should be
     part of ``list``. If you want node owners to change the role via config mode add
-    the package ``gluon-luci-node-role`` to ``site.mk``.
+    the package ``gluon-web-node-role`` to ``site.mk``.
 
-    The strings to display in the LuCI interface are configured per language in the
+    The strings to display in the web interface are configured per language in the
     ``i18n/en.po``, ``i18n/de.po``, etc. files of the site repository using message IDs like
-    ``gluon-luci-node-role:role:node`` and ``gluon-luci-node-role:role:backbone``.
+    ``gluon-web-node-role:role:node`` and ``gluon-web-node-role:role:backbone``.
     ::
 
       roles = {

+ 1 - 5
package/gluon-config-mode-autoupdater/Makefile

@@ -13,14 +13,10 @@ PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 define Package/gluon-config-mode-autoupdater
   SECTION:=gluon
   CATEGORY:=Gluon
-  TITLE:=Let the user know whether the autoupdater is enabled or not.
+  TITLE:=Config Mode: Let the user know whether the autoupdater is enabled or not
   DEPENDS:=gluon-config-mode-core-virtual +gluon-autoupdater
 endef
 
-define Package/gluon-config-mode-autoupdater/description
-	Luci based config mode
-endef
-
 define Build/Prepare
 	mkdir -p $(PKG_BUILD_DIR)
 endef

+ 7 - 18
package/gluon-config-mode-autoupdater/luasrc/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua

@@ -1,19 +1,8 @@
-local cbi = require "luci.cbi"
-local i18n = require "luci.i18n"
-local uci = require("simple-uci").cursor()
-
-local M = {}
-
-function M.section(form)
-  local enabled = uci:get_bool("autoupdater", "settings", "enabled")
-  if enabled then
-    local s = form:section(cbi.SimpleSection, nil,
-      i18n.translate('This node will automatically update its firmware when a new version is available.'))
-  end
+return function(form, uci)
+	if uci:get_bool("autoupdater", "settings", "enabled") then
+		local s = form:section(
+			Section, nil,
+			translate('This node will automatically update its firmware when a new version is available.')
+		)
+	end
 end
-
-function M.handle(data)
-  return
-end
-
-return M

+ 22 - 30
package/gluon-config-mode-contact-info/luasrc/lib/gluon/config-mode/wizard/0500-contact-info.lua

@@ -1,35 +1,27 @@
-local cbi = require "luci.cbi"
-local i18n = require "luci.i18n"
-local uci = require("simple-uci").cursor()
-local site = require 'gluon.site_config'
+return function(form, uci)
+	local site = require 'gluon.site_config'
 
-local M = {}
+	local owner = uci:get_first("gluon-node-info", "owner")
 
-function M.section(form)
-  local s = form:section(cbi.SimpleSection, nil, i18n.translate(
-    'Please provide your contact information here to '
-      .. 'allow others to contact you. Note that '
-      .. 'this information will be visible <em>publicly</em> '
-      .. 'on the internet together with your node\'s coordinates.'
-    )
-  )
+	local s = form:section(Section, nil, translate(
+		'Please provide your contact information here to '
+		.. 'allow others to contact you. Note that '
+		.. 'this information will be visible <em>publicly</em> '
+		.. 'on the internet together with your node\'s coordinates.'
+	))
 
-  local o = s:option(cbi.Value, "_contact", i18n.translate("Contact info"))
-  o.default = uci:get_first("gluon-node-info", "owner", "contact", "")
-  o.rmempty = not ((site.config_mode or {}).owner or {}).obligatory
-  o.datatype = "string"
-  o.description = i18n.translate("e.g. E-mail or phone number")
-  o.maxlen = 140
-end
+	local o = s:option(Value, "contact", translate("Contact info"), translate("e.g. E-mail or phone number"))
+	o.default = uci:get("gluon-node-info", owner, "contact")
+	o.optional = not ((site.config_mode or {}).owner or {}).obligatory
+	-- without a minimal length, an empty string will be accepted even with "optional = false"
+	o.datatype = "minlength(1)"
+	function o:write(data)
+		if data then
+			uci:set("gluon-node-info", owner, "contact", data)
+		else
+			uci:delete("gluon-node-info", owner, "contact")
+		end
+	end
 
-function M.handle(data)
-  if data._contact ~= nil then
-    uci:set("gluon-node-info", uci:get_first("gluon-node-info", "owner"), "contact", data._contact)
-  else
-    uci:delete("gluon-node-info", uci:get_first("gluon-node-info", "owner"), "contact")
-  end
-  uci:save("gluon-node-info")
-  uci:commit("gluon-node-info")
+	return {'gluon-node-info'}
 end
-
-return M

+ 2 - 2
package/gluon-config-mode-core/Makefile

@@ -16,8 +16,8 @@ PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 define Package/gluon-config-mode-core
   SECTION:=gluon
   CATEGORY:=Gluon
-  TITLE:=Luci based config mode for user friendly setup of new mesh nodes
-  DEPENDS:=gluon-setup-mode-virtual +gluon-luci-theme +gluon-lock-password +pretty-hostname $(GLUON_I18N_PACKAGES)
+  TITLE:=Configuration wizard for user friendly setup of new mesh nodes
+  DEPENDS:=gluon-setup-mode-virtual +gluon-web-theme +gluon-lock-password +pretty-hostname
   PROVIDES:=gluon-config-mode-core-virtual
 endef
 

+ 22 - 0
package/gluon-config-mode-core/files/lib/gluon/web/view/gluon/config-mode/reboot.html

@@ -0,0 +1,22 @@
+<h2><%:Your node's setup is now complete.%></h2>
+<%
+	local fs = require "nixio.fs"
+	local util = require "nixio.util"
+
+	local parts_dir = "/lib/gluon/config-mode/reboot/"
+	local files = util.consume(fs.dir(parts_dir) or function() end)
+	table.sort(files)
+
+	local parts = {}
+	for _, entry in ipairs(files) do
+		if entry:sub(1, 1) ~= '.' then
+			local p = assert(loadfile(parts_dir .. entry))
+			setfenv(p, getfenv())
+			table.insert(parts, p)
+		end
+	end
+
+	for _, p in ipairs(parts) do
+		p()
+	end
+%>

+ 11 - 0
package/gluon-config-mode-core/files/lib/gluon/web/view/gluon/config-mode/welcome.html

@@ -0,0 +1,11 @@
+<%-
+	local sysconfig = require 'gluon.sysconfig'
+-%>
+<p>
+	<%=
+		renderer.render_string(translate('gluon-config-mode:welcome'), {
+			hostname = hostname,
+			sysconfig = sysconfig,
+		})
+	%>
+</p>

+ 0 - 53
package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/cbi/config-mode.htm

@@ -1,53 +0,0 @@
-<%-
-	local gluon_luci = require 'gluon.luci'
-	local sysconfig = require 'gluon.sysconfig'
-	local i18n = require 'luci.i18n'
-	local template = require 'luci.template'
--%>
-
-<h2><%:Welcome!%></h2>
-<p>
-	<%= template.render_string(i18n.translate('gluon-config-mode:welcome'), {
-		hostname = hostname,
-		sysconfig = sysconfig,
-		escape = gluon_luci.escape,
-		urlescape = gluon_luci.urlescape,
-	}) %>
-</p>
-
-<% if not self.embedded then %>
-<form method="post" enctype="multipart/form-data" action="<%=REQUEST_URI%>">
-	<div>
-		<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
-		<input type="hidden" name="token" value="<%=token%>" />
-		<input type="hidden" name="cbi.submit" value="1" />
-	</div>
-<% end %>
-	<div class="cbi-map" id="cbi-<%=self.config%>">
-		<% if self.title and #self.title > 0 then %><h2><a id="content" name="content"><%=self.title%></a></h2><% end %>
-		<% if self.description and #self.description > 0 then %><div class="cbi-map-descr"><%=self.description%></div><% end %>
-		<% self:render_children() %>
-		<br />
-	</div>
-<%- if self.message then %>
-	<div><%=self.message%></div>
-<%- end %>
-<%- if self.errmessage then %>
-	<div class="error"><%=self.errmessage%></div>
-<%- end %>
-<% if not self.embedded then %>
-	<div class="cbi-page-actions">
-<%-
-		if type(self.hidden) == "table" then
-		  for k, v in pairs(self.hidden) do
--%>
-		<input type="hidden" id="<%=k%>" name="<%=k%>" value="<%=pcdata(v)%>" />
-<%-
-		  end
-		end
-%>
-		<input class="cbi-button cbi-button-save" type="submit" value="<%:Save & restart%>" />
-		<script type="text/javascript">cbi_d_update();</script>
-	</div>
-</form>
-<% end %>

+ 0 - 17
package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/config-mode/reboot.htm

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%=luci.i18n.context.lang%>" lang="<%=luci.i18n.context.lang%>">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    <title><%=escape(hostname)%> is rebooting</title>
-    <link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
-  </head>
-  <body>
-    <div id="maincontainer">
-      <div id="maincontent">
-        <h2><%:Your node's setup is now complete.%></h2>
-        <% for k, v in ipairs(parts) do v() end %>
-      </div>
-    </div>
-  </body>
-</html>

+ 7 - 13
package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/reboot/0900-msg-reboot.lua

@@ -1,6 +1,4 @@
-local i18n = require 'luci.i18n'
 local site = require 'gluon.site_config'
-local gluon_luci = require 'gluon.luci'
 local sysconfig = require 'gluon.sysconfig'
 local pretty_hostname = require 'pretty_hostname'
 
@@ -9,15 +7,11 @@ local uci = require("simple-uci").cursor()
 local hostname = pretty_hostname.get(uci)
 local contact = uci:get_first('gluon-node-info', 'owner', 'contact')
 
-local msg = i18n.translate('gluon-config-mode:reboot')
+local msg = translate('gluon-config-mode:reboot')
 
-return function ()
-  luci.template.render_string(msg, {
-    hostname = hostname,
-    site = site,
-    sysconfig = sysconfig,
-    contact = contact,
-    escape = gluon_luci.escape,
-    urlescape = gluon_luci.urlescape,
-  })
-end
+renderer.render_string(msg, {
+	hostname = hostname,
+	site = site,
+	sysconfig = sysconfig,
+	contact = contact,
+})

+ 2 - 0
package/gluon-config-mode-core/luasrc/lib/gluon/web/controller/gluon-config-mode/index.lua

@@ -0,0 +1,2 @@
+entry({}, alias("wizard"))
+entry({"wizard"}, model("gluon-config-mode/wizard"), _("Wizard"), 5)

+ 64 - 0
package/gluon-config-mode-core/luasrc/lib/gluon/web/model/gluon-config-mode/wizard.lua

@@ -0,0 +1,64 @@
+local disp = require 'gluon.web.dispatcher'
+local fs = require "nixio.fs"
+local util = require "gluon.web.util"
+local nixio_util = require "nixio.util"
+
+local uci = require("simple-uci").cursor()
+
+local wizard_dir = "/lib/gluon/config-mode/wizard/"
+
+local files = nixio_util.consume(fs.dir(wizard_dir) or function() end)
+table.sort(files)
+
+local wizard = {}
+for _, entry in ipairs(files) do
+	if entry:sub(1, 1) ~= '.' then
+		local f = assert(loadfile(wizard_dir .. entry))
+		setfenv(f, getfenv())
+		local w = f()
+		table.insert(wizard, w)
+	end
+end
+
+local f = Form(translate("Welcome!"))
+f.submit = translate('Save & restart')
+f.reset = false
+
+local s = f:section(Section)
+s.template = "gluon/config-mode/welcome"
+
+local commit = {'gluon-setup-mode'}
+
+for _, w in ipairs(wizard) do
+	for _, c in ipairs(w(f, uci) or {}) do
+		if not util.contains(commit, c) then
+			table.insert(commit, c)
+		end
+	end
+end
+
+function f:write()
+	local nixio = require "nixio"
+
+	uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", true)
+
+	for _, c in ipairs(commit) do
+		uci:commit(c)
+	end
+
+	f.template = "gluon/config-mode/reboot"
+	f.hidenav = true
+
+	if nixio.fork() == 0 then
+		-- Replace stdout with /dev/null
+		nixio.dup(nixio.open('/dev/null', 'w'), nixio.stdout)
+
+		-- Sleep a little so the browser can fetch everything required to
+		-- display the reboot page, then reboot the device.
+		nixio.nanosleep(1)
+
+		nixio.execp("reboot")
+	end
+end
+
+return f

+ 0 - 93
package/gluon-config-mode-core/luasrc/usr/lib/lua/luci/controller/gluon-config-mode/index.lua

@@ -1,93 +0,0 @@
---[[
-Copyright 2013 Nils Schneider <nils@nilsschneider.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
-
-module("luci.controller.gluon-config-mode.index", package.seeall)
-
-function index()
-  local uci_state = luci.model.uci.cursor_state()
-
-  if uci_state:get_first("gluon-setup-mode", "setup_mode", "running", "0") == "1" then
-    local root = node()
-    if not root.target then
-      root.target = alias("gluon-config-mode")
-      root.index = true
-    end
-
-    page          = node()
-    page.lock     = true
-    page.target   = alias("gluon-config-mode")
-    page.subindex = true
-    page.index    = false
-
-    page          = node("gluon-config-mode")
-    page.title    = _("Wizard")
-    page.target   = alias("gluon-config-mode", "wizard")
-    page.order    = 5
-    page.sysauth = "root"
-    page.sysauth_authenticator = function() return "root" end
-    page.index    = true
-
-    entry({"gluon-config-mode", "wizard"}, cbi("gluon-config-mode/wizard")).index = true
-    entry({"gluon-config-mode", "reboot"}, call("action_reboot"))
-  end
-end
-
-function action_reboot()
-  local uci = luci.model.uci.cursor()
-
-  uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", "1")
-  uci:save("gluon-setup-mode")
-  uci:commit("gluon-setup-mode")
-
-  local gluon_luci = require "gluon.luci"
-  local fs = require "nixio.fs"
-  local util = require "nixio.util"
-  local pretty_hostname = require "pretty_hostname"
-
-  local parts_dir = "/lib/gluon/config-mode/reboot/"
-  local files = util.consume(fs.dir(parts_dir))
-
-  table.sort(files)
-
-  local parts = {}
-
-  for _, entry in ipairs(files) do
-    if entry:sub(1, 1) ~= '.' then
-      local f = dofile(parts_dir .. '/' .. entry)
-      if f ~= nil then
-        table.insert(parts, f)
-      end
-    end
-  end
-
-  local hostname = pretty_hostname.get(uci)
-
-  luci.template.render("gluon/config-mode/reboot",
-    {
-      parts = parts,
-      hostname = hostname,
-      escape = gluon_luci.escape,
-      urlescape = gluon_luci.urlescape,
-    }
-  )
-
-  if nixio.fork() == 0 then
-    -- Replace stdout with /dev/null
-    nixio.dup(nixio.open('/dev/null', 'w'), nixio.stdout)
-
-    -- Sleep a little so the browser can fetch everything required to
-    -- display the reboot page, then reboot the device.
-    nixio.nanosleep(1)
-
-    nixio.execp("reboot")
-  end
-end

+ 0 - 42
package/gluon-config-mode-core/luasrc/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua

@@ -1,42 +0,0 @@
-local wizard_dir = "/lib/gluon/config-mode/wizard/"
-local i18n = luci.i18n
-local uci = require("simple-uci").cursor()
-local fs = require "nixio.fs"
-local util = require "nixio.util"
-local f, s
-
-local wizard = {}
-local files = {}
-
-if fs.access(wizard_dir) then
-  files = util.consume(fs.dir(wizard_dir))
-  table.sort(files)
-end
-
-for _, entry in ipairs(files) do
-  if entry:sub(1, 1) ~= '.' then
-    table.insert(wizard, dofile(wizard_dir .. '/' .. entry))
-  end
-end
-
-f = SimpleForm("wizard")
-f.reset = false
-f.template = "gluon/cbi/config-mode"
-
-for _, s in ipairs(wizard) do
-  s.section(f)
-end
-
-function f.handle(self, state, data)
-  if state == FORM_VALID then
-    for _, s in ipairs(wizard) do
-      s.handle(data)
-    end
-
-    luci.http.redirect(luci.dispatcher.build_url("gluon-config-mode", "reboot"))
-  end
-
-  return true
-end
-
-return f

+ 52 - 63
package/gluon-config-mode-geo-location/luasrc/lib/gluon/config-mode/wizard/0400-geo-location.lua

@@ -1,75 +1,64 @@
-local cbi = require "luci.cbi"
-local i18n = require "luci.i18n"
-local uci = require("simple-uci").cursor()
-local site = require 'gluon.site_config'
+return function(form, uci)
+	local site = require 'gluon.site_config'
 
-local M = {}
+	local location = uci:get_first("gluon-node-info", "location")
 
-local function show_altitude()
-  if ((site.config_mode or {}).geo_location or {}).show_altitude ~= false then
-    return true
-  end
-  if uci:get_first("gluon-node-info", "location", "altitude") then
-    return true
-  end
-  return false
-end
-
-function M.section(form)
-  local text = i18n.translate('If you want the location of your node to '
-    .. 'be displayed on the map, you can enter its coordinates here.')
-  if show_altitude() then
-    text = text .. ' ' .. i18n.translate("gluon-config-mode:altitude-help")
-  end
-  local s = form:section(cbi.SimpleSection, nil, text)
+	local function show_altitude()
+		if ((site.config_mode or {}).geo_location or {}).show_altitude ~= false then
+			return true
+		end
 
+		return uci:get_bool("gluon-node-info", location, "altitude")
+	end
 
-  local o
+	local text = translate(
+		'If you want the location of your node to ' ..
+		'be displayed on the map, you can enter its coordinates here.'
+	)
+	if show_altitude() then
+		text = text .. ' ' .. translate("gluon-config-mode:altitude-help")
+	end
 
-  o = s:option(cbi.Flag, "_location", i18n.translate("Show node on the map"))
-  o.default = uci:get_first("gluon-node-info", "location", "share_location", o.disabled)
-  o.rmempty = false
+	local s = form:section(Section, nil, text)
 
-  o = s:option(cbi.Value, "_latitude", i18n.translate("Latitude"))
-  o.default = uci:get_first("gluon-node-info", "location", "latitude")
-  o:depends("_location", "1")
-  o.rmempty = false
-  o.datatype = "float"
-  o.description = i18n.translatef("e.g. %s", "53.873621")
+	local o
 
-  o = s:option(cbi.Value, "_longitude", i18n.translate("Longitude"))
-  o.default = uci:get_first("gluon-node-info", "location", "longitude")
-  o:depends("_location", "1")
-  o.rmempty = false
-  o.datatype = "float"
-  o.description = i18n.translatef("e.g. %s", "10.689901")
+	local share_location = s:option(Flag, "location", translate("Show node on the map"))
+	share_location.default = uci:get_bool("gluon-node-info", location, "share_location")
+	function share_location:write(data)
+		uci:set("gluon-node-info", location, "share_location", data)
+	end
 
-  if show_altitude() then
-    o = s:option(cbi.Value, "_altitude", i18n.translate("gluon-config-mode:altitude-label"))
-    o.default = uci:get_first("gluon-node-info", "location", "altitude")
-    o:depends("_location", "1")
-    o.rmempty = true
-    o.datatype = "float"
-    o.description = i18n.translatef("e.g. %s", "11.51")
-  end
+	o = s:option(Value, "latitude", translate("Latitude"), translatef("e.g. %s", "53.873621"))
+	o.default = uci:get("gluon-node-info", location, "latitude")
+	o:depends(share_location, true)
+	o.datatype = "float"
+	function o:write(data)
+		uci:set("gluon-node-info", location, "latitude", data)
+	end
 
-end
+	o = s:option(Value, "longitude", translate("Longitude"), translatef("e.g. %s", "10.689901"))
+	o.default = uci:get("gluon-node-info", location, "longitude")
+	o:depends(share_location, true)
+	o.datatype = "float"
+	function o:write(data)
+		uci:set("gluon-node-info", location, "longitude", data)
+	end
 
-function M.handle(data)
-  local sname = uci:get_first("gluon-node-info", "location")
+	if show_altitude() then
+		o = s:option(Value, "altitude", translate("gluon-config-mode:altitude-label"), translatef("e.g. %s", "11.51"))
+		o.default = uci:get("gluon-node-info", location, "altitude")
+		o:depends(share_location, true)
+		o.datatype = "float"
+		o.optional = true
+		function o:write(data)
+			if data then
+				uci:set("gluon-node-info", location, "altitude", data)
+			else
+				uci:delete("gluon-node-info", location, "altitude")
+			end
+		end
+	end
 
-  uci:set("gluon-node-info", sname, "share_location", data._location)
-  if data._location and data._latitude ~= nil and data._longitude ~= nil then
-    uci:set("gluon-node-info", sname, "latitude", data._latitude:trim())
-    uci:set("gluon-node-info", sname, "longitude", data._longitude:trim())
-    if data._altitude ~= nil then
-      uci:set("gluon-node-info", sname, "altitude", data._altitude:trim())
-    else
-      uci:delete("gluon-node-info", sname, "altitude")
-    end
-  end
-  uci:save("gluon-node-info")
-  uci:commit("gluon-node-info")
+	return {'gluon-node-info'}
 end
-
-return M

+ 9 - 16
package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua

@@ -1,20 +1,13 @@
-local cbi = require "luci.cbi"
-local i18n = require "luci.i18n"
-local pretty_hostname = require "pretty_hostname"
-local uci = require("simple-uci").cursor()
+return function(form, uci)
+	local pretty_hostname = require "pretty_hostname"
 
-local M = {}
+	local s = form:section(Section)
+	local o = s:option(Value, "hostname", translate("Node name"))
+	o.default = pretty_hostname.get(uci)
 
-function M.section(form)
-  local s = form:section(cbi.SimpleSection, nil, nil)
-  local o = s:option(cbi.Value, "_hostname", i18n.translate("Node name"))
-  o.value = pretty_hostname.get(uci)
-  o.rmempty = false
-end
+	function o:write(data)
+		pretty_hostname.set(uci, data)
+	end
 
-function M.handle(data)
-  pretty_hostname.set(uci, data._hostname)
-  uci:commit("system")
+	return {'system'}
 end
-
-return M

+ 19 - 24
package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua

@@ -2,32 +2,27 @@ local uci = require("simple-uci").cursor()
 local meshvpn_enabled = uci:get_bool("fastd", "mesh_vpn", "enabled")
 
 if not meshvpn_enabled then
-  return nil
-else
-  local i18n = require "luci.i18n"
-  local util = require "luci.util"
+	return
+end
 
-  local gluon_luci = require 'gluon.luci'
-  local site = require 'gluon.site_config'
-  local sysconfig = require 'gluon.sysconfig'
+local lutil = require "gluon.web.util"
 
-  local pretty_hostname = require 'pretty_hostname'
+local site = require 'gluon.site_config'
+local sysconfig = require 'gluon.sysconfig'
+local util = require "gluon.util"
 
-  local pubkey = util.trim(util.exec("/etc/init.d/fastd show_key " .. "mesh_vpn"))
-  local hostname = pretty_hostname.get(uci)
-  local contact = uci:get_first("gluon-node-info", "owner", "contact")
+local pretty_hostname = require 'pretty_hostname'
 
-  local msg = i18n.translate('gluon-config-mode:pubkey')
+local pubkey = util.trim(lutil.exec("/etc/init.d/fastd show_key mesh_vpn"))
+local hostname = pretty_hostname.get(uci)
+local contact = uci:get_first("gluon-node-info", "owner", "contact")
 
-  return function ()
-    luci.template.render_string(msg, {
-      pubkey = pubkey,
-      hostname = hostname,
-      site = site,
-      sysconfig = sysconfig,
-      contact = contact,
-      escape = gluon_luci.escape,
-      urlescape = gluon_luci.urlescape,
-    })
-  end
-end
+local msg = translate('gluon-config-mode:pubkey')
+
+renderer.render_string(msg, {
+	pubkey = pubkey,
+	hostname = hostname,
+	site = site,
+	sysconfig = sysconfig,
+	contact = contact,
+})

+ 46 - 63
package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua

@@ -1,64 +1,47 @@
-local cbi = require "luci.cbi"
-local i18n = require "luci.i18n"
-local uci = require("simple-uci").cursor()
-
-local M = {}
-
-function M.section(form)
-  local msg = i18n.translate('Your internet connection can be used to establish an ' ..
-                             'encrypted connection with other nodes. ' ..
-                             'Enable this option if there are no other nodes reachable ' ..
-                             'over WLAN in your vicinity or you want to make a part of ' ..
-                             'your connection\'s bandwidth available for the network. You can limit how ' ..
-                             'much bandwidth the node will use at most.')
-  local s = form:section(cbi.SimpleSection, nil, msg)
-
-  local o
-
-  o = s:option(cbi.Flag, "_meshvpn", i18n.translate("Use internet connection (mesh VPN)"))
-  o.default = uci:get_bool("fastd", "mesh_vpn", "enabled") and o.enabled or o.disabled
-  o.rmempty = false
-
-  o = s:option(cbi.Flag, "_limit_enabled", i18n.translate("Limit bandwidth"))
-  o:depends("_meshvpn", "1")
-  o.default = uci:get_bool("simple-tc", "mesh_vpn", "enabled") and o.enabled or o.disabled
-  o.rmempty = false
-
-  o = s:option(cbi.Value, "_limit_ingress", i18n.translate("Downstream (kbit/s)"))
-  o:depends("_limit_enabled", "1")
-  o.value = uci:get("simple-tc", "mesh_vpn", "limit_ingress")
-  o.rmempty = false
-  o.datatype = "uinteger"
-
-  o = s:option(cbi.Value, "_limit_egress", i18n.translate("Upstream (kbit/s)"))
-  o:depends("_limit_enabled", "1")
-  o.value = uci:get("simple-tc", "mesh_vpn", "limit_egress")
-  o.rmempty = false
-  o.datatype = "uinteger"
+return function(form, uci)
+	local msg = translate(
+		'Your internet connection can be used to establish an ' ..
+	        'encrypted connection with other nodes. ' ..
+	        'Enable this option if there are no other nodes reachable ' ..
+	        'over WLAN in your vicinity or you want to make a part of ' ..
+	        'your connection\'s bandwidth available for the network. You can limit how ' ..
+	        'much bandwidth the node will use at most.'
+	)
+
+	local s = form:section(Section, nil, msg)
+
+	local o
+
+	local meshvpn = s:option(Flag, "meshvpn", translate("Use internet connection (mesh VPN)"))
+	meshvpn.default = uci:get_bool("fastd", "mesh_vpn", "enabled")
+	function meshvpn:write(data)
+		uci:set("fastd", "mesh_vpn", "enabled", data)
+	end
+
+	local limit = s:option(Flag, "limit_enabled", translate("Limit bandwidth"))
+	limit:depends(meshvpn, true)
+	limit.default = uci:get_bool("simple-tc", "mesh_vpn", "enabled")
+	function limit:write(data)
+		uci:set("simple-tc", "mesh_vpn", "interface")
+		uci:set("simple-tc", "mesh_vpn", "enabled", data)
+		uci:set("simple-tc", "mesh_vpn", "ifname", "mesh-vpn")
+	end
+
+	o = s:option(Value, "limit_ingress", translate("Downstream (kbit/s)"))
+	o:depends(limit, true)
+	o.default = uci:get("simple-tc", "mesh_vpn", "limit_ingress")
+	o.datatype = "uinteger"
+	function o:write(data)
+		uci:set("simple-tc", "mesh_vpn", "limit_ingress", data)
+	end
+
+	o = s:option(Value, "limit_egress", translate("Upstream (kbit/s)"))
+	o:depends(limit, true)
+	o.default = uci:get("simple-tc", "mesh_vpn", "limit_egress")
+	o.datatype = "uinteger"
+	function o:write(data)
+		uci:set("simple-tc", "mesh_vpn", "limit_egress", data)
+	end
+
+	return {'fastd', 'simple-tc'}
 end
-
-function M.handle(data)
-  uci:set("fastd", "mesh_vpn", "enabled", data._meshvpn)
-  uci:save("fastd")
-  uci:commit("fastd")
-
-  -- checks for nil needed due to o:depends(...)
-  if data._limit_enabled ~= nil then
-    uci:set("simple-tc", "mesh_vpn", "interface")
-    uci:set("simple-tc", "mesh_vpn", "enabled", data._limit_enabled)
-    uci:set("simple-tc", "mesh_vpn", "ifname", "mesh-vpn")
-
-    if data._limit_ingress ~= nil then
-      uci:set("simple-tc", "mesh_vpn", "limit_ingress", data._limit_ingress:trim())
-    end
-
-    if data._limit_egress ~= nil then
-      uci:set("simple-tc", "mesh_vpn", "limit_egress", data._limit_egress:trim())
-    end
-
-    uci:save("simple-tc")
-    uci:commit("simple-tc")
-  end
-end
-
-return M

+ 0 - 20
package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_reboot.htm

@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%=luci.i18n.context.lang%>" lang="<%=luci.i18n.context.lang%>">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    <title><%:Upgrading firmware%></title>
-    <link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
-  </head>
-  <body>
-    <div id="maincontainer">
-      <div id="maincontent">
-        <p>
-          <%:The firmware is currently being upgraded.%>
-          <strong><%:Don't switch off the device in any circumstance!%></strong>
-          <%:The upgrade will take a few minutes. When it is finished, your node will reboot automatically.%>
-        </p>
-      </div>
-    </div>
-  </body>
-</html>

+ 0 - 39
package/gluon-luci-admin/luasrc/usr/lib/lua/luci/controller/admin/index.lua

@@ -1,39 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
-
-module("luci.controller.admin.index", package.seeall)
-
-function index()
-	local uci_state = luci.model.uci.cursor_state()
-
-	-- Disable gluon-luci-admin when setup mode is not enabled
-	if uci_state:get_first('gluon-setup-mode', 'setup_mode', 'running', '0') ~= '1' then
-		return
-	end
-
-	local root = node()
-	if not root.lock then
-		root.target = alias("admin")
-		root.index = true
-	end
-
-	local page = entry({"admin"}, alias("admin", "index"), _("Advanced settings"), 10)
-	page.sysauth = "root"
-	page.sysauth_authenticator = function() return "root" end
-	page.index = true
-
-	entry({"admin", "index"}, template("admin/info"), _("Information"), 1)
-	entry({"admin", "remote"}, cbi("admin/remote"), _("Remote access"), 10)
-end

+ 0 - 139
package/gluon-luci-admin/luasrc/usr/lib/lua/luci/controller/admin/upgrade.lua

@@ -1,139 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
-
-module("luci.controller.admin.upgrade", package.seeall)
-
-function index()
-	local has_platform = nixio.fs.access("/lib/upgrade/platform.sh")
-	if has_platform then
-		entry({"admin", "upgrade"}, call("action_upgrade"), _("Upgrade firmware"), 90)
-		entry({"admin", "upgrade", "reboot"}, template("admin/upgrade_reboot"), nil, nil)
-	end
-end
-
-function action_upgrade()
-	local tmpfile = "/tmp/firmware.img"
-
-	-- Install upload handler
-	local file
-	luci.http.setfilehandler(
-		function(meta, chunk, eof)
-			if not nixio.fs.access(tmpfile) and not file and chunk and #chunk > 0 then
-				file = io.open(tmpfile, "w")
-			end
-			if file and chunk then
-				file:write(chunk)
-			end
-			if file and eof then
-				file:close()
-			end
-		end
-	)
-
-	-- Determine state
-	local step         = tonumber(luci.http.formvalue("step") or 1)
-
-        if step ~= 1 and not luci.dispatcher.test_post_security() then
-		nixio.fs.unlink(tmpfile)
-		return
-	end
-
-	local has_image    = nixio.fs.access(tmpfile)
-	local has_support  = image_supported(tmpfile)
-
-	-- Step 1: file upload, error on unsupported image format
-	if not has_image or not has_support or step == 1 then
-		-- If there is an image but user has requested step 1
-		-- or type is not supported, then remove it.
-		if has_image then
-			nixio.fs.unlink(tmpfile)
-		end
-
-		luci.template.render("admin/upgrade", {
-			bad_image=(has_image and not has_support or false)
-		} )
-
-	-- Step 2: present uploaded file, show checksum, confirmation
-	elseif step == 2 then
-		luci.template.render("admin/upgrade_confirm", {
-			checksum=image_checksum(tmpfile),
-			filesize=nixio.fs.stat(tmpfile).size,
-			flashsize=storage_size(),
-			keepconfig=luci.http.formvalue("keepcfg") == "1"
-		} )
-	elseif step == 3 then
-		local keepcfg = luci.http.formvalue("keepcfg") == "1"
-		fork_exec("/sbin/sysupgrade %s %q" % { keepcfg and "" or "-n", tmpfile })
-		luci.http.redirect(luci.dispatcher.build_url("admin", "upgrade", "reboot"))
-	end
-end
-
-function fork_exec(command)
-	local pid = nixio.fork()
-	if pid > 0 then
-		return
-	elseif pid == 0 then
-		-- change to root dir
-		nixio.chdir("/")
-
-		-- patch stdin, out, err to /dev/null
-		local null = nixio.open("/dev/null", "w+")
-		if null then
-			nixio.dup(null, nixio.stderr)
-			nixio.dup(null, nixio.stdout)
-			nixio.dup(null, nixio.stdin)
-			if null:fileno() > 2 then
-				null:close()
-			end
-		end
-
-		-- replace with target command
-		nixio.exec("/bin/sh", "-c", command)
-	end
-end
-
-function image_supported(tmpfile)
-	-- XXX: yay...
-	return ( 0 == os.execute(
-		"/sbin/sysupgrade -T %q >/dev/null"
-			% tmpfile
-	) )
-end
-
-function storage_size()
-	local size = 0
-	if nixio.fs.access("/proc/mtd") then
-		for l in io.lines("/proc/mtd") do
-			local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
-			if n == "linux" then
-				size = tonumber(s, 16)
-				break
-			end
-		end
-	elseif nixio.fs.access("/proc/partitions") then
-		for l in io.lines("/proc/partitions") do
-			local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
-			if b and n and not n:match('[0-9]') then
-				size = tonumber(b) * 1024
-				break
-			end
-		end
-	end
-	return size
-end
-
-function image_checksum(tmpfile)
-	return (luci.sys.exec("md5sum %q" % tmpfile):match("^([^%s]+)"))
-end

+ 0 - 87
package/gluon-luci-admin/luasrc/usr/lib/lua/luci/model/cbi/admin/remote.lua

@@ -1,87 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
-Copyright 2013 Nils Schneider <nils@nilsschneider.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
-
-local fs = require "nixio.fs"
-
-local f_keys = SimpleForm('keys', translate("SSH keys"), translate("You can provide your SSH keys here (one per line):"))
-f_keys.hidden = { submit_keys = '1' }
-
-local keys
-
-keys = f_keys:field(TextValue, "keys", "")
-keys.wrap    = "off"
-keys.rows    = 5
-keys.rmempty = true
-
-function keys.cfgvalue()
-	return fs.readfile("/etc/dropbear/authorized_keys") or ""
-end
-
-function keys.write(self, section, value)
-	if not f_keys:formvalue('submit_keys') then return end
-
-	fs.writefile("/etc/dropbear/authorized_keys", value:gsub("\r\n", "\n"):trim() .. "\n")
-end
-
-function keys.remove(self, section)
-	if not f_keys:formvalue('submit_keys') then return end
-
-	fs.remove("/etc/dropbear/authorized_keys")
-end
-
-local f_password = SimpleForm('password', translate("Password"),
-	translate(
-                "Alternatively, you can set a password to access you node. Please choose a secure password you don't use anywhere else.<br /><br />"
-                .. "If you set an empty password, login via password will be disabled. This is the default."
-	)
-)
-f_password.hidden = { submit_password = '1' }
-f_password.reset = false
-
-local pw1 = f_password:field(Value, "pw1", translate("Password"))
-pw1.password = true
-function pw1.cfgvalue()
-	return ''
-end
-
-local pw2 = f_password:field(Value, "pw2", translate("Confirmation"))
-pw2.password = true
-function pw2.cfgvalue()
-	return ''
-end
-
-function f_password:handle(state, data)
-	if not f_password:formvalue('submit_password') then return end
-
-	if data.pw1 ~= data.pw2 then
-		f_password.errmessage = translate("The password and the confirmation differ.")
-		return
-	end
-
-	if data.pw1 and #data.pw1 > 0 then
-		if luci.sys.user.setpasswd('root', data.pw1) == 0 then
-			f_password.message = translate("Password changed.")
-		else
-			f_password.errmessage = translate("Unable to change the password.")
-		end
-	else
-		-- We don't check the return code here as the error 'password for root is already locked' is normal...
-		os.execute('passwd -l root >/dev/null')
-		f_password.message = translate("Password removed.")
-	end
-end
-
-return f_keys, f_password

+ 0 - 19
package/gluon-luci-autoupdater/luasrc/usr/lib/lua/luci/controller/admin/autoupdater.lua

@@ -1,19 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2013 Nils Schneider <nils@nilsschneider.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
-
-module("luci.controller.admin.autoupdater", package.seeall)
-
-function index()
-        entry({"admin", "autoupdater"}, cbi("admin/autoupdater"), _("Automatic updates"), 80)
-end

+ 0 - 32
package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/view/gluon/cbi/mesh-vpn-fastd-mode.htm

@@ -1,32 +0,0 @@
-<div class="cbi-value">
-  <div class="cbi-value-title">
-    <input class="cbi-input-radio" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)" type="radio" value="security"<%= attr("id", cbid..'1') .. attr("name", cbid) .. ifattr((self:cfgvalue(section) or self.default) == "security", "checked", "checked") %> />
-  </div>
-  <div class="cbi-value-field-long">
-    <label<%= attr("for", cbid..'1') %> class="cbi-value-title"><%:Security mode%></label>
-    <br />
-    <%= translate(
-        'In security mode, the mesh VPN uses an encrypted tunnel to connect to the VPN servers. ' ..
-        'The encryption ensures that it is impossible for your internet access provider to see what ' ..
-        'data is exchanged over your node.'
-    ) %>
-    <br />
-  </div>
-  <div class="cbi-value-field-long-after"></div>
-</div>
-
-<div class="cbi-value cbi-value-last">
-  <div class="cbi-value-title">
-    <input class="cbi-input-radio" onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)" type="radio" value="performance"<%= attr("id", cbid..'2') .. attr("name", cbid) .. ifattr((self:cfgvalue(section) or self.default) == "performance", "checked", "checked") %> />
-  </div>
-  <div class="cbi-value-field-long">
-    <label<%= attr("for", cbid..'2') %> class="cbi-value-title"><%:Performance mode%></label>
-    <br />
-    <%= translate(
-        'In performance mode, no encryption is used. This usually allows for higher throughput, but the data exchanged over your node is not ' ..
-        'protected against eavesdropping.'
-    ) %>
-    <br />
-  </div>
-  <div class="cbi-value-field-long-after"></div>
-</div>

+ 0 - 5
package/gluon-luci-mesh-vpn-fastd/luasrc/usr/lib/lua/luci/controller/admin/mesh_vpn_fastd.lua

@@ -1,5 +0,0 @@
-module("luci.controller.admin.mesh_vpn_fastd", package.seeall)
-
-function index()
-  entry({"admin", "mesh_vpn_fastd"}, cbi("admin/mesh_vpn_fastd"), _("Mesh VPN"), 20)
-end

+ 0 - 40
package/gluon-luci-mesh-vpn-fastd/luasrc/usr/lib/lua/luci/model/cbi/admin/mesh_vpn_fastd.lua

@@ -1,40 +0,0 @@
-local uci = require("simple-uci").cursor()
-local util = luci.util
-
-local f = SimpleForm('mesh_vpn', translate('Mesh VPN'))
-
-local s = f:section(SimpleSection)
-
-local o = s:option(Value, 'mode')
-o.template = "gluon/cbi/mesh-vpn-fastd-mode"
-
-local methods = uci:get('fastd', 'mesh_vpn', 'method')
-if util.contains(methods, 'null') then
-  o.default = 'performance'
-else
-  o.default = 'security'
-end
-
-function f.handle(self, state, data)
-  if state == FORM_VALID then
-    local site = require 'gluon.site_config'
-
-    local methods = {}
-    if data.mode == 'performance' then
-      table.insert(methods, 'null')
-    end
-
-    for _, method in ipairs(site.fastd_mesh_vpn.methods) do
-      if method ~= 'null' then
-	table.insert(methods, method)
-      end
-    end
-
-    uci:set('fastd', 'mesh_vpn', 'method', methods)
-
-    uci:save('fastd')
-    uci:commit('fastd')
-  end
-end
-
-return f

+ 0 - 5
package/gluon-luci-node-role/luasrc/usr/lib/lua/luci/controller/admin/noderole.lua

@@ -1,5 +0,0 @@
-module("luci.controller.admin.noderole", package.seeall)
-
-function index()
-	entry({"admin", "noderole"}, cbi("admin/noderole"), "Node role", 20)
-end

+ 0 - 33
package/gluon-luci-node-role/luasrc/usr/lib/lua/luci/model/cbi/admin/noderole.lua

@@ -1,33 +0,0 @@
-local f, s, o
-local site = require 'gluon.site_config'
-local i18n = require "luci.i18n"
-local uci = require("simple-uci").cursor()
-local config = 'gluon-node-info'
-
--- where to read the configuration from
-local role = uci:get(config, uci:get_first(config, "system"), "role")
-
-f = SimpleForm("role", i18n.translate("Node role"))
-
-s = f:section(SimpleSection, nil, i18n.translate(
-  "If this node has a special role within the freifunk network you can specify this role here. "
-    .. "Please find out about the available roles and their impact first. "
-    .. "Only change the role if you know what you are doing."))
-
-o = s:option(ListValue, "role", i18n.translate("Role"))
-o.default = role
-o.rmempty = false
-for _, role in ipairs(site.roles.list) do
-  o:value(role, i18n.translate('gluon-luci-node-role:role:' .. role))
-end
-
-function f.handle(self, state, data)
-  if state == FORM_VALID then
-    uci:set(config, uci:get_first(config, "system"), "role", data.role)
-
-    uci:save(config)
-    uci:commit(config)
-  end
-end
-
-return f

+ 0 - 19
package/gluon-luci-portconfig/luasrc/usr/lib/lua/luci/controller/admin/portconfig.lua

@@ -1,19 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2013 Nils Schneider <nils@nilsschneider.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-        http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
-
-module("luci.controller.admin.portconfig", package.seeall)
-
-function index()
-        entry({"admin", "portconfig"}, cbi("admin/portconfig"), _("Network"), 20)
-end

+ 0 - 167
package/gluon-luci-portconfig/luasrc/usr/lib/lua/luci/model/cbi/admin/portconfig.lua

@@ -1,167 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2014 Nils Schneider <nils@nilsschneider.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
-
-local uci = require("simple-uci").cursor()
-local sysconfig = require 'gluon.sysconfig'
-local util = require 'gluon.util'
-
-local wan = uci:get_all("network", "wan")
-local wan6 = uci:get_all("network", "wan6")
-local dns = uci:get_first("gluon-wan-dnsmasq", "static")
-
-local f = SimpleForm("portconfig", translate("WAN connection"))
-
-local s
-local o
-
-s = f:section(SimpleSection, nil, nil)
-
-o = s:option(ListValue, "ipv4", translate("IPv4"))
-o:value("dhcp", translate("Automatic (DHCP)"))
-o:value("static", translate("Static"))
-o:value("none", translate("Disabled"))
-o.default = wan.proto
-
-o = s:option(Value, "ipv4_addr", translate("IP address"))
-o:depends("ipv4", "static")
-o.value = wan.ipaddr
-o.datatype = "ip4addr"
-o.rmempty = false
-
-o = s:option(Value, "ipv4_netmask", translate("Netmask"))
-o:depends("ipv4", "static")
-o.value = wan.netmask or "255.255.255.0"
-o.datatype = "ip4addr"
-o.rmempty = false
-
-o = s:option(Value, "ipv4_gateway", translate("Gateway"))
-o:depends("ipv4", "static")
-o.value = wan.gateway
-o.datatype = "ip4addr"
-o.rmempty = false
-
-
-s = f:section(SimpleSection, nil, nil)
-
-o = s:option(ListValue, "ipv6", translate("IPv6"))
-o:value("dhcpv6", translate("Automatic (RA/DHCPv6)"))
-o:value("static", translate("Static"))
-o:value("none", translate("Disabled"))
-o.default = wan6.proto
-
-o = s:option(Value, "ipv6_addr", translate("IP address"))
-o:depends("ipv6", "static")
-o.value = wan6.ip6addr
-o.datatype = "ip6addr"
-o.rmempty = false
-
-o = s:option(Value, "ipv6_gateway", translate("Gateway"))
-o:depends("ipv6", "static")
-o.value = wan6.ip6gw
-o.datatype = "ip6addr"
-o.rmempty = false
-
-
-if dns then
-	s = f:section(SimpleSection, nil, nil)
-
-	o = s:option(DynamicList, "dns", translate("Static DNS servers"))
-	o:write(nil, uci:get("gluon-wan-dnsmasq", dns, "server"))
-	o.datatype = "ipaddr"
-end
-
-s = f:section(SimpleSection, nil, nil)
-
-o = s:option(Flag, "mesh_wan", translate("Enable meshing on the WAN interface"))
-o.default = uci:get_bool("network", "mesh_wan", "auto") and o.enabled or o.disabled
-o.rmempty = false
-
-if sysconfig.lan_ifname then
-	o = s:option(Flag, "mesh_lan", translate("Enable meshing on the LAN interface"))
-	o.default = uci:get_bool("network", "mesh_lan", "auto") and o.enabled or o.disabled
-	o.rmempty = false
-end
-
-if uci:get('system', 'gpio_switch_poe_passthrough') then
-	s = f:section(SimpleSection, nil, nil)
-	o = s:option(Flag, "poe_passthrough", translate("Enable PoE passthrough"))
-	o.default = uci:get_bool("system", "gpio_switch_poe_passthrough", "value") and o.enabled or o.disabled
-	o.rmempty = false
-end
-
-function f.handle(self, state, data)
-	if state == FORM_VALID then
-	uci:set("network", "wan", "proto", data.ipv4)
-	if data.ipv4 == "static" then
-		uci:set("network", "wan", "ipaddr", data.ipv4_addr:trim())
-		uci:set("network", "wan", "netmask", data.ipv4_netmask:trim())
-		uci:set("network", "wan", "gateway", data.ipv4_gateway:trim())
-	else
-		uci:delete("network", "wan", "ipaddr")
-		uci:delete("network", "wan", "netmask")
-		uci:delete("network", "wan", "gateway")
-	end
-
-	uci:set("network", "wan6", "proto", data.ipv6)
-	if data.ipv6 == "static" then
-		uci:set("network", "wan6", "ip6addr", data.ipv6_addr:trim())
-		uci:set("network", "wan6", "ip6gw", data.ipv6_gateway:trim())
-	else
-		uci:delete("network", "wan6", "ip6addr")
-		uci:delete("network", "wan6", "ip6gw")
-	end
-
-	uci:set("network", "mesh_wan", "auto", data.mesh_wan)
-
-	if sysconfig.lan_ifname then
-		uci:set("network", "mesh_lan", "auto", data.mesh_lan)
-
-		local interfaces = uci:get_list("network", "client", "ifname")
-
-		for lanif in sysconfig.lan_ifname:gmatch('%S+') do
-			if data.mesh_lan == '1' then
-				util.remove_from_set(interfaces, lanif)
-			else
-				util.add_to_set(interfaces, lanif)
-			end
-		end
-
-		uci:set_list("network", "client", "ifname", interfaces)
-	end
-
-	uci:save("network")
-	uci:commit("network")
-
-	if uci:get('system', 'gpio_switch_poe_passthrough') then
-	uci:set('system', 'gpio_switch_poe_passthrough', 'value', data.poe_passthrough)
-	uci:save('system')
-	uci:commit('system')
-	end
-
-	if dns then
-		if #data.dns > 0 then
-		uci:set("gluon-wan-dnsmasq", dns, "server", data.dns)
-		else
-		uci:delete("gluon-wan-dnsmasq", dns, "server")
-		end
-
-		uci:save("gluon-wan-dnsmasq")
-		uci:commit("gluon-wan-dnsmasq")
-	end
-	end
-
-	return true
-end
-
-return f

+ 0 - 5
package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/controller/admin/privatewifi.lua

@@ -1,5 +0,0 @@
-module("luci.controller.admin.privatewifi", package.seeall)
-
-function index()
-	entry({"admin", "privatewifi"}, cbi("admin/privatewifi"), _("Private WLAN"), 10)
-end

+ 0 - 67
package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua

@@ -1,67 +0,0 @@
-local uci = require("simple-uci").cursor()
-local util = require 'gluon.util'
-
-local f, s, o, ssid
-
--- where to read the configuration from
-local primary_iface = 'wan_radio0'
-local ssid = uci:get('wireless', primary_iface, "ssid")
-
-f = SimpleForm("wifi", translate("Private WLAN"))
-
-s = f:section(SimpleSection, nil, translate(
-                'Your node can additionally extend your private network by bridging the WAN interface '
-                  .. 'with a separate WLAN. This feature is completely independent of the mesh functionality. '
-                  .. 'Please note that the private WLAN and meshing on the WAN interface should not be enabled '
-                  .. 'at the same time.'
-))
-
-o = s:option(Flag, "enabled", translate("Enabled"))
-o.default = (ssid and not uci:get_bool('wireless', primary_iface, "disabled")) and o.enabled or o.disabled
-o.rmempty = false
-
-o = s:option(Value, "ssid", translate("Name (SSID)"))
-o:depends("enabled", '1')
-o.datatype = "maxlength(32)"
-o.default = ssid
-
-o = s:option(Value, "key", translate("Key"), translate("8-63 characters"))
-o:depends("enabled", '1')
-o.datatype = "wpakey"
-o.default = uci:get('wireless', primary_iface, "key")
-
-function f.handle(self, state, data)
-  if state == FORM_VALID then
-    util.iterate_radios(
-      function(radio, index)
-        local name   = "wan_" .. radio
-
-        if data.enabled == '1' then
-          local macaddr = util.get_wlan_mac(radio, index, 4)
-
-          -- set up WAN wifi-iface
-          uci:section('wireless', "wifi-iface", name,
-                      {
-                        device     = radio,
-                        network    = "wan",
-                        mode       = 'ap',
-                        encryption = 'psk2',
-                        ssid       = data.ssid,
-                        key        = data.key,
-                        macaddr    = macaddr,
-                        disabled   = false,
-                      }
-          )
-        else
-          -- disable WAN wifi-iface
-          uci:set('wireless', name, "disabled", true)
-        end
-      end
-    )
-
-    uci:save('wireless')
-    uci:commit('wireless')
-  end
-end
-
-return f

+ 0 - 6
package/gluon-luci-theme/files/etc/uci-defaults/luci-theme-gluon

@@ -1,6 +0,0 @@
-#!/bin/sh
-uci batch <<-EOF
-	set luci.themes.Gluon=/luci-static/gluon
-        commit luci
-EOF
-	

+ 0 - 19
package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/footer.htm

@@ -1,19 +0,0 @@
-<%#
-LuCI - Lua Configuration Interface
-Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-
--%>
-</div>
-</div>
-
-</body>
-</html>

+ 0 - 171
package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm

@@ -1,171 +0,0 @@
-<%#
-LuCI - Lua Configuration Interface
-Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008-2010 Jo-Philipp Wich <xm@subsignal.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file 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 sys  = require "luci.sys"
-	local http = require "luci.http"
-	local disp = require "luci.dispatcher"
-	local uci  = require("simple-uci").cursor()
-	local fs   = require "nixio.fs"
-	local gluon_luci = require "gluon.luci"
-	local pretty_hostname = require "pretty_hostname"
-
-	local hostname = pretty_hostname.get(uci)
-	local release = fs.readfile("/lib/gluon/release")
-
-	local request  = disp.context.path
-	local request2 = disp.context.request
-
-	local category = request[1]
-	local cattree  = category and disp.node(category)
-
-	local leaf = request2[#request2]
-
-	local tree = disp.node()
-	local node = disp.context.dispatched
-
-	local categories = disp.node_childs(tree)
-
-	local c = tree
-	local i, r
-
-	-- tag all nodes leading to this page
-	for i, r in ipairs(request) do
-		if c.nodes and c.nodes[r] then
-			c = c.nodes[r]
-			c._menu_selected = true
-		end
-	end
-
-	http.prepare_content("application/xhtml+xml")
-
-	local function nodeurl(prefix, name, query)
-		local url = controller .. prefix .. name .. "/"
-		if query then
-			url = url .. http.build_querystring(query)
-		end
-		return pcdata(url)
-	end
-
-	local function subtree(prefix, node, level)
-		if not level then
-			level = 1
-		end
-
-		local childs = disp.node_childs(node)
-		if #childs > 0 then
-%>
-	<div class="tabmenu<%=level%>">
-	<ul class="tabmenu l<%=level%>">
-		<%
-			local selected_node
-			local selected_name
-			local i, v
-
-			for i, v in ipairs(childs) do
-				local nnode = node.nodes[v]
-				if nnode._menu_selected then
-					selected_node = nnode
-					selected_name = v
-				end
-		%>
-			<li class="tabmenu-item-<%=v%><% if nnode._menu_selected or (node.leaf and v == leaf) then %> active<% end %>">
-				<a href="<%=nodeurl(prefix, v, nnode.query)%>"><%=striptags(translate(nnode.title))%></a>
-			</li>
-		<%
-			end
-		%>
-	</ul>
-	<br style="clear:both" />
-<%
-			if selected_node then
-				subtree(prefix .. selected_name .. "/", selected_node, level + 1)
-			end
-%>
-	</div>
-<%
-		end
-	end
--%>
-
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%=luci.i18n.context.lang%>" lang="<%=luci.i18n.context.lang%>">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta http-equiv="Content-Script-Type" content="text/javascript" />
-<link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
-<% if node and node.css then %><link rel="stylesheet" type="text/css" media="screen" href="<%=resource%>/<%=node.css%>" />
-<% end -%>
-<% if css then %><style title="text/css">
-<%= css %>
-</style>
-<% end -%>
-<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
-<title><%=gluon_luci.escape( hostname .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - LuCI</title>
-</head>
-<body class="lang_<%=luci.i18n.context.lang%>">
-
-<div id="menubar">
-<div class="hostinfo">
-	<%=gluon_luci.escape(hostname)%>
-	<% if release then %>
-	/ <%=gluon_luci.escape(release)%>
-	<% end %>
-	<span id="xhr_poll_status" style="display:none" onclick="XHR.running() ? XHR.halt() : XHR.run()">
-		| <%:Auto Refresh%>:
-		<span id="xhr_poll_status_on"><%:on%></span>
-		<span id="xhr_poll_status_off" style="display:none"><%:off%></span>
-	</span>
-</div>
-
-<% if #categories > 1 then %>
-	<ul id="modemenu">
-		<% for i, r in ipairs(categories) do %>
-			<li><a<% if request[1] == r then %> class="active"<%end%> href="<%=controller%>/<%=r%>/"><%=striptags(translate(tree.nodes[r].title))%></a></li>
-		<% end %>
-	</ul>
-<% end %>
-
-<%
-if tree.nodes[category] and tree.nodes[category].ucidata then
-	local ucic = 0
-	for i, j in pairs(require("simple-uci").cursor():changes()) do
-		for k, l in pairs(j) do
-			for m, n in pairs(l) do
-				ucic = ucic + 1;
-			end
-		end
-	end
--%>
-<div id="savemenu">
-	<% if ucic > 0 then %>
-		<a class="warning" href="<%=controller%>/<%=category%>/uci/changes/?redir=<%=luci.http.urlencode(luci.http.formvalue("redir") or REQUEST_URI)%>"><%:Unsaved Changes%>: <%=ucic%></a>
-	<%- else -%>
-		<a href="#"><%:Changes%>: 0</a>
-	<% end -%>
-</div><% end %>
-
-</div>
-
-<div id="maincontainer">
-  <% if category then subtree("/" .. category .. "/", cattree) end %>
-
-	<div id="maincontent">
-		<noscript>
-			<div class="errorbox">
-				<strong><%:Java Script required!%></strong><br />
-				<%:You must enable Java Script in your browser or LuCI will not work properly.%>
-			</div>
-		</noscript>

File diff suppressed because it is too large
+ 0 - 0
package/gluon-luci-theme/files/www/luci-static/gluon/cascade.css


+ 0 - 28
package/gluon-luci-theme/luasrc/usr/lib/lua/gluon/luci.lua

@@ -1,28 +0,0 @@
--- Config mode utility functions
-
-local string = string
-
-module 'gluon.luci'
-
-function escape(s)
-	return (string.gsub(s, '[<>&"]', {
-		['<'] = '&lt;',
-		['>'] = '&gt;',
-		['&'] = '&amp;',
-		['"'] = '&quot;',
-	}))
-end
-
-function urlescape(s)
-	return (string.gsub(s, '[^a-zA-Z0-9%-_%.~]',
-		function(c)
-			local ret = ''
-
-			for i = 1, string.len(c) do
-				ret = ret .. string.format('%%%02X', string.byte(c, i, i))
-			end
-
-			return ret
-		end
-	))
-end

+ 0 - 1029
package/gluon-luci-theme/sass/cascade.scss

@@ -1,1029 +0,0 @@
-/* ATTENTION: This file is not compiled when building gluon.
-   The compiled version is at ../files/www/luci-static/gluon/cascade.css
-
-   Use sass like this to update it:
-
-   sass cascade.scss ../files/www/luci-static/gluon/cascade.css
-
-   When commiting changes to this file make sure to commit the respective
-   changes to the compilid version within the same commit!
-   */
-
-@charset "utf-8";
-
-$ffyellow:  #ffb400;
-$ffmagenta: #dc0067;
-$ffzusatz:  #009ee0;
-$red:       #ee3300;
-
-@mixin button {
-  &::-moz-focus-inner {
-    padding: 0;
-    border: 0;
-  }
-
-  display: inline-block;
-  zoom: 1;
-  line-height: normal;
-  white-space: nowrap;
-  vertical-align: baseline;
-  text-align: center;
-  cursor: pointer;
-  -webkit-user-drag: none;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-
-
-  font-size: 100%;
-  padding: 0.5em 1em;
-  color: rgba(0, 0, 0, 0.80);
-  border: none rgba(0, 0, 0, 0);
-  background-color: #E6E6E6;
-  text-decoration: none;
-  border-radius: 2px;
-
-  /* Transitions */
-  -webkit-transition: 0.1s linear -webkit-box-shadow;
-  -moz-transition: 0.1s linear -moz-box-shadow;
-  -ms-transition: 0.1s linear box-shadow;
-  -o-transition: 0.1s linear box-shadow;
-  transition: 0.1s linear box-shadow;
-
-  &:active {
-    box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;
-  }
-
-  &:focus {
-    outline: 0;
-  }
-
-  &:hover, &:focus {
-    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(transparent), color-stop(40%, rgba(0,0,0, 0.05)), to(rgba(0,0,0, 0.10)));
-    background-image: -webkit-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
-    background-image: -moz-linear-gradient(top, rgba(0,0,0, 0.05) 0%, rgba(0,0,0, 0.10));
-    background-image: -o-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
-    background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
-  }
-
-  &[disabled] {
-    border: none;
-    background-image: none;
-    opacity: 0.40;
-    cursor: not-allowed;
-    box-shadow: none;
-  }
-}
-
-@mixin button-primary {
-  background-color: $ffzusatz;
-  color: #fff;
-}
-
-.lang_he {
-  direction: RTL;
-  unicode-bidi: embed;
-}
-
-.hidden {
-  display: none;
-}
-
-html {
-  min-height: 100%;
-  height: auto;
-  position:relative;
-}
-
-body, input, select, option {
-  font-family: 'Open Sans', Arial, sans-serif;
-  font-size: 12pt;
-}
-
-body {
-  color: rgb(77, 78, 83);
-  line-height: 1.5em;
-  margin: 0;
-  display: flex;
-  flex-direction: column;
-  min-height: 100vh;
-  background-color: #f3f3f3;
-}
-
-a img {
-  border: none;
-  text-decoration: none;
-}
-
-.tabmenu1 {
-  text-align: center;
-}
-
-ul.tabmenu {
-  list-style: none;
-  padding: 0;
-  margin: 2em 0;
-  display: inline-flex;
-}
-
-ul.tabmenu li {
-  white-space: nowrap;
-  margin: 0 0.5em;
-  padding: 0;
-  text-align: center;
-
-  a {
-    display: block;
-    text-decoration: none;
-    padding: 1em;
-    margin: 0;
-    color: #333;
-    border-radius: 2em;
-
-    &:hover {
-      background: lighten($ffyellow, 35);
-    }
-  }
-
-  &.active a {
-    font-weight: bold;
-    background: white;
-    color: #333;
-  }
-}
-
-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;
-}
-
-.error {
-  color: #ff0000;
-  background-color: white;
-}
-
-div.hostinfo {
-  margin: 0;
-  padding: 0;
-  font-size: 80%;
-  padding: 0.5em;
-  flex: 1;
-  font-weight: bold;
-}
-
-#xhr_poll_status {
-  cursor: pointer;
-}
-
-#xhr_poll_status #xhr_poll_status_off {
-  font-weight: bold;
-  color: #FF0000;
-}
-
-#xhr_poll_status #xhr_poll_status_on {
-  font-weight: bold;
-  color: #00FF00;
-}
-
-#menubar {
-  display: flex;
-  background: $ffmagenta;
-  color: #ffffff;
-}
-
-#menubar .warning {
-  color: red;
-  background-color: #557788;
-}
-
-#menubar a:link,
-#menubar a:visited {
-  position: relative;
-  display: block;
-  padding: 0.5em;
-  text-decoration: none;
-  font-size: 80%;
-  font-weight: normal;
-  color: white;
-}
-
-#menubar a:link:hover,
-#menubar a:visited:hover,
-#menubar a:link:focus,
-#menubar a:visited:focus {
-  background: $ffyellow;
-  color: black;
-}
-
-#menubar a:link.active,
-#menubar a:visited.active {
-  background: $ffyellow;
-  color: black;
-  font-weight: bold;
-}
-
-#menubar a:link.warning,
-#menubar a:visited.warning {
-  background: #000000;
-  color: red;
-  font-weight: bold;
-}
-
-#modemenu {
-  list-style: none;
-  margin: 0;
-  padding: 0;
-}
-
-#modemenu li {
-  display: inline-block;
-}
-
-#savemenu {
-}
-
-.lang_he #savemenu {
-}
-
-.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 {
-  padding: 0 1em 2em;
-  max-width: 60em;
-  min-width: 40em;
-  margin: 1em auto;
-}
-
-.lang_he #maincontent {
-  direction: rtl;
-}
-
-#maincontent h2 {
-}
-
-#maincontent h3 {
-}
-
-#maincontent p {
-  margin-bottom: 1em;
-}
-
-.cbi-section {
-  margin: 0;
-  padding: 0;
-  border: none;
-}
-
-.cbi-section legend {
-  font-size: 1.4em;
-  font-weight: bold;
-  position: relative;
-  padding: 0;
-  margin-bottom: 0.5em;
-}
-
-.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: 2em;
-}
-
-.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:-webkit-input-placeholder {
-  color: #AAAAAA;
-}
-
-input:-moz-placeholder {
-  color: #AAAAAA;
-}
-
-input:-ms-input-placeholder {
-  color: #AAAAAA;
-}
-
-input[type=checkbox] {
-  display: none;
-
-  & + label {
-    display: inline-block;
-    width: 1em;
-    height: 1em;
-    margin: 0;
-  }
-
-  &:checked + label:after {
-    content: '✔';
-    color: $ffmagenta;
-    vertical-align: middle;
-    position: absolute;
-    top: 50%;
-    left: 0;
-    margin-top: -0.5em;
-    width: 100%;
-    text-align: center;
-    font-size: 1.7em;
-  }
-}
-
-input[type=submit],
-input[type=reset],
-input[type=image],
-input[type=button] {
-  cursor: pointer;
-}
-
-select,
-input,
-textarea,
-input[type=checkbox] + label {
-  color: darken($ffzusatz, 30);
-  border: none;
-  background: lighten($ffyellow, 30);
-  border-radius: 3pt;
-  padding: 0.5em;
-}
-
-input[type=image] {
-  border: none;
-}
-
-select,
-input[type=text],
-input[type=password] {
-  width: 20em;
-}
-
-td select,
-td input[type=text],
-td input[type=password] {
-  width: 99%;
-}
-
-img.cbi-image-button {
-  cursor: pointer;
-  margin: 0 2px;
-  vertical-align: middle;
-}
-
-input.cbi-button {
-  @include button;
-
-  margin-left: 0.5em;
-  background-repeat: no-repeat;
-}
-
-input.cbi-input-user {
-  background-image: url('../resources/cbi/user.gif');
-  background-repeat: no-repeat;
-  background-position: 1px center;
-  color: #000000;
-  text-indent: 17px;
-}
-
-input.cbi-input-find,
-input.cbi-button-find {
-  background-image: url('../resources/cbi/find.gif');
-  color: #000000;
-  padding-left: 17px;
-}
-
-input.cbi-input-reload {
-  background-image: url('../resources/cbi/reload.gif');
-  color: #000000;
-  padding-left: 17px;
-}
-
-input.cbi-input-add,
-input.cbi-button-add {
-  background-image: url('../resources/cbi/add.gif');
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-input.cbi-input-fieldadd,
-input.cbi-button-fieldadd {
-  background-image: url(../resources/cbi/fieldadd.gif);
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-input.cbi-input-reset,
-input.cbi-button-reset {
-  background-color: $red;
-  color: #fff;
-}
-
-input.cbi-input-save,
-input.cbi-button-save {
-  @include button-primary;
-}
-
-input.cbi-input-apply,
-input.cbi-button-apply {
-  @include button-primary;
-}
-
-input.cbi-input-link,
-input.cbi-button-link {
-  background-image: url('../resources/cbi/link.gif');
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-input.cbi-input-download,
-input.cbi-button-download {
-  background-image: url('../resources/cbi/download.gif');
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-input.cbi-input-remove,
-div.cbi-section-remove input {
-  background-image: url('../resources/cbi/remove.gif');
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-input.cbi-button-up {
-  background-image: url('../resources/cbi/up.gif');
-  padding-left: 11px;
-  padding-right: 1px;
-}
-
-input.cbi-button-down {
-  background-image: url('../resources/cbi/down.gif');
-  padding-left: 11px;
-  padding-right: 1px;
-}
-
-input.cbi-button-edit {
-  background-image: url('../resources/cbi/edit.gif');
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-input.cbi-button-reload {
-  background-image: url('../resources/cbi/reload.gif');
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-input.cbi-button-remove {
-  background-image: url('../resources/cbi/remove.gif');
-  color: #000000;
-  padding-left: 17px;
-  padding-right: 1px;
-}
-
-.cbi-input-invalid {
-  background: $red !important;
-  color: white;
-}
-
-div.cbi-section-remove input {
-  border-bottom: none;
-}
-
-textarea {
-  margin-left: -1px;
-  margin-bottom: 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 {
-  background-color: #eeeeff;
-  color: #000000;
-}
-
-table.cbi-section-table .cbi-rowstyle-1:hover,
-table.cbi-section-table .cbi-rowstyle-2:hover {
-  background-color: #b2c8d4;
-  color: #000000;
-}
-
-table.cbi-section-table .cbi-section-table-cell {
-  padding: 3px;
-  white-space: nowrap;
-}
-
-.cbi-section .cbi-rowstyle-1 h3 {
-  background-color: #eeeeff;
-  color: #555555;
-}
-
-.cbi-rowstyle-2 {
-  color: #000000;
-}
-
-div.cbi-value {
-  display: flex;
-  flex-direction: row;
-  margin-bottom: 0.5em;
-}
-
-.cbi-value-title {
-  flex: 2;
-  text-align: right;
-  padding-right: 1em;
-  font-weight: bold;
-}
-
-div.cbi-value-field {
-  flex: 3;
-  position: relative;
-
-  input, select, input + label {
-    position: relative;
-    top: -0.39em;
-  }
-}
-
-div.cbi-value-field-long {
-  flex: 10;
-  position: relative;
-
-
-  input, select, input + label {
-    position: relative;
-    top: -0.39em;
-  }
-}
-
-div.cbi-value-field-long-after {
-  flex: 2;
-}
-
-div.cbi-value-description {
-  font-size: 8pt;
-}
-
-div.cbi-section-create {
-  clear: left;
-  white-space: nowrap;
-  vertical-align: top;
-}
-
-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;
-}
-
-.cbi-map-descr:empty, .cbi-section-descr:empty {
-  display: none;
-}
-
-.cbi-map-descr, .cbi-section-descr, .cbi-page-actions {
-  padding: 1em;
-  background: #ececec;
-}
-
-.cbi-page-actions {
-  text-align: right;
-  display: flex;
-  display: -moz-flex;
-  -moz-flex-flow: row-reverse;
-  flex-flow: row-reverse;
-}
-
-div.cbi-optionals {
-  padding: 0.25em;
-  border-bottom: 1px dotted #bbbbbb;
-}
-
-div.cbi-section-remove {
-  float: right;
-}
-
-.cbi-section-node {
-  clear: both;
-  position: relative;
-  border: none;
-}
-
-.cbi-section-node-tabbed {
-  border-top-left-radius: 0;
-}
-
-.cbi-section-node .cbi-value-last {
-  border-bottom: none;
-}
-
-.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%;
-  vertical-align: top;
-}
-
-td.cbi-section-table-optionals {
-  text-align: left !important;
-  padding-top: 1em;
-}
-
-.cbi-value-helpicon img {
-  display: none;
-}
-
-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 {
-  background-color: #ffcccc;
-}
-
-.cbi-section-error {
-  color: red;
-  background-color: white;
-  font-size: 95%;
-  border: 1px dotted red;
-  margin: 3px;
-  padding: 3px;
-}
-
-.cbi-value-field var {
-  color: #2222FF;
-}
-
-ul.cbi-tabmenu {
-  padding: 3px 0;
-  margin-left: 0 !important;
-  list-style-type: none;
-  position: relative;
-  z-index: 10;
-  top: 4px;
-  line-height: 20px;
-}
-
-ul.cbi-tabmenu li.cbi-tab,
-ul.cbi-tabmenu li.cbi-tab-disabled {
-  display: inline;
-  margin: 0;
-}
-
-ul.cbi-tabmenu li.cbi-tab a,
-ul.cbi-tabmenu li.cbi-tab-disabled a {
-  text-decoration: none;
-  padding: 3px 7px;
-  margin-right: 3px;
-  border: 1px solid #BBBBBB;
-  border-bottom: none;
-  border-radius: 3px 3px 0 0;
-  background-color: #EEEEEE;
-  color: #BBBBBB;
-}
-
-ul.cbi-tabmenu li.cbi-tab-highlighted a {
-  color: #000000;
-  background-color: #FFEEAA;
-}
-
-ul.cbi-tabmenu li a:hover {
-  color: #000000;
-}
-
-ul.cbi-tabmenu li.cbi-tab a {
-  padding-top: 4px;
-  color: #000000;
-  background-color: #FFFFFF;
-}
-
-div.cbi-tab-descr {
-  background-image: url(/luci-static/resources/cbi/help.gif);
-  background-position: 0.25em 50%;
-  background-repeat: no-repeat;
-  border-bottom: 1px solid #CCCCCC;
-  margin: 0.25em 0.25em 2em;
-  padding: 0.5em 0.5em 0.5em 2em;
-}
-
-.left {
-  text-align: left !important;
-}
-
-.right {
-  text-align: right !important;
-}
-
-.luci {
-  position: absolute;
-  bottom: 0;
-  left: 1em;
-  height: 1.5em;
-  font-size: 80%;
-}
-
-.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;
-}
-
-.errorbox {
-  border: 1px solid #FF0000;
-  background-color: #FFCCCC;
-  padding: 5px;
-  margin-bottom: 5px;
-}
-
-.errorbox a {
-  color: #000000 !important;
-}
-
-
-.ifacebox {
-  background-color: #FFFFFF;
-  border: 1px solid #CCCCCC;
-  margin: 0 10px;
-  text-align: center;
-  white-space: nowrap;
-}
-
-.ifacebox .ifacebox-head {
-  border-bottom: 1px solid #CCCCCC;
-  padding: 2px;
-}
-
-.ifacebox .ifacebox-body {
-  padding: 2px;
-}
-
-
-.ifacebadge {
-  background-color: #FFFFFF;
-  border: 1px solid #CCCCCC;
-  padding: 2px;
-  margin-left: 2px;
-  display: inline-block;
-}
-
-.ifacebadge-active {
-  border-color: #000000;
-  font-weight: bold;
-}
-
-
-.zonebadge {
-  padding: 2px;
-  display: inline-block;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.zonebadge em,
-.zonebadge strong {
-  margin: 3px;
-  display: inline-block;
-}
-
-.zonebadge input {
-  width: 6em;
-  height: 1.5em;
-}
-
-.zonebadge-empty {
-  border: 1px dashed #AAAAAA;
-  color: #AAAAAA;
-  font-style: italic;
-  font-size: smaller;
-}
-
-
-.uci-change-list {
-  font-family: monospace;
-}
-
-.uci-change-list ins,
-.uci-change-legend-label ins {
-  text-decoration: none;
-  border: 1px solid #00FF00;
-  background-color: #CCFFCC;
-  display: block;
-  padding: 2px;
-}
-
-.uci-change-list del,
-.uci-change-legend-label del {
-  text-decoration: none;
-  border: 1px solid #FF0000;
-  background-color: #FFCCCC;
-  display: block;
-  font-style: normal;
-  padding: 2px;
-}
-
-.uci-change-list var,
-.uci-change-legend-label var {
-  text-decoration: none;
-  border: 1px solid #CCCCCC;
-  background-color: #EEEEEE;
-  display: block;
-  font-style: normal;
-  padding: 2px;
-}
-
-.uci-change-list var ins,
-.uci-change-list var del {
-  /*display: inline;*/
-  border: none;
-  white-space: pre;
-  font-style: normal;
-  padding: 0px;
-}
-
-.uci-change-legend {
-  padding: 5px;
-}
-
-.uci-change-legend-label {
-  width: 150px;
-  float: left;
-  font-size: 80%;
-}
-
-.uci-change-legend-label>ins,
-.uci-change-legend-label>del,
-.uci-change-legend-label>var {
-  float: left;
-  margin-right: 4px;
-  width: 10px;
-  height: 10px;
-  display: block;
-}
-
-.uci-change-legend-label var ins,
-.uci-change-legend-label var del {
-  line-height: 6px;
-  border: none;
-}
-
-// Hide show/hide password toggle image
-.cbi-input-password + img {
-  display: none;
-}
-
-.the-key {
-  text-align: left;
-  font-size: 1.4em;
-  background: lighten($ffyellow, 35);
-  border: 3pt dashed $ffmagenta;
-  margin-bottom: 0.5em;
-  padding: 0.5em
-}

+ 0 - 5
package/gluon-luci-wifi-config/luasrc/usr/lib/lua/luci/controller/admin/wifi-config.lua

@@ -1,5 +0,0 @@
-module("luci.controller.admin.wifi-config", package.seeall)
-
-function index()
-  entry({"admin", "wifi-config"}, cbi("admin/wifi-config"), _("WLAN"), 20)
-end

+ 0 - 169
package/gluon-luci-wifi-config/luasrc/usr/lib/lua/luci/model/cbi/admin/wifi-config.lua

@@ -1,169 +0,0 @@
-local uci = require("simple-uci").cursor()
-local fs = require 'nixio.fs'
-local iwinfo = require 'iwinfo'
-
-
-local function find_phy_by_path(path)
-  for phy in fs.glob("/sys/devices/" .. path .. "/ieee80211/phy*") do
-    return phy:match("([^/]+)$")
-  end
-end
-
-local function find_phy_by_macaddr(macaddr)
-  local addr = macaddr:lower()
-  for file in fs.glob("/sys/class/ieee80211/*/macaddress") do
-    if luci.util.trim(fs.readfile(file)) == addr then
-      return file:match("([^/]+)/macaddress$")
-    end
-  end
-end
-
-local function txpower_list(phy)
-  local list = iwinfo.nl80211.txpwrlist(phy) or { }
-  local off  = tonumber(iwinfo.nl80211.txpower_offset(phy)) or 0
-  local new  = { }
-  local prev = -1
-  local _, val
-  for _, val in ipairs(list) do
-    local dbm = val.dbm + off
-    local mw  = math.floor(10 ^ (dbm / 10))
-    if mw ~= prev then
-      prev = mw
-      table.insert(new, {
-                     display_dbm = dbm,
-                     display_mw  = mw,
-                     driver_dbm  = val.dbm,
-      })
-    end
-  end
-  return new
-end
-
-
-local f = SimpleForm("wifi", translate("WLAN"))
-
-local s = f:section(SimpleSection, nil, translate(
-                "You can enable or disable your node's client and mesh network "
-                  .. "SSIDs here. Please don't disable the mesh network without "
-                  .. "a good reason, so other nodes can mesh with yours.<br /><br />"
-                  .. "It is also possible to configure the WLAN adapters transmission power "
-                  .. "here. Please note that the transmission power values include the antenna gain "
-                  .. "where available, but there are many devices for which the gain is unavailable or inaccurate."
-))
-
-local radios = {}
-
--- look for wifi interfaces and add them to the array
-uci:foreach('wireless', 'wifi-device',
-  function(s)
-    table.insert(radios, s['.name'])
-  end
-)
-
--- add a client and mesh checkbox for each interface
-for _, radio in ipairs(radios) do
-  local config = uci:get_all('wireless', radio)
-  local p
-
-  if config.hwmode == '11g' or config.hwmode == '11ng' then
-    p = f:section(SimpleSection, translate("2.4GHz WLAN"))
-  elseif config.hwmode == '11a' or config.hwmode == '11na' then
-    p = f:section(SimpleSection, translate("5GHz WLAN"))
-  end
-
-  if p then
-    local o
-
-    if uci:get('wireless', 'client_' .. radio) then
-      o = p:option(Flag, radio .. '_client_enabled', translate("Enable client network (access point)"))
-      o.default = uci:get_bool('wireless', 'client_' .. radio, "disabled") and o.disabled or o.enabled
-      o.rmempty = false
-    end
-
-    if uci:get('wireless', 'mesh_' .. radio) then
-      o = p:option(Flag, radio .. '_mesh_enabled', translate("Enable mesh network (802.11s)"))
-      o.default = uci:get_bool('wireless', 'mesh_' .. radio, "disabled") and o.disabled or o.enabled
-      o.rmempty = false
-    end
-
-    if uci:get('wireless', 'ibss_' .. radio) then
-      o = p:option(Flag, radio .. '_ibss_enabled', translate("Enable mesh network (IBSS)"))
-      o.default = uci:get_bool('wireless', 'ibss_' .. radio, "disabled") and o.disabled or o.enabled
-      o.rmempty = false
-    end
-
-    local phy
-
-    if config.path then
-      phy = find_phy_by_path(config.path)
-    elseif config.macaddr then
-      phy = find_phy_by_macaddr(config.macaddr)
-    end
-
-    if phy then
-      local txpowers = txpower_list(phy)
-
-      if #txpowers > 1 then
-        local tp = p:option(ListValue, radio .. '_txpower', translate("Transmission power"))
-        tp.rmempty = true
-        tp.default = uci:get('wireless', radio, 'txpower') or 'default'
-
-        tp:value('default', translate("(default)"))
-
-        table.sort(txpowers, function(a, b) return a.driver_dbm > b.driver_dbm end)
-
-        for _, entry in ipairs(txpowers) do
-          tp:value(entry.driver_dbm, "%i dBm (%i mW)" % {entry.display_dbm, entry.display_mw})
-        end
-      end
-    end
-  end
-
-end
-
---when the save-button is pushed
-function f.handle(self, state, data)
-  if state == FORM_VALID then
-
-    for _, radio in ipairs(radios) do
-
-      if uci:get('wireless', 'client_' .. radio) then
-	local disabled = 0
-	if data[radio .. '_client_enabled'] == '0' then
-	  disabled = 1
-	end
-	uci:set('wireless', 'client_' .. radio, "disabled", disabled)
-      end
-
-      if uci:get('wireless', 'mesh_' .. radio) then
-	local disabled = 0
-	if data[radio .. '_mesh_enabled'] == '0' then
-	  disabled = 1
-	end
-	uci:set('wireless', 'mesh_' .. radio, "disabled", disabled)
-      end
-
-      if uci:get('wireless', 'ibss_' .. radio) then
-	local disabled = 0
-	if data[radio .. '_ibss_enabled'] == '0' then
-	  disabled = 1
-	end
-	uci:set('wireless', 'ibss_' .. radio, "disabled", disabled)
-      end
-
-      if data[radio .. '_txpower'] then
-        if data[radio .. '_txpower'] == 'default' then
-          uci:delete('wireless', radio, 'txpower')
-        else
-          uci:set('wireless', radio, 'txpower', data[radio .. '_txpower'])
-        end
-      end
-
-    end
-
-    uci:save('wireless')
-    uci:commit('wireless')
-  end
-end
-
-return f

+ 1 - 1
package/gluon-setup-mode/Makefile

@@ -15,7 +15,7 @@ define Package/gluon-setup-mode
   SECTION:=gluon
   CATEGORY:=Gluon
   TITLE:=Setup mode
-  DEPENDS:=+gluon-core +luci-base +uhttpd +dnsmasq
+  DEPENDS:=+gluon-core +gluon-web +ubus +uhttpd +dnsmasq
   PROVIDES:=gluon-setup-mode-virtual
 endef
 

+ 1 - 3
package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S15gluon-setup-mode

@@ -10,9 +10,7 @@ boot() {
 	uci set 'gluon-setup-mode.@setup_mode[0].enabled=0'
 	uci commit gluon-setup-mode
 
-	if [ "$enabled" = 1 -o "$configured" != 1 ]; then
-		lua -e 'uci_state=require("luci.model.uci").cursor_state(); uci_state:section("gluon-setup-mode", "setup_mode", nil, { running = "1" }); uci_state:save("gluon-setup-mode")'
-	else
+	if [ "$enabled" != 1 -a "$configured" = 1 ]; then
 		# This can happen after an upgrade from a version before the config file was called gluon-setup-mode
 		# We'll just reboot to return to the normal mode...
 		/etc/init.d/done boot

+ 1 - 1
package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50uhttpd

@@ -9,6 +9,6 @@ UHTTPD_BIN="/usr/sbin/uhttpd"
 start_service() {
 	procd_open_instance
 	procd_set_param respawn
-	procd_set_param command "$UHTTPD_BIN" -f -h /lib/gluon/setup-mode/www -x /cgi-bin -A 1 -R -p 0.0.0.0:80
+	procd_set_param command "$UHTTPD_BIN" -f -h /lib/gluon/web/www -x /cgi-bin -A 1 -R -p 0.0.0.0:80
 	procd_close_instance
 }

+ 0 - 10
package/gluon-setup-mode/files/lib/gluon/setup-mode/www/index.html

@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="refresh" content="0; URL=/cgi-bin/luci" />
-</head>
-<body style="background-color: black">
-<a style="color: white; text-decoration: none" href="/cgi-bin/luci">LuCI - Lua Configuration Interface</a>
-</body>
-</html>

+ 0 - 1
package/gluon-setup-mode/files/lib/gluon/setup-mode/www/luci-static

@@ -1 +0,0 @@
-/www/luci-static

+ 0 - 5
package/gluon-setup-mode/luasrc/lib/gluon/setup-mode/www/cgi-bin/luci

@@ -1,5 +0,0 @@
-#!/usr/bin/lua
-require "luci.cacheloader"
-require "luci.sgi.cgi"
-luci.dispatcher.indexcache = "/tmp/luci-indexcache"
-luci.sgi.cgi.run()

+ 7 - 7
package/gluon-luci-admin/Makefile → package/gluon-web-admin/Makefile

@@ -3,7 +3,7 @@
 
 include $(TOPDIR)/rules.mk
 
-PKG_NAME:=gluon-luci-admin
+PKG_NAME:=gluon-web-admin
 PKG_VERSION:=1
 PKG_RELEASE:=1
 
@@ -14,10 +14,10 @@ include ../gluon.mk
 PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 
 
-define Package/gluon-luci-admin
+define Package/gluon-web-admin
   SECTION:=gluon
   CATEGORY:=Gluon
-  TITLE:=Luci based simple administration interface for mesh nodes
+  TITLE:=Web-based simple administration interface for mesh nodes
   DEPENDS:=gluon-config-mode-core-virtual +pretty-hostname
 endef
 
@@ -29,14 +29,14 @@ define Build/Configure
 endef
 
 define Build/Compile
-	$(call GluonBuildI18N,gluon-luci-admin,i18n)
+	$(call GluonBuildI18N,gluon-web-admin,i18n)
 	$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
 endef
 
-define Package/gluon-luci-admin/install
+define Package/gluon-web-admin/install
 	$(CP) ./files/* $(1)/
 	$(CP) $(PKG_BUILD_DIR)/luadest/* $(1)/
-	$(call GluonInstallI18N,gluon-luci-admin,$(1))
+	$(call GluonInstallI18N,gluon-web-admin,$(1))
 endef
 
-$(eval $(call BuildPackage,gluon-luci-admin))
+$(eval $(call BuildPackage,gluon-web-admin))

+ 12 - 13
package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm → package/gluon-web-admin/files/lib/gluon/web/view/admin/info.html

@@ -1,24 +1,23 @@
 <%-
   local fs = require 'nixio.fs'
   local uci = require('simple-uci').cursor()
-  local util = require 'luci.util'
-  local i18n = require 'luci.i18n'
+  local lutil = require 'gluon.web.util'
   local pretty_hostname = require 'pretty_hostname'
 
-  local gluon_luci = require "gluon.luci"
   local site = require 'gluon.site_config'
   local sysconfig = require 'gluon.sysconfig'
   local platform = require 'gluon.platform'
+  local util = require "gluon.util"
 
 
   local keys = {
-    hostname = i18n.translate('Hostname'),
-    primary_mac = i18n.translate('MAC address'),
-    model = i18n.translate('Hardware model'),
-    version = i18n.translate('Gluon version'),
-    release = i18n.translate('Firmware release'),
-    site = i18n.translate('Site'),
-    pubkey = i18n.translate('Public VPN key'),
+    hostname = translate('Hostname'),
+    primary_mac = translate('MAC address'),
+    model = translate('Hardware model'),
+    version = translate('Gluon version'),
+    release = translate('Firmware release'),
+    site = translate('Site'),
+    pubkey = translate('Public VPN key'),
   }
 
   local values = {
@@ -33,7 +32,7 @@
 
   local meshvpn_enabled = uci:get_bool("fastd", "mesh_vpn", "enabled")
   if meshvpn_enabled then
-    local pubkey = util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn'))
+    local pubkey = util.trim(lutil.exec('/etc/init.d/fastd show_key mesh_vpn'))
     if pubkey ~= '' then
       values.pubkey = pubkey
     end
@@ -41,7 +40,7 @@
 -%>
 <h2><%:Information%></h2>
 <% for _, key in ipairs({'hostname', 'primary_mac', 'model', 'version', 'release', 'site', 'pubkey'}) do %>
-<div class="cbi-value">
-  <div class="cbi-value-title"><%=keys[key]%></div><div class="cbi-value-field"><%=gluon_luci.escape(values[key] or 'n/a')%></div>
+<div class="gluon-value">
+  <div class="gluon-value-title"><%=keys[key]%></div><div class="gluon-value-field"><%=pcdata(values[key] or 'n/a')%></div>
 </div>
 <% end %>

+ 12 - 17
package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade.htm → package/gluon-web-admin/files/lib/gluon/web/view/admin/upgrade.html

@@ -1,5 +1,4 @@
 <%#
-LuCI - Lua Configuration Interface
 Copyright 2008 Steven Barth <steven@midlink.org>
 Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
 
@@ -12,44 +11,40 @@ You may obtain a copy of the License at
 $Id$
 
 -%>
-
-<%+header%>
-
 <h2><%:Upgrade firmware%></h2>
 
-<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
+<form method="post" enctype="multipart/form-data" action="<%=url(request)%>">
   <p>
     <%:You can manually upgrade your firmware here.%>
   </p>
   <% if bad_image then %>
   <p class="error"><%:The provided firmware image is not valid for this device.%></p>
   <% end %>
-  <div class="cbi-section-node">
-    <div class="cbi-value">
-      <label class="cbi-value-title">
+  <div class="gluon-section-node">
+    <div class="gluon-value">
+      <label class="gluon-value-title">
 	<%:Firmware image%>
       </label>
-      <div class="cbi-value-field">
-	<input class="cbi-input-file" type="file" name="image" />
+      <div class="gluon-value-field">
+	<input class="gluon-input-file" type="file" name="image" />
       </div>
     </div>
 
-    <div class="cbi-value cbi-value-last">
-      <label class="cbi-value-title">
+    <div class="gluon-value gluon-value-last">
+      <label class="gluon-value-title">
 	<%:Keep settings%>
       </label>
 
-      <div class="cbi-value-field">
-	<input id="keepcfg" class="cbi-input-checkbox" type="checkbox" name="keepcfg" value="1" checked="checked" />
+      <div class="gluon-value-field">
+	<input id="keepcfg" class="gluon-input-checkbox" type="checkbox" name="keepcfg" value="1" checked="checked" />
 	<label for="keepcfg"></label>
       </div>
     </div>
   </div>
 
-  <div class="cbi-page-actions right">
+  <div class="gluon-page-actions right">
     <input type="hidden" name="step" value="2" />
     <input type="hidden" name="token" value="<%=token%>" />
-    <input class="cbi-button cbi-button-apply" type="submit" value="<%:Upload image%>" />
+    <input class="gluon-button gluon-button-submit" type="submit" value="<%:Upload image%>" />
   </div>
 </form>
-<%+footer%>

+ 6 - 13
package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_confirm.htm → package/gluon-web-admin/files/lib/gluon/web/view/admin/upgrade_confirm.html

@@ -1,5 +1,4 @@
 <%#
-LuCI - Lua Configuration Interface
 Copyright 2008 Steven Barth <steven@midlink.org>
 Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
 
@@ -8,13 +7,8 @@ you may not use this file 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%>
-
 <h2><%:Upgrade firmware%></h2>
 
 <p>
@@ -43,7 +37,7 @@ $Id$
       write(byte_format(filesize))
 
       if flashsize > 0 then
-        write(luci.i18n.translatef(
+        write(translatef(
           " (%s available)",
           byte_format(flashsize)
         ))
@@ -51,18 +45,17 @@ $Id$
     %></li>
   </ul>
 </p>
-<div class="cbi-page-actions">
-  <form method="post" action="<%=REQUEST_URI%>" style="display:inline">
+<div class="gluon-page-actions">
+  <form method="post" enctype="multipart/form-data" action="<%=url(request)%>" style="display:inline">
     <input type="hidden" name="step" value="3" />
     <input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
     <input type="hidden" name="token" value="<%=token%>" />
-    <input class="cbi-button cbi-button-apply" type="submit" value="<%:Continue%>" />
+    <input class="gluon-button gluon-button-submit" type="submit" value="<%:Continue%>" />
   </form>
-  <form method="post" action="<%=REQUEST_URI%>" style="display:inline">
+  <form method="post" enctype="multipart/form-data" action="<%=url(request)%>" style="display:inline">
     <input type="hidden" name="step" value="1" />
     <input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
     <input type="hidden" name="token" value="<%=token%>" />
-    <input class="cbi-button cbi-button-reset" type="submit" value="<%:Cancel%>" />
+    <input class="gluon-button gluon-button-reset" type="submit" value="<%:Cancel%>" />
   </form>
 </div>
-<%+footer%>

+ 5 - 0
package/gluon-web-admin/files/lib/gluon/web/view/admin/upgrade_reboot.html

@@ -0,0 +1,5 @@
+<p>
+	<%:The firmware is currently being upgraded.%>
+	<strong><%:Don't switch off the device in any circumstance!%></strong>
+	<%:The upgrade will take a few minutes. When it is finished, your node will reboot automatically.%>
+</p>

+ 24 - 6
package/gluon-luci-admin/i18n/de.po → package/gluon-web-admin/i18n/de.po

@@ -10,6 +10,12 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
+msgid "(%s available)"
+msgstr "(%s verfügbar)"
+
+msgid "Advanced settings"
+msgstr "Erweiterte Einstellungen"
+
 msgid ""
 "Alternatively, you can set a password to access you node. Please choose a "
 "secure password you don't use anywhere else.<br /><br />If you set an empty "
@@ -20,15 +26,18 @@ msgstr ""
 "leeren Passworts wird der Login per Passwort gesperrt (dies ist die Standard-"
 "Einstellung)."
 
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgid "Confirmation"
+msgstr "Bestätigung"
+
 msgid "Continue"
 msgstr "Fortfahren"
 
 msgid "Don't switch off the device in any circumstance!"
 msgstr "Unterbrich auf keinen Fall die Stromversorgung!"
 
-msgid "Advanced settings"
-msgstr "Erweiterte Einstellungen"
-
 msgid "Firmware image"
 msgstr "Firmware-Datei"
 
@@ -41,12 +50,21 @@ msgstr "Gluon-Version"
 msgid "Hardware model"
 msgstr "Hardware-Modell"
 
+msgid "Hostname"
+msgstr "Hostname"
+
 msgid "Information"
 msgstr "Info"
 
+msgid "Keep settings"
+msgstr "Konfiguration behalten"
+
 msgid "MAC address"
 msgstr "MAC-Adresse"
 
+msgid "Password"
+msgstr "Passwort"
+
 msgid "Password changed."
 msgstr "Passwort geändert."
 
@@ -65,6 +83,9 @@ msgstr "SSH-Schlüssel"
 msgid "Site"
 msgstr "Site"
 
+msgid "Size"
+msgstr "Größe"
+
 msgid ""
 "The firmware image has been transmitted. Please ensure the MD5 checksum and "
 "image size are correct and click \"continue\"."
@@ -97,9 +118,6 @@ msgstr "Das Passwort konnte nicht geändert werden."
 msgid "Upgrade firmware"
 msgstr "Firmware aktualisieren"
 
-msgid "Upgrading firmware"
-msgstr "Firmware wird aktualisiert"
-
 msgid "Upload image"
 msgstr "Datei hochladen"
 

+ 24 - 6
package/gluon-luci-admin/i18n/fr.po → package/gluon-web-admin/i18n/fr.po

@@ -10,6 +10,12 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
+msgid "(%s available)"
+msgstr ""
+
+msgid "Advanced settings"
+msgstr "Paramètres avancés"
+
 msgid ""
 "Alternatively, you can set a password to access you node. Please choose a "
 "secure password you don't use anywhere else.<br /><br />If you set an empty "
@@ -21,15 +27,18 @@ msgstr ""
 "par mot de passe sera désactivée. La connexion par mot de passe est "
 "désactivée par défaut."
 
+msgid "Cancel"
+msgstr "Annuler"
+
+msgid "Confirmation"
+msgstr "Confirmation"
+
 msgid "Continue"
 msgstr "Continuer"
 
 msgid "Don't switch off the device in any circumstance!"
 msgstr "N'interrompez en aucun cas l'alimentation!"
 
-msgid "Advanced settings"
-msgstr "Paramètres avancés"
-
 msgid "Firmware image"
 msgstr "Fichier image"
 
@@ -42,12 +51,21 @@ msgstr "Version de Gluon"
 msgid "Hardware model"
 msgstr "Modèle du Matériel"
 
+msgid "Hostname"
+msgstr "Nom d'hôte"
+
 msgid "Information"
 msgstr "Informations"
 
+msgid "Keep settings"
+msgstr "Garder le paramètrage"
+
 msgid "MAC address"
 msgstr "Adresse MAC"
 
+msgid "Password"
+msgstr "Mot de passe"
+
 msgid "Password changed."
 msgstr "Mot de passe changé."
 
@@ -66,6 +84,9 @@ msgstr "Clé SSH"
 msgid "Site"
 msgstr "Site"
 
+msgid "Size"
+msgstr "Taille"
+
 msgid ""
 "The firmware image has been transmitted. Please ensure the MD5 checksum and "
 "image size are correct and click \"continue\"."
@@ -98,9 +119,6 @@ msgstr "Le mot de passe n'a pas pu être changé."
 msgid "Upgrade firmware"
 msgstr "Mettre à jour la firmware"
 
-msgid "Upgrading firmware"
-msgstr "Mise à jour de la firmware"
-
 msgid "Upload image"
 msgstr "Transférer l'image"
 

+ 24 - 6
package/gluon-luci-admin/i18n/gluon-luci-admin.pot → package/gluon-web-admin/i18n/gluon-web-admin.pot

@@ -1,19 +1,28 @@
 msgid ""
 msgstr "Content-Type: text/plain; charset=UTF-8"
 
+msgid "(%s available)"
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
 msgid ""
 "Alternatively, you can set a password to access you node. Please choose a "
 "secure password you don't use anywhere else.<br /><br />If you set an empty "
 "password, login via password will be disabled. This is the default."
 msgstr ""
 
-msgid "Continue"
+msgid "Cancel"
 msgstr ""
 
-msgid "Don't switch off the device in any circumstance!"
+msgid "Confirmation"
 msgstr ""
 
-msgid "Advanced settings"
+msgid "Continue"
+msgstr ""
+
+msgid "Don't switch off the device in any circumstance!"
 msgstr ""
 
 msgid "Firmware image"
@@ -28,12 +37,21 @@ msgstr ""
 msgid "Hardware model"
 msgstr ""
 
+msgid "Hostname"
+msgstr ""
+
 msgid "Information"
 msgstr ""
 
+msgid "Keep settings"
+msgstr ""
+
 msgid "MAC address"
 msgstr ""
 
+msgid "Password"
+msgstr ""
+
 msgid "Password changed."
 msgstr ""
 
@@ -52,6 +70,9 @@ msgstr ""
 msgid "Site"
 msgstr ""
 
+msgid "Size"
+msgstr ""
+
 msgid ""
 "The firmware image has been transmitted. Please ensure the MD5 checksum and "
 "image size are correct and click \"continue\"."
@@ -80,9 +101,6 @@ msgstr ""
 msgid "Upgrade firmware"
 msgstr ""
 
-msgid "Upgrading firmware"
-msgstr ""
-
 msgid "Upload image"
 msgstr ""
 

+ 9 - 0
package/gluon-web-admin/luasrc/lib/gluon/web/controller/admin/index.lua

@@ -0,0 +1,9 @@
+local root = node()
+if not root.target then
+	root.target = alias("admin")
+end
+
+entry({"admin"}, alias("admin", "info"), _("Advanced settings"), 10)
+
+entry({"admin", "info"}, template("admin/info"), _("Information"), 1)
+entry({"admin", "remote"}, model("admin/remote"), _("Remote access"), 10)

+ 139 - 0
package/gluon-web-admin/luasrc/lib/gluon/web/controller/admin/upgrade.lua

@@ -0,0 +1,139 @@
+--[[
+Copyright 2008 Steven Barth <steven@midlink.org>
+Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+]]--
+
+local fs = require 'nixio.fs'
+
+local tmpfile = "/tmp/firmware.img"
+
+
+local function filehandler(meta, chunk, eof)
+	if not fs.access(tmpfile) and not file and chunk and #chunk > 0 then
+		file = io.open(tmpfile, "w")
+	end
+	if file and chunk then
+		file:write(chunk)
+	end
+	if file and eof then
+		file:close()
+	end
+end
+
+local function action_upgrade(http, renderer)
+	local disp = require 'gluon.web.dispatcher'
+	local nixio = require 'nixio'
+
+	local function fork_exec(...)
+		local pid = nixio.fork()
+		if pid > 0 then
+			return
+		elseif pid == 0 then
+			-- change to root dir
+			nixio.chdir("/")
+
+			-- patch stdin, out, err to /dev/null
+			local null = nixio.open("/dev/null", "w+")
+			if null then
+				nixio.dup(null, nixio.stderr)
+				nixio.dup(null, nixio.stdout)
+				nixio.dup(null, nixio.stdin)
+				if null:fileno() > 2 then
+					null:close()
+				end
+			end
+
+			-- Sleep a little so the browser can fetch everything required to
+			-- display the reboot page, then reboot the device.
+			nixio.nanosleep(1)
+
+			-- replace with target command
+			nixio.exec(...)
+		end
+	end
+
+	local function image_supported(tmpfile)
+		-- XXX: yay...
+		return (os.execute(string.format("/sbin/sysupgrade -T %q >/dev/null", tmpfile)) == 0)
+	end
+
+	local function storage_size()
+		local size = 0
+		if fs.access("/proc/mtd") then
+			for l in io.lines("/proc/mtd") do
+				local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
+				if n == "linux" then
+					size = tonumber(s, 16)
+					break
+				end
+			end
+		elseif fs.access("/proc/partitions") then
+			for l in io.lines("/proc/partitions") do
+				local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
+				if b and n and not n:match('[0-9]') then
+					size = tonumber(b) * 1024
+					break
+				end
+			end
+		end
+		return size
+	end
+
+	local function image_checksum(tmpfile)
+		return (gluon.web.util.exec(string.format("md5sum %q", tmpfile)):match("^([^%s]+)"))
+	end
+
+
+	-- Determine state
+	local step = tonumber(http:getenv("REQUEST_METHOD") == "POST" and http:formvalue("step")) or 1
+
+	local has_image   = fs.access(tmpfile)
+	local has_support = has_image and image_supported(tmpfile)
+
+	-- Step 1: file upload, error on unsupported image format
+	if step == 1 or not has_support then
+		-- If there is an image but user has requested step 1
+		-- or type is not supported, then remove it.
+		if has_image then
+			fs.unlink(tmpfile)
+		end
+
+		renderer.render("layout", {
+			content = "admin/upgrade",
+			bad_image = has_image and not has_support,
+		})
+
+	-- Step 2: present uploaded file, show checksum, confirmation
+	elseif step == 2 then
+		renderer.render("layout", {
+			content = "admin/upgrade_confirm",
+			checksum   = image_checksum(tmpfile),
+			filesize   = fs.stat(tmpfile).size,
+			flashsize  = storage_size(),
+			keepconfig = (http:formvalue("keepcfg") == "1"),
+		})
+	elseif step == 3 then
+		if http:formvalue("keepcfg") == "1" then
+			fork_exec("/sbin/sysupgrade", tmpfile)
+		else
+			fork_exec("/sbin/sysupgrade", "-n", tmpfile)
+		end
+		renderer.render("layout", {
+			content = "admin/upgrade_reboot",
+			hidenav = true,
+		})
+	end
+end
+
+
+local has_platform = fs.access("/lib/upgrade/platform.sh")
+if has_platform then
+	local upgrade = entry({"admin", "upgrade"}, call(action_upgrade), _("Upgrade firmware"), 90)
+	upgrade.filehandler = filehandler
+end

+ 109 - 0
package/gluon-web-admin/luasrc/lib/gluon/web/model/admin/remote.lua

@@ -0,0 +1,109 @@
+--[[
+Copyright 2008 Steven Barth <steven@midlink.org>
+Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
+Copyright 2013 Nils Schneider <nils@nilsschneider.net>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+]]--
+
+local nixio = require "nixio"
+local fs = require "nixio.fs"
+local util = require "gluon.util"
+
+local f_keys = Form(translate("SSH keys"), translate("You can provide your SSH keys here (one per line):"), 'keys')
+local s = f_keys:section(Section)
+local keys = s:option(TextValue, "keys")
+keys.wrap    = "off"
+keys.rows    = 5
+keys.default = fs.readfile("/etc/dropbear/authorized_keys") or ""
+
+function keys:write(value)
+	value = util.trim(value:gsub("\r", ""))
+	if value ~= "" then
+		fs.writefile("/etc/dropbear/authorized_keys", value .. "\n")
+	else
+		fs.remove("/etc/dropbear/authorized_keys")
+	end
+end
+
+
+local f_password = Form(translate("Password"),
+	translate(
+                "Alternatively, you can set a password to access you node. Please choose a secure password you don't use anywhere else.<br /><br />"
+                .. "If you set an empty password, login via password will be disabled. This is the default."
+	), 'password'
+)
+f_password.reset = false
+
+local s = f_password:section(Section)
+
+local pw1 = s:option(Value, "pw1", translate("Password"))
+pw1.password = true
+function pw1.cfgvalue()
+	return ''
+end
+
+local pw2 = s:option(Value, "pw2", translate("Confirmation"))
+pw2.password = true
+function pw2.cfgvalue()
+	return ''
+end
+
+local function set_password(password)
+	local inr, inw = nixio.pipe()
+	local pid = nixio.fork()
+
+	if pid < 0 then
+		return false
+	elseif pid == 0 then
+		inw:close()
+
+		local null = nixio.open('/dev/null', 'w')
+		nixio.dup(null, nixio.stderr)
+		nixio.dup(null, nixio.stdout)
+		if null:fileno() > 2 then
+			null:close()
+		end
+
+		nixio.dup(inr, nixio.stdin)
+		inr:close()
+
+		nixio.execp('passwd')
+		os.exit(127)
+	end
+
+	inr:close()
+
+	inw:write(string.format('%s\n%s\n', password, password))
+	inw:close()
+
+	local wpid, status, code = nixio.waitpid(pid)
+	return wpid and status == 'exited' and code == 0
+end
+
+function f_password:write()
+	if pw1.data ~= pw2.data then
+		f_password.errmessage = translate("The password and the confirmation differ.")
+		return
+	end
+
+	local pw = pw1.data
+
+	if #pw > 0 then
+		if set_password(pw) then
+			f_password.message = translate("Password changed.")
+		else
+			f_password.errmessage = translate("Unable to change the password.")
+		end
+	else
+		-- We don't check the return code here as the error 'password for root is already locked' is normal...
+		os.execute('passwd -l root >/dev/null')
+		f_password.message = translate("Password removed.")
+	end
+end
+
+return f_keys, f_password

+ 8 - 8
package/gluon-luci-autoupdater/Makefile → package/gluon-web-autoupdater/Makefile

@@ -3,7 +3,7 @@
 
 include $(TOPDIR)/rules.mk
 
-PKG_NAME:=gluon-luci-autoupdater
+PKG_NAME:=gluon-web-autoupdater
 PKG_VERSION:=1
 PKG_RELEASE:=1
 
@@ -14,11 +14,11 @@ include ../gluon.mk
 PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 
 
-define Package/gluon-luci-autoupdater
+define Package/gluon-web-autoupdater
   SECTION:=gluon
   CATEGORY:=Gluon
-  TITLE:=Luci module for gluon-autoupdater
-  DEPENDS:=+gluon-luci-admin +gluon-autoupdater
+  TITLE:=gluon-web module for gluon-autoupdater
+  DEPENDS:=+gluon-web-admin +gluon-autoupdater
 endef
 
 define Build/Prepare
@@ -29,13 +29,13 @@ define Build/Configure
 endef
 
 define Build/Compile
-	$(call GluonBuildI18N,gluon-luci-autoupdater,i18n)
+	$(call GluonBuildI18N,gluon-web-autoupdater,i18n)
 	$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
 endef
 
-define Package/gluon-luci-autoupdater/install
+define Package/gluon-web-autoupdater/install
 	$(CP) $(PKG_BUILD_DIR)/luadest/* $(1)/
-	$(call GluonInstallI18N,gluon-luci-autoupdater,$(1))
+	$(call GluonInstallI18N,gluon-web-autoupdater,$(1))
 endef
 
-$(eval $(call BuildPackage,gluon-luci-autoupdater))
+$(eval $(call BuildPackage,gluon-web-autoupdater))

+ 4 - 1
package/gluon-luci-autoupdater/i18n/de.po → package/gluon-web-autoupdater/i18n/de.po

@@ -1,12 +1,12 @@
 msgid ""
 msgstr ""
-"Content-Type: text/plain; charset=UTF-8\n"
 "Project-Id-Version: PACKAGE VERSION\n"
 "PO-Revision-Date: 2015-05-04 01:55+0200\n"
 "Last-Translator:  <mschiffer@universe-factory.net>\n"
 "Language-Team: German\n"
 "Language: de\n"
 "MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
@@ -15,3 +15,6 @@ msgstr "Automatische Updates"
 
 msgid "Branch"
 msgstr "Branch"
+
+msgid "Enable"
+msgstr "Aktivieren"

+ 4 - 1
package/gluon-luci-autoupdater/i18n/fr.po → package/gluon-web-autoupdater/i18n/fr.po

@@ -1,12 +1,12 @@
 msgid ""
 msgstr ""
-"Content-Type: text/plain; charset=UTF-8\n"
 "Project-Id-Version: PACKAGE VERSION\n"
 "PO-Revision-Date: 2015-08-19 20:20+0100\n"
 "Last-Translator: Bernot Tobias <tqbs@airmail.cc>\n"
 "Language-Team: French\n"
 "Language: fr\n"
 "MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
@@ -15,3 +15,6 @@ msgstr "Mise a jour automatique"
 
 msgid "Branch"
 msgstr "Branche"
+
+msgid "Enable"
+msgstr "Activer"

+ 3 - 0
package/gluon-luci-autoupdater/i18n/gluon-luci-autoupdater.pot → package/gluon-web-autoupdater/i18n/gluon-web-autoupdater.pot

@@ -6,3 +6,6 @@ msgstr ""
 
 msgid "Branch"
 msgstr ""
+
+msgid "Enable"
+msgstr ""

+ 1 - 0
package/gluon-web-autoupdater/luasrc/lib/gluon/web/controller/admin/autoupdater.lua

@@ -0,0 +1 @@
+entry({"admin", "autoupdater"}, model("admin/autoupdater"), _("Automatic updates"), 80)

+ 10 - 17
package/gluon-luci-autoupdater/luasrc/usr/lib/lua/luci/model/cbi/admin/autoupdater.lua → package/gluon-web-autoupdater/luasrc/lib/gluon/web/model/admin/autoupdater.lua

@@ -1,6 +1,4 @@
 --[[
-LuCI - Lua Configuration Interface
-
 Copyright 2013 Nils Schneider <nils@nilsschneider.net>
 
 Licensed under the Apache License, Version 2.0 (the "License");
@@ -8,20 +6,20 @@ you may not use this file 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 uci = require("simple-uci").cursor()
 local autoupdater = uci:get_first("autoupdater", "autoupdater")
 
-local f = SimpleForm("autoupdater", translate("Automatic updates"))
-local s = f:section(SimpleSection, nil, nil)
+local f = Form(translate("Automatic updates"))
+local s = f:section(Section)
 local o
 
 o = s:option(Flag, "enabled", translate("Enable"))
-o.default = uci:get_bool("autoupdater", autoupdater, "enabled") and o.enabled or o.disabled
-o.rmempty = false
+o.default = uci:get_bool("autoupdater", autoupdater, "enabled")
+function o:write(data)
+	uci:set("autoupdater", autoupdater, "enabled", data)
+end
 
 o = s:option(ListValue, "branch", translate("Branch"))
 uci:foreach("autoupdater", "branch",
@@ -30,16 +28,11 @@ uci:foreach("autoupdater", "branch",
 	end
 )
 o.default = uci:get("autoupdater", autoupdater, "branch")
+function o:write(data)
+	uci:set("autoupdater", autoupdater, "branch", data)
+end
 
-function f.handle(self, state, data)
-	if state ~= FORM_VALID then
-		return
-	end
-
-	uci:set("autoupdater", autoupdater, "enabled", data.enabled)
-	uci:set("autoupdater", autoupdater, "branch", data.branch)
-
-	uci:save("autoupdater")
+function f:write()
 	uci:commit("autoupdater")
 end
 

+ 7 - 7
package/gluon-luci-mesh-vpn-fastd/Makefile → package/gluon-web-mesh-vpn-fastd/Makefile

@@ -1,6 +1,6 @@
 include $(TOPDIR)/rules.mk
 
-PKG_NAME:=gluon-luci-mesh-vpn-fastd
+PKG_NAME:=gluon-web-mesh-vpn-fastd
 PKG_VERSION:=1
 PKG_RELEASE:=1
 
@@ -11,11 +11,11 @@ include ../gluon.mk
 PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 
 
-define Package/gluon-luci-mesh-vpn-fastd
+define Package/gluon-web-mesh-vpn-fastd
   SECTION:=gluon
   CATEGORY:=Gluon
-  TITLE:=Luci module to enable and disable encryption for the mesh VPN
-  DEPENDS:=+gluon-luci-admin +gluon-mesh-vpn-fastd
+  TITLE:=gluon-web module to enable and disable encryption for the mesh VPN
+  DEPENDS:=+gluon-web-admin +gluon-mesh-vpn-fastd
 endef
 
 define Build/Prepare
@@ -30,15 +30,15 @@ define Build/Compile
 	$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
 endef
 
-define Package/gluon-luci-mesh-vpn-fastd/install
+define Package/gluon-web-mesh-vpn-fastd/install
 	$(CP) ./files/* $(1)/
 	$(CP) $(PKG_BUILD_DIR)/luadest/* $(1)/
 	$(call GluonInstallI18N,gluon-mesh-vpn-fastd,$(1))
 endef
 
-define Package/gluon-luci-mesh-vpn-fastd/postinst
+define Package/gluon-web-mesh-vpn-fastd/postinst
 #!/bin/sh
 $(call GluonCheckSite,check_site.lua)
 endef
 
-$(eval $(call BuildPackage,gluon-luci-mesh-vpn-fastd))
+$(eval $(call BuildPackage,gluon-web-mesh-vpn-fastd))

+ 0 - 0
package/gluon-luci-mesh-vpn-fastd/check_site.lua → package/gluon-web-mesh-vpn-fastd/check_site.lua


+ 32 - 0
package/gluon-web-mesh-vpn-fastd/files/lib/gluon/web/view/gluon/model/mesh-vpn-fastd.html

@@ -0,0 +1,32 @@
+<div class="gluon-value">
+  <div class="gluon-value-title">
+    <input class="gluon-input-radio" data-update="change" type="radio" value="security"<%= attr("id", id..'1') .. attr("name", id) .. attr("checked", ((self:cfgvalue() or self.default) == "security") and "checked") %> />
+  </div>
+  <div class="gluon-value-field-long">
+    <label<%= attr("for", id..'1') %> class="gluon-value-title"><%:Security mode%></label>
+    <br />
+    <%= translate(
+        'In security mode, the mesh VPN uses an encrypted tunnel to connect to the VPN servers. ' ..
+        'The encryption ensures that it is impossible for your internet access provider to see what ' ..
+        'data is exchanged over your node.'
+    ) %>
+    <br />
+  </div>
+  <div class="gluon-value-field-long-after"></div>
+</div>
+
+<div class="gluon-value gluon-value-last">
+  <div class="gluon-value-title">
+    <input class="gluon-input-radio" data-update="change" type="radio" value="performance"<%= attr("id", id..'2') .. attr("name", id) .. attr("checked", ((self:cfgvalue() or self.default) == "performance") and "checked") %> />
+  </div>
+  <div class="gluon-value-field-long">
+    <label<%= attr("for", id..'2') %> class="gluon-value-title"><%:Performance mode%></label>
+    <br />
+    <%= translate(
+        'In performance mode, no encryption is used. This usually allows for higher throughput, but the data exchanged over your node is not ' ..
+        'protected against eavesdropping.'
+    ) %>
+    <br />
+  </div>
+  <div class="gluon-value-field-long-after"></div>
+</div>

+ 2 - 2
package/gluon-luci-mesh-vpn-fastd/i18n/de.po → package/gluon-web-mesh-vpn-fastd/i18n/de.po

@@ -15,7 +15,7 @@ msgid ""
 "throughput, but the data exchanged over your node is not protected against "
 "eavesdropping."
 msgstr ""
-"Im Modus &bdquo;Hohe Geschwindigkeit&ldquo; wird auf Verschlüsselung "
+"Im Modus „Hohe Geschwindigkeit“ wird auf Verschlüsselung "
 "verzichtet. Dies erlaubt häufig eine höhere Bandbreite als mit "
 "Verschlüsselung, aber die Verbindung ist nicht gegen Abhören geschützt."
 
@@ -24,7 +24,7 @@ msgid ""
 "VPN servers. The encryption ensures that it is impossible for your internet "
 "access provider to see what data is exchanged over your node."
 msgstr ""
-"Im Modus &bdquo;Hohe Sicherheit&ldquo; wird ein verschlüsselter Tunnel "
+"Im Modus „Hohe Sicherheit“ wird ein verschlüsselter Tunnel "
 "verwendet. Dies schließt aus, dass dein Internetzugangsprovider herausfinden "
 "kann, was für Daten über deinen Knoten übertragen werden."
 

+ 0 - 0
package/gluon-luci-mesh-vpn-fastd/i18n/fr.po → package/gluon-web-mesh-vpn-fastd/i18n/fr.po


+ 0 - 0
package/gluon-luci-mesh-vpn-fastd/i18n/gluon-luci-mesh-vpn-fastd.pot → package/gluon-web-mesh-vpn-fastd/i18n/gluon-web-mesh-vpn-fastd.pot


+ 1 - 0
package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/web/controller/admin/mesh_vpn_fastd.lua

@@ -0,0 +1 @@
+entry({"admin", "mesh_vpn_fastd"}, model("admin/mesh_vpn_fastd"), _("Mesh VPN"), 20)

+ 38 - 0
package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/web/model/admin/mesh_vpn_fastd.lua

@@ -0,0 +1,38 @@
+local uci = require("simple-uci").cursor()
+local util = gluon.web.util
+
+local f = Form(translate('Mesh VPN'))
+
+local s = f:section(Section)
+
+local mode = s:option(Value, 'mode')
+mode.template = "gluon/model/mesh-vpn-fastd"
+
+local methods = uci:get('fastd', 'mesh_vpn', 'method')
+if util.contains(methods, 'null') then
+	mode.default = 'performance'
+else
+	mode.default = 'security'
+end
+
+function mode:write(data)
+	local site = require 'gluon.site_config'
+
+	local methods = {}
+	if data == 'performance' then
+		table.insert(methods, 'null')
+	end
+
+	for _, method in ipairs(site.fastd_mesh_vpn.methods) do
+		if method ~= 'null' then
+			table.insert(methods, method)
+		end
+	end
+
+	uci:set('fastd', 'mesh_vpn', 'method', methods)
+
+	uci:save('fastd')
+	uci:commit('fastd')
+end
+
+return f

+ 8 - 8
package/gluon-luci-portconfig/Makefile → package/gluon-web-network/Makefile

@@ -3,7 +3,7 @@
 
 include $(TOPDIR)/rules.mk
 
-PKG_NAME:=gluon-luci-portconfig
+PKG_NAME:=gluon-web-network
 PKG_VERSION:=1
 PKG_RELEASE:=1
 
@@ -14,11 +14,11 @@ include ../gluon.mk
 PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 
 
-define Package/gluon-luci-portconfig
+define Package/gluon-web-network
   SECTION:=gluon
   CATEGORY:=Gluon
-  TITLE:=Luci module for advanced ethernet port configuration
-  DEPENDS:=+gluon-luci-admin +gluon-client-bridge
+  TITLE:=gluon-web module for network port configuration
+  DEPENDS:=+gluon-web-admin +gluon-client-bridge
 endef
 
 define Build/Prepare
@@ -29,13 +29,13 @@ define Build/Configure
 endef
 
 define Build/Compile
-	$(call GluonBuildI18N,gluon-luci-portconfig,i18n)
+	$(call GluonBuildI18N,gluon-web-network,i18n)
 	$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
 endef
 
-define Package/gluon-luci-portconfig/install
+define Package/gluon-web-network/install
 	$(CP) $(PKG_BUILD_DIR)/luadest/* $(1)/
-	$(call GluonInstallI18N,gluon-luci-portconfig,$(1))
+	$(call GluonInstallI18N,gluon-web-network,$(1))
 endef
 
-$(eval $(call BuildPackage,gluon-luci-portconfig))
+$(eval $(call BuildPackage,gluon-web-network))

+ 21 - 0
package/gluon-luci-portconfig/i18n/de.po → package/gluon-web-network/i18n/de.po

@@ -16,6 +16,9 @@ msgstr "Automatisch (DHCP)"
 msgid "Automatic (RA/DHCPv6)"
 msgstr "Automatisch (RA/DHCPv6)"
 
+msgid "Disabled"
+msgstr "Deaktiviert"
+
 msgid "Enable PoE passthrough"
 msgstr "PoE-Passthrough aktivieren"
 
@@ -25,6 +28,24 @@ msgstr "Mesh auf dem LAN-Port aktivieren"
 msgid "Enable meshing on the WAN interface"
 msgstr "Mesh auf dem WAN-Port aktivieren"
 
+msgid "Gateway"
+msgstr "Gateway"
+
+msgid "IP address"
+msgstr "IP-Adresse"
+
+msgid "IPv4"
+msgstr "IPv4"
+
+msgid "IPv6"
+msgstr "IPv6"
+
+msgid "Netmask"
+msgstr "Netzmaske"
+
+msgid "Network"
+msgstr "Netzwerk"
+
 msgid "Static"
 msgstr "Statisch"
 

+ 21 - 0
package/gluon-luci-portconfig/i18n/fr.po → package/gluon-web-network/i18n/fr.po

@@ -16,6 +16,9 @@ msgstr "Automatique (DHCP)"
 msgid "Automatic (RA/DHCPv6)"
 msgstr "Automatique (RA/DHCPv6)"
 
+msgid "Disabled"
+msgstr "Désactivé"
+
 msgid "Enable PoE passthrough"
 msgstr ""
 
@@ -25,6 +28,24 @@ msgstr "Activer le réseau MESH sur le port LAN"
 msgid "Enable meshing on the WAN interface"
 msgstr "Activer le réseau MESH sur les ports WAN"
 
+msgid "Gateway"
+msgstr "Passerelle"
+
+msgid "IP address"
+msgstr "Adresse IP"
+
+msgid "IPv4"
+msgstr "IPv4"
+
+msgid "IPv6"
+msgstr "IPv6"
+
+msgid "Netmask"
+msgstr "Masque de réseau"
+
+msgid "Network"
+msgstr "Réseau"
+
 msgid "Static"
 msgstr "Statique"
 

+ 21 - 0
package/gluon-luci-portconfig/i18n/gluon-luci-portconfig.pot → package/gluon-web-network/i18n/gluon-web-network.pot

@@ -7,6 +7,9 @@ msgstr ""
 msgid "Automatic (RA/DHCPv6)"
 msgstr ""
 
+msgid "Disabled"
+msgstr ""
+
 msgid "Enable PoE passthrough"
 msgstr ""
 
@@ -16,6 +19,24 @@ msgstr ""
 msgid "Enable meshing on the WAN interface"
 msgstr ""
 
+msgid "Gateway"
+msgstr ""
+
+msgid "IP address"
+msgstr ""
+
+msgid "IPv4"
+msgstr ""
+
+msgid "IPv6"
+msgstr ""
+
+msgid "Netmask"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
 msgid "Static"
 msgstr ""
 

+ 1 - 0
package/gluon-web-network/luasrc/lib/gluon/web/controller/admin/network.lua

@@ -0,0 +1 @@
+entry({"admin", "network"}, model("admin/network"), _("Network"), 20)

+ 143 - 0
package/gluon-web-network/luasrc/lib/gluon/web/model/admin/network.lua

@@ -0,0 +1,143 @@
+--[[
+Copyright 2014 Nils Schneider <nils@nilsschneider.net>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+]]--
+
+local uci = require("simple-uci").cursor()
+local sysconfig = require 'gluon.sysconfig'
+local util = require 'gluon.util'
+
+local wan = uci:get_all("network", "wan")
+local wan6 = uci:get_all("network", "wan6")
+local dns_static = uci:get_first("gluon-wan-dnsmasq", "static")
+
+local f = Form(translate("WAN connection"))
+
+local s = f:section(Section)
+
+local ipv4 = s:option(ListValue, "ipv4", translate("IPv4"))
+ipv4:value("dhcp", translate("Automatic (DHCP)"))
+ipv4:value("static", translate("Static"))
+ipv4:value("none", translate("Disabled"))
+ipv4.default = wan.proto
+
+local ipv4_addr = s:option(Value, "ipv4_addr", translate("IP address"))
+ipv4_addr:depends(ipv4, "static")
+ipv4_addr.default = wan.ipaddr
+ipv4_addr.datatype = "ip4addr"
+
+local ipv4_netmask = s:option(Value, "ipv4_netmask", translate("Netmask"))
+ipv4_netmask:depends(ipv4, "static")
+ipv4_netmask.default = wan.netmask or "255.255.255.0"
+ipv4_netmask.datatype = "ip4addr"
+
+local ipv4_gateway = s:option(Value, "ipv4_gateway", translate("Gateway"))
+ipv4_gateway:depends(ipv4, "static")
+ipv4_gateway.default = wan.gateway
+ipv4_gateway.datatype = "ip4addr"
+
+
+local s = f:section(Section)
+
+local ipv6 = s:option(ListValue, "ipv6", translate("IPv6"))
+ipv6:value("dhcpv6", translate("Automatic (RA/DHCPv6)"))
+ipv6:value("static", translate("Static"))
+ipv6:value("none", translate("Disabled"))
+ipv6.default = wan6.proto
+
+local ipv6_addr = s:option(Value, "ipv6_addr", translate("IP address"))
+ipv6_addr:depends(ipv6, "static")
+ipv6_addr.default = wan6.ip6addr
+ipv6_addr.datatype = "ip6addr"
+
+local ipv6_gateway = s:option(Value, "ipv6_gateway", translate("Gateway"))
+ipv6_gateway:depends(ipv6, "static")
+ipv6_gateway.default = wan6.ip6gw
+ipv6_gateway.datatype = "ip6addr"
+
+if dns_static then
+	local s = f:section(Section)
+
+	local dns = s:option(DynamicList, "dns", translate("Static DNS servers"))
+	dns.default = uci:get_list("gluon-wan-dnsmasq", dns_static, "server")
+	dns.datatype = "ipaddr"
+	dns.optional = true
+
+	function dns:write(data)
+		uci:set_list("gluon-wan-dnsmasq", dns_static, "server", data)
+		uci:commit("gluon-wan-dnsmasq")
+	end
+end
+
+local s = f:section(Section)
+
+local mesh_wan = s:option(Flag, "mesh_wan", translate("Enable meshing on the WAN interface"))
+mesh_wan.default = uci:get_bool("network", "mesh_wan", "auto")
+
+function mesh_wan:write(data)
+	uci:set("network", "mesh_wan", "auto", data)
+end
+
+if sysconfig.lan_ifname then
+	local mesh_lan = s:option(Flag, "mesh_lan", translate("Enable meshing on the LAN interface"))
+	mesh_lan.default = uci:get_bool("network", "mesh_lan", "auto")
+
+	function mesh_lan:write(data)
+		uci:set("network", "mesh_lan", "auto", data)
+
+		local interfaces = uci:get_list("network", "client", "ifname")
+
+		for lanif in sysconfig.lan_ifname:gmatch('%S+') do
+			if data then
+				util.remove_from_set(interfaces, lanif)
+			else
+				util.add_to_set(interfaces, lanif)
+			end
+		end
+
+		uci:set_list("network", "client", "ifname", interfaces)
+	end
+end
+
+if uci:get('system', 'gpio_switch_poe_passthrough') then
+	local s = f:section(Section)
+	local poe_passthrough = s:option(Flag, "poe_passthrough", translate("Enable PoE passthrough"))
+	poe_passthrough.default = uci:get_bool("system", "gpio_switch_poe_passthrough", "value")
+
+	function poe_passthrough:write(data)
+		uci:set('system', 'gpio_switch_poe_passthrough', 'value', data)
+	end
+end
+
+function f:write()
+	uci:set("network", "wan", "proto", ipv4.data)
+	if ipv4.data == "static" then
+		uci:set("network", "wan", "ipaddr", ipv4_addr.data)
+		uci:set("network", "wan", "netmask", ipv4_netmask.data)
+		uci:set("network", "wan", "gateway", ipv4_gateway.data)
+	else
+		uci:delete("network", "wan", "ipaddr")
+		uci:delete("network", "wan", "netmask")
+		uci:delete("network", "wan", "gateway")
+	end
+
+	uci:set("network", "wan6", "proto", ipv6.data)
+	if ipv6.data == "static" then
+		uci:set("network", "wan6", "ip6addr", ipv6_addr.data)
+		uci:set("network", "wan6", "ip6gw", ipv6_gateway.data)
+	else
+		uci:delete("network", "wan6", "ip6addr")
+		uci:delete("network", "wan6", "ip6gw")
+	end
+
+
+	uci:commit("network")
+	uci:commit('system')
+end
+
+return f

+ 8 - 8
package/gluon-luci-node-role/Makefile → package/gluon-web-node-role/Makefile

@@ -1,6 +1,6 @@
 include $(TOPDIR)/rules.mk
 
-PKG_NAME:=gluon-luci-node-role
+PKG_NAME:=gluon-web-node-role
 PKG_VERSION:=0.1
 PKG_RELEASE:=1
 
@@ -11,10 +11,10 @@ include ../gluon.mk
 PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 
 
-define Package/gluon-luci-node-role
+define Package/gluon-web-node-role
   SECTION:=gluon
   CATEGORY:=Gluon
-  DEPENDS:=+gluon-luci-admin +gluon-node-info
+  DEPENDS:=+gluon-web-admin +gluon-node-info
   TITLE:=UI for specifying node role
 endef
 
@@ -26,18 +26,18 @@ define Build/Configure
 endef
 
 define Build/Compile
-	$(call GluonBuildI18N,gluon-luci-node-role,i18n)
+	$(call GluonBuildI18N,gluon-web-node-role,i18n)
 	$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
 endef
 
-define Package/gluon-luci-node-role/install
+define Package/gluon-web-node-role/install
 	$(CP) $(PKG_BUILD_DIR)/luadest/* $(1)/
-	$(call GluonInstallI18N,gluon-luci-node-role,$(1))
+	$(call GluonInstallI18N,gluon-web-node-role,$(1))
 endef
 
-define Package/gluon-luci-node-role/postinst
+define Package/gluon-web-node-role/postinst
 #!/bin/sh
 $(call GluonCheckSite,check_site.lua)
 endef
 
-$(eval $(call BuildPackage,gluon-luci-node-role))
+$(eval $(call BuildPackage,gluon-web-node-role))

+ 0 - 0
package/gluon-luci-node-role/check_site.lua → package/gluon-web-node-role/check_site.lua


+ 0 - 0
package/gluon-luci-node-role/i18n/de.po → package/gluon-web-node-role/i18n/de.po


+ 0 - 0
package/gluon-luci-node-role/i18n/fr.po → package/gluon-web-node-role/i18n/fr.po


+ 0 - 0
package/gluon-luci-node-role/i18n/gluon-luci-node-role.pot → package/gluon-web-node-role/i18n/gluon-web-node-role.pot


+ 1 - 0
package/gluon-web-node-role/luasrc/lib/gluon/web/controller/admin/noderole.lua

@@ -0,0 +1 @@
+entry({"admin", "noderole"}, model("admin/noderole"), "Node role", 20)

+ 28 - 0
package/gluon-web-node-role/luasrc/lib/gluon/web/model/admin/noderole.lua

@@ -0,0 +1,28 @@
+local f, s, o
+local site = require 'gluon.site_config'
+local uci = require("simple-uci").cursor()
+local config = 'gluon-node-info'
+
+-- where to read the configuration from
+local role = uci:get(config, uci:get_first(config, "system"), "role")
+
+f = Form(translate("Node role"))
+
+s = f:section(Section, nil, translate(
+	"If this node has a special role within the freifunk network you can specify this role here. "
+	.. "Please find out about the available roles and their impact first. "
+	.. "Only change the role if you know what you are doing."
+))
+
+o = s:option(ListValue, "role", translate("Role"))
+o.default = role
+for _, role in ipairs(site.roles.list) do
+	o:value(role, translate('gluon-web-node-role:role:' .. role))
+end
+
+function o:write(data)
+	uci:set(config, uci:get_first(config, "system"), "role", data)
+	uci:commit(config)
+end
+
+return f

+ 7 - 7
package/gluon-luci-private-wifi/Makefile → package/gluon-web-private-wifi/Makefile

@@ -1,6 +1,6 @@
 include $(TOPDIR)/rules.mk
 
-PKG_NAME:=gluon-luci-private-wifi
+PKG_NAME:=gluon-web-private-wifi
 PKG_VERSION:=1
 PKG_RELEASE:=1
 
@@ -11,10 +11,10 @@ include ../gluon.mk
 PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
 
 
-define Package/gluon-luci-private-wifi
+define Package/gluon-web-private-wifi
   SECTION:=gluon
   CATEGORY:=Gluon
-  DEPENDS:=+gluon-luci-admin
+  DEPENDS:=+gluon-web-admin
   TITLE:=UI for activating a private WLAN
 endef
 
@@ -26,13 +26,13 @@ define Build/Configure
 endef
 
 define Build/Compile
-	$(call GluonBuildI18N,gluon-luci-private-wifi,i18n)
+	$(call GluonBuildI18N,gluon-web-private-wifi,i18n)
 	$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
 endef
 
-define Package/gluon-luci-private-wifi/install
+define Package/gluon-web-private-wifi/install
 	$(CP) $(PKG_BUILD_DIR)/luadest/* $(1)/
-	$(call GluonInstallI18N,gluon-luci-private-wifi,$(1))
+	$(call GluonInstallI18N,gluon-web-private-wifi,$(1))
 endef
 
-$(eval $(call BuildPackage,gluon-luci-private-wifi))
+$(eval $(call BuildPackage,gluon-web-private-wifi))

+ 6 - 0
package/gluon-luci-private-wifi/i18n/de.po → package/gluon-web-private-wifi/i18n/de.po

@@ -13,6 +13,12 @@ msgstr ""
 msgid "8-63 characters"
 msgstr "8-63 Zeichen"
 
+msgid "Enabled"
+msgstr "Aktiviert"
+
+msgid "Key"
+msgstr "Schlüssel"
+
 msgid "Name (SSID)"
 msgstr "Name (SSID)"
 

+ 6 - 0
package/gluon-luci-private-wifi/i18n/fr.po → package/gluon-web-private-wifi/i18n/fr.po

@@ -13,6 +13,12 @@ msgstr ""
 msgid "8-63 characters"
 msgstr "8-63 charactères"
 
+msgid "Enabled"
+msgstr "Activé"
+
+msgid "Key"
+msgstr "Clé"
+
 msgid "Name (SSID)"
 msgstr "Nom (SSID)"
 

+ 6 - 0
package/gluon-luci-private-wifi/i18n/gluon-luci-private-wifi.pot → package/gluon-web-private-wifi/i18n/gluon-web-private-wifi.pot

@@ -4,6 +4,12 @@ msgstr "Content-Type: text/plain; charset=UTF-8"
 msgid "8-63 characters"
 msgstr ""
 
+msgid "Enabled"
+msgstr ""
+
+msgid "Key"
+msgstr ""
+
 msgid "Name (SSID)"
 msgstr ""
 

+ 1 - 0
package/gluon-web-private-wifi/luasrc/lib/gluon/web/controller/admin/privatewifi.lua

@@ -0,0 +1 @@
+entry({"admin", "privatewifi"}, model("admin/privatewifi"), _("Private WLAN"), 10)

+ 54 - 0
package/gluon-web-private-wifi/luasrc/lib/gluon/web/model/admin/privatewifi.lua

@@ -0,0 +1,54 @@
+local uci = require("simple-uci").cursor()
+local util = require 'gluon.util'
+
+-- where to read the configuration from
+local primary_iface = 'wan_radio0'
+
+local f = Form(translate("Private WLAN"))
+
+local s = f:section(Section, nil, translate(
+	'Your node can additionally extend your private network by bridging the WAN interface '
+	.. 'with a separate WLAN. This feature is completely independent of the mesh functionality. '
+	.. 'Please note that the private WLAN and meshing on the WAN interface should not be enabled '
+	.. 'at the same time.'
+))
+
+local enabled = s:option(Flag, "enabled", translate("Enabled"))
+enabled.default = (ssid and not uci:get_bool('wireless', primary_iface, "disabled"))
+
+local ssid = s:option(Value, "ssid", translate("Name (SSID)"))
+ssid:depends(enabled, true)
+ssid.datatype = "maxlength(32)"
+ssid.default = uci:get('wireless', primary_iface, "ssid")
+
+local key = s:option(Value, "key", translate("Key"), translate("8-63 characters"))
+key:depends(enabled, true)
+key.datatype = "wpakey"
+key.default = uci:get('wireless', primary_iface, "key")
+
+function f:write()
+	util.iterate_radios(function(radio, index)
+		local name   = "wan_" .. radio
+
+		if enabled.data then
+			local macaddr = util.get_wlan_mac(radio, index, 4)
+
+			uci:section('wireless', "wifi-iface", name, {
+				device     = radio,
+				network    = "wan",
+				mode       = 'ap',
+				encryption = 'psk2',
+				ssid       = ssid.data,
+				key        = key.data,
+				macaddr    = macaddr,
+				disabled   = false,
+			})
+		else
+			uci:set('wireless', name, "disabled", true)
+		end
+	end)
+
+	uci:commit('wireless')
+end
+
+return f

+ 5 - 11
package/gluon-luci-theme/Makefile → package/gluon-web-theme/Makefile

@@ -3,7 +3,7 @@
 
 include $(TOPDIR)/rules.mk
 
-PKG_NAME:=gluon-luci-theme
+PKG_NAME:=gluon-web-theme
 PKG_VERSION:=0.1
 PKG_RELEASE:=1
 
@@ -12,17 +12,13 @@ PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 include ../gluon.mk
 
 
-define Package/gluon-luci-theme
+define Package/gluon-web-theme
   SECTION:=gluon
   CATEGORY:=Gluon
-  TITLE:=Luci theme for Gluon
+  TITLE:=gluon-web theme
   DEPENDS:=+pretty-hostname
 endef
 
-define Package/gluon-luci-theme/description
-	Luci based config mode
-endef
-
 define Build/Prepare
 	mkdir -p $(PKG_BUILD_DIR)
 endef
@@ -31,12 +27,10 @@ define Build/Configure
 endef
 
 define Build/Compile
-	$(call GluonSrcDiet,./luasrc,$(PKG_BUILD_DIR)/luadest/)
 endef
 
-define Package/gluon-luci-theme/install
+define Package/gluon-web-theme/install
 	$(CP) ./files/* $(1)/
-	$(CP) $(PKG_BUILD_DIR)/luadest/* $(1)/
 endef
 
-$(eval $(call BuildPackage,gluon-luci-theme))
+$(eval $(call BuildPackage,gluon-web-theme))

+ 122 - 0
package/gluon-web-theme/files/lib/gluon/web/view/themes/gluon/layout.html

@@ -0,0 +1,122 @@
+<%#
+Copyright 2008 Steven Barth <steven@midlink.org>
+Copyright 2008-2010 Jo-Philipp Wich <xm@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+-%>
+<%
+	local uci  = require("simple-uci").cursor()
+	local disp = require "gluon.web.dispatcher"
+	local fs   = require "nixio.fs"
+	local pretty_hostname = require "pretty_hostname"
+
+	local hostname = pretty_hostname.get(uci)
+	local release = fs.readfile("/lib/gluon/release")
+
+	local root = node()
+	local rnode = node(unpack(request))
+
+	local category = request[1]
+	local cattree  = category and node(category)
+
+	local categories = disp.node_children(root)
+
+	http:prepare_content("application/xhtml+xml")
+
+	local function append(xs, x)
+		local r = {unpack(xs)}
+		r[#r+1] = x
+		return r
+	end
+
+	local function subtree(prefix, node, name, ...)
+		if not node then return end
+
+		local children = disp.node_children(node)
+		if #children == 0 then return end
+
+	%>
+	<div class="tabmenu<%=#prefix%>">
+		<ul class="tabmenu l<%=#prefix%>">
+			<%
+				for i, v in ipairs(children) do
+					local child = node.nodes[v]
+					local active = (v == name)
+			%>
+			<li class="tabmenu-item-<%=v%><% if active then %> active<% end %>">
+				<a href="<%=url(append(prefix, v))%>"><%=pcdata(translate(child.title))%></a>
+			</li>
+			<%
+				end
+			%>
+		</ul>
+		<br style="clear:both" />
+		<%
+			subtree(append(prefix, name), node.nodes[name], ...)
+		%>
+	</div>
+	<%
+	end
+
+	local function menutree(path, ...)
+		subtree({path}, root.nodes[category], ...)
+	end
+-%>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
+	<head>
+		<meta charset="UTF-8" />
+		<link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
+		<title><%=pcdata( hostname .. ( (rnode and rnode.title) and ' - ' .. translate(rnode.title) or '')) %></title>
+	</head>
+	<body>
+
+	<div id="menubar">
+		<div class="hostinfo">
+			<a href="<%=url({})%>">
+				<%=pcdata(hostname)%>
+				<% if release then %>
+				/ <%=pcdata(release)%>
+				<% end %>
+			</a>
+		</div>
+
+		<% if #categories > 1 and not hidenav then %>
+			<ul id="topmenu">
+				<% for i, r in ipairs(categories) do %>
+					<li><a class="topcat<% if request[1] == r then %> active<%end%>" href="<%=url({r})%>"><%=pcdata(translate(root.nodes[r].title))%></a></li>
+				<% end %>
+			</ul>
+		<% end %>
+	</div>
+
+	<div id="maincontainer">
+	  <%
+			if not hidenav then
+				menutree(unpack(request))
+			end
+		%>
+
+		<div id="maincontent">
+			<noscript>
+				<div class="errorbox">
+					<strong><%:JavaScript required!%></strong><br />
+					<%:You must enable JavaScript in your browser or the web interface will not work properly.%>
+				</div>
+			</noscript>
+
+			<%
+				ok, err = pcall(include, content)
+				if not ok then
+					renderer.render('error500', {message = err})
+				end
+			%>
+
+			</div>
+		</div>
+	</body>
+</html>

Some files were not shown because too many files changed in this diff