Browse Source

Merge pull request #81 from YunoHost-Apps/enh-v2

Enh v2
Alexandre Aubin 3 years ago
parent
commit
2a75479cb2
68 changed files with 549 additions and 15930 deletions
  1. 8 15
      check_process
  2. 0 73
      conf/config.php.tpl
  3. 1 1
      conf/dhcpdv4.conf.tpl
  4. 1 1
      conf/dhcpdv6.conf.tpl
  5. 1 1
      conf/dnsmasq_dhcpdv4.conf.tpl
  6. 1 1
      conf/dnsmasq_dhcpdv6.conf.tpl
  7. 0 20
      conf/ipv6_compressed
  8. 0 20
      conf/ipv6_expanded
  9. 0 20
      conf/iw_devices
  10. 0 27
      conf/iw_multissid
  11. 0 20
      conf/iw_ssids
  12. 0 49
      conf/nginx.conf
  13. 0 430
      conf/php-fpm.conf
  14. 0 12
      conf/sudoers.conf
  15. 18 8
      conf/ynh-hotspot
  16. 239 0
      config_panel.toml
  17. 2 0
      doc/DESCRIPTION.md
  18. 2 0
      doc/DESCRIPTION_fr.md
  19. BIN
      doc/screenshots/hotspot.png
  20. 7 22
      manifest.json
  21. 6 1
      scripts/_common.sh
  22. 0 24
      scripts/backup
  23. 221 0
      scripts/config
  24. 14 98
      scripts/install
  25. 0 45
      scripts/remove
  26. 3 55
      scripts/restore
  27. 25 71
      scripts/upgrade
  28. 0 367
      sources/controller.php
  29. 0 45
      sources/i18n/README.md
  30. BIN
      sources/i18n/fr_FR/LC_MESSAGES/localization.mo
  31. 0 299
      sources/i18n/fr_FR/LC_MESSAGES/localization.po
  32. 0 267
      sources/i18n/localization.pot
  33. 0 27
      sources/index.php
  34. 0 2707
      sources/lib/limonade.php
  35. 0 193
      sources/lib/limonade/abstract.php
  36. 0 173
      sources/lib/limonade/assertions.php
  37. 0 220
      sources/lib/limonade/public/css/screen.css
  38. BIN
      sources/lib/limonade/public/img/bg_header.png
  39. 0 350
      sources/lib/limonade/tests.php
  40. 0 37
      sources/lib/limonade/views/_debug.html.php
  41. 0 15
      sources/lib/limonade/views/_notices.html.php
  42. 0 22
      sources/lib/limonade/views/default_layout.php
  43. 0 6
      sources/lib/limonade/views/error.html.php
  44. 0 49
      sources/lib/unix_func.php
  45. 0 457
      sources/public/bootstrap/css/bootstrap-theme.css
  46. 0 1
      sources/public/bootstrap/css/bootstrap-theme.css.map
  47. 0 5
      sources/public/bootstrap/css/bootstrap-theme.min.css
  48. 0 6358
      sources/public/bootstrap/css/bootstrap.css
  49. 0 1
      sources/public/bootstrap/css/bootstrap.css.map
  50. 0 5
      sources/public/bootstrap/css/bootstrap.min.css
  51. BIN
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.eot
  52. 0 229
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.svg
  53. BIN
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.ttf
  54. BIN
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.woff
  55. 0 2276
      sources/public/bootstrap/js/bootstrap.js
  56. 0 7
      sources/public/bootstrap/js/bootstrap.min.js
  57. 0 13
      sources/public/bootstrap/js/npm.js
  58. 0 28
      sources/public/css/bootstrap-toggle.min.css
  59. 0 169
      sources/public/css/style.css
  60. BIN
      sources/public/img/github.png
  61. BIN
      sources/public/img/loading.gif
  62. BIN
      sources/public/img/nice.ogg
  63. 0 4
      sources/public/jquery/jquery-2.1.1.min.js
  64. 0 9
      sources/public/js/bootstrap-toggle.min.js
  65. 0 247
      sources/public/js/custom.js
  66. 0 116
      sources/views/_ssid.html.php
  67. 0 70
      sources/views/layout.html.php
  68. 0 144
      sources/views/settings.html.php

+ 8 - 15
check_process

@@ -1,27 +1,20 @@
 ;; Test complet
 	; Manifest
-		domain="domain.tld"	(DOMAIN)
-		path="/path"	(PATH)
 		wifi_ssid="myNeutralNetwork"
-		wifi_passphrase="VhegT8oev0jZI"	(PASSWORD)
+		wifi_passphrase="VhegT8oev0jZI"
 		firmware_nonfree="no"
 	; Checks
 		pkg_linter=1
-		setup_sub_dir=1
-		setup_root=1
-		setup_nourl=0
-		setup_private=1
+		setup_sub_dir=0
+		setup_root=0
+		setup_nourl=1
+		setup_private=0
 		setup_public=0
 		upgrade=1
-		upgrade=1	from_commit=546fd17712c7a9df428a4f26e7f8e4394884aaaf
-		upgrade=1	from_commit=ec919eb58fdc9c358ddbe17558874ae968a7f527
+		upgrade=1	from_commit=539a1f26c30ba850455c63746d50ce3d8f33b119
 		backup_restore=1
 		multi_instance=0
-		port_already_use=0
 		change_url=0
 ;;; Upgrade options
-	; commit=546fd17712c7a9df428a4f26e7f8e4394884aaaf
-		name=29 Jan 2019
-		manifest_arg=domain=DOMAIN&path=PATH&wifi_ssid="myNeutralNetwork"&wifi_passphrase=PASSWORD&firmware_nonfree="no"
-	; commit=ec919eb58fdc9c358ddbe17558874ae968a7f527
-		name=3 Sep 2019 / 1.2.0
+	; commit=539a1f26c30ba850455c63746d50ce3d8f33b119
+		name=Pre-2.0

+ 0 - 73
conf/config.php.tpl

@@ -1,73 +0,0 @@
-<?php
-
-/* Wifi Hotspot app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/hotspot_ynh
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-// Framework configuration
-function configure() {
-  option('env', ENV_PRODUCTION);
-  option('debug', false);
-  option('base_uri', '__PATH__/');
-
-  layout('layout.html.php');
-
-  define('PUBLIC_DIR', '__PATH__/public');
-}
-
-// Before routing
-function before($route) {
-  $lang_mapping = array(
-    'fr' => 'fr_FR'
-  );
-
-  if(!isset($_SESSION['locale'])) {
-    $locale = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
-    $_SESSION['locale'] = strtolower(substr(chop($locale[0]), 0, 2));
-  }
-
-  $lang = $_SESSION['locale'];
-
-  // Convert simple language code into full language code
-  if(array_key_exists($lang, $lang_mapping)) {
-    $lang = $lang_mapping[$lang];
-  }
-
-  $lang = "$lang.utf8";
-  $textdomain = "localization";
-
-  putenv("LANGUAGE=$lang");
-  putenv("LANG=$lang");
-  putenv("LC_ALL=$lang");
-  putenv("LC_MESSAGES=$lang");
-
-  setlocale(LC_ALL, $lang);
-  setlocale(LC_CTYPE, $lang);
-
-  $locales_dir = '__FINAL_PATH__/i18n';
-
-  bindtextdomain($textdomain, $locales_dir);
-  bind_textdomain_codeset($textdomain, 'UTF-8');
-  textdomain($textdomain);
-
-  set('locale', $lang);
-}
-
-// After routing
-function after($output, $route) {
-  return $output;
-}

+ 1 - 1
conf/dhcpdv4.conf.tpl

@@ -19,7 +19,7 @@
 dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP4_NAT_PREFIX>.2,<TPL:IP4_NAT_PREFIX>.254,4h
 
 # Send DHCPv4 option.
-dhcp-option=option:dns-server,<TPL:IP4_DNS0>,<TPL:IP4_DNS1>
+dhcp-option=option:dns-server,<TPL:IP4_DNS>
 
 # Set the DHCP server to authoritative mode. In this mode it will barge in
 # and take over the lease for any client which broadcasts on the network,

+ 1 - 1
conf/dhcpdv6.conf.tpl

@@ -20,4 +20,4 @@
 dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP6_NET>,slaac,64,4h
 
 # Send DHCPv6 option. Note [] around IPv6 addresses.
-dhcp-option=option6:dns-server,[<TPL:IP6_DNS0>],[<TPL:IP6_DNS1>]
+dhcp-option=option6:dns-server,<TPL:IP6_DNS>

+ 1 - 1
conf/dnsmasq_dhcpdv4.conf.tpl

@@ -19,7 +19,7 @@
 dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP4_NAT_PREFIX>.2,<TPL:IP4_NAT_PREFIX>.254,4h
 
 # Send DHCPv4 option.
-dhcp-option=option:dns-server,<TPL:IP4_DNS0>,<TPL:IP4_DNS1>
+dhcp-option=option:dns-server,<TPL:IP4_DNS>
 
 # Set the DHCP server to authoritative mode. In this mode it will barge in
 # and take over the lease for any client which broadcasts on the network,

+ 1 - 1
conf/dnsmasq_dhcpdv6.conf.tpl

@@ -20,4 +20,4 @@
 dhcp-range=interface:<TPL:WIFI_DEVICE>,<TPL:IP6_NET>,slaac,64,4h
 
 # Send DHCPv6 option. Note [] around IPv6 addresses.
-dhcp-option=option6:dns-server,[<TPL:IP6_DNS0>],[<TPL:IP6_DNS1>]
+dhcp-option=option6:dns-server,<TPL:IP6_DNS>

+ 0 - 20
conf/ipv6_compressed

@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# Wifi Hotspot app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-sipcalc "${1}" | grep Compressed | awk '{ print $NF; }'

+ 0 - 20
conf/ipv6_expanded

@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# Wifi Hotspot app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-sipcalc "${1}" | grep Expanded | awk '{ print $NF; }'

+ 0 - 20
conf/iw_devices

@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# Wifi Hotspot app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-echo -n $(/sbin/iw dev | grep Interface | grep -v 'mon\.' | grep -v hotspot | awk '{ print $NF }') | tr ' ' \|

+ 0 - 27
conf/iw_multissid

@@ -1,27 +0,0 @@
-#!/bin/bash
-
-# Wifi Hotspot app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-phy=$(/sbin/iw "${1}" info | grep wiphy | awk '{ print $NF }')
-multissid=$(/sbin/iw "phy${phy}" info | grep -A1 'valid interface combinations' | tail -n1 | sed 's/.*{.*AP.*}\s<=\s\(.*\),.*/\1/')
-
-if [ -z "${multissid}" ]; then
-  echo 1
-else
-  echo $multissid
-fi

+ 0 - 20
conf/iw_ssids

@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# Wifi Hotspot app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-echo -n hotspot0 $(/sbin/iw dev | grep Interface | grep hotspot | awk '{ print $NF }') | tr ' ' \|

+ 0 - 49
conf/nginx.conf

@@ -1,49 +0,0 @@
-# Wifi Hotspot app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-# 
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent;
-location __PATH__/ {
-
-  # Path to source
-  alias __FINALPATH__/ ;
-
-  # Force usage of https
-  if ($scheme = http) {
-    rewrite ^ https://$server_name$request_uri? permanent;
-  }
-
-  index index.php;
-
-  # Common parameter to increase upload size limit in conjunction with dedicated php-fpm file
-  client_max_body_size 10G;
-
-  try_files $uri $uri/ index.php;
-  location ~ [^/]\.php(/|$) {
-    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
-    fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock;
-
-    fastcgi_index index.php;
-    include fastcgi_params;
-    fastcgi_read_timeout 600;
-    fastcgi_param REMOTE_USER $remote_user;
-    fastcgi_param PATH_INFO $fastcgi_path_info;
-    fastcgi_param SCRIPT_FILENAME $request_filename;
-  }
-
-  # Include SSOWAT user panel.
-  include conf.d/yunohost_panel.conf.inc;
-}

+ 0 - 430
conf/php-fpm.conf

@@ -1,430 +0,0 @@
-; Start a new pool named 'www'.
-; the variable $pool can be used in any directive and will be replaced by the
-; pool name ('www' here)
-[__NAMETOCHANGE__]
-
-; Per pool prefix
-; It only applies on the following directives:
-; - 'access.log'
-; - 'slowlog'
-; - 'listen' (unixsocket)
-; - 'chroot'
-; - 'chdir'
-; - 'php_values'
-; - 'php_admin_values'
-; When not set, the global prefix (or /usr) applies instead.
-; Note: This directive can also be relative to the global prefix.
-; Default Value: none
-;prefix = /path/to/pools/$pool
-
-; Unix user/group of processes
-; Note: The user is mandatory. If the group is not set, the default user's group
-;       will be used.
-user = __USER__
-group = __USER__
-
-; The address on which to accept FastCGI requests.
-; Valid syntaxes are:
-;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
-;                            a specific port;
-;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
-;                            a specific port;
-;   'port'                 - to listen on a TCP socket to all addresses
-;                            (IPv6 and IPv4-mapped) on a specific port;
-;   '/path/to/unix/socket' - to listen on a unix socket.
-; Note: This value is mandatory.
-listen = /var/run/php/php__PHPVERSION__-fpm-__NAMETOCHANGE__.sock
-
-; Set listen(2) backlog.
-; Default Value: 511 (-1 on FreeBSD and OpenBSD)
-;listen.backlog = 511
-
-; Set permissions for unix socket, if one is used. In Linux, read/write
-; permissions must be set in order to allow connections from a web server. Many
-; BSD-derived systems allow connections regardless of permissions.
-; Default Values: user and group are set as the running user
-;                 mode is set to 0660
-listen.owner = www-data
-listen.group = www-data
-;listen.mode = 0660
-; When POSIX Access Control Lists are supported you can set them using
-; these options, value is a comma separated list of user/group names.
-; When set, listen.owner and listen.group are ignored
-;listen.acl_users =
-;listen.acl_groups =
-
-; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
-; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
-; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
-; must be separated by a comma. If this value is left blank, connections will be
-; accepted from any ip address.
-; Default Value: any
-;listen.allowed_clients = 127.0.0.1
-
-; Specify the nice(2) priority to apply to the pool processes (only if set)
-; The value can vary from -19 (highest priority) to 20 (lower priority)
-; Note: - It will only work if the FPM master process is launched as root
-;       - The pool processes will inherit the master process priority
-;         unless it specified otherwise
-; Default Value: no set
-; process.priority = -19
-
-; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user
-; or group is differrent than the master process user. It allows to create process
-; core dump and ptrace the process for the pool user.
-; Default Value: no
-; process.dumpable = yes
-
-; Choose how the process manager will control the number of child processes.
-; Possible Values:
-;   static  - a fixed number (pm.max_children) of child processes;
-;   dynamic - the number of child processes are set dynamically based on the
-;             following directives. With this process management, there will be
-;             always at least 1 children.
-;             pm.max_children      - the maximum number of children that can
-;                                    be alive at the same time.
-;             pm.start_servers     - the number of children created on startup.
-;             pm.min_spare_servers - the minimum number of children in 'idle'
-;                                    state (waiting to process). If the number
-;                                    of 'idle' processes is less than this
-;                                    number then some children will be created.
-;             pm.max_spare_servers - the maximum number of children in 'idle'
-;                                    state (waiting to process). If the number
-;                                    of 'idle' processes is greater than this
-;                                    number then some children will be killed.
-;  ondemand - no children are created at startup. Children will be forked when
-;             new requests will connect. The following parameter are used:
-;             pm.max_children           - the maximum number of children that
-;                                         can be alive at the same time.
-;             pm.process_idle_timeout   - The number of seconds after which
-;                                         an idle process will be killed.
-; Note: This value is mandatory.
-pm = dynamic
-
-; The number of child processes to be created when pm is set to 'static' and the
-; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
-; This value sets the limit on the number of simultaneous requests that will be
-; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
-; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
-; CGI. The below defaults are based on a server without much resources. Don't
-; forget to tweak pm.* to fit your needs.
-; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
-; Note: This value is mandatory.
-pm.max_children = 5
-
-; The number of child processes created on startup.
-; Note: Used only when pm is set to 'dynamic'
-; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
-pm.start_servers = 2
-
-; The desired minimum number of idle server processes.
-; Note: Used only when pm is set to 'dynamic'
-; Note: Mandatory when pm is set to 'dynamic'
-pm.min_spare_servers = 1
-
-; The desired maximum number of idle server processes.
-; Note: Used only when pm is set to 'dynamic'
-; Note: Mandatory when pm is set to 'dynamic'
-pm.max_spare_servers = 3
-
-; The number of seconds after which an idle process will be killed.
-; Note: Used only when pm is set to 'ondemand'
-; Default Value: 10s
-;pm.process_idle_timeout = 10s;
-
-; The number of requests each child process should execute before respawning.
-; This can be useful to work around memory leaks in 3rd party libraries. For
-; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
-; Default Value: 0
-;pm.max_requests = 500
-
-; The URI to view the FPM status page. If this value is not set, no URI will be
-; recognized as a status page. It shows the following informations:
-;   pool                 - the name of the pool;
-;   process manager      - static, dynamic or ondemand;
-;   start time           - the date and time FPM has started;
-;   start since          - number of seconds since FPM has started;
-;   accepted conn        - the number of request accepted by the pool;
-;   listen queue         - the number of request in the queue of pending
-;                          connections (see backlog in listen(2));
-;   max listen queue     - the maximum number of requests in the queue
-;                          of pending connections since FPM has started;
-;   listen queue len     - the size of the socket queue of pending connections;
-;   idle processes       - the number of idle processes;
-;   active processes     - the number of active processes;
-;   total processes      - the number of idle + active processes;
-;   max active processes - the maximum number of active processes since FPM
-;                          has started;
-;   max children reached - number of times, the process limit has been reached,
-;                          when pm tries to start more children (works only for
-;                          pm 'dynamic' and 'ondemand');
-; Value are updated in real time.
-; Example output:
-;   pool:                 www
-;   process manager:      static
-;   start time:           01/Jul/2011:17:53:49 +0200
-;   start since:          62636
-;   accepted conn:        190460
-;   listen queue:         0
-;   max listen queue:     1
-;   listen queue len:     42
-;   idle processes:       4
-;   active processes:     11
-;   total processes:      15
-;   max active processes: 12
-;   max children reached: 0
-;
-; By default the status page output is formatted as text/plain. Passing either
-; 'html', 'xml' or 'json' in the query string will return the corresponding
-; output syntax. Example:
-;   http://www.foo.bar/status
-;   http://www.foo.bar/status?json
-;   http://www.foo.bar/status?html
-;   http://www.foo.bar/status?xml
-;
-; By default the status page only outputs short status. Passing 'full' in the
-; query string will also return status for each pool process.
-; Example:
-;   http://www.foo.bar/status?full
-;   http://www.foo.bar/status?json&full
-;   http://www.foo.bar/status?html&full
-;   http://www.foo.bar/status?xml&full
-; The Full status returns for each process:
-;   pid                  - the PID of the process;
-;   state                - the state of the process (Idle, Running, ...);
-;   start time           - the date and time the process has started;
-;   start since          - the number of seconds since the process has started;
-;   requests             - the number of requests the process has served;
-;   request duration     - the duration in µs of the requests;
-;   request method       - the request method (GET, POST, ...);
-;   request URI          - the request URI with the query string;
-;   content length       - the content length of the request (only with POST);
-;   user                 - the user (PHP_AUTH_USER) (or '-' if not set);
-;   script               - the main script called (or '-' if not set);
-;   last request cpu     - the %cpu the last request consumed
-;                          it's always 0 if the process is not in Idle state
-;                          because CPU calculation is done when the request
-;                          processing has terminated;
-;   last request memory  - the max amount of memory the last request consumed
-;                          it's always 0 if the process is not in Idle state
-;                          because memory calculation is done when the request
-;                          processing has terminated;
-; If the process is in Idle state, then informations are related to the
-; last request the process has served. Otherwise informations are related to
-; the current request being served.
-; Example output:
-;   ************************
-;   pid:                  31330
-;   state:                Running
-;   start time:           01/Jul/2011:17:53:49 +0200
-;   start since:          63087
-;   requests:             12808
-;   request duration:     1250261
-;   request method:       GET
-;   request URI:          /test_mem.php?N=10000
-;   content length:       0
-;   user:                 -
-;   script:               /home/fat/web/docs/php/test_mem.php
-;   last request cpu:     0.00
-;   last request memory:  0
-;
-; Note: There is a real-time FPM status monitoring sample web page available
-;       It's available in: /usr/share/php/7.0/fpm/status.html
-;
-; Note: The value must start with a leading slash (/). The value can be
-;       anything, but it may not be a good idea to use the .php extension or it
-;       may conflict with a real PHP file.
-; Default Value: not set
-;pm.status_path = /status
-
-; The ping URI to call the monitoring page of FPM. If this value is not set, no
-; URI will be recognized as a ping page. This could be used to test from outside
-; that FPM is alive and responding, or to
-; - create a graph of FPM availability (rrd or such);
-; - remove a server from a group if it is not responding (load balancing);
-; - trigger alerts for the operating team (24/7).
-; Note: The value must start with a leading slash (/). The value can be
-;       anything, but it may not be a good idea to use the .php extension or it
-;       may conflict with a real PHP file.
-; Default Value: not set
-;ping.path = /ping
-
-; This directive may be used to customize the response of a ping request. The
-; response is formatted as text/plain with a 200 response code.
-; Default Value: pong
-;ping.response = pong
-
-; The access log file
-; Default: not set
-;access.log = log/$pool.access.log
-
-; The access log format.
-; The following syntax is allowed
-;  %%: the '%' character
-;  %C: %CPU used by the request
-;      it can accept the following format:
-;      - %{user}C for user CPU only
-;      - %{system}C for system CPU only
-;      - %{total}C  for user + system CPU (default)
-;  %d: time taken to serve the request
-;      it can accept the following format:
-;      - %{seconds}d (default)
-;      - %{miliseconds}d
-;      - %{mili}d
-;      - %{microseconds}d
-;      - %{micro}d
-;  %e: an environment variable (same as $_ENV or $_SERVER)
-;      it must be associated with embraces to specify the name of the env
-;      variable. Some exemples:
-;      - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
-;      - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
-;  %f: script filename
-;  %l: content-length of the request (for POST request only)
-;  %m: request method
-;  %M: peak of memory allocated by PHP
-;      it can accept the following format:
-;      - %{bytes}M (default)
-;      - %{kilobytes}M
-;      - %{kilo}M
-;      - %{megabytes}M
-;      - %{mega}M
-;  %n: pool name
-;  %o: output header
-;      it must be associated with embraces to specify the name of the header:
-;      - %{Content-Type}o
-;      - %{X-Powered-By}o
-;      - %{Transfert-Encoding}o
-;      - ....
-;  %p: PID of the child that serviced the request
-;  %P: PID of the parent of the child that serviced the request
-;  %q: the query string
-;  %Q: the '?' character if query string exists
-;  %r: the request URI (without the query string, see %q and %Q)
-;  %R: remote IP address
-;  %s: status (response code)
-;  %t: server time the request was received
-;      it can accept a strftime(3) format:
-;      %d/%b/%Y:%H:%M:%S %z (default)
-;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
-;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
-;  %T: time the log has been written (the request has finished)
-;      it can accept a strftime(3) format:
-;      %d/%b/%Y:%H:%M:%S %z (default)
-;      The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag
-;      e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t
-;  %u: remote user
-;
-; Default: "%R - %u %t \"%m %r\" %s"
-;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
-
-; The log file for slow requests
-; Default Value: not set
-; Note: slowlog is mandatory if request_slowlog_timeout is set
-;slowlog = log/$pool.log.slow
-
-; The timeout for serving a single request after which a PHP backtrace will be
-; dumped to the 'slowlog' file. A value of '0s' means 'off'.
-; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
-; Default Value: 0
-;request_slowlog_timeout = 0
-
-; The timeout for serving a single request after which the worker process will
-; be killed. This option should be used when the 'max_execution_time' ini option
-; does not stop script execution for some reason. A value of '0' means 'off'.
-; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
-; Default Value: 0
-request_terminate_timeout = 1d
-
-; Set open file descriptor rlimit.
-; Default Value: system defined value
-;rlimit_files = 1024
-
-; Set max core size rlimit.
-; Possible Values: 'unlimited' or an integer greater or equal to 0
-; Default Value: system defined value
-;rlimit_core = 0
-
-; Chroot to this directory at the start. This value must be defined as an
-; absolute path. When this value is not set, chroot is not used.
-; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
-; of its subdirectories. If the pool prefix is not set, the global prefix
-; will be used instead.
-; Note: chrooting is a great security feature and should be used whenever
-;       possible. However, all PHP paths will be relative to the chroot
-;       (error_log, sessions.save_path, ...).
-; Default Value: not set
-;chroot =
-
-; Chdir to this directory at the start.
-; Note: relative path can be used.
-; Default Value: current directory or / when chroot
-chdir = __FINALPATH__
-
-; Redirect worker stdout and stderr into main error log. If not set, stdout and
-; stderr will be redirected to /dev/null according to FastCGI specs.
-; Note: on highloaded environement, this can cause some delay in the page
-; process time (several ms).
-; Default Value: no
-;catch_workers_output = yes
-
-; Clear environment in FPM workers
-; Prevents arbitrary environment variables from reaching FPM worker processes
-; by clearing the environment in workers before env vars specified in this
-; pool configuration are added.
-; Setting to "no" will make all environment variables available to PHP code
-; via getenv(), $_ENV and $_SERVER.
-; Default Value: yes
-;clear_env = no
-
-; Limits the extensions of the main script FPM will allow to parse. This can
-; prevent configuration mistakes on the web server side. You should only limit
-; FPM to .php extensions to prevent malicious users to use other extensions to
-; execute php code.
-; Note: set an empty value to allow all extensions.
-; Default Value: .php
-;security.limit_extensions = .php .php3 .php4 .php5 .php7
-
-; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
-; the current environment.
-; Default Value: clean env
-;env[HOSTNAME] = $HOSTNAME
-;env[PATH] = /usr/local/bin:/usr/bin:/bin
-;env[TMP] = /tmp
-;env[TMPDIR] = /tmp
-;env[TEMP] = /tmp
-
-; Additional php.ini defines, specific to this pool of workers. These settings
-; overwrite the values previously defined in the php.ini. The directives are the
-; same as the PHP SAPI:
-;   php_value/php_flag             - you can set classic ini defines which can
-;                                    be overwritten from PHP call 'ini_set'.
-;   php_admin_value/php_admin_flag - these directives won't be overwritten by
-;                                     PHP call 'ini_set'
-; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
-
-; Defining 'extension' will load the corresponding shared extension from
-; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
-; overwrite previously defined php.ini values, but will append the new value
-; instead.
-
-; Note: path INI options can be relative and will be expanded with the prefix
-; (pool, global or /usr)
-
-; Default Value: nothing is defined by default except the values in php.ini and
-;                specified at startup with the -d argument
-;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
-;php_flag[display_errors] = off
-;php_admin_value[error_log] = /var/log/fpm-php.www.log
-;php_admin_flag[log_errors] = on
-;php_admin_value[memory_limit] = 32M
-
-; Common values to change to increase file upload limit
-php_value[upload_max_filesize] = 10G
-php_value[post_max_size] = 10G
-; php_admin_flag[mail.add_x_header] = Off
-
-; Other common parameters
-php_value[max_execution_time] = 600
-; php_admin_value[max_input_time] = 300
-; php_admin_value[memory_limit] = 256M
-; php_admin_flag[short_open_tag] = On

+ 0 - 12
conf/sudoers.conf

@@ -1,12 +0,0 @@
-Cmnd_Alias HOTSPOT_YUNOHOST = /usr/bin/yunohost app info hotspot *,\
-                              /usr/bin/yunohost app setting hotspot *,\
-                              /usr/bin/yunohost app setting vpnclient *
-
-Cmnd_Alias HOTSPOT_SERVICE  = /bin/systemctl stop ynh-hotspot,\
-                              /bin/systemctl start ynh-hotspot
-
-Cmnd_Alias HOTSPOT_MISC     = /usr/local/bin/ynh-hotspot *,\
-                              /usr/local/bin/iw_devices *,\
-                              /usr/local/bin/iw_multissid *
-
-__HOTSPOT_SYSUSER__ ALL = NOPASSWD: /bin/grep, HOTSPOT_YUNOHOST, HOTSPOT_SERVICE, HOTSPOT_MISC

+ 18 - 8
conf/ynh-hotspot

@@ -140,8 +140,7 @@ start_dhcpd6() {
 
   sed "s|<TPL:WIFI_DEVICE>|${dev}|g" -i /etc/dnsmasq.dhcpd/dhcpdv6-ssid${i}.conf
   sed "s|<TPL:IP6_NET>|${ynh_ip6_net[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv6-ssid${i}.conf
-  sed "s|<TPL:IP6_DNS0>|${ynh_ip6_dns0[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv6-ssid${i}.conf
-  sed "s|<TPL:IP6_DNS1>|${ynh_ip6_dns1[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv6-ssid${i}.conf
+  sed "s|<TPL:IP6_DNS>|${ynh_ip6_dns[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv6-ssid${i}.conf
 
   dnsmasq -C /etc/dnsmasq.dhcpd/dhcpdv6-ssid${i}.conf -p0
 }
@@ -152,8 +151,7 @@ start_dhcpd4() {
 
   cp /etc/dnsmasq.dhcpd/dhcpdv4{.conf.tpl,-ssid${i}.conf}
 
-  sed "s|<TPL:IP4_DNS0>|${ynh_ip4_dns0[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv4-ssid${i}.conf
-  sed "s|<TPL:IP4_DNS1>|${ynh_ip4_dns1[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv4-ssid${i}.conf
+  sed "s|<TPL:IP4_DNS>|${ynh_ip4_dns[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv4-ssid${i}.conf
   sed "s|<TPL:WIFI_DEVICE>|${dev}|g" -i /etc/dnsmasq.dhcpd/dhcpdv4-ssid${i}.conf
   sed "s|<TPL:IP4_NAT_PREFIX>|${ynh_ip4_nat_prefix[${i}]}|g" -i /etc/dnsmasq.dhcpd/dhcpdv4-ssid${i}.conf
 
@@ -253,6 +251,7 @@ ynh_setting_get() {
   setting=${2}
 
   grep "^${setting}:" "/etc/yunohost/apps/${app}/settings.yml" | sed s/^[^:]\\+:\\s*[\"\']\\?// | sed s/\\s*[\"\']\$//
+  # '"
 }
 
 ynh_setting_set() {
@@ -304,11 +303,22 @@ if [ "$1" != restart ]; then
   IFS='|' read -a ynh_ip6_addr <<< "$(ynh_setting_get hotspot ip6_addr)"
   IFS='|' read -a ynh_ip6_firewall <<< "$(ynh_setting_get hotspot ip6_firewall)"
   IFS='|' read -a ynh_ip6_net <<< "$(ynh_setting_get hotspot ip6_net)"
-  IFS='|' read -a ynh_ip6_dns0 <<< "$(ynh_setting_get hotspot ip6_dns0)"
-  IFS='|' read -a ynh_ip6_dns1 <<< "$(ynh_setting_get hotspot ip6_dns1)"
-  IFS='|' read -a ynh_ip4_dns0 <<< "$(ynh_setting_get hotspot ip4_dns0)"
-  IFS='|' read -a ynh_ip4_dns1 <<< "$(ynh_setting_get hotspot ip4_dns1)"
+  IFS='|' read -a ynh_dns <<< "$(ynh_setting_get hotspot dns)"
   IFS='|' read -a ynh_ip4_nat_prefix <<< "$(ynh_setting_get hotspot ip4_nat_prefix)"
+  for i in $(seq 0 $((${ynh_multissid} - 1))); do
+    ynh_ip6_dns[${i}]=""
+    ynh_ip4_dns[${i}]=""
+    for ip in ; do
+      if [[ "$ip" == *":"* ]]
+      then
+        ynh_ip6_dns[${i}]+="[$ip],"
+      else
+        ynh_ip4_dns[${i}]+="$ip,"
+      fi
+    done
+    ynh_ip6_dns[${i}]="${ynh_ip6_dns[${i}]%%*,}"
+    ynh_ip4_dns[${i}]="${ynh_ip4_dns[${i}]%%*,}"
+  done
 
   old_internet_device=$(ynh_setting_get hotspot internet_device)
   new_internet_device=$(ip route | awk '/default via/ { print $NF; }')

+ 239 - 0
config_panel.toml

@@ -0,0 +1,239 @@
+version = "1.0"
+
+[main]
+name = "Configuration"
+
+    [main.service]
+    name = ""
+    optional = false
+        
+        [main.service.no_antenna]
+        ask = "No wifi antenna has been detected! If you use a wifi USB dongle and that this one is not listed here, try to unplug and replug it, then reload this page."
+        type = "alert"
+        style = "danger"
+        visible = "no_antenna"
+        
+        [main.service.status]
+        ask = "The status of your VPN is unknown."
+        type = "alert"
+        style = "info"
+        visible = "! no_antenna"
+        
+        [main.service.service_enabled]
+        ask = "Enable Hotspot"
+        type = "boolean"
+        visible = "! no_antenna"
+
+        [main.service.wifi_device]
+        ask = "Device"
+        type = "select"
+        choices.wlan0 = "wlan0"
+        visible = "! no_antenna"
+        
+        [main.service.wifi_channel]
+        ask = "Channel"
+        type = "select"
+        choices.1 = "1"
+        choices.2 = "2"
+        choices.3 = "3"
+        choices.4 = "4"
+        choices.5 = "5"
+        choices.6 = "6"
+        choices.7 = "7"
+        choices.8 = "8"
+        choices.9 = "9"
+        choices.10 = "10"
+        choices.11 = "11"
+        visible = "! no_antenna"
+        
+        [main.service.multissid]
+        ask = "Hotspot number"
+        type = "select"
+        choices.1 = "1"
+        choices.2 = "2"
+        choices.3 = "3"
+        visible = "! no_antenna"
+        
+    [main.hotspot1]
+    name = "Hotspot 1"
+    optional = false
+    visible = "! no_antenna"
+
+        [main.hotspot1.wifi_ssid__1]
+        ask = "Name (SSID)"
+        type = "string"
+        bind = "array_settings()"
+        pattern.regexp = '^[\w \-]{1,32}$'
+        pattern.error = "SSID in this app are limited to letter, number space, dash and underscores."
+        
+        [main.hotspot1.wifi_secure__1]
+        ask = "Secure"
+        type = "boolean"
+        bind = "array_settings()"
+
+        [main.hotspot1.wifi_passphrase__1]
+        ask = "Password (WPA2)"
+        type = "string"
+        bind = "array_settings()"
+        redact = true
+        optional = true
+        visible = "wifi_secure__1" 
+        pattern.regexp = '^[a-zA-Z0-9]{8,63}$'
+        pattern.error = "Only printable alphanumeric characters are permitted in your password. Maximal size 63 chars"
+        
+        [main.hotspot1.advanced__1]
+        ask = "Advanced settings"
+        type = "boolean"
+        bind = "array_settings()"
+        
+        [main.hotspot1.ip4_nat_prefix__1]
+        ask = "IPv4 NAT prefix (/24)"
+        type = "string"
+        bind = "array_settings()"
+        visible = "advanced__1"
+        pattern.regexp = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
+        pattern.error = "Please provide a private /24 range in the format xxx.xxx.xxx"
+        
+        [main.hotspot1.ip6_net__1]
+        ask = "IPv6 delegated prefix"
+        type = "string"
+        bind = "array_settings()"
+        optional = "true"
+        visible = "advanced__1"
+        pattern.regexp = '^[0-9a-fA-F:]+$'
+        pattern.error = "Please provide a valid IPv6 Prefix"
+        
+        [main.hotspot1.ip6_firewall__1]
+        ask = "IPv6 firewall"
+        type = "boolean"
+        bind = "array_settings()"
+        visible = "advanced__1"
+        
+        [main.hotspot1.dns__1]
+        ask = "DNS resolvers"
+        type = "tags"
+        bind = "array_settings()"
+        visible = "advanced__1"
+        pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
+        pattern.error = "Not an ip"
+    
+    [main.hotspot2]
+    name = "Hotspot 2"
+    visible = "! no_antenna && multissid >= 2"
+
+        [main.hotspot2.wifi_ssid__2]
+        ask = "Name (SSID)"
+        type = "string"
+        bind = "array_settings()"
+        pattern.regexp = '^[\w \-]{1,32}$'
+        pattern.error = "SSID in this app are limited to letter, number space, dash and underscores."
+        
+        [main.hotspot2.wifi_secure__2]
+        ask = "Secure"
+        type = "boolean"
+        bind = "array_settings()"
+
+        [main.hotspot2.wifi_passphrase__2]
+        ask = "Password (WPA2)"
+        type = "string"
+        bind = "array_settings()"
+        redact = true
+        visible = "wifi_secure__2" 
+        pattern.regexp = '^[a-zA-Z0-9]{8,63}$'
+        pattern.error = "Only printable alphanumeric characters are permitted in your password. Maximal size 63 chars"
+        
+        [main.hotspot2.advanced__2]
+        ask = "Advanced settings"
+        type = "boolean"
+        bind = "array_settings()"
+        
+        [main.hotspot2.ip4_nat_prefix__2]
+        ask = "IPv4 NAT prefix (/24)"
+        type = "string"
+        bind = "array_settings()"
+        visible = "advanced__2"
+        pattern.regexp = '^[0-9.]{7,15}$'
+        pattern.error = "Please provide a valid IP"
+        
+        [main.hotspot2.ip6_net__2]
+        ask = "IPv6 delegated prefix"
+        type = "string"
+        bind = "array_settings()"
+        visible = "advanced__2"
+        pattern.regexp = '^[0-9a-fA-F:]+$'
+        pattern.error = "Please provide a valid IPv6 Prefix"
+        
+        [main.hotspot2.ip6_firewall__2]
+        ask = "IPv6 firewall"
+        type = "boolean"
+        bind = "array_settings()"
+        visible = "advanced__2"
+        
+        [main.hotspot2.dns__2]
+        ask = "DNS resolvers"
+        type = "tags"
+        bind = "array_settings()"
+        visible = "advanced__2"
+        pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
+        pattern.error = "Not an ip"
+    
+    [main.hotspot3]
+    name = "Hotspot 3"
+    visible = "! no_antenna && multissid >= 3"
+
+        [main.hotspot3.wifi_ssid__3]
+        ask = "Name (SSID)"
+        type = "string"
+        bind = "array_settings()"
+        pattern.regexp = '^[\w \-]{1,32}$'
+        pattern.error = "SSID in this app are limited to letter, number space, dash and underscores."
+        
+        [main.hotspot3.wifi_secure__3]
+        ask = "Secure"
+        type = "boolean"
+        bind = "array_settings()"
+
+        [main.hotspot3.wifi_passphrase__3]
+        ask = "Password (WPA2)"
+        type = "string"
+        bind = "array_settings()"
+        redact = true
+        visible = "wifi_secure__3" 
+        pattern.regexp = '^[a-zA-Z0-9]{8,63}$'
+        pattern.error = "Only printable alphanumeric characters are permitted in your password. Maximal size 63 chars"
+        
+        [main.hotspot3.advanced__3]
+        ask = "Advanced settings"
+        type = "boolean"
+        bind = "array_settings()"
+        
+        [main.hotspot3.ip4_nat_prefix__3]
+        ask = "IPv4 NAT prefix (/24)"
+        type = "string"
+        bind = "array_settings()"
+        visible = "advanced__3"
+        pattern.regexp = '^[0-9.]{7,15}$'
+        pattern.error = "Please provide a valid IP"
+        
+        [main.hotspot3.ip6_net__3]
+        ask = "IPv6 delegated prefix"
+        type = "string"
+        bind = "array_settings()"
+        visible = "advanced__3"
+        pattern.regexp = '^[0-9a-fA-F:]+$'
+        pattern.error = "Please provide a valid IPv6 Prefix"
+        
+        [main.hotspot3.ip6_firewall__3]
+        ask = "IPv6 firewall"
+        type = "boolean"
+        bind = "array_settings()"
+        visible = "advanced__3"
+        
+        [main.hotspot3.dns__3]
+        ask = "DNS resolvers"
+        type = "tags"
+        bind = "array_settings()"
+        visible = "advanced__3"
+        pattern.regexp = '^([0-9.]{7,15}|[0-9a-fA-F:]+)$'
+        pattern.error = "Not an ip"
+    

+ 2 - 0
doc/DESCRIPTION.md

@@ -0,0 +1,2 @@
+* Broadcast a Wi-Fi access point from your self-hosted server
+* Combine with the [VPN Client app](https://github.com/labriqueinternet/vpnclient_ynh) to obtain a VPN-protected WiFi

+ 2 - 0
doc/DESCRIPTION_fr.md

@@ -0,0 +1,2 @@
+* Diffusez un point d'accès Wi-Fi depuis votre serveur auto-hébergé
+* À combiner avec l'[app VPN Client](https://github.com/labriqueinternet/vpnclient_ynh) pour obtenir un accès internet aumatiquement protégé par votre VPN

BIN
doc/screenshots/hotspot.png


+ 7 - 22
manifest.json

@@ -15,26 +15,13 @@
         "url": "http://julien.vaubourg.com"
     },
     "requirements": {
-        "yunohost": ">= 4.1.0"
+        "yunohost": ">= 4.2.8"
     },
     "multi_instance": false,
-    "services": [
-        "nginx",
-        "php7.0-fpm"
-    ],
+    "services": [],
     "arguments": {
         "install" : [
             {
-                "name": "domain",
-                "type": "domain",
-                "example": "domain.org"
-            },
-            {
-                "name": "path",
-                "type": "path",
-                "default": "/wifiadmin"
-            },
-            {
                 "name": "wifi_ssid",
                 "type": "string",
                 "ask": {
@@ -50,18 +37,16 @@
                 "ask": {
                     "en": "Choose a wifi password (at least 8 characters for WPA2)",
                     "fr": "Choisissez un mot de passe wifi (au minimum 8 caractères pour le WPA2)"
-                },
-                "example": "VhegT8oev0jZI"
+                }
             },
             {
                 "name": "firmware_nonfree",
-                "type": "string",
+                "type": "boolean",
                 "ask": {
-                    "en": "Install non-free firmwares - in addition to the free ones - for the wifi dongle (yes/no)",
-                    "fr": "Installer des firmwares non-libres (en plus des libres) pour la clé USB wifi (yes/no)"
+                    "en": "Install non-free firmwares - in addition to the free ones - for the wifi dongle",
+                    "fr": "Installer des firmwares non-libres (en plus des libres) pour la clé USB wifi"
                 },
-                "choice": [ "yes", "no" ],
-                "default": "no"
+                "default": false
             }
         ]
     }

+ 6 - 1
scripts/_common.sh

@@ -4,7 +4,7 @@
 # COMMON VARIABLES
 #=================================================
 
-pkg_dependencies="sipcalc hostapd iptables iw dnsmasq kmod"
+pkg_dependencies="sipcalc hostapd iw kmod"
 nonfree_firmware_packages="firmware-atheros firmware-realtek firmware-ralink firmware-libertas atmel-firmware firmware-zd1211"
 free_firmware_packages="firmware-ath9k-htc"
 
@@ -12,6 +12,11 @@ free_firmware_packages="firmware-ath9k-htc"
 # PERSONAL HELPERS
 #=================================================
 
+function iw_devices()
+{
+  echo -n $(/sbin/iw dev | grep Interface | grep -v 'mon\.' | grep -v hotspot | awk '{ print $NF }') | tr ' ' '|'
+}
+
 function check_armbian_nonfree_conflict()
 {
 

+ 0 - 24
scripts/backup

@@ -28,10 +28,8 @@ ynh_print_info --message="Loading installation settings..."
 app=$YNH_APP_INSTANCE_NAME
 
 final_path=$(ynh_app_setting_get --app=$app --key=final_path)
-domain=$(ynh_app_setting_get --app=$app --key=domain)
 firmware_nonfree=$(ynh_app_setting_get --app=$app --key=firmware_nonfree)
 service_name=$(ynh_app_setting_get --app=$app --key=service_name)
-phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
 
 #=================================================
 # DECLARE DATA AND CONF FILES TO BACKUP
@@ -42,16 +40,6 @@ ynh_print_info --message="Declaring files to be backed up..."
 # BACKUP THE APP MAIN DIR
 #=================================================
 
-ynh_backup --src_path="$final_path"
-
-ynh_backup --src_path="/etc/sudoers.d/${app}_ynh"
-
-ynh_backup --src_path="/usr/local/bin/iw_multissid"
-ynh_backup --src_path="/usr/local/bin/iw_devices"
-ynh_backup --src_path="/usr/local/bin/iw_ssids"
-ynh_backup --src_path="/usr/local/bin/ipv6_expanded"
-ynh_backup --src_path="/usr/local/bin/ipv6_compressed"
-
 for FILE in $(ls /etc/hostapd/hostapd.conf{.tpl?,} 2>/dev/null)
 do
 	ynh_backup --src_path="$FILE"
@@ -64,18 +52,6 @@ ynh_backup --src_path="/usr/local/bin/$service_name"
 ynh_backup --src_path="/etc/init.d/hostapd"
 
 #=================================================
-# BACKUP THE NGINX CONFIGURATION
-#=================================================
-
-ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf"
-
-#=================================================
-# BACKUP THE PHP-FPM CONFIGURATION
-#=================================================
-
-ynh_backup --src_path="/etc/php/$phpversion/fpm/pool.d/$app.conf"
-
-#=================================================
 # SPECIFIC BACKUP
 #=================================================
 # BACKUP SYSTEMD

+ 221 - 0
scripts/config

@@ -0,0 +1,221 @@
+#!/bin/bash
+
+#=================================================
+# GENERIC STARTING
+#=================================================
+# IMPORT GENERIC HELPERS
+#=================================================
+
+source _common.sh
+source /usr/share/yunohost/helpers
+
+#=================================================
+# MANAGE SCRIPT FAILURE
+#=================================================
+
+# Exit if an error occurs during the execution of the script
+ynh_abort_if_errors
+
+#=================================================
+# RETRIEVE ARGUMENTS
+#=================================================
+
+final_path=$(ynh_app_setting_get $app final_path)
+
+#=================================================
+# SPECIFIC GETTERS FOR TOML SHORT KEY
+#=================================================
+
+get__no_antenna() {
+    if [[ $(iw_devices) == "" ]]
+    then
+        echo "value: false"
+    else
+        cat << EOF
+value: false
+ask: Wifi antenna correctly detected
+style: info
+EOF
+    fi
+}
+
+get__status() {
+    local service_enabled=$(ynh_app_setting_get $app service_enabled)
+    if systemctl is-active hostapd -q
+    then
+        if [ $service_enabled -eq 1 ]
+        then
+            cat << EOF
+style: success
+ask:
+  en: |-
+    Your Hotspot is running :)
+EOF
+        else
+            cat << EOF
+style: warning
+ask:
+  en: Your Hotspot is running, but it shouldn't !
+EOF
+        fi
+    elif [ $service_enabled -eq 1 ]
+    then
+        cat << EOF
+style: danger
+ask:
+  en: |-
+    Your Hotspot is down ! Here are errors logged in the last 5 minutes
+    \`\`\`
+$(journalctl -u hostapd -n10 -o cat | sed 's/^/    /g')
+    \`\`\`
+EOF
+    else
+        cat << EOF
+style: info
+ask:
+  en: Your Hotspot is down as expected.
+EOF
+
+    fi
+}
+
+get__wifi_device() {
+    if [[ $(iw_devices) == "" ]]
+    then
+        echo "choices: []"
+    else
+        cat << EOF
+choices:
+EOF
+        for device in $(iw_devices)
+        do
+            echo "  $device: $device"
+        done
+    fi
+}
+
+get__array_settings() {
+    local short_setting="${1%%__*}"
+    local index="${1#*__}"
+    IFS='|' read -a values <<< "$(ynh_app_setting_get $app $short_setting)"
+    echo "value: \"${values[$(($index - 1))]:-}\""
+}
+
+#=================================================
+# SPECIFIC VALIDATORS FOR TOML SHORT KEYS
+#=================================================
+is_unique() {
+    local short_setting="$1"
+    local short_setting__1="$1__1"
+    local short_setting__2="$1__2"
+    local short_setting__3="$1__3"
+    if [[ "${!short_setting__1}" == "${!short_setting__2}" ]]
+    then
+        return 1
+    elif [ "$multissid" -ge "3" ] && [[ "${!short_setting__1}" == "${!short_setting__3}" ]]
+    then
+        return 1
+    elif [ "$multissid" -ge "3" ] && [[ "${!short_setting__2}" == "${!short_setting__3}" ]]
+    then
+        return 1
+    fi
+    return 0
+}
+validate__wifi_ssid() {
+    local wifi_ssid_var="wifi_ssid__$1"
+    if [ "$multissid" -ge "$1" ] && [[ -z "${!wifi_ssid_var}" ]]
+    then
+        echo 'SSID required'
+    fi
+    if ! is_unique wifi_ssid
+    then
+        echo 'All Wifi names must be unique'
+    fi
+}
+
+validate__wifi_passphrase() {
+    local wifi_secure_var="wifi_secure__$1"
+    local wifi_passphrase_var="wifi_passphrase__$1"
+    if [ "$multissid" -ge "$1" ] && [[ "${!wifi_secure_var}" == "1" ]] && [[ -z "${!wifi_passphrase_var}" ]]
+    then
+        echo 'In WPA2 secure mode, you need to provide a passphrase'
+    fi
+}
+
+validate__ip4_nat_prefix() {
+    local ip4_nat_prefix_var="ip4_nat_prefix__$1"
+    if [ "$multissid" -ge "$1" ] && [[ -z "${!ip4_nat_prefix_var}" ]]
+    then
+        echo 'Private IPv4 nat prefix required'
+    fi
+    if ! is_unique ip4_nat_prefix
+    then
+        echo 'All IPv4 prefix must be unique'
+    fi
+}
+
+validate__dns() {
+    local dns_var="dns__$1"
+    local ip6_net_var="dns__$1"
+    if [ "$multissid" -ge "$1" ] && ! echo "${!dns_var}" | grep -q "\."
+    then
+        echo 'IPv4 DNS required'
+    fi
+    if [ "$multissid" -ge "$1" ] && [[ -n "${!ip6_net_var}" ]] && ! echo "${!dns_var}" | grep -q ":"
+    then
+        echo 'IPv6 DNS required'
+    fi
+}
+
+validate__array_settings() {
+    local short_setting="${1%%__*}"
+    local index="${1#*__}"
+    if type -t validate__$short_setting | grep -q '^function$' 2>/dev/null;
+    then
+        validate__$short_setting $index
+    fi
+}
+
+#=================================================
+# SPECIFIC SETTERS FOR TOML SHORT KEYS
+#=================================================
+set__array_settings() {
+    local short_setting="${1%%__*}"
+    local index="${1#*__}"
+    local type="${types[$1]}"
+    local value="${!1}"
+    if [[ "$type" == "string" ]] && [ "$multissid" -lt "$index" ]
+    then
+        value=""
+    fi
+    local values="$(ynh_app_setting_get $app $short_setting | awk 'BEGIN{FS=OFS="|"} {$'$index'="'${!1}'"}'1)"
+    ynh_app_setting_set --app=$app --key=$short_setting --value="$values"
+    ynh_print_info --message="Configuration key '$short_setting' edited in app settings"
+}
+
+
+#=================================================
+# OVERWRITING VALIDATE STEP 
+#=================================================
+ynh_app_config_validate() {
+    _ynh_app_config_validate
+}
+
+#=================================================
+# OVERWRITING APPLY STEP 
+#=================================================
+ynh_app_config_apply() {
+    
+    # Stop vpn client
+    ynh_print_info --message="Stopping hotspot in order to edit files"
+    /usr/local/bin/ynh-hotspot stop
+
+    _ynh_app_config_apply
+    
+    # Start vpn client
+    ynh_print_info --message="Starting hotspot service if needed"
+    /usr/local/bin/ynh-hotspot start
+
+}
+
+ynh_app_config_run $1

+ 14 - 98
scripts/install

@@ -1,22 +1,5 @@
 #!/bin/bash
 
-# Wifi Hotspot app for YunoHost
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
 #=================================================
 # GENERIC START
 #=================================================
@@ -40,8 +23,6 @@ ynh_abort_if_errors
 # RETRIEVE ARGUMENTS FROM THE MANIFEST
 #=================================================
 
-domain=$YNH_APP_ARG_DOMAIN
-path_url=$YNH_APP_ARG_PATH
 wifi_ssid=$YNH_APP_ARG_WIFI_SSID
 wifi_passphrase=$YNH_APP_ARG_WIFI_PASSPHRASE
 firmware_nonfree=$YNH_APP_ARG_FIRMWARE_NONFREE
@@ -56,26 +37,14 @@ service_name='ynh-hotspot'
 #=================================================
 ynh_script_progression --message="Validating installation parameters..."
 
-final_path=/var/www/$app
-test ! -e "$final_path" || ynh_die --message="This path already contains a folder"
-
-# Register (book) web path
-ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url
-
-if [ $firmware_nonfree = "no" ]; then
-	firmware_nonfree=0
-elif [ $firmware_nonfree = "yes" ]; then
-	firmware_nonfree=1
-fi
-
 # Check arguments
-if [[ -z $wifi_ssid || -z $wifi_passphrase ]]; then
+if [[ -z $wifi_ssid ]] || [[ -z $wifi_passphrase ]]; then
 	ynh_die --message="Your Wifi Hotspot needs a name and a password"
 fi
 
 # Check passphrase length
-wifi_passphrase_length="$(echo -n "${wifi_passphrase}" | wc -c)"
-if [[ $wifi_passphrase_length -lt 8 || $wifi_passphrase_length -gt 63 ]]; then
+wifi_passphrase_length="$(wc -c <<< "${wifi_passphrase}")"
+if [[ $wifi_passphrase_length -lt 8 ]] || [[ $wifi_passphrase_length -gt 63 ]]; then
 	ynh_die --message="Your password must from 8 to 63 characters (WPA2 passphrase)"
 fi
 
@@ -89,7 +58,6 @@ fi
 #=================================================
 ynh_script_progression --message="Storing installation settings..."
 
-ynh_app_setting_set --app=$app --key=domain --value=$domain
 ynh_app_setting_set --app=$app --key=wifi_ssid --value="$wifi_ssid"
 ynh_app_setting_set --app=$app --key=wifi_passphrase --value="$wifi_passphrase"
 ynh_app_setting_set --app=$app --key=firmware_nonfree --value="$firmware_nonfree"
@@ -137,20 +105,10 @@ ynh_script_progression --message="Configuring system user..."
 # Create a system user
 ynh_system_user_create --username=$app
 
-# Ensure the system user has enough sudo permissions
-install -b -o root -g root -m 0440 ../conf/sudoers.conf /etc/sudoers.d/${app}_ynh
-ynh_replace_string --match_string="__HOTSPOT_SYSUSER__" --replace_string="${app}" --target_file="/etc/sudoers.d/${app}_ynh"
-
 #=================================================
-# INSTALL CUSTOM SCRIPTS
+# SPECIFIC SETTINGS
 #=================================================
-ynh_script_progression --message="Installing custom script..."
-
-install -o root -g root -m 0755 ../conf/iw_multissid /usr/local/bin/
-install -o root -g root -m 0755 ../conf/iw_devices /usr/local/bin/
-install -o root -g root -m 0755 ../conf/iw_ssids /usr/local/bin/
-install -o root -g root -m 0755 ../conf/ipv6_expanded /usr/local/bin/
-install -o root -g root -m 0755 ../conf/ipv6_compressed /usr/local/bin/
+ynh_script_progression --message="Configuring hotspot..."
 
 if [[ ! -v ip6_net ]]; then # if ip6_net not set
 	ip6_net=none
@@ -168,9 +126,10 @@ if [[ ! -v ip6_net ]]; then # if ip6_net not set
 fi
 
 hot_reload_usb_wifi_cards
-wifi_device=$(bash ../conf/iw_devices | awk -F\| '{ print $1 }')
+wifi_device=$(iw_devices | awk -F\| '{ print $1 }')
 
 ynh_app_setting_set --app=$app --key=multissid --value=1
+ynh_app_setting_set --app=$app --key=ssid_nb --value=1
 ynh_app_setting_set --app=$app --key=wifi_ssid --value="${wifi_ssid}"
 ynh_app_setting_set --app=$app --key=wifi_secure --value=1
 ynh_app_setting_set --app=$app --key=wifi_passphrase --value="${wifi_passphrase}"
@@ -179,16 +138,12 @@ ynh_app_setting_set --app=$app --key=wifi_channel --value=6
 ynh_app_setting_set --app=$app --key=ip6_addr --value="${ip6_addr}"
 ynh_app_setting_set --app=$app --key=ip6_firewall --value=1
 ynh_app_setting_set --app=$app --key=ip6_net --value="${ip6_net}"
-ynh_app_setting_set --app=$app --key=ip6_dns0 --value=2001:913::8
-ynh_app_setting_set --app=$app --key=ip6_dns1 --value=2001:910:800::12
-ynh_app_setting_set --app=$app --key=ip4_dns0 --value=80.67.188.188
-ynh_app_setting_set --app=$app --key=ip4_dns1 --value=80.67.169.12
+ynh_app_setting_set --app=$app --key=dns --value="2001:913::8,2001:910:800::12,80.67.188.188,80.67.169.12"
 ynh_app_setting_set --app=$app --key=ip4_nat_prefix --value=10.0.242
 ynh_app_setting_set --app=$app --key=vpnclient --value=no
 
 if [[ -z $wifi_device ]]; then
 	ynh_app_setting_set --app=$app --key=service_enabled --value=0
-	wifi_device=none
 else
 	ynh_app_setting_set --app=$app --key=service_enabled --value=1
 fi
@@ -196,7 +151,7 @@ fi
 #=================================================
 # COPY CONFIGS
 #=================================================
-ynh_script_progression --message="Copying configuration..."
+ynh_script_progression --message="Copying configuration files..."
 
 mkdir -pm 0755 /etc/dnsmasq.dhcpd/
 chown root: /etc/dnsmasq.dhcpd/
@@ -207,36 +162,6 @@ install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv4.conf.tpl /etc/dnsmasq
 
 # Copy init script
 install -o root -g root -m 0755 ../conf/$service_name /usr/local/bin/
-ynh_replace_string --match_string="__PHPVERSION__" --replace_string="${YNH_PHP_VERSION}" --target_file="/usr/local/bin/$service_name"
-
-#=================================================
-# COPY WEB SOURCES
-#=================================================
-ynh_script_progression --message="Setting up source files..."
-
-ynh_app_setting_set --app=$app --key=final_path --value=$final_path
-mkdir -pm 0755 $final_path
-cp -a ../sources/* ${final_path}/
-
-chmod 750 "$final_path"
-chmod o-rwx "$final_path"
-chown -R $app:www-data "$final_path"
-
-#=================================================
-# NGINX CONFIGURATION
-#=================================================
-ynh_script_progression --message="Configuring NGINX web server..."
-
-# Create a dedicated NGINX config
-ynh_add_nginx_config
-
-#=================================================
-# PHP-FPM CONFIGURATION
-#=================================================
-ynh_script_progression --message="Configuring PHP-FPM..."
-
-# Create a dedicated PHP-FPM config
-ynh_add_fpm_config
 
 #=================================================
 # CONFIGURE HOSTAPD
@@ -245,15 +170,13 @@ ynh_script_progression --message="Configuring hostapd..."
 
 ## hostapd
 ynh_replace_string --match_string="^DAEMON_CONF=$" --replace_string="&/etc/hostapd/hostapd.conf" --target_file=/etc/init.d/hostapd
+ynh_store_file_checksum --file="/etc/init.d/hostapd"
+
 # We also need to put this in /etc/default/hostapd because on some setup
 # like RPi, the version of hostapd is different and /etc/init.d/hostapd
 # isnt used ... instead the service is "pure systemd" ...
 echo "DAEMON_CONF=/etc/hostapd/hostapd.conf" > /etc/default/hostapd
 
-# Apply configuration
-ynh_add_config --template="config.php.tpl" --destination="$final_path/config.php"
-chown $app:$app "$final_path/config.php"
-
 # Set default inits
 # The boot order of these services are important, so they are disabled by default
 # and the ynh-hotspot service handles them.
@@ -262,14 +185,6 @@ systemctl stop hostapd
 systemctl unmask hostapd # On some system e.g. RPi, for some reason hostapd is masked after install ...
 
 #=================================================
-# STORE THE CONFIG FILE CHECKSUM
-#=================================================
-ynh_script_progression --message="Storing the config file checksum..."
-
-# Calculate and store the config file checksum into the app settings
-ynh_store_file_checksum --file="/etc/init.d/hostapd"
-
-#=================================================
 # SETUP SYSTEMD
 #=================================================
 ynh_script_progression --message="Configuring a systemd service..."
@@ -278,7 +193,8 @@ ynh_script_progression --message="Configuring a systemd service..."
 ynh_add_systemd_config --service=$service_name
 
 # Remove IPv6 address set if there is a VPN installed
-if [[ $ip6_addr != none ]]; then
+# ... but why ? ...
+if [[ $ip6_addr != "" ]]; then
 	if ip -6 address show dev tun0 2> /dev/null | grep -q "${ip6_addr}/"; then
 		ip address delete "${ip6_addr}/128" dev tun0 &> /dev/null
 	fi
@@ -297,7 +213,7 @@ yunohost service add $service_name --description "Creates a Wi-Fi access point"
 ynh_script_progression --message="Starting a systemd service..."
 
 # Start a systemd service if device is present
-if [[ $wifi_device == none ]]; then
+if [[ $wifi_device == "" ]]; then
 	echo "WARNING: Wifi Hotspot is not started because no wifi device was found (please, check the web admin)" >&2
 else
 	ynh_systemd_action --service_name=$service_name --action="start" --log_path=systemd #--line_match="Started YunoHost Wifi Hotspot"

+ 0 - 45
scripts/remove

@@ -1,22 +1,5 @@
 #!/bin/bash
 
-# Wifi Hotspot app for YunoHost
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/hotspot_ynh
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
 #=================================================
 # GENERIC START
 #=================================================
@@ -33,10 +16,8 @@ ynh_script_progression --message="Loading installation settings..."
 
 app=$YNH_APP_INSTANCE_NAME
 
-domain=$(ynh_app_setting_get --app=$app --key=domain)
 firmware_nonfree=$(ynh_app_setting_get --app=$app --key=firmware_nonfree)
 service_name=$(ynh_app_setting_get --app=$app --key=service_name)
-final_path=$(ynh_app_setting_get --app=$app --key=final_path)
 
 #=================================================
 # STANDARD REMOVE
@@ -74,18 +55,8 @@ ynh_remove_app_dependencies
 ynh_script_progression --message="Removing app main directory..."
 
 # Remove the app directory securely
-ynh_secure_remove --file="$final_path"
-
 ynh_secure_remove --file="/usr/local/bin/$service_name"
 
-ynh_secure_remove --file="/usr/local/bin/iw_multissid"
-ynh_secure_remove --file="/usr/local/bin/iw_devices"
-ynh_secure_remove --file="/usr/local/bin/iw_ssids"
-ynh_secure_remove --file="/usr/local/bin/ipv6_expanded"
-ynh_secure_remove --file="/usr/local/bin/ipv6_compressed"
-
-ynh_secure_remove --file="/etc/sudoers.d/${app}_ynh"
-
 for FILE in $(ls /tmp/.ynh-hotspot-* 2>/dev/null)
 do
     ynh_secure_remove --file="$FILE"
@@ -100,22 +71,6 @@ do
 done
 
 #=================================================
-# REMOVE NGINX CONFIGURATION
-#=================================================
-ynh_script_progression --message="Removing NGINX web server configuration..."
-
-# Remove the dedicated NGINX config
-ynh_remove_nginx_config
-
-#=================================================
-# REMOVE PHP-FPM CONFIGURATION
-#=================================================
-ynh_script_progression --message="Removing PHP-FPM configuration..."
-
-# Remove the dedicated PHP-FPM config
-ynh_remove_fpm_config
-
-#=================================================
 # CLOSE A PORT
 #=================================================
 

+ 3 - 55
scripts/restore

@@ -27,51 +27,25 @@ ynh_script_progression --message="Loading installation settings..."
 
 app=$YNH_APP_INSTANCE_NAME
 
-domain=$(ynh_app_setting_get --app=$app --key=domain)
-path_url=$(ynh_app_setting_get --app=$app --key=path)
-final_path=$(ynh_app_setting_get --app=$app --key=final_path)
 firmware_nonfree=$(ynh_app_setting_get --app=$app --key=firmware_nonfree)
 service_name=$(ynh_app_setting_get --app=$app --key=service_name)
-phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
 
 #=================================================
 # CHECK IF THE APP CAN BE RESTORED
 #=================================================
 ynh_script_progression --message="Validating restoration parameters..."
 
-ynh_webpath_available --domain=$domain --path_url=$path_url \
-	|| ynh_die --message="Path not available: ${domain}${path_url}"
-test ! -d $final_path \
-	|| ynh_die --message="There is already a directory: $final_path "
 
 #=================================================
 # STANDARD RESTORATION STEPS
 #=================================================
-# RESTORE THE NGINX CONFIGURATION
-#=================================================
-ynh_script_progression --message="Restoring the NGINX configuration..."
-
-ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf"
-
 #=================================================
 # RECREATE THE DEDICATED USER
 #=================================================
 ynh_script_progression --message="Recreating the dedicated system user..."
 
 # Create the dedicated user (if not existing)
-ynh_system_user_create --username=$app --home_dir=$final_path
-
-#=================================================
-# RESTORE THE APP MAIN DIR
-#=================================================
-ynh_script_progression --message="Restoring the app main directory..."
-
-ynh_restore_file --origin_path="$final_path"
-
-# Restore permissions on app files
-chmod 750 "$final_path"
-chmod o-rwx "$final_path"
-chown -R $app:www-data "$final_path"
+ynh_system_user_create --username=$app
 
 
 if [[ $firmware_nonfree -eq 1 ]]; then
@@ -81,14 +55,6 @@ else
 	pkg_dependencies="$pkg_dependencies $free_firmware_packages"
 fi
 
-ynh_restore_file --origin_path="/etc/sudoers.d/${app}_ynh"
-
-ynh_restore_file --origin_path="/usr/local/bin/iw_multissid"
-ynh_restore_file --origin_path="/usr/local/bin/iw_devices"
-ynh_restore_file --origin_path="/usr/local/bin/iw_ssids"
-ynh_restore_file --origin_path="/usr/local/bin/ipv6_expanded"
-ynh_restore_file --origin_path="/usr/local/bin/ipv6_compressed"
-
 for FILE in $(ls /etc/hostapd/hostapd.conf{.tpl?,} 2>/dev/null)
 do
     ynh_restore_file --origin_path="$FILE"
@@ -101,13 +67,6 @@ ynh_restore_file --origin_path="/usr/local/bin/$service_name"
 ynh_restore_file --origin_path="/etc/init.d/hostapd"
 
 #=================================================
-# RESTORE THE PHP-FPM CONFIGURATION
-#=================================================
-ynh_script_progression --message="Restoring the PHP-FPM configuration..."
-
-ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf"
-
-#=================================================
 # SPECIFIC RESTORATION
 #=================================================
 # REINSTALL DEPENDENCIES
@@ -138,33 +97,22 @@ yunohost service add $service_name --description "Creates a Wi-Fi access point"
 ynh_script_progression --message="Starting a systemd service..."
 
 hot_reload_usb_wifi_cards
-wifi_device=$(bash ../settings/conf/iw_devices | awk -F\| '{ print $1 }')
+wifi_device=$(iw_devices | awk -F\| '{ print $1 }')
 
 if [[ -z $wifi_device ]]; then
 	ynh_app_setting_set --app=$app --key=service_enabled --value=0
-	wifi_device=none
 else
 	ynh_app_setting_set --app=$app --key=service_enabled --value=1
 fi
 
 # Start a systemd service if device is present
-if [[ $wifi_device == none ]]; then
+if [[ $wifi_device == "" ]]; then
 	echo "WARNING: Wifi Hotspot is not started because no wifi device was found (please, check the web admin)" >&2
 else
 	ynh_systemd_action --service_name=$service_name --action="start" --log_path=systemd #--line_match="Started YunoHost Wifi Hotspot"
 fi
 
 #=================================================
-# GENERIC FINALIZATION
-#=================================================
-# RELOAD NGINX AND PHP-FPM
-#=================================================
-ynh_script_progression --message="Reloading NGINX web server and PHP-FPM..."
-
-ynh_systemd_action --service_name=php$phpversion-fpm --action=reload
-ynh_systemd_action --service_name=nginx --action=reload
-
-#=================================================
 # END OF SCRIPT
 #=================================================
 

+ 25 - 71
scripts/upgrade

@@ -16,12 +16,8 @@ ynh_script_progression --message="Loading installation settings..."
 
 app=$YNH_APP_INSTANCE_NAME
 
-domain=$(ynh_app_setting_get --app=$app --key=domain)
-path_url=$(ynh_app_setting_get --app=$app --key=path)
-final_path=$(ynh_app_setting_get --app=$app --key=final_path)
 firmware_nonfree=$(ynh_app_setting_get --app=$app --key=firmware_nonfree)
 service_name=$(ynh_app_setting_get --app=$app --key=service_name)
-phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
 
 #=================================================
 # CHECK VERSION
@@ -58,22 +54,8 @@ ynh_systemd_action --service_name=$service_name --action="stop" --log_path=syste
 #=================================================
 ynh_script_progression --message="Ensuring downward compatibility..."
 
-if [ -z $phpversion ]; then
-	phpversion=$YNH_PHP_VERSION
-	ynh_app_setting_set --app=$app --key=phpversion --value=$phpversion
-fi
-
-# If final_path doesn't exist, create it
-if [ -z "$final_path" ]; then
-	final_path=/var/www/$app
-	ynh_app_setting_set --app=$app --key=final_path --value=$final_path
-fi
-
 if [ -d /var/www/wifiadmin/ ]; then
-	mv /var/www/wifiadmin $final_path
-	mv /etc/php/7.0/fpm/pool.d/wifiadmin.conf /etc/php/$phpversion/fpm/pool.d/$app.conf
-	ynh_replace_string --match_string="wifiadmin" --replace_string="$app" --target_file=/etc/php/$phpversion/fpm/pool.d/$app.conf
-	ynh_systemd_action --service_name=php$phpversion-fpm --action=reload
+    ynh_secure_remove /var/www/wifiadmin/
 fi
 
 if [ $firmware_nonfree = "yes" ]; then
@@ -89,38 +71,36 @@ if [ -z $service_name ]; then
 	ynh_app_setting_set --app=$app --key=service_name --value=$service_name
 fi
 
-#=================================================
-# CREATE DEDICATED USER
-#=================================================
-ynh_script_progression --message="Making sure dedicated system user exists..."
+# Old stuff prior to 2.x
 
-# Create a dedicated user (if not existing)
-ynh_system_user_create --username=$app --home_dir=$final_path
+if [ -f /etc/nginx/conf.d/*.d/$app.conf ]; then
+	ynh_secure_remove /etc/nginx/conf.d/*.d/$app.conf
+    ynh_systemd_action --service_name=nginx --action=reload
+fi
+if [ -f /etc/php/*/fpm/pool.d/$app.conf ]; then
+	ynh_secure_remove /etc/php/*/fpm/pool.d/$app.conf
+    ynh_systemd_action --service_name=php$YNH_DEFAULT_PHP_VERSION-fpm --action=reload
+fi
 
-#=================================================
-# DOWNLOAD, CHECK AND UNPACK SOURCE
-#=================================================
+if [ -d /var/www/$app ]; then
+	ynh_secure_remove /var/www/$app
+fi
 
-if [ "$upgrade_type" == "UPGRADE_APP" ]
-then
-	ynh_script_progression --message="Upgrading source files..."
+[ -z "$(ynh_app_setting_get $app domain)" ] || ynh_app_setting_delete $app domain
+[ -z "$(ynh_app_setting_get $app path)" ] || ynh_app_setting_delete $app path
+[ -z "$(ynh_app_setting_get $app final_path)" ] || ynh_app_setting_delete $app final_path
 
-	# Download, check integrity, uncompress and patch the source from app.src
-	cp -a ../sources/* ${final_path}/
+if [ -e "/etc/sudoers.d/${app}_ynh" ]; then
+  ynh_secure_remove "/etc/sudoers.d/${app}_ynh"
 fi
 
-# Restore permissions on app files
-chmod 750 "$final_path"
-chmod o-rwx "$final_path"
-chown -R $app:www-data "$final_path"
-
 #=================================================
-# NGINX CONFIGURATION
+# CREATE DEDICATED USER
 #=================================================
-ynh_script_progression --message="Upgrading NGINX web server configuration..."
+ynh_script_progression --message="Making sure dedicated system user exists..."
 
-# Create a dedicated NGINX config
-ynh_add_nginx_config
+# Create a dedicated user (if not existing)
+ynh_system_user_create --username=$app
 
 #=================================================
 # UPGRADE DEPENDENCIES
@@ -137,14 +117,6 @@ fi
 ynh_install_app_dependencies $pkg_dependencies
 
 #=================================================
-# PHP-FPM CONFIGURATION
-#=================================================
-ynh_script_progression --message="Upgrading PHP-FPM configuration..."
-
-# Create a dedicated PHP-FPM config
-ynh_add_fpm_config
-
-#=================================================
 # SPECIFIC UPGRADE
 #=================================================
 # COPY CONFIGS
@@ -160,17 +132,6 @@ install -b -o root -g root -m 0644 ../conf/dnsmasq_dhcpdv4.conf.tpl /etc/dnsmasq
 
 # Copy init script
 install -o root -g root -m 0755 ../conf/$service_name /usr/local/bin/
-ynh_replace_string --match_string="__PHPVERSION__" --replace_string="${phpversion}" --target_file="/usr/local/bin/$service_name"
-
-#=================================================
-# UPDATE A CONFIG FILE
-#=================================================
-ynh_script_progression --message="Updating a configuration file..."
-
-ynh_add_config --template="config.php.tpl" --destination="$final_path/config.php"
-
-chmod 400 "$final_path/config.php"
-chown $app:$app "$final_path/config.php"
 
 #=================================================
 # SETUP SYSTEMD
@@ -195,30 +156,23 @@ yunohost service add $service_name --description "Creates a Wi-Fi access point"
 ynh_script_progression --message="Starting a systemd service..."
 
 hot_reload_usb_wifi_cards
-wifi_device=$(bash ../conf/iw_devices | awk -F\| '{ print $1 }')
+wifi_device=$(iw_devices | awk -F\| '{ print $1 }')
 
 if [[ -z $wifi_device ]]; then
 	ynh_app_setting_set --app=$app --key=service_enabled --value=0
-	wifi_device=none
+	wifi_device=""
 else
 	ynh_app_setting_set --app=$app --key=service_enabled --value=1
 fi
 
 # Start a systemd service if device is present
-if [[ $wifi_device == none ]]; then
+if [[ $wifi_device == "" ]]; then
 	echo "WARNING: Wifi Hotspot is not started because no wifi device was found (please, check the web admin)" >&2
 else
 	ynh_systemd_action --service_name=$service_name --action="start" --log_path=systemd #--line_match="Started YunoHost Wifi Hotspot"
 fi
 
 #=================================================
-# RELOAD NGINX
-#=================================================
-ynh_script_progression --message="Reloading NGINX web server..."
-
-ynh_systemd_action --service_name=nginx --action=reload
-
-#=================================================
 # END OF SCRIPT
 #=================================================
 

+ 0 - 367
sources/controller.php

@@ -1,367 +0,0 @@
-<?php
-
-/* Wifi Hotspot app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/hotspot_ynh
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-function ynh_setting_get($setting) {
-  $value = exec("sudo grep \"^$setting:\" /etc/yunohost/apps/hotspot/settings.yml");
-  $value = preg_replace('/^[^:]+:\s*["\']?/', '', $value);
-  $value = preg_replace('/\s*["\']$/', '', $value);
-
-  return htmlspecialchars($value);
-}
-
-function ynh_setting_set($setting, $value) {
-  return exec('sudo yunohost app setting hotspot '.escapeshellarg($setting).' -v '.escapeshellarg($value));
-}
-
-function stop_service() {
-  exec('sudo systemctl stop ynh-hotspot');
-}
-
-function start_service() {
-  exec('sudo systemctl start ynh-hotspot', $output, $retcode);
-
-  return $retcode;
-}
-
-function service_status() {
-  exec('sudo ynh-hotspot status', $output);
-
-  return $output;
-}
-
-function service_faststatus() {
-  exec('systemctl is-active hostapd', $output, $retcode);
-
-  return $retcode;
-}
-
-function ipv6_expanded($ip) {
-  exec('ipv6_expanded '.escapeshellarg($ip), $output);
-
-  return $output[0];
-}
-
-function ipv6_compressed($ip) {
-  exec('ipv6_compressed '.escapeshellarg($ip), $output);
-
-  return $output[0];
-}
-
-function iw_multissid($nic) {
-  exec('sudo iw_multissid '.escapeshellarg($nic), $output);
-
-  return $output[0];
-}
-
-function iw_devices() {
-  exec('sudo iw_devices', $output);
-
-  return !empty($output) ? getArray($output[0]) : '';
-}
-
-function getArray($str) {
-  return explode('|', $str);
-}
-
-function noneValue($str) {
-  return ($str == 'none') ? '' : $str;
-}
-
-function is_connected_through_hotspot($ip6_net, $ip4_nat_prefix) {
-  $ip = $_SERVER['REMOTE_ADDR'];
-
-  foreach($ip6_net as $net) {
-    $ip6_regex = '/^'.preg_quote(preg_replace('/::$/', '', $net)).':/';
-
-    if(preg_match($ip6_regex, $ip)) {
-      return true;
-    }
-  }
-
-  foreach($ip4_nat_prefix as $prefix) {
-    $ip4_regex = '/^'.preg_quote($prefix).'\./';
-
-    if(preg_match($ip4_regex, $ip)) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-dispatch('/', function() {
-  $ssids = array();
-  $devs = iw_devices();
-  $devs_list = '';
-
-  $wifi_device = noneValue(ynh_setting_get('wifi_device'));
-  $multissid = ynh_setting_get('multissid');
-  $wifi_channel = ynh_setting_get('wifi_channel');
-
-  foreach($devs AS $dev) {
-    $dev_multissid = iw_multissid($dev);
-
-    $active = ($dev == $wifi_device) ? 'class="active"' : '';
-    $devs_list .= "<li $active data-multissid='$dev_multissid'><a href='#'>$dev</a></li>\n";
-  }
-
-  $wifi_ssid = getArray(ynh_setting_get('wifi_ssid'));
-  $wifi_secure = getArray(ynh_setting_get('wifi_secure'));
-  $wifi_passphrase = getArray(ynh_setting_get('wifi_passphrase'));
-  $ip6_net = getArray(ynh_setting_get('ip6_net'));
-  $ip6_firewall = getArray(ynh_setting_get('ip6_firewall'));
-  $ip6_dns0 = getArray(ynh_setting_get('ip6_dns0'));
-  $ip6_dns1 = getArray(ynh_setting_get('ip6_dns1'));
-  $ip4_nat_prefix = getArray(ynh_setting_get('ip4_nat_prefix'));
-  $ip4_dns0 = getArray(ynh_setting_get('ip4_dns0'));
-  $ip4_dns1 = getArray(ynh_setting_get('ip4_dns1'));
-
-  for($i = 0; $i < $multissid; $i++) {
-    $ssid = [
-      'id' => $i,
-      'wifi_ssid' => noneValue($wifi_ssid[$i]),
-      'wifi_secure' => noneValue($wifi_secure[$i]),
-      'wifi_passphrase' => noneValue($wifi_passphrase[$i]),
-      'ip6_net' => noneValue($ip6_net[$i]),
-      'ip6_firewall' => noneValue($ip6_firewall[$i]),
-      'ip6_dns0' => noneValue($ip6_dns0[$i]),
-      'ip6_dns1' => noneValue($ip6_dns1[$i]),
-      'ip4_nat_prefix' => noneValue($ip4_nat_prefix[$i]),
-      'ip4_dns0' => noneValue($ip4_dns0[$i]),
-      'ip4_dns1' => noneValue($ip4_dns1[$i]),
-    ];
-
-    array_push($ssids, $ssid);
-  }
-
-  $ip6_net = ynh_setting_get('ip6_net');
-  $ip6_net = ($ip6_net == 'none') ? '' : getArray($ip6_net);
-  $ip4_nat_prefix = getArray(ynh_setting_get('ip4_nat_prefix'));
-
-  set('service_enabled', ynh_setting_get('service_enabled'));
-  set('ssids', $ssids);
-  set('wifi_device', $wifi_device);
-  set('wifi_channel', $wifi_channel);
-  set('wifi_device_list', $devs_list);
-  set('faststatus', service_faststatus() == 0);
-  set('is_connected_through_hotspot', is_connected_through_hotspot($ip6_net, $ip4_nat_prefix));
-
-  return render('settings.html.php');
-});
-
-dispatch_put('/settings', function() {
-  $retcode = 1;
-
-  if(!empty($_POST['wifi_device'])) {
-    exec('ip link show '.escapeshellarg($_POST['wifi_device']), $output, $retcode);
-  }
-
-  $wifi_device_exists = ($retcode == 0);
-  $service_enabled = isset($_POST['service_enabled']) ? 1 : 0;
-  $wifi_ssid_uniqueness = array();
-  $ip4_nat_prefix_uniqueness = array();
-  $ip6_net_uniqueness = array();
-  $ssids = array();
-  $id = 0;
-
-  if($service_enabled == 1) {
-    try {
-      if(!$wifi_device_exists) {
-        if(empty($_POST['wifi_device'])) {
-          throw new Exception(_('You have to choose a wifi antenna interface'));
-        }
-
-        throw new Exception(_('The wifi antenna interface seems not exist on the system'));
-      }
-
-      foreach($_POST['ssid'] as $key => $ssid) {
-        $id = $key + 1;
-
-        $ssid['ip6_net'] = empty($ssid['ip6_net']) ? 'none' : $ssid['ip6_net'];
-        $ssid['ip6_addr'] = 'none';
-        $ssid['ip6_firewall'] = isset($ssid['ip6_firewall']) ? 1 : 0;
-        $ssid['wifi_secure'] = isset($ssid['wifi_secure']) ? 1 : 0;
-
-        if(!$ssid['wifi_secure']) {
-          $ssid['wifi_passphrase'] = 'none';
-        }
-
-        if(in_array($ssid['wifi_ssid'], $wifi_ssid_uniqueness)) {
-          throw new Exception(_('All Wifi names must be unique'));
-        } else {
-          array_push($wifi_ssid_uniqueness, $ssid['wifi_ssid']);
-        }
-    
-        if(in_array($ssid['ip4_nat_prefix'], $ip4_nat_prefix_uniqueness)) {
-          throw new Exception(_('All IPv4 NAT prefixes must be unique'));
-        } else {
-          array_push($ip4_nat_prefix_uniqueness, $ssid['ip4_nat_prefix']);
-        }
-
-        if($ssid['ip6_net'] != 'none' && in_array($ssid['ip6_net'], $ip6_net_uniqueness)) {
-          throw new Exception(_('All IPv6 delegated prefixes must be unique'));
-        } else {
-          array_push($ip6_net_uniqueness, $ssid['ip6_net']);
-        }
-
-        if(empty($ssid['wifi_ssid']) || empty($ssid['wifi_passphrase'])) {
-          throw new Exception(_('Your Wifi Hotspot needs a name and a password'));
-        }
-     
-        if($ssid['wifi_secure'] && (strlen($ssid['wifi_passphrase']) < 8 || strlen($ssid['wifi_passphrase']) > 63)) {
-          throw new Exception(_('Your password must from 8 to 63 characters (WPA2 passphrase)'));
-        }
-     
-        if($ssid['wifi_secure'] && preg_match('/[^[:print:]]/', $ssid['wifi_passphrase'])) {
-          $msg = _('Only <LINK:ASCII>printable ASCII characters</LINK:ASCII> are permitted in your password');
-          $msg = str_replace('<LINK:ASCII>', '<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/ASCII_full.svg/217px-ASCII_full.svg.png" class="alert-link">', $msg);
-          $msg = str_replace('</LINK:ASCII>', '</a>', $msg);
-
-          throw new Exception($msg);
-        }
-     
-        if($ssid['ip6_net'] != 'none') {
-          $ssid['ip6_net'] = ipv6_expanded($ssid['ip6_net']);
-      
-          if(empty($ssid['ip6_net'])) {
-            throw new Exception(_('The IPv6 Delegated Prefix format looks bad'));
-          }
-      
-          $ip6_blocs = explode(':', $ssid['ip6_net']);
-          $ssid['ip6_addr'] = "${ip6_blocs[0]}:${ip6_blocs[1]}:${ip6_blocs[2]}:${ip6_blocs[3]}:${ip6_blocs[4]}:${ip6_blocs[5]}:${ip6_blocs[6]}:42";
-      
-          $ssid['ip6_net'] = ipv6_compressed($ssid['ip6_net']);
-          $ssid['ip6_addr'] = ipv6_compressed($ssid['ip6_addr']);
-        }
-     
-        if(!empty($ssid['ip6_dns0'])) {
-          $ssid['ip6_dns0'] = ipv6_expanded($ssid['ip6_dns0']);
-     
-          if(empty($ssid['ip6_dns0'])) {
-            throw new Exception(_('The format of the first IPv6 DNS Resolver looks bad'));
-          }
-     
-          $ssid['ip6_dns0'] = ipv6_compressed($ssid['ip6_dns0']);
-     
-          if(!empty($ssid['ip6_dns1'])) {
-            $ssid['ip6_dns1'] = ipv6_expanded($ssid['ip6_dns1']);
-      
-            if(empty($ssid['ip6_dns1'])) {
-               throw new Exception(_('The format of the second IPv6 DNS Resolver looks bad'));
-            }
-     
-            $ssid['ip6_dns1'] = ipv6_compressed($ssid['ip6_dns1']);
-          }
-        }
-     
-        if(inet_pton($ssid['ip4_dns0']) === false) {
-          throw new Exception(_('The format of the first IPv4 DNS Resolver looks bad'));
-        }
-     
-        if(inet_pton($ssid['ip4_dns1']) === false) {
-          throw new Exception(_('The format of the second IPv4 DNS Resolver looks bad'));
-        }
-     
-        if(inet_pton("${ssid['ip4_nat_prefix']}.0") === false) {
-          throw new Exception(_('The format of the IPv4 NAT Prefix (/24) looks bad: x.x.x expected'));
-        }
-     
-        if(filter_var("${ssid['ip4_nat_prefix']}.0", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false) {
-          throw new Exception(_('The IPv4 NAT Prefix must be from a private range'));
-        }
-
-        array_push($ssids, $ssid);
-      }
-    } catch(Exception $e) {
-      flash('error', ($id != 0 ? _('Hotspot')." $id: " : '').$e->getMessage().' ('._('configuration not updated').').');
-      goto redirect;
-    }
-  }
-
-  stop_service();
-
-  ynh_setting_set('service_enabled', $service_enabled);
-  $settings = array();
-
-  if($service_enabled == 1) {
-    foreach($ssids as $ssid) {
-      foreach($ssid as $setting => $value) {
-        $settings[$setting] .= "$value|";
-      }
-    }
-
-    ynh_setting_set('multissid', count($ssids));
-    ynh_setting_set('wifi_device', $_POST['wifi_device']);
-    ynh_setting_set('wifi_channel', $_POST['wifi_channel']);
-
-    foreach($settings as $setting => $value) {
-      ynh_setting_set($setting, preg_replace('/\|$/', '', $value));
-    }
-
-    $retcode = start_service();
-
-    if($retcode == 0) {
-      flash('success', _('Configuration updated and service successfully reloaded'));
-    } else {
-      flash('error', _('Configuration updated but service reload failed'));
-    }
-
-  } else {
-      flash('success', _('Service successfully disabled'));
-  }
-
-  redirect:
-  redirect_to('/');
-});
-
-dispatch('/status', function() {
-  $status_lines = service_status();
-  $status_list = '';
-
-  foreach($status_lines AS $status_line) {
-    if(preg_match('/^\[INFO\]/', $status_line)) {
-      $status_list .= '<li class="status-info">'.htmlspecialchars($status_line).'</li>';
-    }
-    elseif(preg_match('/^\[OK\]/', $status_line)) {
-      $status_list .= '<li class="status-success">'.htmlspecialchars($status_line).'</li>';
-    }
-    elseif(preg_match('/^\[WARN\]/', $status_line)) {
-      $status_list .= '<li class="status-warning">'.htmlspecialchars($status_line).'</li>';
-    }
-    elseif(preg_match('/^\[ERR\]/', $status_line)) {
-      $status_list .= '<li class="status-danger">'.htmlspecialchars($status_line).'</li>';
-    }
-  }
-
-  echo $status_list;
-});
-
-dispatch('/lang/:locale', function($locale = 'en') {
-  switch($locale) {
-    case 'fr':
-      $_SESSION['locale'] = 'fr';
-    break;
-
-    default:
-      $_SESSION['locale'] = 'en';
-  }
-
-  redirect_to('/');
-});

+ 0 - 45
sources/i18n/README.md

@@ -1,45 +0,0 @@
-## Force language
-
-The default language of the web admin depends on your browser language.
-
-You can force a language by using (e.g. for French):
-```
-/wifiadmin/?/lang/fr
-```
-
-English is the default language when the browser language is not available.
-
-## Update the default string list
-
-Updating the pot file from template files:
-```
-xgettext sources/*.php sources/views/*.php -o sources/i18n/localization.pot
-```
-
-## Add a new language
-
-Create a new directory path (e.g. for French):
-```
-mkdir -p sources/i18n/fr_FR/LC_MESSAGES/
-```
-
-Generate the po file:
-```
-msginit --locale=fr_FR.UTF-8 --no-translator -i sources/i18n/localization.pot -o sources/i18n/fr_FR/LC_MESSAGES/localization.po
-```
-
-You can use poedit for translating the po:
-```
-poedit sources/i18n/fr_FR/LC_MESSAGES/localization.po
-```
-
-With poedit, just save your modifications with the button and the *localization.mo* (compiled version of the po) file will automatically be created or updated.
-
-If you edited the po by hand, you have to compile the mo file:
-```
-msgfmt sources/i18n/fr_FR/localization.po -o sources/i18n/fr_FR/LC_MESSAGES/localization.mo
-```
-
-Change the default language of your browser, and test this new translation.
-
-You should add the locale to the list at the end of *sources/controller.php*.

BIN
sources/i18n/fr_FR/LC_MESSAGES/localization.mo


+ 0 - 299
sources/i18n/fr_FR/LC_MESSAGES/localization.po

@@ -1,299 +0,0 @@
-# French translations
-# Traductions françaises
-# Copyright (C) 2015
-# This file is distributed under the same license as the project.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: \n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-15 21:41+0200\n"
-"PO-Revision-Date: 2015-09-15 21:45+0200\n"
-"Last-Translator: root <root@ustelo>\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"
-"X-Generator: Poedit 1.8.4\n"
-
-#: sources/controller.php:199
-msgid "All Wifi names must be unique"
-msgstr "Tous les noms de de WiFi doivent être uniques"
-
-#: sources/controller.php:205
-msgid "All IPv4 NAT prefixes must be unique"
-msgstr "Tous les préfixes NAT doivent être uniques"
-
-#: sources/controller.php:211
-msgid "All IPv6 delegated prefixes must be unique"
-msgstr "Tous les préfixes IPv6 délégués doivent être uniques"
-
-#: sources/controller.php:217
-msgid "Your Wifi Hotspot needs a name and a password"
-msgstr "Votre point d'accès doit avoir un nom et un mot de passe"
-
-#: sources/controller.php:221
-msgid "Your password must from 8 to 63 characters (WPA2 passphrase)"
-msgstr ""
-"Votre mot de passe doit avoir entre 8 et 63 caractères (passphrase WPA2)"
-
-#: sources/controller.php:225
-msgid ""
-"Only <LINK:ASCII>printable ASCII characters</LINK:ASCII> are permitted in "
-"your password"
-msgstr ""
-"Seuls des <LINK:ASCII>caractères ASCII imprimables</LINK:ASCII> sont "
-"autorisés dans votre mot de passe"
-
-#: sources/controller.php:234
-msgid "You have to choose a wifi antenna interface"
-msgstr "Vous devez choisir une interface d'antenne WiFi"
-
-#: sources/controller.php:237
-msgid "The wifi antenna interface seems not exist on the system"
-msgstr "L'interface de l'antenne WiFi ne semble pas exister sur le système"
-
-#: sources/controller.php:244
-msgid "The IPv6 Delegated Prefix format looks bad"
-msgstr "Le format du préfixe IPv6 délégué semble incorrect"
-
-#: sources/controller.php:258
-msgid "The format of the first IPv6 DNS Resolver looks bad"
-msgstr "Le format du premier résolveur DNS IPv6 semble incorrect"
-
-#: sources/controller.php:267
-msgid "The format of the second IPv6 DNS Resolver looks bad"
-msgstr "Le format du second résolveur DNS IPv6 semble incorrect"
-
-#: sources/controller.php:275
-msgid "The format of the first IPv4 DNS Resolver looks bad"
-msgstr "Le format du premier résolveur DNS IPv4 semble incorrect"
-
-#: sources/controller.php:279
-msgid "The format of the second IPv4 DNS Resolver looks bad"
-msgstr "Le format du second résolveur DNS IPv4 semble incorrect"
-
-#: sources/controller.php:283
-msgid "The format of the IPv4 NAT Prefix (/24) looks bad: x.x.x expected"
-msgstr "Le format du préfixe NAT IPv4 (/24) semble incorrect : x.x.x attendu"
-
-#: sources/controller.php:287
-msgid "The IPv4 NAT Prefix must be from a private range"
-msgstr "Le préfixe NAT IPv4 doit correspondre à une plage privée"
-
-#: sources/controller.php:293 sources/views/_ssid.html.php:3
-msgid "Hotspot"
-msgstr "Point d'accès"
-
-#: sources/controller.php:293
-msgid "configuration not updated"
-msgstr "configuration non-mise à jour"
-
-#: sources/controller.php:321
-msgid "Configuration updated and service successfully reloaded"
-msgstr "Configuration mise à jour et service rechargé avec succès"
-
-#: sources/controller.php:323
-msgid "Configuration updated but service reload failed"
-msgstr "Configuration mise à jour mais le rechargement du service a échoué"
-
-#: sources/controller.php:327
-msgid "Service successfully disabled"
-msgstr "Service désactivé avec succès"
-
-#: sources/views/layout.html.php:27
-msgid "Wifi Hotspot"
-msgstr "Point d'accès WiFi"
-
-#: sources/views/layout.html.php:49
-msgid "Error"
-msgstr "Erreur"
-
-#: sources/views/layout.html.php:54 sources/views/settings.html.php:76
-#: sources/views/settings.html.php:129 sources/views/_ssid.html.php:44
-msgid "Notice"
-msgstr "Notice"
-
-#: sources/views/layout.html.php:66
-msgid "Any problem? Contribute!"
-msgstr "Un problème ? Contribuez !"
-
-#: sources/views/settings.html.php:37
-msgid "Wifi Hotspot Configuration"
-msgstr "Configuration du point d'accès"
-
-#: sources/views/settings.html.php:39 sources/views/settings.html.php:41
-msgid ""
-"This is a fast status. Click on More details to show the complete status."
-msgstr ""
-"Ceci est un résumé du statut. Cliquez sur « Plus de détails » pour consulter "
-"l'intégralité du statut."
-
-#: sources/views/settings.html.php:39
-msgid "Running"
-msgstr "En cours d'exécution"
-
-#: sources/views/settings.html.php:41
-msgid "Not Running"
-msgstr "Éteint"
-
-#: sources/views/settings.html.php:44
-msgid "Loading complete status may take a few minutes. Be patient."
-msgstr "Le chargement du statut peut prendre quelques minutes. Soyez patient."
-
-#: sources/views/settings.html.php:44
-msgid "More details"
-msgstr "Plus de détails"
-
-#: sources/views/settings.html.php:60
-msgid "Service"
-msgstr "Service"
-
-#: sources/views/settings.html.php:65
-msgid "Hotspot Enabled"
-msgstr "Point d'accès activé"
-
-#: sources/views/settings.html.php:76
-msgid ""
-"You need to select a wifi antenna interface. If you use a wifi USB dongle "
-"and that this one is not listed here, try to unplug and replug it, then "
-"<LINK:RELOAD>reload</LINK:RELOAD> this page."
-msgstr ""
-"Vous devez sélectionner une interface d'antenne WiFI. Si vous utilisez une "
-"antenne WiFI en USB and que celle-ci n'est pas listée ici, essayez de la "
-"débrancher et la rebrancher, puis de <LINK:RELOAD>recharger</LINK:RELOAD> "
-"cette page."
-
-#: sources/views/settings.html.php:80
-msgid "Device"
-msgstr "Interface"
-
-#: sources/views/settings.html.php:84
-msgid "None"
-msgstr "Aucun"
-
-#: sources/views/settings.html.php:92
-msgid "Channel"
-msgstr "Canal"
-
-#: sources/views/settings.html.php:123
-msgid "Add a hotspot"
-msgstr "Ajouter un point d'accès"
-
-#: sources/views/settings.html.php:129
-msgid ""
-"You are currently connected through the wifi hotspot. Please, confirm the "
-"reloading, wait for the wifi disconnect/reconnect and go back here to check "
-"that everything is okay."
-msgstr ""
-"Vous êtes actuellement connecté(e) au point d'accès WiFi. Veuillez confirmer "
-"le rechargement, attendre que le WiFi se déconnecte/reconnecte et revenir "
-"ici pour vérifier que tout est correct."
-
-#: sources/views/settings.html.php:131 sources/views/settings.html.php:137
-msgid "Reloading may take a few minutes. Be patient."
-msgstr "Le rechargement peut prendre quelques minutes. Soyez patient."
-
-#: sources/views/settings.html.php:131
-msgid "Confirm"
-msgstr "Confirmer"
-
-#: sources/views/settings.html.php:135 sources/views/settings.html.php:137
-msgid "Save and reload"
-msgstr "Sauvegarder et recharger"
-
-#: sources/views/_ssid.html.php:7
-msgid "Wifi"
-msgstr "WiFi"
-
-#: sources/views/_ssid.html.php:8
-msgid "IPv6"
-msgstr "IPv6"
-
-#: sources/views/_ssid.html.php:9
-msgid "IPv4"
-msgstr "IPv4"
-
-#: sources/views/_ssid.html.php:15
-msgid "Name (SSID)"
-msgstr "Nom (SSID)"
-
-#: sources/views/_ssid.html.php:22
-msgid "Secure"
-msgstr "Sécurisé"
-
-#: sources/views/_ssid.html.php:23
-msgid ""
-"Disabling the Secure Wifi allows everyone to join the hotspot and spy the "
-"traffic (but it's perfect for a PirateBox)"
-msgstr ""
-"Désactiver le WiFi sécurisé permet à n'importe qui de se connecter au point "
-"d'accès et d'espionner le trafic (c'est cependant parfait dans le cas d'une "
-"PirateBox)"
-
-#: sources/views/_ssid.html.php:31
-msgid "Password (WPA2)"
-msgstr "Mot de passe (WPA2)"
-
-#: sources/views/_ssid.html.php:33
-msgid "At least 8 characters"
-msgstr "Au moins 8 caractères"
-
-#: sources/views/_ssid.html.php:34
-msgid "Show to your friends how to access to your hotspot"
-msgstr "Montrez à vos amis comment accéder à votre point d'accès"
-
-#: sources/views/_ssid.html.php:44
-msgid ""
-"Currently, your wifi clients don't have IPv6 and it's a very bad thing. Ask "
-"your Internet Service Provider an IPv6 delegated prefix, or <LINK:"
-"FFDN>change providers</LINK:FFDN>!"
-msgstr ""
-"Actuellement, vous clients WiFI n'ont pas d'IPv6 et c'est vraiment dommage. "
-"Demandez un préfixe IPv6 délégué à votre fournisseur d'accès à Internet, ou "
-"<LINK:FFDN>changez de fournisseur</LINK:FFDN> !"
-
-#: sources/views/_ssid.html.php:49
-msgid "Delegated prefix"
-msgstr "Préfixe délégué"
-
-#: sources/views/_ssid.html.php:56
-msgid "Firewall"
-msgstr "Pare-feu"
-
-#: sources/views/_ssid.html.php:57
-msgid ""
-"Disabling the Firewall allows everyone to make connections to client hosts, "
-"depending on their own security policy"
-msgstr ""
-"Désactiver le pare-feu permet à n'importe qui de créer des connexions vers "
-"les clients, en fonction de leur propre politique de sécurité"
-
-#: sources/views/_ssid.html.php:65 sources/views/_ssid.html.php:89
-msgid "First DNS resolver"
-msgstr "Premier résolveur DNS"
-
-#: sources/views/_ssid.html.php:72 sources/views/_ssid.html.php:96
-msgid "Second DNS resolver"
-msgstr "Second résolveur DNS"
-
-#: sources/views/_ssid.html.php:82
-msgid "NAT prefix (/24)"
-msgstr "Préfixe NAT (/24)"
-
-#: sources/views/_ssid.html.php:104
-msgid "Delete"
-msgstr "Supprimer"
-
-#~ msgid ""
-#~ "Currently, your wifi clients don't have IPv6 and it's a very bad thing. "
-#~ "Ask your Internet Service Provider an IPv6 delegated prefix, or"
-#~ msgstr ""
-#~ "Actuellement, vos clients WiFi n'utilisent pas IPv6, ce qui n'est pas une "
-#~ "bonne chose. Demandez un préfixe IPv6 à votre Fournisseur d'Accès à "
-#~ "Internet, ou"
-
-#~ msgid "change providers"
-#~ msgstr "changez de fournisseur"

+ 0 - 267
sources/i18n/localization.pot

@@ -1,267 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-29 16:56+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"Language: \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: sources/controller.php:188
-msgid "You have to choose a wifi antenna interface"
-msgstr ""
-
-#: sources/controller.php:191
-msgid "The wifi antenna interface seems not exist on the system"
-msgstr ""
-
-#: sources/controller.php:207
-msgid "All Wifi names must be unique"
-msgstr ""
-
-#: sources/controller.php:213
-msgid "All IPv4 NAT prefixes must be unique"
-msgstr ""
-
-#: sources/controller.php:219
-msgid "All IPv6 delegated prefixes must be unique"
-msgstr ""
-
-#: sources/controller.php:225
-msgid "Your Wifi Hotspot needs a name and a password"
-msgstr ""
-
-#: sources/controller.php:229
-msgid "Your password must from 8 to 63 characters (WPA2 passphrase)"
-msgstr ""
-
-#: sources/controller.php:233
-msgid ""
-"Only <LINK:ASCII>printable ASCII characters</LINK:ASCII> are permitted in "
-"your password"
-msgstr ""
-
-#: sources/controller.php:244
-msgid "The IPv6 Delegated Prefix format looks bad"
-msgstr ""
-
-#: sources/controller.php:258
-msgid "The format of the first IPv6 DNS Resolver looks bad"
-msgstr ""
-
-#: sources/controller.php:267
-msgid "The format of the second IPv6 DNS Resolver looks bad"
-msgstr ""
-
-#: sources/controller.php:275
-msgid "The format of the first IPv4 DNS Resolver looks bad"
-msgstr ""
-
-#: sources/controller.php:279
-msgid "The format of the second IPv4 DNS Resolver looks bad"
-msgstr ""
-
-#: sources/controller.php:283
-msgid "The format of the IPv4 NAT Prefix (/24) looks bad: x.x.x expected"
-msgstr ""
-
-#: sources/controller.php:287
-msgid "The IPv4 NAT Prefix must be from a private range"
-msgstr ""
-
-#: sources/controller.php:293 sources/views/_ssid.html.php:3
-msgid "Hotspot"
-msgstr ""
-
-#: sources/controller.php:293
-msgid "configuration not updated"
-msgstr ""
-
-#: sources/controller.php:321
-msgid "Configuration updated and service successfully reloaded"
-msgstr ""
-
-#: sources/controller.php:323
-msgid "Configuration updated but service reload failed"
-msgstr ""
-
-#: sources/controller.php:327
-msgid "Service successfully disabled"
-msgstr ""
-
-#: sources/views/layout.html.php:27
-msgid "Wifi Hotspot"
-msgstr ""
-
-#: sources/views/layout.html.php:49
-msgid "Error"
-msgstr ""
-
-#: sources/views/layout.html.php:54 sources/views/settings.html.php:76
-#: sources/views/settings.html.php:129 sources/views/_ssid.html.php:44
-msgid "Notice"
-msgstr ""
-
-#: sources/views/layout.html.php:66
-msgid "Any problem? Contribute!"
-msgstr ""
-
-#: sources/views/settings.html.php:37
-msgid "Wifi Hotspot Configuration"
-msgstr ""
-
-#: sources/views/settings.html.php:39 sources/views/settings.html.php:41
-msgid ""
-"This is a fast status. Click on More details to show the complete status."
-msgstr ""
-
-#: sources/views/settings.html.php:39
-msgid "Running"
-msgstr ""
-
-#: sources/views/settings.html.php:41
-msgid "Not Running"
-msgstr ""
-
-#: sources/views/settings.html.php:44
-msgid "Loading complete status may take a few minutes. Be patient."
-msgstr ""
-
-#: sources/views/settings.html.php:44
-msgid "More details"
-msgstr ""
-
-#: sources/views/settings.html.php:60
-msgid "Service"
-msgstr ""
-
-#: sources/views/settings.html.php:65
-msgid "Hotspot Enabled"
-msgstr ""
-
-#: sources/views/settings.html.php:76
-msgid ""
-"You need to select a wifi antenna interface. If you use a wifi USB dongle "
-"and that this one is not listed here, try to unplug and replug it, then "
-"<LINK:RELOAD>reload</LINK:RELOAD> this page."
-msgstr ""
-
-#: sources/views/settings.html.php:80
-msgid "Device"
-msgstr ""
-
-#: sources/views/settings.html.php:84
-msgid "None"
-msgstr ""
-
-#: sources/views/settings.html.php:92
-msgid "Channel"
-msgstr ""
-
-#: sources/views/settings.html.php:123
-msgid "Add a hotspot"
-msgstr ""
-
-#: sources/views/settings.html.php:129
-msgid ""
-"You are currently connected through the wifi hotspot. Please, confirm the "
-"reloading, wait for the wifi disconnect/reconnect and go back here to check "
-"that everything is okay."
-msgstr ""
-
-#: sources/views/settings.html.php:131 sources/views/settings.html.php:137
-msgid "Reloading may take a few minutes. Be patient."
-msgstr ""
-
-#: sources/views/settings.html.php:131
-msgid "Confirm"
-msgstr ""
-
-#: sources/views/settings.html.php:135 sources/views/settings.html.php:137
-msgid "Save and reload"
-msgstr ""
-
-#: sources/views/_ssid.html.php:7
-msgid "Wifi"
-msgstr ""
-
-#: sources/views/_ssid.html.php:8
-msgid "IPv6"
-msgstr ""
-
-#: sources/views/_ssid.html.php:9
-msgid "IPv4"
-msgstr ""
-
-#: sources/views/_ssid.html.php:15
-msgid "Name (SSID)"
-msgstr ""
-
-#: sources/views/_ssid.html.php:22
-msgid "Secure"
-msgstr ""
-
-#: sources/views/_ssid.html.php:23
-msgid ""
-"Disabling the Secure Wifi allows everyone to join the hotspot and spy the "
-"traffic (but it's perfect for a PirateBox)"
-msgstr ""
-
-#: sources/views/_ssid.html.php:31
-msgid "Password (WPA2)"
-msgstr ""
-
-#: sources/views/_ssid.html.php:33
-msgid "At least 8 characters"
-msgstr ""
-
-#: sources/views/_ssid.html.php:34
-msgid "Show to your friends how to access to your hotspot"
-msgstr ""
-
-#: sources/views/_ssid.html.php:44
-msgid ""
-"Currently, your wifi clients don't have IPv6 and it's a very bad thing. Ask "
-"your Internet Service Provider an IPv6 delegated prefix, or <LINK:"
-"FFDN>change providers</LINK:FFDN>!"
-msgstr ""
-
-#: sources/views/_ssid.html.php:49
-msgid "Delegated prefix"
-msgstr ""
-
-#: sources/views/_ssid.html.php:56
-msgid "Firewall"
-msgstr ""
-
-#: sources/views/_ssid.html.php:57
-msgid ""
-"Disabling the Firewall allows everyone to make connections to client hosts, "
-"depending on their own security policy"
-msgstr ""
-
-#: sources/views/_ssid.html.php:65 sources/views/_ssid.html.php:89
-msgid "First DNS resolver"
-msgstr ""
-
-#: sources/views/_ssid.html.php:72 sources/views/_ssid.html.php:96
-msgid "Second DNS resolver"
-msgstr ""
-
-#: sources/views/_ssid.html.php:82
-msgid "NAT prefix (/24)"
-msgstr ""
-
-#: sources/views/_ssid.html.php:104
-msgid "Delete"
-msgstr ""

+ 0 - 27
sources/index.php

@@ -1,27 +0,0 @@
-<?php
-
-/* Wifi Hotspot app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/hotspot_ynh
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-require dirname(__FILE__).'/lib/limonade.php';
-require dirname(__FILE__).'/controller.php';
-require dirname(__FILE__).'/lib/unix_func.php';
-//require '/usr/share/php/php-gettext/gettext.inc';
-require dirname(__FILE__).'/config.php';
-
-run();

File diff suppressed because it is too large
+ 0 - 2707
sources/lib/limonade.php


+ 0 - 193
sources/lib/limonade/abstract.php

@@ -1,193 +0,0 @@
-<?php
-/**
- * Abstract methods that might be redefined by user
- * Do not include this file in your app: it only aims to provide documentation
- * about those functions.
- * 
- * @package limonade
- * @subpackage abstract
- */
- 
-/**
- * It will be called when app is launched (at the begining of the run function).
- * You can define options inside it, a connection to a database ...
- *
- * @abstract this function might be redefined by user
- * @return void 
- */
-function configure()
-{
-  return;
-}
-
-/**
- * Called in run() just after session start, and before checking request method
- * and output buffer start.  
- *
- * @abstract this function might be redefined by user
- * @return void 
- */
-function initialize()
-{
-  return;
-}
-
-/**
- * Called in run() just after the route matching, in order to load controllers. 
- * If not specfied, the default function is called:
- * 
- * <code>
- * function autoload_controller($callback)
- * {
- *   require_once_dir(option('controllers_dir'));
- * }
- * </code>
- * 
- *
- * @param string $callback the callback defined in matching route
- * @return void
- */
-function autoload_controller($callback)
-{
-  return;
-}
- 
-/**
- * Called before each request.
- * This is very useful to define a default layout or passing common variables
- * to the templates.
- *
- * @abstract this function might be redefined by user
- * @param array() $route array (like returned by {@link route_build()},
- *   with keys "method", "pattern", "names", "callback", "options")
- * @return void 
- */
-function before($route)
-{
-  
-}
- 
-/**
- * An `after` output filter
- * 
- * Called after each request and can apply a transformation to the output
- * (except for `render_file` outputs  which are sent directly to the output buffer).
- *
- * @abstract this function might be redefined by user
- * @param string $output 
- * @param array() $route array (like returned by {@link route_find()},
- *   with keys "method", "pattern", "names", "callback", "params", "options")
- * @return string 
- */
-function after($output, $route)
-{
-  # Call functions...
-  # .. modifies $output...
-  return $output;
-}
- 
-/**
- * Not found error output
- *
- * @abstract this function might be redefined by user
- * @param string $errno 
- * @param string $errstr 
- * @param string $errfile 
- * @param string $errline 
- * @return string "not found" output string
- */
-function not_found($errno, $errstr, $errfile=null, $errline=null)
-{
- 
-}
- 
-/**
- * Server error output
- *
- * @abstract this function might be redefined by user
- * @param string $errno 
- * @param string $errstr 
- * @param string $errfile 
- * @param string $errline 
- * @return string "server error" output string
- */
-function server_error($errno, $errstr, $errfile=null, $errline=null)
-{
-  
-}
- 
-/**
- * Called when a route is not found.
- * 
- * 
- * @abstract this function might be redefined by user
- * @param string $request_method 
- * @param string $request_uri 
- * @return void 
- */
-function route_missing($request_method, $request_uri)
-{
-  halt(NOT_FOUND, "($request_method) $request_uri"); # by default
-}
-
-/**
- * Called before stoppping and exiting application.
- *
- * @abstract this function might be redefined by user
- * @param boolean exit or not
- * @return void 
- */
-function before_exit($exit)
-{
-  
-}
-
-/**
- * Rendering prefilter.
- * Useful if you want to transform your views before rendering.
- * The first three parameters are the same as those provided 
- * to the `render` function.
- *
- * @abstract this function might be redefined by user
- * @param string $content_or_func a function, a file in current views dir or a string
- * @param string $layout 
- * @param array $locals 
- * @param array $view_path (by default <code>file_path(option('views_dir'),$content_or_func);</code>)
- * @return array with, in order, $content_or_func, $layout, $locals vars
- *  and the calculated $view_path
- */
-function before_render($content_or_func, $layout, $locals, $view_path)
-{
-  # transform $content_or_func, $layout, $locals or $view_path…
-  return array($content_or_func, $layout, $locals, $view_path);
-}
-
-
-/**
- * Called only if rendering $output is_null,
- * like in a controller with no return statement.
- *
- * @abstract this function might be defined by user
- * @param array() $route array (like returned by {@link route_build()},
- *   with keys "method", "pattern", "names", "callback", "options")
- * @return string
- */
-function autorender($route)
-{
-  # process output depending on $route
-  return $output;
-}
-
-/**
- * Called if a header is about to be sent
- *
- * @abstract this function might be defined by user
- * @param string the headers that limonade will send
- * @return void
- */
-function before_sending_header($header)
-{
-
-}
-
-

+ 0 - 173
sources/lib/limonade/assertions.php

@@ -1,173 +0,0 @@
-<?php
-/**
- * @package tests
- * @subpackage assertions
- */
-# ============================================================================ #
-#    ASSERTIONS                                                                #
-# ============================================================================ #
-
-/**
- * assert_true
- *
- * @param string $value 
- * @param string $message 
- * @return boolean
- */
-function assert_true($value, $message = '<1> should be TRUE')
-{
-   test_run_assertion();
-   return assert('$value === TRUE; //'.$message);
-}
-
-function assert_false($value, $message = '<1> should be FALSE')
-{
-   test_run_assertion();
-   return assert('$value === FALSE; //'.$message);
-}
-
-function assert_null($value, $message = '<1> should be NULL')
-{
-   test_run_assertion();
-   return assert('$value === NULL; //'.$message);
-}
-
-function assert_not_null($value, $message = '<1> should not be NULL')
-{
-   test_run_assertion();
-   return assert('$value !== NULL; //'.$message);
-}
-
-function assert_empty($value, $message = '<1> should be empty')
-{
-   test_run_assertion();
-   return assert('empty($value); //'.$message);
-}
-
-function assert_not_empty($value, $message = '<1> should not be empty')
-{
-   test_run_assertion();
-   return assert('!empty($value); //'.$message);
-}
-
-function assert_equal($expected, $value, $message = '<1> should be equal to <2>')
-{
-   test_run_assertion();
-   return assert('$expected == $value; //'.$message);
-}
-
-function assert_not_equal($expected, $value, $message = '<1> should not equal to <2>')
-{
-   test_run_assertion();
-   return assert('$expected != $value; //'.$message);
-}
-
-function assert_identical($expected, $value, $message = '<1> should be identical to <2>')
-{
-   test_run_assertion();
-   return assert('$expected === $value; //'.$message);
-}
-
-function assert_not_identical($expected, $value, $message = '<1> should not be identical to <2>')
-{
-   test_run_assertion();
-   return assert('$expected !== $value; //'.$message);
-}
-
-function assert_match($pattern, $string, $message = '<2> expected to match regular expression <1>') {
-   test_run_assertion();
-   return assert('preg_match($pattern, $string); //'.$message);
-}
- 
-function assert_no_match($pattern, $string, $message = '<2> expected to not match regular expression <1>') {
-   test_run_assertion();
-   return assert('!preg_match($pattern, $string); //'.$message);
-}
-
-function assert_type($type, $value, $message = '<1> is not of type <2>') {
-  test_run_assertion();
-  $predicate = 'is_' . strtolower(is_string($type) ? $type : gettype($type));
-  return assert('$predicate($value); //'.$message);
-}
- 
-function assert_instance_of($class, $object, $message = '<2> is not an instance of class <1>') {
-   test_run_assertion();
-   return assert('$object instanceof $class; //'.$message);
-}
- 
-function assert_length_of($value, $length, $message = '<1> expected to be of length <2>') {
-   test_run_assertion();
-   $count = is_string($value) ? 'strlen' : 'count';
-   return assert('$count($value) == $length; //'.$message);
-}
-
-function assert_trigger_error($callable, $args = array(), $message = '<1> should trigger an error') {
-  test_run_assertion();
-  $trigger_errors = count($GLOBALS["limonade"]["test_errors"]);
-  set_error_handler("test_error_handler");
-  $result = call_user_func_array($callable, $args);
-  restore_error_handler();
-  return assert('$trigger_errors < count($GLOBALS["limonade"]["test_errors"]); //'.$message);
-}
-
-# TODO add web browser assertions assert_http_get, assert_http_response... as in SimpleTest (http://www.simpletest.org/en/web_tester_documentation.html)
-
-function assert_header($response, $expected_name, $expected_value = null, $message = "expected header '%s' to be equal to '%s' but received '%s: %s'")
-{
-  test_run_assertion();
-  # see assert_header in http://github.com/fnando/voodoo-test/blob/f3b0994ef138a6ba94d5e7cef6c1fb1720797a86/lib/assertions.php
-  $headers = preg_split("/^\s*$/ms", $response);
-  //var_dump($headers);    
-  $headers = preg_replace("/\s*$/sm", "", $headers[0]);
-  //var_dump($headers);   
-  
-  $regex_header = str_replace("/", "\\/", $expected_name);
-  $regex_header = str_replace(".", "\\.", $regex_header);
-  
-  $header = $expected_name;
-  
-  # from http://www.faqs.org/rfcs/rfc2616
-  # Field names are case-insensitive
-  if ($expected_value) {
-      $regex = "/^{$regex_header}:(.*?)$/ism";
-      $header .= ": {$expected_value}";
-  } else {
-      $regex = "/^{$regex_header}(:.*?)?$/ism";
-  }
-  
-  $has_header = preg_match($regex, $headers, $matches);    
-  $sent_header = trim((string)$matches[1]);
-
-  
-  if(empty($sent_header))
-  {
-    if(is_null($expected_value))
-    {
-      $message = "expected header '%s' but header has not been sent";
-    }
-    else
-    {
-      $message = "expected header '%s' to be equal to '%s' but header has not been sent";
-    }
-    
-    $message = sprintf($message, $expected_name, $expected_value);
-    return assert("false; //".$message);
-  }
-  else if($expected_value)
-  {
-    $message = sprintf($message, $expected_name, $expected_value, $expected_name, $sent_header);
-    return assert('$expected_value && $sent_header == $expected_value; //'.$message);
-  }
-  return assert("true; //");
-}
-
-function assert_status($response, $expected_status, $message = "expected status code to be equal to '%s' but received '%s'")
-{
-  $lines = explode('\n', trim($response));
-  if (preg_match('/HTTP\/(\d+\.\d+)\s+(\d+)/i', $lines[0], $matches))
-  {
-      $status = $matches[2];
-      return assert('$expected_status == $status; //'.sprintf($message, $expected_status, $status));
-  }
-  return assert("false; //no status code returned in this response string");
-}

+ 0 - 220
sources/lib/limonade/public/css/screen.css

@@ -1,220 +0,0 @@
-/* -----------------------------------------------------------------------
-
-
- Blueprint CSS Framework 0.8
- http://blueprintcss.org
-
-   * Copyright (c) 2007-Present. See LICENSE for more info.
-   * See README for instructions on how to use Blueprint.
-   * For credits and origins, see AUTHORS.
-   * This is a compressed file. See the sources in the 'src' directory.
-
------------------------------------------------------------------------ */
-
-/* reset.css */
-html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
-body {line-height:1.5;}
-table {border-collapse:separate;border-spacing:0;}
-caption, th, td {text-align:left;font-weight:normal;}
-table, td, th {vertical-align:middle;}
-blockquote:before, blockquote:after, q:before, q:after {content:"";}
-blockquote, q {quotes:"" "";}
-a img {border:none;}
-
-/* typography.css */
-body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
-h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
-h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
-h2 {font-size:2em;margin-bottom:0.75em;}
-h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
-h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
-h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
-h6 {font-size:1em;font-weight:bold;}
-h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
-p {margin:0 0 1.5em;}
-p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;}
-p img.right {float:right;margin:1.5em 0 1.5em 1.5em;}
-a:focus, a:hover {color:#000;}
-a {color:#009;text-decoration:underline;}
-blockquote {margin:1.5em;color:#666;font-style:italic;}
-strong {font-weight:bold;}
-em, dfn {font-style:italic;}
-dfn {font-weight:bold;}
-sup, sub {line-height:0;}
-abbr, acronym {border-bottom:1px dotted #666;}
-address {margin:0 0 1.5em;font-style:italic;}
-del {color:#666;}
-pre {margin:1.5em 0;white-space:pre;}
-pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
-li ul, li ol {margin:0 1.5em;}
-ul, ol {margin:0 1.5em 1.5em 1.5em;}
-ul {list-style-type:disc;}
-ol {list-style-type:decimal;}
-dl {margin:0 0 1.5em 0;}
-dl dt {font-weight:bold;}
-dd {margin-left:1.5em;}
-table {margin-bottom:1.4em;width:100%;}
-th {font-weight:bold;}
-thead th {background:#c3d9ff;}
-th, td, caption {padding:4px 10px 4px 5px;}
-tr.even td {background:#e5ecf9;}
-tfoot {font-style:italic;}
-caption {background:#eee;}
-.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
-.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
-.hide {display:none;}
-.quiet {color:#666;}
-.loud {color:#000;}
-.highlight {background:#ff0;}
-.added {background:#060;color:#fff;}
-.removed {background:#900;color:#fff;}
-.first {margin-left:0;padding-left:0;}
-.last {margin-right:0;padding-right:0;}
-.top {margin-top:0;padding-top:0;}
-.bottom {margin-bottom:0;padding-bottom:0;}
-
-/* forms.css */
-label {font-weight:bold;}
-fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
-legend {font-weight:bold;font-size:1.2em;}
-input.text, input.title, textarea, select {margin:0.5em 0;border:1px solid #bbb;}
-input.text:focus, input.title:focus, textarea:focus, select:focus {border:1px solid #666;}
-input.text, input.title {width:300px;padding:5px;}
-input.title {font-size:1.5em;}
-textarea {width:390px;height:250px;padding:5px;}
-.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
-.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
-.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
-.success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
-.error a {color:#8a1f11;}
-.notice a {color:#514721;}
-.success a {color:#264409;}
-
-.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;}
-hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;}
-hr.space {background:#fff;color:#fff;}
-.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
-.clearfix, .container {display:block;}
-.clear {clear:both;}
-
-/* -----------------------------------------------------------------------
-
- LIMONADE
- 
- Design and logo by <a href="http://www.minimau.com">Minimau</a>
-
------------------------------------------------------------------------ */
-
-html {
- 	background-color: #b4a689;
- 	text-align: center;
- 	}
- 	body {
- 		width: auto; /* 16 col */
- 		margin: 0 20px;
- 		text-align: left;
- 		/*background: #fff url(blueprint/src/grid.png);*/
- 		font-family: Verdana, Geneva, sans-serif;
- 		color: #303030;
- 		}
- 		a, a:hover, a:visited {
- 			color: #4596cd;
- 			}
- 		a:hover {
- 			text-decoration: none;
- 			}
- 		#header, h1, h2, h3, h4 {
- 			font-family: "Arial Black", Gadget, sans-serif;
- 			}
- 		h1 {
- 			color: #b4a689;
- 			font-size: 2em;
- 			line-height: 2;
- 			border-bottom: 7px solid #000;
- 			margin-bottom: 0.75em;
- 			margin-top:0;
- 			}
- 		h2 {
- 			font-size: 1.5em;
- 			color: #cddb12;
- 			margin-top: 2em;
- 			line-height: 0.8;
- 			margin-bottom: 1.2em;
- 			}
- 		h3 {
- 			font-size: 1.33em;
- 			line-height: 0.89;
- 			margin-top: 2.66em;
- 			margin-bottom: 1.33em;
- 			color:#95b383;
- 			}
- 		pre {
- 			background-color: #cddb12;
- 			font-size: 12px;
- 			padding: 1.5em;
- 			margin-bottom: 1.5em;
- 			overflow: auto;
- 			}
- 		code {
- 			font: 10px Monaco, "Courier New", Courier, monospace;
- 			color: #0d562a;
- 			}
- 		#header {
- 			/*position:relative;*/
- 			height: 187px; /* 12 lines */
- 			background: #fff url(<?=url_for('/_lim_public/img/bg_header.png')?>) no-repeat 0 0;
- 			margin-top: 10px;
-      padding:0;
- 			}
- 			#header h1 {
- 				position: absolute;
- 				left:-9999px;
- 				   			margin:0;
- 				}
- 		#footer {
- 			padding: 0 55px;
- 			background-color: #1a1818;
- 			color: #999;
- 			height: 2em;
- 			line-height: 2em;
- 			text-align: right;
- 			}
- 			#footer a {
- 				color: #a3d8de;
- 				text-decoration: none;
- 				}
- 			#footer a:hover {
- 				color: #fff;
- 				}
- 		#content {
- 		  background-color: #fff;
- 			padding: 0 55px;
- 			min-height: 400px;
- 			}
-    		p.bt {
-    		   text-align:right;
-    		   }
-       		p.bt a {
-       		   text-decoration:none;
-       		   padding: 2px 4px;
-       		   }
-       		p.bt a:hover {
-      	      background-color: #4596cd;
-      	      color: #fff;
-      	      }
-      	#debug-menu {
-      	   position: fixed;
-      	   top: 0px;
-      	   right:20px;
-      	   background-color: rgba(100,100,100, 0.7);
-      	   padding:5px;
-      	}
-      	#debug-menu a {
-      	   color: #fff;
-      	   font-size: 90%;
-      	   text-decoration:none;
-   	   }
-   	   #debug-menu a:hover {
-   	      text-decoration: underline;
-	      }
-   	

BIN
sources/lib/limonade/public/img/bg_header.png


+ 0 - 350
sources/lib/limonade/tests.php

@@ -1,350 +0,0 @@
-<?php
-/**
- * @package tests
- */
- 
-# ============================================================================ #
-#    TESTS                                                                     #
-# ============================================================================ #
-
-/**
- * load assertions
- */
-require_once dirname(__FILE__)."/assertions.php";
-
-
- 
-/**
- * Constants and globals
- */
-if(!defined('DS')) define("DS", DIRECTORY_SEPARATOR);
-
-if(!array_key_exists("limonade", $GLOBALS))
-   $GLOBALS["limonade"] = array();
-if(!array_key_exists("test_cases", $GLOBALS["limonade"]))
-   $GLOBALS["limonade"]["test_cases"] = array();
-if(!array_key_exists("test_errors", $GLOBALS["limonade"]))
-   $GLOBALS["limonade"]["test_errors"] = array();
-if(!array_key_exists("test_case_current", $GLOBALS["limonade"]))
-   $GLOBALS["limonade"]["test_case_current"] = NULL;
-if(!array_key_exists("test_suites", $GLOBALS["limonade"]))
-   $GLOBALS["limonade"]["test_suites"] = NULL;
-
-ini_set("display_errors", true);
-error_reporting(E_ALL ^ (E_USER_WARNING | E_NOTICE | E_USER_NOTICE));
-// error_reporting(E_ALL | E_STRICT);
-assert_options(ASSERT_ACTIVE, 1);
-assert_options(ASSERT_WARNING, 0);
-assert_options(ASSERT_BAIL, 0);
-assert_options(ASSERT_QUIET_EVAL, 0);
-assert_options(ASSERT_CALLBACK, 'test_assert_failure');
-
-# TODO: separate display from logic
-# TODO: clean results output
-# TODO: add all tests results
-
-/**
- * Starts a test suite
- *
- * @param string $name 
- * @return void
- */
-function test_suite($name)
-{
-  $GLOBALS["limonade"]["test_suites"] = $name;
-  echo test_cli_format("===========================================================\n", 'white');
-  echo test_cli_format(">>>> START $name tests suites\n", 'white');
-  echo test_cli_format("-----------------------------------------------------------\n", 'white');
-}
-
-/**
- * Ends the last group of test suites
- *
- * @return void
- */
-function end_test_suite()
-{
-  $name         = $GLOBALS["limonade"]["test_suites"];
-  $failures     = 0;
-  $tests        = 0;
-  $passed_tests = 0;
-  $assertions   = 0;
-
-  foreach($GLOBALS["limonade"]["test_cases"] as $test)
-  {
-    $failures += $test['failures'];
-    $assertions += $test['assertions'];
-    if(empty($test['failures'])) $passed_tests++;
-    $tests++;
-  }
-  echo ">> ENDING $name tests suites\n  ";
-  echo $failures > 0 ? test_cli_format("|FAILED!|", "red") : test_cli_format("|PASSED|", "green");;
-  echo " Passes ".$passed_tests."/".$tests.", ";
-  echo " {$failures} failures for {$assertions} assertions.\n";
-  echo test_cli_format("===========================================================\n", 'white');
-}
-
-/**
- * Starting a new test case
- *
- * @param string $name 
- * @return void
- */
-function test_case($name)
-{
-   $name = strtolower($name); // TODO: normalize name
-   
-   if(!array_key_exists($name, $GLOBALS["limonade"]["test_cases"]))
-   {
-      $GLOBALS["limonade"]["test_cases"][$name] = array( 
-                                                      "name" => $name,
-                                                      "assertions" => 0, 
-                                                      "failures" => 0,
-                                                      "description" => NULL
-                                                   );      
-      $GLOBALS["limonade"]["test_case_current"] = $name;
-   }
-   else
-   {
-      
-   }
-}
-
-/**
- * Displays and ending the current tests suite
- * 
- * @return void
- */
-function end_test_case()
-{
-   $name = $GLOBALS["limonade"]["test_case_current"];
-   echo "## ".strtoupper($name)."\n";
-      
-   $desc = test_case_describe();
-   if(!is_null($desc)) echo $desc."\n";
-
-   echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
-   
-   test_case_execute_current();
-   
-   
-   if(!is_null($name))
-   {
-      $test = $GLOBALS["limonade"]["test_cases"][$name];
-      // closing previous test
-      echo "\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
-      echo $test['failures'] > 0 ? test_cli_format("|FAILED!|", "red") : test_cli_format("|PASSED|", "green");
-      echo " Test case '$name' finished: ";
-      echo count(test_case_all_func())." tests, ";
-      echo " {$test['failures']} failures for {$test['assertions']} assertions.\n";
-      
-      echo "-----------------------------------------------------------\n";
-   }
-   $GLOBALS["limonade"]["test_case_current"] = null;
-}
-
-/**
- * Describes the current tests suite
- *
- * @param string $msg 
- * @return string tests description
- */
-function test_case_describe($msg = NULL)
-{
-   $test =& test_case_current();
-   if(!is_null($msg))
-   {
-      $test["description"] = $msg;
-   }
-   //var_dump($test["description"]);
-   return $test["description"];
-}
-
-/**
- * Returns all user test case functions
- *
- * @access private
- * @return void
- */
-function test_case_all_func()
-{
-   $functions = get_defined_functions();
-   $functions = $functions['user'];
-   $tests = array();
-   $name = $GLOBALS["limonade"]["test_case_current"];
-   while ($func = array_shift($functions)) {
-      $regexp = "/^test_{$name}_(.*)$/";
-      if(!preg_match($regexp, $func)) continue;
-      if($func == test_before_func_name()) continue;
-      // TODO: adding break for all test api methods
-      
-      $tests[] = $func;
-   }
-   return $tests;
-}
-
-/**
- * Execute current test case
- *
- * @access private
- * @return void
- */
-function test_case_execute_current()
-{
-   $tests = test_case_all_func();
-   while($func = array_shift($tests))
-   {
-      test_call_func(test_before_func_name());
-      call_user_func($func);
-   }
-}
-
-
-function &test_case_current()
-{
-   $name = $GLOBALS["limonade"]["test_case_current"];
-   return $GLOBALS["limonade"]["test_cases"][$name];
-}
-
-
-
-function test_before_func_name()
-{
-   $test = test_case_current();
-   $func = "before_each_test_in_".$test["name"];
-   return $func;
-}
-
-function test_before_assert_func_name()
-{
-   $test = test_case_current();
-   $func = "before_each_assert_in_$name".$test["name"];
-   return $func;
-}
-
-function test_run_assertion()
-{
-   $name = $GLOBALS["limonade"]["test_case_current"];
-   $GLOBALS["limonade"]["test_cases"][$name]['assertions']++;
-   test_call_func(test_before_assert_func_name());
-}
-
-/**
- * Calls a function if exists
- *
- * @param string $func the function name
- * @param mixed $arg,.. (optional)
- * @return mixed
- */
-function test_call_func($func)
-{
-  if(empty($func)) return;
-  $args = func_get_args();
-  $func = array_shift($args);
-  if(function_exists($func)) return call_user_func_array($func, $args);
-  return;
-}
-
-/**
- * Error handler 
- * 
- * @access private
- * @return boolean true
- */
-function test_error_handler($errno, $errstr, $errfile, $errline)
-{
-	if($errno < E_USER_ERROR || $errno > E_USER_NOTICE) 
-	   echo test_cli_format("!!! ERROR", "red") . " [$errno], $errstr in $errfile at line $errline\n";
-	$GLOBALS["limonade"]["test_errors"][] = array($errno, $errstr, $errfile, $errline);
-   return true;
-}
-
-/**
- * Assert callback
- * 
- * @access private
- * @param string $script 
- * @param string $line 
- * @param string $message 
- * @return void
- */
-function test_assert_failure($script, $line, $message)
-{
-   // Using the stack trace, find the outermost assert*() call
-   $stacktrace = array_slice(debug_backtrace(), 1); // skip self
-   $assertion = reset($stacktrace);
-   while ($stackframe = array_shift($stacktrace)) {
-    if (!preg_match('/^assert/', $stackframe['function']))
-      break;
-    $assertion = $stackframe;
-   }
-
-   extract($assertion, EXTR_PREFIX_ALL, 'assert');
-   $code = explode("\n", file_get_contents($assert_file));
-   $code = trim($code[$assert_line - 1]);
-   
-   list($assert_code, $message) = explode("//", $message);
-   echo test_cli_format("Assertion failed", "yellow");
-   echo " in script *{$assert_file}* (line {$assert_line}):\n";
-   echo "   * assertion: $code\n";
-   echo "   * message:   $message\n";
-   $name = $GLOBALS["limonade"]["test_case_current"];
-   $GLOBALS["limonade"]["test_cases"][$name]['failures']++;
-}
-
-function test_cli_format($text, $format) {
-    $formats = array(
-        "blue"       => 34,
-        "bold"       => 1,
-        "green"      => 32,
-        "highlight"  => 7,
-        "light_blue" => 36,
-        "purple"     => 35,
-        "red"        => 31,
-        "underline"  => 4,
-        "white"      => 37,
-        "yellow"     => 33
-    );
-
-    if (array_key_exists($format, $formats)) $format = $formats[$format];
-    return chr(27) . "[01;{$format} m{$text}" . chr(27) . "[00m";
-}
-
-/**
- * Do HTTP request and return the response content.
- * 
- * @param string $url
- * @param string $method
- * @param bool $include_header
- * @return string
- * @author Nando Vieira
- */
-function test_request($url, $method="GET", $include_header=false, $post_data=array(), $http_header=array()) {
-    $method = strtoupper($method);
-    $allowed_methods = array("GET", "PUT", "POST", "DELETE", "HEAD");
-    if(!in_array($method, $allowed_methods))
-    {
-      $message = "The requested method '$method' is not allowed";
-      return assert('false; //'.$message);
-    }
-    
-    $curl = curl_init($url);
-    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($curl, CURLOPT_HEADER, $include_header);
-    curl_setopt($curl, CURLOPT_HTTPHEADER, $http_header);
-    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
-    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); 
-    if($method == 'POST' || $method == 'PUT')
-    {
-      curl_setopt($curl, CURLOPT_POST, 1);
-      curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
-    }
-    if($method == 'HEAD')
-    {
-      curl_setopt($curl, CURLOPT_NOBODY, true);
-    }
-    $response = curl_exec($curl);
-    curl_close($curl);
-
-    return $response;
-}

+ 0 - 37
sources/lib/limonade/views/_debug.html.php

@@ -1,37 +0,0 @@
-<?php if(option('env') > ENV_PRODUCTION && option('debug')): ?>
-  <?php if(!$is_http_error): ?>
-  <p>[<?php echo error_type($errno)?>]
-  	<?php echo $errstr?> (in <strong><?php echo $errfile?></strong> line <strong><?php echo $errline?></strong>)
-  	</p>
-  	<?php endif; ?>
-
-
-  <?php if($debug_args = set('_lim_err_debug_args')): ?>
-  <h2 id="debug-arguments">Debug arguments</h2>
-  	<pre><code><?php echo h(print_r($debug_args, true))?></code></pre>
-  <?php endif; ?>
-  
-  <h2 id="limonade-options">Options</strong></h2>
-  <pre><code><?php echo h(print_r(option(), true))?></code></pre>
-  <p class="bt top"><a href="#header">[ &#x2191; ]</a></p>
-  
-  <h2 id="environment">Environment</h2>
-  <pre><code><?php echo h(print_r(env(), true))?></code></pre>
-  <p class="bt top"><a href="#header">[ &#x2191; ]</a></p>
-  
-  <h2 id="debug-backtrace">Backtrace</h2>
-  <pre><code><?php echo h(print_r(debug_backtrace(), true))?></code></pre>
-  <p class="bt top"><a href="#header">[ &#x2191; ]</a></p>
-
-  <div id="debug-menu">
-    
-    <?php if($debug_args = set('_lim_err_debug_args')): ?>
-    <a href="#debug-arguments">Debug arguments</a> |
-    <?php endif; ?>
-    <a href="#limonade-options">Options</a> |
-    <a href="#environment">Environment</a> |
-    <a href="#debug-backtrace">Backtrace</a> |
-    <a href="#header">[ &#x2191; ]</a>
-  </div>
-  
-<?php endif; ?>

+ 0 - 15
sources/lib/limonade/views/_notices.html.php

@@ -1,15 +0,0 @@
-<?php if(!empty($notices)): ?>
-<div class="lim-debug lim-notices">
-  <h4> &#x2192; Notices and warnings</h4>
-  <dl>
-  <?php $cpt = 1; foreach($notices as $notice): ?>
-    <dt>[<?php echo $cpt.'. '.error_type($notice['errno'])?>]</dt>
-    <dd>
-    <?php echo $notice['errstr']?> in <strong><code><?php echo $notice['errfile']?></code></strong> 
-    line <strong><code><?php echo $notice['errline']?></code></strong>
-    </dd>
-  <?php $cpt++; endforeach; ?>
-  </dl>
-  <hr>
-</div>
-<?php endif; ?>

+ 0 - 22
sources/lib/limonade/views/default_layout.php

@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-	<title>Limonade, the fizzy PHP micro-framework</title>
-	<link rel="stylesheet" href="<?php echo url_for('/_lim_css/screen.css');?>" type="text/css" media="screen">
-</head>
-<body>
-  <div id="header">
-    <h1>Limonade</h1>
-  </div>
-  
-  <div id="content">
-    <?php echo error_notices_render(); ?>
-    <div id="main">
-      <?php echo $content;?>
-      <hr class="space">
-    </div>
-  </div>
-
-</body>
-</html>

+ 0 - 6
sources/lib/limonade/views/error.html.php

@@ -1,6 +0,0 @@
-  <h1><?php echo h(error_http_status($errno));?></h1>
-  <?php if($is_http_error): ?>
-  <p><?php echo h($errstr)?></p>
-  <?php endif; ?>
-  
-  <?php echo  render('_debug.html.php', null, $vars); ?>

+ 0 - 49
sources/lib/unix_func.php

@@ -1,49 +0,0 @@
-<?php 
-
- /**
-  *  YunoHost - Self-hosting for all
-  *  Copyright (C) 2012  Kload <kload@kload.fr>
-  *
-  *  This program is free software: you can redistribute it and/or modify
-  *  it under the terms of the GNU Affero General Public License as
-  *  published by the Free Software Foundation, either version 3 of the
-  *  License, or (at your option) any later version.
-  *
-  *  This program is distributed in the hope that it will be useful,
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  *  GNU Affero General Public License for more details.
-  *
-  *  You should have received a copy of the GNU Affero General Public License
-  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  */
-  
-function read_file($file, $lines = 20) {
-
-    if (!$handle = fopen($file, "r"))
-        return false;
-    $linecounter = $lines;
-    $pos = -2;
-    $beginning = false;
-    $text = array();
-    while ($linecounter > 0) {
-        $t = " ";
-        while ($t != "\n") {
-            if(fseek($handle, $pos, SEEK_END) == -1) {
-                $beginning = true;
-                break;
-            }
-            $t = fgetc($handle);
-            $pos --;
-        }
-        $linecounter --;
-        if ($beginning) {
-            rewind($handle);
-        }
-        $text[$lines-$linecounter-1] = fgets($handle);
-        if ($beginning) break;
-    }
-    fclose ($handle);
-    return array_reverse($text);
-}
-

+ 0 - 457
sources/public/bootstrap/css/bootstrap-theme.css

@@ -1,457 +0,0 @@
-/*!
- * Bootstrap v3.3.0 (http://getbootstrap.com)
- * Copyright 2011-2014 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-
-.btn-default,
-.btn-primary,
-.btn-success,
-.btn-info,
-.btn-warning,
-.btn-danger {
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
-          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
-}
-.btn-default:active,
-.btn-primary:active,
-.btn-success:active,
-.btn-info:active,
-.btn-warning:active,
-.btn-danger:active,
-.btn-default.active,
-.btn-primary.active,
-.btn-success.active,
-.btn-info.active,
-.btn-warning.active,
-.btn-danger.active {
-  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
-          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
-}
-.btn-default .badge,
-.btn-primary .badge,
-.btn-success .badge,
-.btn-info .badge,
-.btn-warning .badge,
-.btn-danger .badge {
-  text-shadow: none;
-}
-.btn:active,
-.btn.active {
-  background-image: none;
-}
-.btn-default {
-  text-shadow: 0 1px 0 #fff;
-  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
-  background-image:      -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
-  background-image:         linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-  border-color: #dbdbdb;
-  border-color: #ccc;
-}
-.btn-default:hover,
-.btn-default:focus {
-  background-color: #e0e0e0;
-  background-position: 0 -15px;
-}
-.btn-default:active,
-.btn-default.active {
-  background-color: #e0e0e0;
-  border-color: #dbdbdb;
-}
-.btn-default:disabled,
-.btn-default[disabled] {
-  background-color: #e0e0e0;
-  background-image: none;
-}
-.btn-primary {
-  background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
-  background-image:      -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
-  background-image:         linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-  border-color: #2b669a;
-}
-.btn-primary:hover,
-.btn-primary:focus {
-  background-color: #2d6ca2;
-  background-position: 0 -15px;
-}
-.btn-primary:active,
-.btn-primary.active {
-  background-color: #2d6ca2;
-  border-color: #2b669a;
-}
-.btn-primary:disabled,
-.btn-primary[disabled] {
-  background-color: #2d6ca2;
-  background-image: none;
-}
-.btn-success {
-  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
-  background-image:      -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
-  background-image:         linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-  border-color: #3e8f3e;
-}
-.btn-success:hover,
-.btn-success:focus {
-  background-color: #419641;
-  background-position: 0 -15px;
-}
-.btn-success:active,
-.btn-success.active {
-  background-color: #419641;
-  border-color: #3e8f3e;
-}
-.btn-success:disabled,
-.btn-success[disabled] {
-  background-color: #419641;
-  background-image: none;
-}
-.btn-info {
-  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
-  background-image:      -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
-  background-image:         linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-  border-color: #28a4c9;
-}
-.btn-info:hover,
-.btn-info:focus {
-  background-color: #2aabd2;
-  background-position: 0 -15px;
-}
-.btn-info:active,
-.btn-info.active {
-  background-color: #2aabd2;
-  border-color: #28a4c9;
-}
-.btn-info:disabled,
-.btn-info[disabled] {
-  background-color: #2aabd2;
-  background-image: none;
-}
-.btn-warning {
-  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
-  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
-  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-  border-color: #e38d13;
-}
-.btn-warning:hover,
-.btn-warning:focus {
-  background-color: #eb9316;
-  background-position: 0 -15px;
-}
-.btn-warning:active,
-.btn-warning.active {
-  background-color: #eb9316;
-  border-color: #e38d13;
-}
-.btn-warning:disabled,
-.btn-warning[disabled] {
-  background-color: #eb9316;
-  background-image: none;
-}
-.btn-danger {
-  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
-  background-image:      -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
-  background-image:         linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-  border-color: #b92c28;
-}
-.btn-danger:hover,
-.btn-danger:focus {
-  background-color: #c12e2a;
-  background-position: 0 -15px;
-}
-.btn-danger:active,
-.btn-danger.active {
-  background-color: #c12e2a;
-  border-color: #b92c28;
-}
-.btn-danger:disabled,
-.btn-danger[disabled] {
-  background-color: #c12e2a;
-  background-image: none;
-}
-.thumbnail,
-.img-thumbnail {
-  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
-          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
-}
-.dropdown-menu > li > a:hover,
-.dropdown-menu > li > a:focus {
-  background-color: #e8e8e8;
-  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
-  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
-  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
-  background-repeat: repeat-x;
-}
-.dropdown-menu > .active > a,
-.dropdown-menu > .active > a:hover,
-.dropdown-menu > .active > a:focus {
-  background-color: #357ebd;
-  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
-  background-image:      -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
-  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
-  background-repeat: repeat-x;
-}
-.navbar-default {
-  background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
-  background-image:      -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
-  background-image:         linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-  border-radius: 4px;
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
-          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
-}
-.navbar-default .navbar-nav > .open > a,
-.navbar-default .navbar-nav > .active > a {
-  background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
-  background-image:      -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
-  background-image:         linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
-  background-repeat: repeat-x;
-  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
-          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
-}
-.navbar-brand,
-.navbar-nav > li > a {
-  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
-}
-.navbar-inverse {
-  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
-  background-image:      -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
-  background-image:         linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  background-repeat: repeat-x;
-}
-.navbar-inverse .navbar-nav > .open > a,
-.navbar-inverse .navbar-nav > .active > a {
-  background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
-  background-image:      -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
-  background-image:         linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
-  background-repeat: repeat-x;
-  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
-          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
-}
-.navbar-inverse .navbar-brand,
-.navbar-inverse .navbar-nav > li > a {
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
-}
-.navbar-static-top,
-.navbar-fixed-top,
-.navbar-fixed-bottom {
-  border-radius: 0;
-}
-.alert {
-  text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
-          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
-}
-.alert-success {
-  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
-  background-image:      -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
-  background-image:         linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
-  background-repeat: repeat-x;
-  border-color: #b2dba1;
-}
-.alert-info {
-  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
-  background-image:      -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
-  background-image:         linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
-  background-repeat: repeat-x;
-  border-color: #9acfea;
-}
-.alert-warning {
-  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
-  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
-  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
-  background-repeat: repeat-x;
-  border-color: #f5e79e;
-}
-.alert-danger {
-  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
-  background-image:      -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
-  background-image:         linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
-  background-repeat: repeat-x;
-  border-color: #dca7a7;
-}
-.progress {
-  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
-  background-image:      -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
-  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
-  background-repeat: repeat-x;
-}
-.progress-bar {
-  background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
-  background-image:      -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
-  background-image:         linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
-  background-repeat: repeat-x;
-}
-.progress-bar-success {
-  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
-  background-image:      -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
-  background-image:         linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
-  background-repeat: repeat-x;
-}
-.progress-bar-info {
-  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
-  background-image:      -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
-  background-image:         linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
-  background-repeat: repeat-x;
-}
-.progress-bar-warning {
-  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
-  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
-  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
-  background-repeat: repeat-x;
-}
-.progress-bar-danger {
-  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
-  background-image:      -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
-  background-image:         linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
-  background-repeat: repeat-x;
-}
-.progress-bar-striped {
-  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
-  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
-  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
-}
-.list-group {
-  border-radius: 4px;
-  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
-          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
-}
-.list-group-item.active,
-.list-group-item.active:hover,
-.list-group-item.active:focus {
-  text-shadow: 0 -1px 0 #3071a9;
-  background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
-  background-image:      -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
-  background-image:         linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
-  background-repeat: repeat-x;
-  border-color: #3278b3;
-}
-.list-group-item.active .badge,
-.list-group-item.active:hover .badge,
-.list-group-item.active:focus .badge {
-  text-shadow: none;
-}
-.panel {
-  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
-          box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
-}
-.panel-default > .panel-heading {
-  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
-  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
-  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
-  background-repeat: repeat-x;
-}
-.panel-primary > .panel-heading {
-  background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
-  background-image:      -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
-  background-image:         linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
-  background-repeat: repeat-x;
-}
-.panel-success > .panel-heading {
-  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
-  background-image:      -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
-  background-image:         linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
-  background-repeat: repeat-x;
-}
-.panel-info > .panel-heading {
-  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
-  background-image:      -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
-  background-image:         linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
-  background-repeat: repeat-x;
-}
-.panel-warning > .panel-heading {
-  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
-  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
-  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
-  background-repeat: repeat-x;
-}
-.panel-danger > .panel-heading {
-  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
-  background-image:      -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
-  background-image:         linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
-  background-repeat: repeat-x;
-}
-.well {
-  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
-  background-image:      -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
-  background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
-  background-image:         linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
-  background-repeat: repeat-x;
-  border-color: #dcdcdc;
-  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
-          box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
-}
-/*# sourceMappingURL=bootstrap-theme.css.map */

File diff suppressed because it is too large
+ 0 - 1
sources/public/bootstrap/css/bootstrap-theme.css.map


File diff suppressed because it is too large
+ 0 - 5
sources/public/bootstrap/css/bootstrap-theme.min.css


File diff suppressed because it is too large
+ 0 - 6358
sources/public/bootstrap/css/bootstrap.css


File diff suppressed because it is too large
+ 0 - 1
sources/public/bootstrap/css/bootstrap.css.map


File diff suppressed because it is too large
+ 0 - 5
sources/public/bootstrap/css/bootstrap.min.css


BIN
sources/public/bootstrap/fonts/glyphicons-halflings-regular.eot


File diff suppressed because it is too large
+ 0 - 229
sources/public/bootstrap/fonts/glyphicons-halflings-regular.svg


BIN
sources/public/bootstrap/fonts/glyphicons-halflings-regular.ttf


BIN
sources/public/bootstrap/fonts/glyphicons-halflings-regular.woff


File diff suppressed because it is too large
+ 0 - 2276
sources/public/bootstrap/js/bootstrap.js


File diff suppressed because it is too large
+ 0 - 7
sources/public/bootstrap/js/bootstrap.min.js


+ 0 - 13
sources/public/bootstrap/js/npm.js

@@ -1,13 +0,0 @@
-// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
-require('../../js/transition.js')
-require('../../js/alert.js')
-require('../../js/button.js')
-require('../../js/carousel.js')
-require('../../js/collapse.js')
-require('../../js/dropdown.js')
-require('../../js/modal.js')
-require('../../js/tooltip.js')
-require('../../js/popover.js')
-require('../../js/scrollspy.js')
-require('../../js/tab.js')
-require('../../js/affix.js')

+ 0 - 28
sources/public/css/bootstrap-toggle.min.css

@@ -1,28 +0,0 @@
-/*! ========================================================================
- * Bootstrap Toggle: bootstrap-toggle.css v2.0.0
- * http://www.bootstraptoggle.com
- * ========================================================================
- * Copyright 2014 Min Hur, The New York Times Company
- * Licensed under MIT
- * ======================================================================== */
-.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px}
-.toggle{position:relative;overflow:hidden}
-.toggle input[type=checkbox]{display:none}
-.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}
-.toggle.off .toggle-group{left:-100%}
-.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}
-.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}
-.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}
-.toggle.btn{min-width:59px;min-height:34px}
-.toggle-on.btn{padding-right:24px}
-.toggle-off.btn{padding-left:24px}
-.toggle.btn-lg{min-width:79px;min-height:45px}
-.toggle-on.btn-lg{padding-right:31px}
-.toggle-off.btn-lg{padding-left:31px}
-.toggle-handle.btn-lg{width:40px}
-.toggle.btn-sm{min-width:50px;min-height:30px}
-.toggle-on.btn-sm{padding-right:20px}
-.toggle-off.btn-sm{padding-left:20px}
-.toggle.btn-xs{min-width:35px;min-height:22px}
-.toggle-on.btn-xs{padding-right:12px}
-.toggle-off.btn-xs{padding-left:12px}

+ 0 - 169
sources/public/css/style.css

@@ -1,169 +0,0 @@
-/* Wifi Hotspot app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/hotspot_ynh
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-li.status-info {
-  color: #5BC0DE;
-}
-
-li.status-warning {
-  color: #D9534F;
-}
-
-li.status-danger {
-  color: #D9534F;
-}
-
-li.status-success {
-  color: #5CB85C;
-}
-
-img#status-loading {
-  display: none;
-  padding-right: 5px;
-}
-
-img#save-loading {
-  display: none;
-  margin-left: 5px;
-}
-
-div#status {
-  display: none;
-  margin-top: 10px;
-}
-
-div#status ul {
-  list-style-type: none;
-  padding: 0;
-  margin: 0;
-}
-
-div#github {
-  margin: -10px 0 20px 20px;
-  background: url(../img/github.png) no-repeat 0 4px;
-}
-
-div#github a {
-  margin-left: 17px;
-}
-
-div#saveconfirmation {
-  display: none;
-  padding-right: 15px;
-  width: 60%;
-  margin: 15px auto 0;
-}
-
-div#saveconfirmation div#confirm {
-  background-color: #fff;
-  padding: 10px;
-  margin: 15px 0 0 0;
-  border: 1px solid #F5E79E;
-}
-
-div#wifiparty_screen {
-  top: 0;
-  left: 0;
-  display: none;
-  position: fixed;
-  height: 100vh;
-  width: 100vw;
-  z-index: 998;
-  background-color: #fff;
-  text-align: center;
-}
-
-div#wifiparty_screen div.btn-group {
-  display: block;
-  margin: 5px;
-  opacity: 0.3;
-}
-
-div#wifiparty_screen div.btn-group:hover {
-  opacity: 0.7;
-}
-
-div#wifiparty_ssid_part {
-  background: #5CB85C;
-  color: #fff;
-}
-
-div#wifiparty_ssid_part div.btn-group {
-  float: left;
-  position: fixed;
-  top: 0;
-  left: 0;
-  z-index: 999;
-  opacity: 0.2;
-}
-
-div#wifiparty_ssid_part div.btn-group:hover {
-  opacity: 0.8;
-}
-
-span#wifiparty_ssid {
-  font-size: 70px;
-}
-
-div.wifiparty_passphrase {
-  clear: both;
-  font-size: 140px;
-  font-style: italic;
-  margin: 50px 20px;
-  word-wrap: break-word;
-  line-height: 0.9;
-  display: none;
-}
-
-div.wifiparty_passphrase span.passdigit {
-  color: #428BCA;
-}
-
-div.wifiparty_passphrase span.passother {
-  color: #D9534F;
-}
-
-div.wifiparty_passphrase span.passspace {
-  color: #CCC;
-}
-
-ul.nav-tabs {
-  margin-top: 5px;
-}
-
-div.tabs {
-  padding: 14px 14px 0 10px;
-}
-
-ul.nav a {
-  outline: none;
-}
-
-div.deletessid {
-  text-align: center;
-  padding: 10px;
-}
-
-div.deletessid button {
-  display: block;
-  width: 100%;
-}
-
-button#newssid {
-  margin-bottom: 20px;
-}

BIN
sources/public/img/github.png


BIN
sources/public/img/loading.gif


BIN
sources/public/img/nice.ogg


File diff suppressed because it is too large
+ 0 - 4
sources/public/jquery/jquery-2.1.1.min.js


File diff suppressed because it is too large
+ 0 - 9
sources/public/js/bootstrap-toggle.min.js


+ 0 - 247
sources/public/js/custom.js

@@ -1,247 +0,0 @@
-/* Wifi Hotspot app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/hotspot_ynh
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- * 
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-function wifiSecureBtn() {
-  if($(this).parent().hasClass('off')) {
-    $(this).closest('.form-group').next().hide('slow');
-  } else {
-    $(this).closest('.form-group').next().show('slow');
-  }
-}
-
-function tabsClick() {
-  var ssid = $(this).closest('.ssid');
-  var tab = $(this).parent().attr('data-tab');
-
-  ssid.find('li.active').removeClass('active');
-  $(this).parent().addClass('active');
-
-  ssid.find('.tabs').hide();
-  ssid.find('.tab' + tab).show();
-
-  return false;
-}
-
-function deviceDropDownClick() {
-  var menu = $(this).parent();
-  var items = menu.children();
-  var button = menu.prev();
-  var input = button.prev();
-
-  items.removeClass('active');
-  $(this).addClass('active');
-
-  button.text($(this).text());
-  button.append(' <span class="caret"></span>');
-
-  input.val($(this).text());
-
-  updateNbSsidRemaining();
-}
-
-function updateNbSsidRemaining() {
-  multissid = $('#devlist .active').data('multissid');
-  current = $('.ssid').length;
-  remaining = multissid - current;
-  remaining = isNaN(remaining) ? 0 : remaining;
-
-  $('.ssid').each(function(i) {
-    if(i >= multissid) {
-      $(this).removeClass('panel-default');
-      $(this).addClass('panel-danger');
-
-    } else {
-      $(this).removeClass('panel-danger');
-      $(this).addClass('panel-default');
-    }
-  });
-
-  $('.ssid').find('.deletessid').hide();
-  $('.ssid').last().find('.deletessid').show();
-  $('.ssid').first().find('.deletessid').hide();
-
-  if(remaining <= 0) {
-    $('#newssid').attr('disabled', true);
-    $('#newssid').removeClass('btn-success');
-    $('#newssid').addClass('btn-danger');
-
-  } else {
-    $('#newssid').attr('disabled', false);
-    $('#newssid').removeClass('btn-danger');
-    $('#newssid').addClass('btn-success');
-  }
-
-  $('#newssid span').text(remaining);
-}
-
-function nice() {
-  if($(this).val() == 'YoloCowboy') {
-    $('#nice')[0].play();
-  }
-}
-
-function deleteClick() {
-  $(this).closest('.ssid').remove();
-  updateNbSsidRemaining();
-}
-
-$(document).ready(function() {
-  $('.btn-group').button();
-  $('[data-toggle="tooltip"]').tooltip();
-
-  $('.dropdown-menu li').click(deviceDropDownClick);
-
-  $('.switch').bootstrapToggle();
-
-  $('#save').click(function() {
-    $(this).prop('disabled', true);
-    $('#save-loading').show();
-    $('#form').submit();
-  });
-
-  $('#saveconfirm').click(function() {
-    $(this).hide();
-    $('#saveconfirmation').show();
-  });
-
-  $('#status .close').click(function() {
-    $(this).parent().hide();
-  });
-
-  $('#statusbtn').click(function() {
-    if($('#status-loading').is(':hidden')) {
-      $('#status').hide();
-      $('#status-loading').show();
-
-      $.ajax({
-        url: '?/status',
-      }).done(function(data) {
-        $('#status-loading').hide();
-        $('#status-text').html('<ul>' + data + '</ul>');
-        $('#status').show('slow');
-      });
-    }
-  });
-
-  $('.wifiparty').click(function() {
-    var screen = $('#wifiparty_screen');
-    var passphrase = $(this).closest('.ssid').find('.wifiparty_passphrase').clone();
-
-    screen.find('#wifiparty_ssid span').last().text($(this).closest('.ssid').find('input[type=text]').first().val());
-    screen.find('.wifiparty_passphrase').remove();
-    screen.append(passphrase);
-    screen.find('.wifiparty_passphrase').show();
-
-    screen.show('slow');
-  });
-
-  $('#wifiparty_zoomin_ssid').mousedown(function() {
-    $('#wifiparty_ssid').css('fontSize', (parseInt($('#wifiparty_ssid').css('fontSize')) + 5) + "px");
-  });
-
-  $('#wifiparty_zoomout_ssid').mousedown(function() {
-    $('#wifiparty_ssid').css('fontSize', (parseInt($('#wifiparty_ssid').css('fontSize')) - 5) + "px");
-  });
-
-  $('#wifiparty_zoomin_passphrase').mousedown(function() {
-    $('#wifiparty_screen .wifiparty_passphrase').css('fontSize', (parseInt($('#wifiparty_screen .wifiparty_passphrase').css('fontSize')) + 7) + "px");
-  });
-
-  $('#wifiparty_zoomout_passphrase').mousedown(function() {
-    $('#wifiparty_screen .wifiparty_passphrase').css('fontSize', (parseInt($('#wifiparty_screen .wifiparty_passphrase').css('fontSize')) - 7) + "px");
-  });
-
-  $('#wifiparty_close').click(function() {
-    $('#wifiparty_screen').hide();
-  });
-
-  $('.wifi_secure').change(wifiSecureBtn);
-
-  $('#service_enabled').change(function() {
-    if($('#service_enabled').parent().hasClass('off')) {
-      $('.enabled').hide('slow');
-    } else {
-      $('.enabled').show('slow');
-    }
-  });
-
-  $('.nav-tabs a').click(tabsClick);
-  $('.ssidin').blur(nice);
-
-  $('#newssid').click(function() {
-    var clone = $('#ssids').children().first().clone();
-    var id = parseInt($('.ssid').length);
-
-    clone.find('[name]').each(function() {
-      $(this).attr('name', $(this).attr('name').replace('[0]', '[' + id + ']'));
-    });
-
-    clone.find('[data-toggle="tooltip"]').tooltip();
-    clone.find('.deletessid').click(deleteClick);
-    clone.find('.ssidin').blur(nice);
-    clone.find('.wifiparty_passphrase').remove();
-    clone.find('.wifiparty').attr('disabled', true);
-
-    clone.find('input[type=text]').each(function() {
-      if($(this).attr('name').match('dns')) {
-        $(this).val($(this).attr('placeholder'));
-
-      } else if($(this).attr('name').match('ip4_nat_prefix')) {
-        var o1 = parseInt(Math.random() * (255 - 1) + 1);
-        var o2 = parseInt(Math.random() * (255 - 1) + 1);
-
-        $(this).val('10.' + o1 + '.' + o2);
-
-      } else if($(this).attr('name').match('wifi_ssid')) {
-        $(this).val('myNeutralNetwork' + (id + 1));
-
-      } else {
-        $(this).val('');
-      }
-    });
-
-    clone.find('input[type=checkbox]').each(function() {
-      $(this).parent().after($(this));
-      $(this).prev().remove();
-      $(this).attr('checked', false);
-    });
-
-    clone.find('.switch').bootstrapToggle();
-    clone.find('.wifi_secure').change(wifiSecureBtn);
-    clone.find('.nav-tabs a').click(tabsClick);
-    clone.find('.wifi_passphrase').hide();
-
-    clone.find('h3').each(function() {
-      $(this).text($(this).data('label') + ' ' + (id + 1));
-    });
-
-    $('#ssids').append(clone);
-
-    updateNbSsidRemaining(); 
-  });
-
-  $('.deletessid').click(deleteClick);
-
-  updateNbSsidRemaining(); 
-});
-
-$(document).keydown(function(e) {
-  if(e.keyCode == 27) {
-    $('#wifiparty_close').click();
-  }
-});

+ 0 - 116
sources/views/_ssid.html.php

@@ -1,116 +0,0 @@
-<div class="panel panel-default ssid enabled" <?= $service_enabled == 0 ? 'style="display: none"' : '' ?>>
-  <div class="panel-heading">
-    <h3 class="panel-title" data-label="<?= _("Hotspot") ?>"><?= _("Hotspot") ?> <?= $ssid['id'] + 1 ?></h3>
-  </div>
-
-  <ul class="nav nav-tabs nav-justified">
-    <li role="presentation" data-tab="wifi" class="active"><a href="#"><?= _("Wifi") ?></a></li>
-    <li role="presentation" data-tab="ipv6"><a href="#"><?= _("IPv6") ?></a></li>
-    <li role="presentation" data-tab="ipv4"><a href="#"><?= _("IPv4") ?></a></li>
-  </ul>
-
-  <!-- Wifi -->
-  <div class="tabs tabwifi">
-    <div class="form-group">
-      <label class="col-sm-3 control-label"><?= _('Name (SSID)') ?></label>
-      <div class="col-sm-9">
-        <input type="text" class="form-control ssidin" name="ssid[<?= $ssid['id'] ?>][wifi_ssid]" placeholder="myNeutralNetwork" value="<?= $ssid['wifi_ssid'] ?>" />
-      </div>
-    </div>
-
-    <div class="form-group">
-      <label for="wifi_secure" class="col-sm-3 control-label"><?= _('Secure') ?></label>
-      <div class="col-sm-9 input-group-btn" data-toggle="tooltip" data-title="<?= _('Disabling the Secure Wifi allows everyone to join the hotspot and spy the traffic (but it\'s perfect for a PirateBox)') ?>">
-        <div class="input-group">
-          <input type="checkbox" class="form-control switch wifi_secure" name="ssid[<?= $ssid['id'] ?>][wifi_secure]" value="1" <?= $ssid['wifi_secure'] == 1 ? 'checked="checked"' : '' ?> />
-        </div>
-      </div>
-    </div>
-
-    <div class="form-group wifi_passphrase" <?= $ssid['wifi_secure'] == 0 ? 'style="display: none"' : '' ?>>
-      <label class="col-sm-3 control-label"><?= _('Password (WPA2)') ?></label>
-      <div class="input-group col-sm-9" style="padding: 0 15px">
-        <input type="text" data-toggle="tooltip" data-title="<?= _('At least 8 characters') ?>" class="form-control" name="ssid[<?= $ssid['id'] ?>][wifi_passphrase]" placeholder="VhegT8oev0jZI" value="<?= $ssid['wifi_passphrase'] ?>" />
-        <a class="btn input-group-addon wifiparty" data-toggle="tooltip" data-title="<?= _('Show to your friends how to access to your hotspot') ?>"><span class="glyphicon glyphicon-fullscreen"></span></a>
-      </div>
-    </div>
-  </div>
-
-  <!-- IPv6 -->
-  <div class="tabs tabipv6" style="display: none">
-    <?php if(empty($ssid['ip6_net'])): ?>
-      <div class="alert alert-dismissible alert-warning fade in" style="margin: 2px 2px 17px" role="alert">
-        <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-        <strong><?= _('Notice') ?>:</strong> <?= str_replace('<LINK:FFDN>', '<a href="http://db.ffdn.org" class="alert-link">', str_replace('</LINK:FFDN>', '</a>', _("Currently, your wifi clients don't have IPv6 and it's a very bad thing. Ask your Internet Service Provider an IPv6 delegated prefix, or <LINK:FFDN>change providers</LINK:FFDN>!"))) ?>
-      </div>
-    <?php endif; ?>
-
-    <div class="form-group">
-      <label class="col-sm-3 control-label"><?= _('Delegated prefix') ?></label>
-      <div class="col-sm-9">
-        <input type="text" class="form-control" name="ssid[<?= $ssid['id'] ?>][ip6_net]" placeholder="2001:db8:42::" value="<?= $ssid['ip6_net'] ?>" />
-      </div>
-    </div>
-
-    <div class="form-group">
-      <label for="ip6_firewall" class="col-sm-3 control-label"><?= _('Firewall') ?></label>
-      <div class="col-sm-9 input-group-btn" data-toggle="tooltip" data-title="<?= _('Disabling the Firewall allows everyone to make connections to client hosts, depending on their own security policy') ?>">
-        <div class="input-group">
-          <input type="checkbox" class="form-control switch ip6_firewall" name="ssid[<?= $ssid['id'] ?>][ip6_firewall]" value="1" <?= $ssid['ip6_firewall'] == 1 ? 'checked="checked"' : '' ?> />
-        </div>
-      </div>
-    </div>
-
-    <div class="form-group">
-      <label class="col-sm-3 control-label"><?= _('First DNS resolver') ?></label>
-      <div class="col-sm-9">
-        <input type="text" class="form-control" name="ssid[<?= $ssid['id'] ?>][ip6_dns0]" placeholder="2001:913::8" value="<?= $ssid['ip6_dns0'] ?>" />
-      </div>
-    </div>
-
-    <div class="form-group">
-      <label class="col-sm-3 control-label"><?= _('Second DNS resolver') ?></label>
-      <div class="col-sm-9">
-        <input type="text" class="form-control" name="ssid[<?= $ssid['id'] ?>][ip6_dns1]" placeholder="2001:910:800::40" value="<?= $ssid['ip6_dns1'] ?>" />
-      </div>
-    </div>
-  </div>
-
-  <!-- IPv4 -->
-  <div class="tabs tabipv4" style="display: none">
-    <div class="form-group">
-      <label class="col-sm-3 control-label"><?= _('NAT prefix (/24)') ?></label>
-      <div class="col-sm-9">
-        <input type="text" class="form-control" name="ssid[<?= $ssid['id'] ?>][ip4_nat_prefix]" placeholder="10.0.242" value="<?= $ssid['ip4_nat_prefix'] ?>" />
-      </div>
-    </div>
-
-    <div class="form-group">
-      <label class="col-sm-3 control-label"><?= _('First DNS resolver') ?></label>
-      <div class="col-sm-9">
-        <input type="text" class="form-control" name="ssid[<?= $ssid['id'] ?>][ip4_dns0]" placeholder="80.67.188.188" value="<?= $ssid['ip4_dns0'] ?>" />
-      </div>
-    </div>
-
-    <div class="form-group">
-      <label class="col-sm-3 control-label"><?= _('Second DNS resolver') ?></label>
-      <div class="col-sm-9">
-        <input type="text" class="form-control" name="ssid[<?= $ssid['id'] ?>][ip4_dns1]" placeholder="80.67.169.12" value="<?= $ssid['ip4_dns1'] ?>" />
-      </div>
-    </div>
-  </div>
-
-  <div class="deletessid" style="display: none">
-    <button type="button" class="btn btn-danger"><?= _("Delete") ?></button>
-  </div>
-
-  <div class="wifiparty_passphrase"><?php
-    $pw = preg_replace('/[^0-9a-z ]/i', '<span-class="passother">$0</span>', $ssid['wifi_passphrase']);
-    $pw = preg_replace('/\d/', '<span-class="passdigit">$0</span>', $pw);
-    $pw = preg_replace('/ /', '<span class="passspace">&#x25AE;</span>', $pw);
-    $pw = preg_replace('/span-class/', 'span class', $pw);
-
-    echo $pw;
-  ?></div>
-</div>
-

+ 0 - 70
sources/views/layout.html.php

@@ -1,70 +0,0 @@
-<!doctype html>
-
-<!--
-  Wifi Hotspot app for YunoHost 
-  Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-  Contribute at https://github.com/labriqueinternet/hotspot_ynh
-  
-  This program is free software: you can redistribute it and/or modify
-  it under the terms of the GNU Affero General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-  
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU Affero General Public License for more details.
-  
-  You should have received a copy of the GNU Affero General Public License
-  along with this program.  If not, see <http://www.gnu.org/licenses/>.
--->
-
-<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
-<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
-<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
-<!--[if gt IE 8]><!--> <html class="no-js" lang="<?= $locale ?>"> <!--<![endif]-->
-<head>
-  <title><?= _("Wifi Hotspot") ?><?php isset($title) ? " | $title" : '' ?></title>
-
-  <meta charset="utf-8">
-  <meta name="viewport" content="width=device-width">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-
-  <link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/bootstrap/css/bootstrap.min.css" rel="stylesheet">
-  <link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet">
-  <link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/css/bootstrap-toggle.min.css" rel="stylesheet">
-  <link media="all" type="text/css" href="<?= PUBLIC_DIR ?>/css/style.css" rel="stylesheet">
-
-  <script src="<?= PUBLIC_DIR ?>/jquery/jquery-2.1.1.min.js"></script>
-  <script src="<?= PUBLIC_DIR ?>/bootstrap/js/bootstrap.min.js"></script>
-  <script src="<?= PUBLIC_DIR ?>/js/bootstrap-toggle.min.js"></script>
-  <script src="<?= PUBLIC_DIR ?>/js/custom.js"></script>
-</head>
-
-<body>
-  <div class="container">
-    <?php if(isset($flash['error'])): ?>
-      <div class="alert alert-dismissible alert-danger fade in" style="margin-top: 20px" role="alert">
-        <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-        <strong><?= _('Error') ?>:</strong> <?= $flash['error'] ?>
-      </div>
-    <?php elseif(isset($flash['notice'])): ?>
-      <div class="alert alert-dismissible alert-info fade in" style="margin-top: 20px" role="alert">
-        <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-        <strong><?= _('Notice') ?>:</strong> <?= $flash['notice'] ?>
-      </div>
-    <?php elseif(isset($flash['success'])): ?>
-      <div class="alert alert-dismissible alert-success fade in" style="margin-top: 20px" role="alert">
-        <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-        <?= $flash['success'] ?>
-      </div>
-    <?php endif; ?>
-
-    <?= $content?>
-
-    <hr />
-    <div id="github"><a href="https://github.com/labriqueinternet/hotspot_ynh"><?= _('Any problem? Contribute!') ?></a> - AGPL 3.0</div>
-  </div>
-</body>
-
-</html>

+ 0 - 144
sources/views/settings.html.php

@@ -1,144 +0,0 @@
-<!--
-  Wifi Hotspot app for YunoHost 
-  Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-  Contribute at https://github.com/labriqueinternet/hotspot_ynh
-  
-  This program is free software: you can redistribute it and/or modify
-  it under the terms of the GNU Affero General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-  
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU Affero General Public License for more details.
-  
-  You should have received a copy of the GNU Affero General Public License
-  along with this program.  If not, see <http://www.gnu.org/licenses/>.
--->
-
-<div id="wifiparty_screen">
-  <div id="wifiparty_ssid_part">
-    <div class="btn-group" role="group">
-      <button type="button" class="btn btn-default" id="wifiparty_close"><span class="glyphicon glyphicon-eye-close"></span></button>
-      <button type="button" class="btn btn-default" id="wifiparty_zoomin_ssid"><span class="glyphicon glyphicon-zoom-in"></span></button>
-      <button type="button" class="btn btn-default" id="wifiparty_zoomout_ssid"><span class="glyphicon glyphicon-zoom-out"></span></button>
-    </div>
-  
-    <span id="wifiparty_ssid"><span class="glyphicon glyphicon-signal"></span> <span></span></span>
-  </div>
-  
-  <div class="btn-group" role="group">
-    <button type="button" class="btn btn-default" id="wifiparty_zoomin_passphrase"><span class="glyphicon glyphicon-zoom-in"></span></button>
-    <button type="button" class="btn btn-default" id="wifiparty_zoomout_passphrase"><span class="glyphicon glyphicon-zoom-out"></span></button>
-  </div>
-</div>
-
-<h2><?= _("Wifi Hotspot Configuration") ?></h2>
-<?php if($faststatus): ?>
-  <span class="label label-success" data-toggle="tooltip" data-title="<?= _('This is a fast status. Click on More details to show the complete status.') ?>"><?= _('Running') ?></span>
-<?php else: ?>
-  <span class="label label-danger" data-toggle="tooltip" data-title="<?= _('This is a fast status. Click on More details to show the complete status.') ?>"><?= _('Not Running') ?></span>
-<?php endif; ?>
-
- &nbsp; <img src="public/img/loading.gif" id="status-loading" alt="Loading..." /><a href="#" id="statusbtn" data-toggle="tooltip" data-title="<?= _('Loading complete status may take a few minutes. Be patient.') ?>"><?= _('More details') ?></a>
-
-<div id="status" class="alert alert-dismissible alert-info fade in" style="margin-top: 10px" role="alert">
-  <button type="button" class="close"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-  <div id="status-text"></div>
-</div>
-
-<hr />
-
-<div class="row">
-  <div class="col-sm-offset-2 col-sm-8">
-    <form method="post" enctype="multipart/form-data" action="?/settings" class="form-horizontal" role="form" id="form">
-      <input type="hidden" name="_method" value="put" />
-
-      <div class="panel panel-default">
-        <div class="panel-heading">
-          <h3 class="panel-title"><?= _("Service") ?></h3>
-        </div>
-
-        <div style="padding: 14px 14px 0 10px">
-          <div class="form-group">
-            <label for="service_enabled" class="col-sm-3 control-label"><?= _('Hotspot Enabled') ?></label>
-            <div class="col-sm-9 input-group-btn">
-              <div class="input-group">
-                <input type="checkbox" class="form-control switch" name="service_enabled" id="service_enabled" value="1" <?= $service_enabled == 1 ? 'checked="checked"' : '' ?> />
-              </div>
-            </div>
-          </div>
-          <div class="form-group">
-            <?php if(empty($wifi_device)): ?>
-              <div class="alert alert-dismissible alert-warning fade in" style="margin: 2px 16px 17px" role="alert">
-                <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-                <strong><?= _('Notice') ?>:</strong> <?= str_replace('<LINK:RELOAD>', '<a href="javascript:location.reload()" class="alert-link">', str_replace('</LINK:RELOAD>', '</a>', _("You need to select a wifi antenna interface. If you use a wifi USB dongle and that this one is not listed here, try to unplug and replug it, then <LINK:RELOAD>reload</LINK:RELOAD> this page."))) ?>
-              </div>
-            <?php endif; ?>
-
-            <label for="wifi_device" class="col-sm-3 control-label"><?= _('Device') ?></label>
-            <div class="col-sm-9 input-group-btn">
-              <div class="input-group">
-                  <input type="text" name="wifi_device" id="wifi_device" value="<?= $wifi_device ?>" style="display: none" />
-                  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><?= empty($wifi_device) ? '<em>'._("None").'</em>' : $wifi_device ?> <span class="caret"></span></button>
-                  <ul class="dropdown-menu dropdown-menu-left" id="devlist" role="menu">
-                    <?= $wifi_device_list ?>
-                  </ul>
-              </div>
-            </div>
-          </div>
-          <div class="form-group">
-            <label class="col-sm-3 control-label"><?= _('Channel') ?></label>
-            <div class="col-sm-9 input-group-btn">
-              <div class="input-group dropdownmenu">
-                  <input type="text" name="wifi_channel" value="<?= $wifi_channel ?>" style="display: none" />
-                  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><?= $wifi_channel ?> <span class="caret"></span></button>
-                  <ul class="dropdown-menu dropdown-menu-left" role="menu">
-                    <li <?= $wifi_channel == 1 ? 'class="active"' : '' ?>><a href="javascript:;">1</a></li>
-                    <li <?= $wifi_channel == 2 ? 'class="active"' : '' ?>><a href="javascript:;">2</a></li>
-                    <li <?= $wifi_channel == 3 ? 'class="active"' : '' ?>><a href="javascript:;">3</a></li>
-                    <li <?= $wifi_channel == 4 ? 'class="active"' : '' ?>><a href="javascript:;">4</a></li>
-                    <li <?= $wifi_channel == 5 ? 'class="active"' : '' ?>><a href="javascript:;">5</a></li>
-                    <li <?= $wifi_channel == 6 ? 'class="active"' : '' ?>><a href="javascript:;">6</a></li>
-                    <li <?= $wifi_channel == 7 ? 'class="active"' : '' ?>><a href="javascript:;">7</a></li>
-                    <li <?= $wifi_channel == 8 ? 'class="active"' : '' ?>><a href="javascript:;">8</a></li>
-                    <li <?= $wifi_channel == 9 ? 'class="active"' : '' ?>><a href="javascript:;">9</a></li>
-                    <li <?= $wifi_channel == 10 ? 'class="active"' : '' ?>><a href="javascript:;">10</a></li>
-                    <li <?= $wifi_channel == 11 ? 'class="active"' : '' ?>><a href="javascript:;">11</a></li>
-                  </ul>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <div id="ssids">
-      <?php foreach($ssids as $ssid): ?>
-        <?php set('ssid', $ssid) ?>
-        <?= partial('_ssid.html.php') ?>
-      <?php endforeach; ?>
-      </div>
-
-      <button id="newssid" type="button" class="btn btn-success enabled" <?= $service_enabled == 0 ? 'style="display: none"' : '' ?>><?= _("Add a hotspot") ?> <span class="badge">0</span></button>
-
-      <div class="form-group">
-        <div style="text-align: center">
-<?php if($is_connected_through_hotspot): ?>
-          <div class="alert alert-dismissible alert-warning fade in" role="alert" id="saveconfirmation">
-            <strong><?= _('Notice') ?>:</strong> <?= _("You are currently connected through the wifi hotspot. Please, confirm the reloading, wait for the wifi disconnect/reconnect and go back here to check that everything is okay.") ?>
-            <div id="confirm">
-              <button type="submit" class="btn btn-default" data-toggle="tooltip" id="save" data-title="<?= _('Reloading may take a few minutes. Be patient.') ?>"><?= _('Confirm') ?></button> <img src="public/img/loading.gif" id="save-loading" alt="Loading..." />
-            </div>
-          </div>
-
-          <button type="button" class="btn btn-default" id="saveconfirm"><?= _('Save and reload') ?></button>
-<?php else: ?>
-          <button type="submit" class="btn btn-default" data-toggle="tooltip" id="save" data-title="<?= _('Reloading may take a few minutes. Be patient.') ?>"><?= _('Save and reload') ?></button> <img src="public/img/loading.gif" id="save-loading" alt="Loading..." />
-<?php endif; ?>
-          <audio id="nice" preload><source src="<?= PUBLIC_DIR ?>/img/nice.ogg" type="audio/ogg"></audio>
-        </div>
-      </div>
-    </form>
-  </div>
-</div>