Parcourir la source

Merge pull request #80 from YunoHost-Apps/testing

Testing
Alexandre Aubin il y a 3 ans
Parent
commit
1f038f3273
68 fichiers modifiés avec 891 ajouts et 15652 suppressions
  1. 55 0
      .github/ISSUE_TEMPLATE.md
  2. 16 0
      .github/PULL_REQUEST_TEMPLATE.md
  3. 38 25
      README.md
  4. 51 0
      README_fr.md
  5. 6 12
      check_process
  6. 57 42
      conf/hook_post-iptable-rules
  7. 0 20
      conf/ipv6_compressed
  8. 0 20
      conf/ipv6_expanded
  9. 0 49
      conf/nginx.conf
  10. 9 9
      conf/openvpn_client.conf.tpl
  11. 0 202
      conf/php-fpm.conf
  12. 0 13
      conf/sudoers.conf
  13. 84 105
      conf/ynh-vpnclient
  14. 1 70
      conf/ynh-vpnclient-loadcubefile.sh
  15. 115 0
      config_panel.toml
  16. 7 0
      doc/DESCRIPTION.md
  17. 7 0
      doc/DESCRIPTION_fr.md
  18. 1 0
      doc/DISCLAIMER.md
  19. 1 0
      doc/DISCLAIMER_fr.md
  20. BIN
      doc/screenshots/vpnclient.png
  21. 21 25
      manifest.json
  22. 1 40
      scripts/_common.sh
  23. 0 25
      scripts/backup
  24. 363 0
      scripts/config
  25. 6 16
      scripts/install
  26. 6 24
      scripts/remove
  27. 1 50
      scripts/restore
  28. 45 22
      scripts/upgrade
  29. 0 73
      sources/config.php
  30. 0 366
      sources/controller.php
  31. 0 45
      sources/i18n/README.md
  32. BIN
      sources/i18n/fr_FR/LC_MESSAGES/localization.mo
  33. 0 336
      sources/i18n/fr_FR/LC_MESSAGES/localization.po
  34. 0 301
      sources/i18n/localization.pot
  35. 0 27
      sources/index.php
  36. 0 2707
      sources/lib/limonade.php
  37. 0 193
      sources/lib/limonade/abstract.php
  38. 0 173
      sources/lib/limonade/assertions.php
  39. 0 220
      sources/lib/limonade/public/css/screen.css
  40. BIN
      sources/lib/limonade/public/img/bg_header.png
  41. 0 350
      sources/lib/limonade/tests.php
  42. 0 37
      sources/lib/limonade/views/_debug.html.php
  43. 0 15
      sources/lib/limonade/views/_notices.html.php
  44. 0 22
      sources/lib/limonade/views/default_layout.php
  45. 0 6
      sources/lib/limonade/views/error.html.php
  46. 0 49
      sources/lib/unix_func.php
  47. 0 457
      sources/public/bootstrap/css/bootstrap-theme.css
  48. 0 1
      sources/public/bootstrap/css/bootstrap-theme.css.map
  49. 0 5
      sources/public/bootstrap/css/bootstrap-theme.min.css
  50. 0 6358
      sources/public/bootstrap/css/bootstrap.css
  51. 0 1
      sources/public/bootstrap/css/bootstrap.css.map
  52. 0 5
      sources/public/bootstrap/css/bootstrap.min.css
  53. BIN
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.eot
  54. 0 229
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.svg
  55. BIN
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.ttf
  56. BIN
      sources/public/bootstrap/fonts/glyphicons-halflings-regular.woff
  57. 0 2276
      sources/public/bootstrap/js/bootstrap.js
  58. 0 7
      sources/public/bootstrap/js/bootstrap.min.js
  59. 0 13
      sources/public/bootstrap/js/npm.js
  60. 0 28
      sources/public/css/bootstrap-toggle.min.css
  61. 0 107
      sources/public/css/style.css
  62. BIN
      sources/public/img/github.png
  63. BIN
      sources/public/img/loading.gif
  64. 0 4
      sources/public/jquery/jquery-2.1.1.min.js
  65. 0 9
      sources/public/js/bootstrap-toggle.min.js
  66. 0 133
      sources/public/js/custom.js
  67. 0 70
      sources/views/layout.html.php
  68. 0 260
      sources/views/settings.html.php

+ 55 - 0
.github/ISSUE_TEMPLATE.md

@@ -0,0 +1,55 @@
+---
+name: Bug report
+about: When creating a bug report, please use the following template to provide all the relevant information and help debugging efficiently.
+
+---
+
+**How to post a meaningful bug report**
+1. *Read this whole template first.*
+2. *Determine if you are on the right place:*
+   - *If you were performing an action on the app from the webadmin or the CLI (install, update, backup, restore, change_url...), you are on the right place!*
+   - *Otherwise, the issue may be due to the app itself. Refer to its documentation or repository for help.*
+   - *When in doubt, post here and we will figure it out together.*
+3. *Delete the italic comments as you write over them below, and remove this guide.*
+--- 
+
+### Describe the bug
+
+*A clear and concise description of what the bug is.*
+
+### Context
+
+- Hardware: *VPS bought online / Old laptop or computer / Raspberry Pi at home / Internet Cube with VPN / Other ARM board / ...*
+- YunoHost version: x.x.x
+- I have access to my server: *Through SSH | through the webadmin | direct access via keyboard / screen | ...*
+- Are you in a special context or did you perform some particular tweaking on your YunoHost instance?: *no / yes*
+  - If yes, please explain:
+- Using, or trying to install package version/branch:
+- If upgrading, current package version: *can be found in the admin, or with `yunohost app info $app_id`*
+
+### Steps to reproduce
+
+- *If you performed a command from the CLI, the command itself is enough. For example:*
+    ```sh
+    sudo yunohost app install the_app
+    ```
+- *If you used the webadmin, please perform the equivalent command from the CLI first.*
+- *If the error occurs in your browser, explain what you did:*
+   1. *Go to '...'*
+   2. *Click on '...'*
+   3. *Scroll down to '...'*
+   4. *See error*
+
+### Expected behavior
+
+*A clear and concise description of what you expected to happen. You can remove this section if the command above is enough to understand your intent.*
+
+### Logs
+
+*When an operation fails, YunoHost provides a simple way to share the logs.*
+- *In the webadmin, the error message contains a link to the relevant log page. On that page, you will be able to 'Share with Yunopaste'. If you missed it, the logs of previous operations are also available under Tools > Logs.*
+- *In command line, the command to share the logs is displayed at the end of the operation and looks like `yunohost log display [log name] --share`. If you missed it, you can find the log ID of a previous operation using `yunohost log list`.*
+
+*After sharing the log, please copypaste directly the link provided by YunoHost (to help readability, no need to copypaste the entire content of the log here, just the link is enough...)*
+
+*If applicable and useful, add screenshots to help explain your problem.*

+ 16 - 0
.github/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,16 @@
+## Problem
+
+- *Description of why you made this PR*
+
+## Solution
+
+- *And how do you fix that problem*
+
+## PR Status
+
+- [ ] Code finished and ready to be reviewed/tested
+- [ ] The fix/enhancement were manually tested (if applicable)
+
+## Automatic tests
+
+Automatic tests can be triggered on https://ci-apps-dev.yunohost.org/ *after creating the PR*, by commenting "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!". (N.B. : for this to work you need to be a member of the Yunohost-Apps organization)

+ 38 - 25
README.md

@@ -1,42 +1,55 @@
-# VPN Client
+<!--
+N.B.: This README was automatically generated by https://github.com/YunoHost/apps/tree/master/tools/README-generator
+It shall NOT be edited by hand.
+-->
 
-[![Build Status](https://travis-ci.org/labriqueinternet/vpnclient_ynh.svg?branch=master)](https://travis-ci.org/labriqueinternet/vpnclient_ynh) [![Integration level](https://dash.yunohost.org/integration/vpnclient.svg)](https://dash.yunohost.org/appci/app/vpnclient)  
-[![Install LaBriqueInterNet VPNclient with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=vpnclient)
+# VPN Client for YunoHost
 
-This YunoHost app is a part of the "[La Brique Internet](http://labriqueinter.net)" project but can be used independently.
+[![Integration level](https://dash.yunohost.org/integration/vpnclient.svg)](https://dash.yunohost.org/appci/app/vpnclient) ![](https://ci-apps.yunohost.org/ci/badges/vpnclient.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/vpnclient.maintain.svg)  
+[![Install VPN Client with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=vpnclient)
 
-## Overview
+*[Lire ce readme en français.](./README_fr.md)*
+
+> *This package allows you to install VPN Client quickly and simply on a YunoHost server.
+If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.*
 
-VPN Client app for [YunoHost](http://yunohost.org/).
+## Overview
 
 * Install a VPN connection on your self-hosted server.
 * Useful for hosting your server behind a filtered (and/or non-neutral) internet access.
 * Useful to have static IP addresses (IPv6 and IPv4).
 * Useful to easily move your server anywhere.
-* With the [Hotspot app for YunoHost](https://github.com/labriqueinternet/hotspot_ynh), you can broadcast your VPN access by wifi to use a clean internet connection (depending on your VPN provider) on your laptop (or those of your friends) without having to configure it.
+* Strong firewalling (internet access and self-hosted services only available through the VPN, not leaking to your commercial ISP)
+* Combine with the [Hotspot app](https://github.com/YunoHost-Apps/hotspot_ynh) to broadcast VPN-protected WiFi to other laptops without any further technical configuration needed.
+
+
+
+**Shipped version:** 2.0~ynh1
 
-## Features
 
-* Authentication based on certificates or login (or both), with or without shared-secret (*ta.key*)
-* IPv6 compliant (with a delegated prefix)
-* Set an IPv6 from your delegated prefix (*prefix::42*) on the server, to use for the AAAA records
-* Use native IPv6 if available for creating the tunnel
-* Port selection, with UDP or TCP
-* Set DNS resolvers on the host
-* Strong firewalling (internet access and self-hosted services only available through the VPN)
-* Advanced mode for editing the default OpenVPN configuration
-* Auto-configuration mode, with [dot cube files](http://internetcu.be/dotcubefiles.html)
-* Web interface
 
-## Screenshot
+## Screenshots
 
-![Screenshot of the web interface](https://raw.githubusercontent.com/labriqueinternet/vpnclient_ynh/master/screenshot.png)
+![](./doc/screenshots/vpnclient.png)
 
+## Disclaimers / important information
 
-## Running vpnclient inside lxc
-If you want to run openvpn inside lxc, you should add this to your container:
+Please note that this application is designed to interface with **dedicated, public IP VPNs accepting inbound traffic**, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. **Do not** expect that any VPN you randomly bought on the Internet can be used! Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.
+
+## Documentation and resources
+
+* YunoHost documentation for this app: https://yunohost.org/app_vpnclient
+* Report a bug: https://github.com/YunoHost-Apps/vpnclient_ynh/issues
+
+## Developer info
+
+Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing).
+
+To try the testing branch, please proceed like that.
 ```
-lxc.hook.autodev = sh -c "modprobe tun"
-lxc.mount.entry=/dev/net/tun dev/net/tun none bind,create=file
-lxc.hook.autodev = sh -c "chmod 0666 dev/net/tun"
+sudo yunohost app install https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing --debug
+or
+sudo yunohost app upgrade vpnclient -u https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing --debug
 ```
+
+**More info regarding app packaging:** https://yunohost.org/packaging_apps

+ 51 - 0
README_fr.md

@@ -0,0 +1,51 @@
+# VPN Client pour YunoHost
+
+[![Niveau d'intégration](https://dash.yunohost.org/integration/vpnclient.svg)](https://dash.yunohost.org/appci/app/vpnclient) ![](https://ci-apps.yunohost.org/ci/badges/vpnclient.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/vpnclient.maintain.svg)  
+[![Installer VPN Client avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=vpnclient)
+
+*[Read this readme in english.](./README.md)*
+*[Lire ce readme en français.](./README_fr.md)*
+
+> *Ce package vous permet d'installer VPN Client rapidement et simplement sur un serveur YunoHost.
+Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.*
+
+## Vue d'ensemble
+
+* Installez une connexion VPN sur votre serveur auto-hébergé
+* Utile pour héberger votre serveur derrière un accès internet filtré (et/ou non-neutre)
+* Utile pour obtenir une IP statique (v4 et v6)
+* Utile pour pouvoir facilement déplacer votre serveur
+* Pare-feu strict (le traffice entrant et sortant se fait seulement via le pare-feu et ne fuite pas de données à votre FAI commercial)
+* Peut-être combiné avec [l'application Hotspot](https://github.com/YunoHost-Apps/hotspot_ynh) pour diffuser un WiFi protégé par le VPN à d'autres laptop sans configuration technique requise sur les machines clientes.
+
+
+
+**Version incluse :** 2.0~ynh1
+
+
+
+## Captures d'écran
+
+![](./doc/screenshots/vpnclient.png)
+
+## Avertissements / informations importantes
+
+Notez que cette application est prévue pour fonctionner avec des **VPN dédiés et à IP publique qui acceptent le traffic entrant**, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Un VPN acheté au hasard sur Internet ne fonctionnera sans doute pas ! Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos.
+
+## Documentations et ressources
+
+* Documentation YunoHost pour cette app : https://yunohost.org/app_vpnclient
+* Signaler un bug : https://github.com/YunoHost-Apps/vpnclient_ynh/issues
+
+## Informations pour les développeurs
+
+Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing).
+
+Pour essayer la branche testing, procédez comme suit.
+```
+sudo yunohost app install https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing --debug
+ou
+sudo yunohost app upgrade vpnclient -u https://github.com/YunoHost-Apps/vpnclient_ynh/tree/testing --debug
+```
+
+**Plus d'infos sur le packaging d'applications :** https://yunohost.org/packaging_apps

+ 6 - 12
check_process

@@ -1,22 +1,16 @@
 ;; Test complet
     ; Manifest
-        domain="domain.tld" (DOMAIN)
-        path="/vpnconfig"   (PATH)
     ; 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=623d8a30453a26ee21aa2ce1142674a2ffdb85b9
-        upgrade=1   from_commit=73aa672346e40fc1857aef7441c449f0bd322082
+        upgrade=1   from_commit=0d2a6b1d9a71f63dedfc2b05b35c93c73a130886
         backup_restore=1
         multi_instance=0
-        incorrect_path=1
+        incorrect_path=0
         port_already_use=0
         change_url=0
-;;; Options
-Email=pitchum@gramaton.org
-Notification=down

+ 57 - 42
conf/hook_post-iptable-rules

@@ -1,78 +1,93 @@
 #!/bin/bash
 
-host6=$(dig AAAA +short <TPL:SERVER_NAME> | grep -v '\.$')
-host4=$(dig A +short <TPL:SERVER_NAME> | grep -v '\.$')
+server_names=$(grep -o -P '^\s*remote\s+\K([^\s]+)' /etc/openvpn/client.conf | sort | uniq)
+host6=$(dig AAAA +short $server_names @127.0.0.1 | grep -v '\.$' | grep -v "timed out")
+host4=$(dig A +short $server_names @127.0.0.1 | grep -v '\.$' | grep -v "timed out")
+
+# In case an ip has been provided in ovpn conf
+for i in ${server_names}; do
+  if [[ "${i}" =~ : ]]; then
+      host6+=" ${i}"
+  elif [[ "${i}" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
+      host4+=" ${i}"
+  fi
+done
+
+interface=$(ip route | awk '/default via/ { print $NF; }')
+dns=$(grep -o -P '\s*nameserver\s+\K[ABCDEFabcdef\d.:]+' /etc/resolv.dnsmasq.conf)
 
 # IPv6
 
-sudo ip6tables -w -N vpnclient_in
-sudo ip6tables -w -N vpnclient_out
-sudo ip6tables -w -N vpnclient_fwd
+ip6tables -w -N vpnclient_in
+ip6tables -w -N vpnclient_out
+ip6tables -w -N vpnclient_fwd
 
-sudo ip6tables -w -A vpnclient_in -p icmpv6 -j ACCEPT
-sudo ip6tables -w -A vpnclient_in -s fd00::/8,fe80::/10 -j ACCEPT
-sudo ip6tables -w -A vpnclient_in -p tcp --dport 22 -j ACCEPT
-sudo ip6tables -w -A vpnclient_in -p tcp --dport 443 -j ACCEPT
-sudo ip6tables -w -A vpnclient_in -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-sudo ip6tables -w -A vpnclient_in -j DROP
+ip6tables -w -A vpnclient_in -p icmpv6 -j ACCEPT
+ip6tables -w -A vpnclient_in -s fd00::/8,fe80::/10 -j ACCEPT
+ip6tables -w -A vpnclient_in -p tcp --dport 22 -j ACCEPT
+ip6tables -w -A vpnclient_in -p tcp --dport 443 -j ACCEPT
+ip6tables -w -A vpnclient_in -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+ip6tables -w -A vpnclient_in -j DROP
 
 if [ ! -z "${host6}" ]; then
   for i in ${host6}; do
-    sudo ip6tables -w -A vpnclient_out -d "${i}" -p <TPL:PROTO> --dport <TPL:SERVER_PORT> -j ACCEPT
+    ip6tables -w -A vpnclient_out -d "${i}" -j ACCEPT
   done
 fi
 
-for i in <TPL:DNS0> <TPL:DNS1>; do
+for i in ${dns};
+do
   if [[ "${i}" =~ : ]]; then
-    sudo ip6tables -w -A vpnclient_out -p udp -d "${i}" --dport 53 -j ACCEPT
+    ip6tables -w -A vpnclient_out -p udp -d "${i}" --dport 53 -j ACCEPT
   fi
 done
 
-sudo ip6tables -w -A vpnclient_out -d fd00::/8,fe80::/10 -j ACCEPT
-sudo ip6tables -w -A vpnclient_out -p udp --dport 5353 -d ff02::fb -j ACCEPT
-sudo ip6tables -w -A vpnclient_out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-sudo ip6tables -w -A vpnclient_out -j DROP
+ip6tables -w -A vpnclient_out -d fd00::/8,fe80::/10 -j ACCEPT
+ip6tables -w -A vpnclient_out -p udp --dport 5353 -d ff02::fb -j ACCEPT
+ip6tables -w -A vpnclient_out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+ip6tables -w -A vpnclient_out -j DROP
 
-sudo ip6tables -w -A vpnclient_fwd -j DROP
+ip6tables -w -A vpnclient_fwd -j DROP
 
-sudo ip6tables -w -I INPUT 1 -i <TPL:WIRED_DEVICE> -j vpnclient_in
-sudo ip6tables -w -I OUTPUT 1 -o <TPL:WIRED_DEVICE> -j vpnclient_out
-sudo ip6tables -w -I FORWARD 1 -o <TPL:WIRED_DEVICE> -j vpnclient_fwd
+ip6tables -w -I INPUT 1 -i $interface -j vpnclient_in
+ip6tables -w -I OUTPUT 1 -o $interface -j vpnclient_out
+ip6tables -w -I FORWARD 1 -o $interface -j vpnclient_fwd
 
 # IPv4
 
-sudo iptables -w -N vpnclient_in
-sudo iptables -w -N vpnclient_out
-sudo iptables -w -N vpnclient_fwd
+iptables -w -N vpnclient_in
+iptables -w -N vpnclient_out
+iptables -w -N vpnclient_fwd
 
-sudo iptables -w -A vpnclient_in -p icmp -j ACCEPT
-sudo iptables -w -A vpnclient_in -s 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16 -j ACCEPT
-sudo iptables -w -A vpnclient_in -p tcp --dport 22 -j ACCEPT
-sudo iptables -w -A vpnclient_in -p tcp --dport 443 -j ACCEPT
-sudo iptables -w -A vpnclient_in -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-sudo iptables -w -A vpnclient_in -j DROP
+iptables -w -A vpnclient_in -p icmp -j ACCEPT
+iptables -w -A vpnclient_in -s 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16 -j ACCEPT
+iptables -w -A vpnclient_in -p tcp --dport 22 -j ACCEPT
+iptables -w -A vpnclient_in -p tcp --dport 443 -j ACCEPT
+iptables -w -A vpnclient_in -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+iptables -w -A vpnclient_in -j DROP
 
 if [ ! -z "${host4}" ]; then
   for i in ${host4}; do
-    sudo iptables -w -A vpnclient_out -d "${i}" -p <TPL:PROTO> --dport <TPL:SERVER_PORT> -j ACCEPT
+    iptables -w -A vpnclient_out -d "${i}" -j ACCEPT
   done
 fi
 
-for i in <TPL:DNS0> <TPL:DNS1>; do
+for i in ${dns};
+do
   if [[ "${i}" =~ \. ]]; then
-    sudo iptables -w -A vpnclient_out -p udp -d "${i}" --dport 53 -j ACCEPT
+    iptables -w -A vpnclient_out -p udp -d "${i}" --dport 53 -j ACCEPT
   fi
 done
 
-sudo iptables -w -A vpnclient_out -d 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16 -j ACCEPT
-sudo iptables -w -A vpnclient_out -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
-sudo iptables -w -A vpnclient_out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-sudo iptables -w -A vpnclient_out -j DROP
+iptables -w -A vpnclient_out -d 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16 -j ACCEPT
+iptables -w -A vpnclient_out -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
+iptables -w -A vpnclient_out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+iptables -w -A vpnclient_out -j DROP
 
-sudo iptables -w -A vpnclient_fwd -j DROP
+iptables -w -A vpnclient_fwd -j DROP
 
-sudo iptables -w -I INPUT 1 -i <TPL:WIRED_DEVICE> -j vpnclient_in
-sudo iptables -w -I OUTPUT 1 -o <TPL:WIRED_DEVICE> -j vpnclient_out
-sudo iptables -w -I FORWARD 1 -o  <TPL:WIRED_DEVICE> -j vpnclient_fwd
+iptables -w -I INPUT 1 -i $interface -j vpnclient_in
+iptables -w -I OUTPUT 1 -o $interface -j vpnclient_out
+iptables -w -I FORWARD 1 -o  $interface -j vpnclient_fwd
 
 exit 0

+ 0 - 20
conf/ipv6_compressed

@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# VPN Client app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/vpnclient_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
-
-# VPN Client app for YunoHost 
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/vpnclient_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 - 49
conf/nginx.conf

@@ -1,49 +0,0 @@
-# VPN Client app for YunoHost
-# Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-# Contribute at https://github.com/labriqueinternet/vpnclient_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;
-  }
-
-  # Common parameter to increase upload size limit in conjunction with dedicated php-fpm file
-  client_max_body_size 10G;
-
-  index index.php;
-
-  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;
-}

+ 9 - 9
conf/openvpn_client.conf.tpl

@@ -1,12 +1,12 @@
 # [WARN] Edit this raw configuration ONLY IF YOU KNOW 
 #        what you do!
-# [WARN] Continue to use the placeholders <TPL:*> and
+# [WARN] Continue to use the placeholders and
 #        keep update their value on the web admin (they 
 #        are not only used for this file).
 
-remote <TPL:SERVER_NAME>
-proto <TPL:PROTO>
-port <TPL:SERVER_PORT>
+remote __SERVER_NAME__
+proto __SERVER_PROTO__
+port __SERVER_PORT__
 
 pull
 nobind
@@ -17,19 +17,19 @@ comp-lzo adaptive
 resolv-retry infinite
 
 # Authentication by login
-<TPL:LOGIN_COMMENT>auth-user-pass /etc/openvpn/keys/credentials
+__LOGIN_COMMENT__auth-user-pass /etc/openvpn/keys/credentials
 
 # UDP only
-<TPL:UDP_COMMENT>explicit-exit-notify
+__UDP_COMMENT__explicit-exit-notify
 
 # TLS
 tls-client
-<TPL:TA_COMMENT>tls-auth /etc/openvpn/keys/user_ta.key 1
+__TA_COMMENT__tls-auth /etc/openvpn/keys/user_ta.key 1
 remote-cert-tls server
 ns-cert-type server
 ca /etc/openvpn/keys/ca-server.crt
-<TPL:CERT_COMMENT>cert /etc/openvpn/keys/user.crt
-<TPL:CERT_COMMENT>key /etc/openvpn/keys/user.key
+__CERT_COMMENT__cert /etc/openvpn/keys/user.crt
+__CERT_COMMENT__key /etc/openvpn/keys/user.key
 
 # Logs
 verb 3

+ 0 - 202
conf/php-fpm.conf

@@ -1,202 +0,0 @@
-; VPN Client app for YunoHost
-; Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-; Contribute at https://github.com/labriqueinternet/vpnclient_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/>.
-
-; Start a new pool named 'www'.
-; the variable $pool can we used in any directive and will be replaced by the
-; pool name ('www' here)
-[__NAMETOCHANGE__]
-
-; 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 address on
-;                            a specific port;
-;   'port'                 - to listen on a TCP socket to all addresses 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 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 0666
-listen.owner = www-data
-listen.group = www-data
-listen.mode = 0600
-
-; 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__
-
-; 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:
-;             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.
-; 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 to be created when pm is set to 'dynamic'.
-; 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.
-; Note: Used when pm is set to either 'static' or 'dynamic'
-; Note: This value is mandatory.
-pm.max_children = 6
-
-; 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 = 3
-
-; 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 = 3
-
-; 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 = 5
-
-; 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. By default, the status page shows the following
-; information:
-;   accepted conn        - the number of request accepted by the pool;
-;   pool                 - the name of the pool;
-;   process manager      - static or dynamic;
-;   idle processes       - the number of idle processes;
-;   active processes     - the number of active processes;
-;   total processes      - the number of idle + active processes.
-;   max children reached - number of times, the process limit has been reached,
-;                          when pm tries to start more children (works only for
-;                          pm 'dynamic')
-; The values of 'idle processes', 'active processes' and 'total processes' are
-; updated each second. The value of 'accepted conn' is updated in real time.
-; Example output:
-;   accepted conn:        12073
-;   pool:                 www
-;   process manager:      static
-;   idle processes:       35
-;   active processes:     65
-;   total processes:      100
-;   max children reached: 1
-; By default the status page output is formatted as text/plain. Passing either
-; 'html' or 'json' as a 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
-; 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 = /fpm-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
-
-; 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 = 600s
-
-; 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 log file for slow requests
-; Default Value: not set
-; Note: slowlog is mandatory if request_slowlog_timeout is set
-slowlog = /var/log/nginx/[__NAMETOCHANGE__].slow.log
-
-; Set open file descriptor rlimit.
-; Default Value: system defined value
-rlimit_files = 4096
-
-; Set max core size rlimit.
-; Possible Values: 'unlimited' or an integer greater or equal to 0
-; Default Value: system defined value
-rlimit_core = 0
-
-; 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 = no
-
-; 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)
-
-php_value[max_execution_time] = 600
-php_value[upload_max_filesize] = 10G
-php_value[post_max_size] = 10G

+ 0 - 13
conf/sudoers.conf

@@ -1,13 +0,0 @@
-Cmnd_Alias VPNCLIENTTASKS = /bin/systemctl stop ynh-vpnclient, \
-                            /bin/systemctl start ynh-vpnclient, \
-                            /usr/local/bin/ynh-vpnclient *
-
-Cmnd_Alias YUNOHOST = /usr/bin/yunohost app setting vpnclient *,\
-                      /usr/bin/yunohost app info hotspot *
-
-Cmnd_Alias HOTSPOT = /bin/systemctl stop ynh-hotspot,\
-                     /bin/systemctl start ynh-hotspot,\
-                     /usr/bin/yunohost app setting hotspot *
-
-__VPNCLIENT_SYSUSER__ ALL = NOPASSWD: /bin/grep, VPNCLIENTTASKS, YUNOHOST, HOTSPOT
-

+ 84 - 105
conf/ynh-vpnclient

@@ -57,15 +57,15 @@ function critical()
 ###################################################################################
 
 has_nativeip6() {
-  ip -6 route | grep -q default\ via
+  ip -6 route | grep -q "default via"
 }
 
 has_ip6delegatedprefix() {
-  [ "${ynh_ip6_addr}" != none ]
+  [ "${ynh_ip6_addr}" != none ] && [ "${ynh_ip6_addr}" != "" ]
 }
 
 is_ip6addr_set() {
-  ip address show dev tun0 2> /dev/null | grep -q "${ynh_ip6_addr}/128"
+  ip address show dev tun0 2> /dev/null | grep -q "${ynh_ip6_addr}/"
 }
 
 set_ip6addr() {
@@ -83,32 +83,41 @@ unset_ip6addr() {
 #
 
 is_serverip6route_set() {
-  server_ip6=${1}
+  server_ip6s=${1}
 
   if [ -z "${server_ip6}" ]; then
     false
   else
-    ip -6 route | grep -q "${server_ip6}/"
+    for server_ip6 in ${server_ip6s};
+    do
+        ip -6 route | grep -q "${server_ip6}/" || return 1
+    done
   fi
 }
 
 set_serverip6route() {
-  server_ip6=${1}
+  server_ip6s=${1}
   ip6_gw=${2}
   wired_device=${3}
 
   info "Adding IPv6 server route"
-  ip route add "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
+    for server_ip6 in ${server_ip6s};
+    do
+        ip route add "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
+    done
 }
 
 
 unset_serverip6route() {
-  server_ip6=${1}
+  server_ip6s=${1}
   ip6_gw=${2}
   wired_device=${3}
 
   info "Removing IPv6 server route"
-  ip route delete "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
+    for server_ip6 in ${server_ip6s};
+    do
+        ip route delete "${server_ip6}/128" via "${ip6_gw}" dev "${wired_device}"
+    done
 }
 
 
@@ -131,41 +140,45 @@ is_hotspot_knowme() {
 ###################################################################################
 
 is_dns_set() {
-  # FIXME : having the ynh_dns0 in the resolv.dnsmasq.conf is not necessarily good enough
-  # We want it to be the only one (with ynh_dns1) but nowadays for example ARN's resolver is
-  # in the default list from yunohost...
-  [ -e /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient ]\
-  && ( grep -q ${ynh_dns0} /etc/resolv.conf || grep -q ${ynh_dns0} /etc/resolv.dnsmasq.conf )
+  if [[ "$ynh_dns_method" == "custom" ]]
+  then
+  
+    current_dns=$(grep -o -P '\s*nameserver\s+\K[abcdefabcdef\d.:]+' /etc/resolv.dnsmasq.conf | sort | uniq)
+    wanted_dns=$(echo "${ynh_dns}" | sed 's/,/\n/g'  | sort | uniq)
+    [ -e /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient ]\
+    && [[ "$current_dns" == "$wanted_dns" ]]
+  else
+    true
+  fi
 }
 
 set_dns() {
   info "Enforcing custom DNS resolvers from vpnclient"
 
-  resolvconf=/etc/resolv.conf
-  [ -e /etc/resolv.dnsmasq.conf ] && resolvconf=/etc/resolv.dnsmasq.conf
+  resolvconf=/etc/resolv.dnsmasq.conf
 
   cp -fa "${resolvconf}" "${resolvconf}.ynh"
-
-  cat << EOF > /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
-echo nameserver ${ynh_dns0} > ${resolvconf}
-echo nameserver ${ynh_dns1} >> ${resolvconf}
+  if [[ "$ynh_dns_method" == "custom" ]]
+  then
+    cat << EOF > /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
+echo "${ynh_dns}" | sed 's/,/\n/g' | sort | uniq | sed 's/^/nameserver /g' > ${resolvconf}
 EOF
+    bash /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
+  fi
 
-  bash /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
 }
 
 unset_dns() {
-  resolvconf=/etc/resolv.conf
-  [ -e /etc/resolv.dnsmasq.conf ] && resolvconf=/etc/resolv.dnsmasq.conf
+  resolvconf=/etc/resolv.dnsmasq.conf
 
   info "Removing custom DNS resolvers from vpnclient"
   rm -f /etc/dhcp/dhclient-exit-hooks.d/ynh-vpnclient
-  mv "${resolvconf}.ynh" "${resolvconf}"
+  [ -e "${resolvconf}.ynh" ] && mv "${resolvconf}.ynh" "${resolvconf}"
 
   # FIXME : this situation happened to a user ...
   # We could try to force regen the dns conf 
   # (though for now it's tightly coupled to dnsmasq)
-  grep -q "^nameserver" "${resolvconf}" || error "${resolvconf} does not have any nameserver line !?"
+  grep -q "^nameserver\s" "${resolvconf}" || error "${resolvconf} does not have any nameserver line !?"
 }
 
 ###################################################################################
@@ -173,7 +186,7 @@ unset_dns() {
 ###################################################################################
 
 is_firewall_set() {
-  wired_device=${1}
+  wired_device=$(ip route | awk '/default via/ { print $5; }')
 
   ip6tables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}"\
   && iptables -w -nvL OUTPUT | grep vpnclient_out | grep -q "${wired_device}"
@@ -182,26 +195,17 @@ is_firewall_set() {
 set_firewall() {
   info "Adding vpnclient custom rules to the firewall"
 
-  wired_device=${1}
-
   cp /etc/yunohost/hooks.d/{90-vpnclient.tpl,post_iptable_rules/90-vpnclient}
 
-  sed "s|<TPL:SERVER_NAME>|${ynh_server_name}|g" -i /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
-  sed "s|<TPL:SERVER_PORT>|${ynh_server_port}|g" -i /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
-  sed "s|<TPL:PROTO>|${ynh_server_proto}|g" -i /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
-  sed "s|<TPL:WIRED_DEVICE>|${wired_device}|g" -i /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
-  sed "s|<TPL:DNS0>|${ynh_dns0}|g" -i /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
-  sed "s|<TPL:DNS1>|${ynh_dns1}|g" -i /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
-
   info "Restarting yunohost firewall..."
-  yunohost firewall reload && success "Firewall restarted!"
+  yunohost firewall reload >/dev/null && success "Firewall restarted!"
 }
 
 unset_firewall() {
   info "Cleaning vpnclient custom rules from the firewall"
   rm -f /etc/yunohost/hooks.d/post_iptable_rules/90-vpnclient
   info "Restarting yunohost firewall..."
-  yunohost firewall reload && success "Firewall restarted!"
+  yunohost firewall reload >/dev/null && success "Firewall restarted!"
 }
 
 ###################################################################################
@@ -217,9 +221,9 @@ sync_time() {
   # Try to get the date with an http request on the internetcube web site
   if [ $? -ne 0 ]; then
     info "ntp synchronization failed, falling back to curl method"
-    http_date=`curl -sD - labriqueinter.net | grep '^Date:' | cut -d' ' -f3-6`
-    http_date_seconds=`date -d "${http_date}" +%s`
-    curr_date_seconds=`date +%s`
+    http_date=$(curl --max-time 5 -sD - labriqueinter.net | grep '^Date:' | cut -d' ' -f3-6)
+    http_date_seconds=$(date -d "${http_date}" +%s)
+    curr_date_seconds=$(date +%s)
 
     # Set the new date if it's greater than the current date
     # So it does if 1970 year or if old fake-hwclock date is used
@@ -240,63 +244,20 @@ is_openvpn_running() {
 
 start_openvpn() {
 
-  ip6_gw=${1}
-  server_ip6=${2}
-
-  if [ ! -z "${ip6_gw}" -a ! -z "${server_ip6}" ]; then
-    proto=udp6
-    [ "${ynh_server_proto}" == tcp ] && proto=tcp6-client
-  else
-    proto=udp
-    [ "${ynh_server_proto}" == tcp ] && proto=tcp-client
-  fi
-
   # Unset firewall to let DNS and NTP resolution works
   # Firewall is reset after vpn is mounted (more details on #1016)
   unset_firewall
 
   sync_time
 
-  info "Preparing openvpn configuration..."
-  cp /etc/openvpn/client.conf{.tpl,}
-
-  sed "s|<TPL:SERVER_NAME>|${ynh_server_name}|g" -i /etc/openvpn/client.conf
-  sed "s|<TPL:SERVER_PORT>|${ynh_server_port}|g" -i /etc/openvpn/client.conf
-  sed "s|<TPL:PROTO>|${proto}|g" -i /etc/openvpn/client.conf
-
-  if [ -e /etc/openvpn/keys/user.key ]; then
-    sed 's|^<TPL:CERT_COMMENT>||' -i /etc/openvpn/client.conf
-  else
-    sed 's|^<TPL:CERT_COMMENT>|;|' -i /etc/openvpn/client.conf
-  fi
-
-  if [ -e /etc/openvpn/keys/user_ta.key ]; then
-    sed 's|^<TPL:TA_COMMENT>||' -i /etc/openvpn/client.conf
-  else
-    sed 's|^<TPL:TA_COMMENT>|;|' -i /etc/openvpn/client.conf
-  fi
-
-  if [[ "${proto}" =~ udp ]]; then
-    sed 's|^<TPL:UDP_COMMENT>||' -i /etc/openvpn/client.conf
-  else
-    sed 's|^<TPL:UDP_COMMENT>|;|' -i /etc/openvpn/client.conf
-  fi
-
-  if [ -z "${ynh_login_user}" ]; then
-    sed 's|^<TPL:LOGIN_COMMENT>|;|' -i /etc/openvpn/client.conf
-  else
-    sed 's|^<TPL:LOGIN_COMMENT>||' -i /etc/openvpn/client.conf
-  fi
-
   info "Now actually starting OpenVPN client..."
-  systemctl start openvpn@client.service
 
-  if [ ! $? -eq 0 ]
+  if systemctl start openvpn@client.service
   then
+    info "OpenVPN client started ... waiting for tun0 interface to show up"
+  else
     tail -n 20 /var/log/openvpn-client.log | tee -a $LOGFILE
 	critical "Failed to start OpenVPN :/"
-  else
-    info "OpenVPN client started ... waiting for tun0 interface to show up"
   fi
 
   for attempt in $(seq 0 20)
@@ -339,6 +300,7 @@ ynh_setting_get() {
   setting=${2}
 
   grep "^${setting}:" "/etc/yunohost/apps/${app}/settings.yml" | sed s/^[^:]\\+:\\s*[\"\']\\?// | sed s/\\s*[\"\']\$//
+  # '"
 }
 
 ynh_setting_set() {
@@ -380,26 +342,24 @@ if [ "$1" != restart ]; then
   info "Retrieving Yunohost settings... "
 
   ynh_service_enabled=$(ynh_setting_get vpnclient service_enabled)
-  ynh_server_name=$(ynh_setting_get vpnclient server_name)
-  ynh_server_port=$(ynh_setting_get vpnclient server_port)
-  ynh_server_proto=$(ynh_setting_get vpnclient server_proto)
   ynh_ip6_addr=$(ynh_setting_get vpnclient ip6_addr)
-  ynh_login_user=$(ynh_setting_get vpnclient login_user)
-  ynh_dns0=$(ynh_setting_get vpnclient dns0)
-  ynh_dns1=$(ynh_setting_get vpnclient dns1)
+  ynh_dns_method=$(ynh_setting_get vpnclient dns_method)
+  ynh_dns=$(ynh_setting_get vpnclient nameservers)
 
   old_ip6_gw=$(ynh_setting_get vpnclient ip6_gw)
   old_wired_device=$(ynh_setting_get vpnclient wired_device)
   old_server_ip6=$(ynh_setting_get vpnclient server_ip6)
 
-  new_ip6_gw=$(ip -6 route | grep default\ via | awk '{ print $3 }')
-  new_wired_device=$(ip route | awk '/default via/ { print $NF; }')
-  new_server_ip6=$(host "${ynh_server_name}" 2> /dev/null | awk '/IPv6/ { print $NF; }')
+  new_ip6_gw=$(ip -6 route | awk '/default via/ { print $3 }')
+  new_wired_device=$(ip route | awk '/default via/ { print $5; }')
+  ynh_server_names=$(grep -o -P '^\s*remote\s+\K([^\s]+)' /etc/openvpn/client.conf | sort | uniq)
+  new_server_ip6=$(dig AAAA +short $ynh_server_names @127.0.0.1 | grep -v '\.$' | grep -v "timed out" | sort | uniq)
 
-  if [ -z "${new_server_ip6}" ]; then
-    # FIXME wtf is this hardcoded IP ...
-    new_server_ip6=$(host "${ynh_server_name}" 80.67.188.188 2> /dev/null | awk '/IPv6/ { print $NF; }')
-  fi
+  for i in $ynh_server_names; do
+    if [[ "${i}" =~ : ]] && [[ ! "$new_server_ip6" == *"${i}"* ]] ; then
+        new_server_ip6+=" ${i}"
+    fi
+  done
 
   success "Settings retrieved"
 
@@ -425,6 +385,11 @@ case "${1}" in
       exit 0
     fi
 
+    if [ ! -e /etc/openvpn/keys/user.crt ] || ! cat /etc/openvpn/keys/user.crt | openssl x509 -noout -checkend 0 >/dev/null
+    then
+        critical "Failed to start OpenVPN client : user certificate expired"
+    fi
+
     info "[vpnclient] Starting..."
     touch /tmp/.ynh-vpnclient-started
 
@@ -433,7 +398,7 @@ case "${1}" in
     then
       info "(openvpn is already running)"
     else
-      start_openvpn "${new_ip6_gw}" "${new_server_ip6}"
+      start_openvpn
     fi
 
     # Check old state of the server ipv6 route
@@ -464,9 +429,9 @@ case "${1}" in
     fi
 
     # Set ipv6/ipv4 firewall
-    if ! is_firewall_set "${new_wired_device}"
+    if ! is_firewall_set
     then
-      set_firewall "${new_wired_device}"
+      set_firewall
     fi
 
     # Update dynamic settings
@@ -481,7 +446,21 @@ case "${1}" in
       ynh-hotspot start
     fi
 
-    success "YunoHost VPN client started!"
+    ping -c1 -w5 debian.org >/dev/null
+
+    ipv4=$(ping -w3 -c1 ip.yunohost.org  >/dev/null 2>&1 && curl --max-time 5 https://ip.yunohost.org --silent)
+    ipv6=$(ping -w3 -c1 ip6.yunohost.org >/dev/null 2>&1 && curl --max-time 5 https://ip6.yunohost.org --silent)
+
+    info "Validating that VPN is up and the server is connected to internet..."
+    if ip route get 1.2.3.4 | grep -q tun0; then
+        if ping -c1 -w5 debian.org >/dev/null; then
+            success "YunoHost VPN client started!"
+        else
+            critical "The VPN is up but debian.org cannot be reached, indicating that something is probably misconfigured/blocked."
+        fi
+    else
+        critical "IPv4 routes are misconfigured !?"
+    fi
   ;;
 
   # ########## #
@@ -500,7 +479,7 @@ case "${1}" in
       unset_serverip6route "${old_server_ip6}" "${old_ip6_gw}" "${old_wired_device}"
     fi
 
-    is_firewall_set "${old_wired_device}" && unset_firewall
+    is_firewall_set && unset_firewall
 
     is_dns_set && unset_dns
 
@@ -573,7 +552,7 @@ case "${1}" in
       info "No IPv6 server route to set"
     fi
 
-    if is_firewall_set "${new_wired_device}"; then
+    if is_firewall_set; then
       success "IPv6/IPv4 firewall set"
     else
       info "No IPv6/IPv4 firewall set"

+ 1 - 70
conf/ynh-vpnclient-loadcubefile.sh

@@ -50,79 +50,10 @@ while getopts "u:p:c:h" opt; do
   esac
 done
 
-if [ -z "${ynh_user}" ]; then
-  echo "[ERR] Option -u is mandatory (-h for help)" >&2
-  exit 1
-fi
-
-if [ -z "${ynh_password}" ]; then
-  echo "[ERR] Option -p is mandatory (-h for help)" >&2
-  exit 1
-fi
-
 if [ -z "${cubefile_path}" ]; then
   echo "[ERR] Option -c is mandatory (-h for help)" >&2
   exit 1
 fi
 
 
-# Other variables
-
-ynh_setting() {
-  app=${1}
-  setting=${2}
-
-  sudo grep "^${setting}:" "/etc/yunohost/apps/${app}/settings.yml" | sed s/^[^:]\\+:\\s*[\"\']\\?// | sed s/\\s*[\"\']\$//
-}
-
-tmpdir=$(mktemp -dp /tmp/ vpnclient-loadcubefile-XXXXX)
-
-cubefile_ip6=$(sed -n '/ip6_net/ { s/.*"\([0-9a-zA-Z:]\+\)".*/\1/p }' "${cubefile_path}")
-
-ynh_domain=$(ynh_setting vpnclient domain)
-ynh_path=$(ynh_setting vpnclient path)
-ynh_service_enabled=$(ynh_setting vpnclient service_enabled)
-
-
-# SSO login
-
-curl -D - -skLe "https://${ynh_domain}/yunohost/sso/" --data-urlencode "user=${ynh_user}" --data-urlencode "password=${ynh_password}" "https://${ynh_domain}/yunohost/sso/" --resolve "${ynh_domain}:443:127.0.0.1" -o /dev/null -c "${tmpdir}/cookies" 2> /dev/null | grep -q "set-cookie: SSOwAuthUser=${ynh_user}"
-
-if [ $? -ne 0 ]; then
-  echo "[ERROR] SSO login failed" >&2
-  exit 1
-fi
-
-
-# Upload cube file
-
-output=$(curl -kL -H "X-Requested-With: yunohost-config" -F "service_enabled=${ynh_service_enabled}" -F _method=put -F "cubefile=@${cubefile_path}" "https://${ynh_domain}/${ynh_path}/?/settings" --resolve "${ynh_domain}:443:127.0.0.1" -b "${tmpdir}/cookies" 2> /dev/null | grep RETURN_MSG | sed 's/<!-- RETURN_MSG -->//' | sed 's/<\/?[^>]\+>//g' | sed 's/^ \+//g')
-
-
-# Configure IPv6 Delegated Prefix on Hotspot
-
-if [ ! -z "${cubefile_ip6}" ] && (sudo yunohost app info hotspot | grep -q Hotspot); then
-  ynh_multissid=$(ynh_setting hotspot multissid)
-
-  if [ "${ynh_multissid}" -eq 1 ]; then
-    ynh_ip6_net=$(ynh_setting vpnclient ip6_net)
-    ynh_ip6_addr=$(ynh_setting vpnclient ip6_addr)
-
-    sudo systemctl stop ynh-hotspot &> /dev/null
-    sudo yunohost app setting hotspot ip6_net -v "${ynh_ip6_net}"
-    sudo yunohost app setting hotspot ip6_addr -v "${ynh_ip6_addr}"
-    sudo systemctl start ynh-hotspot &> /dev/null
-
-    echo "[INFO] Wifi Hotspot found with only one SSID: IPv6 Delegated Prefix automatically configured" >&2
-  fi
-fi
-
-
-# Done!
-
-echo [VPN] $output
-(echo $output | grep -q Error) && exit 1
-
-rm -r "${tmpdir}/"
-
-exit 0
+sudo yunohost app config set vpnclient --args "config_file=${cubefile_path}"

+ 115 - 0
config_panel.toml

@@ -0,0 +1,115 @@
+version = "1.0"
+
+[main]
+name = "Auto-configuration"
+
+    [main.vpn]
+    name = ""
+    optional = false
+        
+        [main.vpn.status]
+        ask = "The status of your VPN is unknown."
+        type = "alert"
+        style = "info"
+        
+        [main.vpn.service_enabled]
+        ask = "Enable VPN"
+        type = "boolean"
+        help = "If disabled, the VPN service will not automatically be started at boot."
+        
+        [main.vpn.doc]
+        ask.en = "VPNclient only interfaces with *dedicated, public IP VPNs accepting inbound traffic*, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info."
+        ask.fr = "VPNclient est prévu pour fonctionner avec des *VPN dédiés et à IP publique qui acceptent le traffic entrant*, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos."
+        type = "alert"
+        style = "info"
+
+        [main.vpn.config_file]
+        ask = "Configuration file"
+        type = "file"
+        accept = ".cube, .ovpn, .conf"
+        help = ".cube file recommended, .ovpn file accepted"
+        bind = "/etc/openvpn/client.conf"
+        
+    [main.auth]
+    name = "Authentication"
+    optional = true
+    visible = 'config_file && ((match(config_file,"^\s*ca\s") && ! match(config_file,"^\s*<ca>")) || (match(config_file,"^\s*cert\s") && ! match(config_file,"^\s*<cert>")) || (match(config_file,"^\s*key\s") && ! match(config_file,"^\s*<key>")) || (match(config_file,"^\s*tls-auth\s") && ! match(config_file,"^\s*<tls-auth>")) || match(config_file,"^\s*auth-user-pass(\s.*)?$"))'
+
+        [main.auth.crt_server_ca]
+        ask = "Update Server CA"
+        type = "file"
+        bind = "/etc/openvpn/keys/ca-server.crt"
+        visible = 'config_file && match(config_file,"^\s*ca\s") && ! match(config_file,"^\s*<ca>")'
+        
+        [main.auth.crt_client]
+        ask = "Update Client Certificate"
+        type = "file"
+        bind = "/etc/openvpn/keys/user.crt"
+        visible = 'config_file && match(config_file,"^\s*cert\s") && ! match(config_file,"^\s*<cert>")'
+        
+        [main.auth.crt_client_key]
+        ask = "Update Client Key"
+        type = "file"
+        help = "This file begins with -----BEGIN PRIVATE KEY-----"
+        bind = "/etc/openvpn/keys/user.key"
+        visible = 'config_file && match(config_file,"^\s*key\s") && ! match(config_file,"^\s*<key>")'
+        
+        [main.auth.login_user]
+        ask = "Username"
+        type = "string"
+        example = "camille"
+        pattern.regexp = '^[a-zA-Z_\-\\\.@]+$'
+        pattern.error = "OpenVPN accept only alphabetic chars and -_\\.@"
+        visible = 'config_file && match(config_file,"^\s*auth-user-pass\s")'
+        
+        [main.auth.login_passphrase]
+        ask = "Password"
+        type = "password"
+        visible = 'config_file && match(config_file,"^\s*auth-user-pass(\s.*)?$")'
+        
+        [main.auth.crt_client_ta]
+        ask = "TLS Auth shared secret"
+        type = "file"
+        example = "ta.key"
+        help = "Some servers have an additional protection agains Deny of Service attack. If you have no tls-auth key in your ovpn, skip this question."
+        bind = "/etc/openvpn/keys/user_ta.key"
+        visible = 'config_file && match(config_file,"^\s*tls-auth\s") && ! match(config_file,"^\s*<tls-auth>")'
+        
+[advanced]
+name = "DNS & IPv6"
+    [advanced.dns]
+    name = "DNS"
+
+        [advanced.dns.dns_method]
+        ask = "DNS resolvers"
+        type = "select"
+        choices.yunohost = "Default DNS resolvers from YunoHost"
+        choices.custom = "Use custom DNS resolvers"
+
+        [advanced.dns.nameservers]
+        ask = "Custom DNS resolvers"
+        type = "tags"
+        optional = true
+        visible = "dns_method == 'custom'"
+        pattern.regexp = "^([0-9.]{7,15}|[0-9a-fA-F:]+)$"
+        pattern.error = "Not an ip"
+        
+    [advanced.ipv6]
+    name = "IPv6"
+
+        [advanced.ipv6.ip6_net]
+        ask = "IPv6 prefix"
+        type = "string"
+        optional = true
+        example = "2001:db8:42::"
+        pattern.regexp = "^[0-9a-fA-F:]+$"
+        pattern.error = "Please provide a valid IPv6 Prefix"
+        
+        [advanced.ipv6.ip6_addr]
+        ask = "IPv6"
+        type = "string"
+        optional = true
+        example = "2001:db8:42::2"
+        help = "If no IPv6 address is pushed directly by your VPN provider, you can indicate a specific IP to use here."
+        pattern.regexp = "^[0-9a-fA-F:]+$"
+        pattern.error = "Please provide a valid IPv6"

+ 7 - 0
doc/DESCRIPTION.md

@@ -0,0 +1,7 @@
+* Install a VPN connection on your self-hosted server.
+* Useful for hosting your server behind a filtered (and/or non-neutral) internet access.
+* Useful to have static IP addresses (IPv6 and IPv4).
+* Useful to easily move your server anywhere.
+* Strong firewalling (internet access and self-hosted services only available through the VPN, not leaking to your commercial ISP)
+* Combine with the [Hotspot app](https://github.com/YunoHost-Apps/hotspot_ynh) to broadcast VPN-protected WiFi to other laptops without any further technical configuration needed.
+

+ 7 - 0
doc/DESCRIPTION_fr.md

@@ -0,0 +1,7 @@
+* Installez une connexion VPN sur votre serveur auto-hébergé
+* Utile pour héberger votre serveur derrière un accès internet filtré (et/ou non-neutre)
+* Utile pour obtenir une IP statique (v4 et v6)
+* Utile pour pouvoir facilement déplacer votre serveur
+* Pare-feu strict (le traffice entrant et sortant se fait seulement via le pare-feu et ne fuite pas de données à votre FAI commercial)
+* Peut-être combiné avec [l'application Hotspot](https://github.com/YunoHost-Apps/hotspot_ynh) pour diffuser un WiFi protégé par le VPN à d'autres laptop sans configuration technique requise sur les machines clientes.
+

+ 1 - 0
doc/DISCLAIMER.md

@@ -0,0 +1 @@
+Please note that this application is designed to interface with **dedicated, public IP VPNs accepting inbound traffic**, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. **Do not** expect that any VPN you randomly bought on the Internet can be used! Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.

+ 1 - 0
doc/DISCLAIMER_fr.md

@@ -0,0 +1 @@
+Notez que cette application est prévue pour fonctionner avec des **VPN dédiés et à IP publique qui acceptent le traffic entrant**, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Un VPN acheté au hasard sur Internet ne fonctionnera sans doute pas ! Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos.

BIN
doc/screenshots/vpnclient.png


+ 21 - 25
manifest.json

@@ -6,7 +6,7 @@
     "en": "Tunnel the internet traffic through a VPN",
     "fr": "Fait passer le trafic internet à travers un VPN"
   },
-  "version": "1.4.1~ynh3",
+  "version": "2.0~ynh1",
   "url": "https://labriqueinter.net",
   "license": "AGPL-3.0",
   "maintainer": {
@@ -15,33 +15,29 @@
   },
   "multi_instance": false,
   "requirements": {
-    "yunohost": ">= 4.0"
+    "yunohost": ">= 4.3.2"
   },
-  "services": [
-    "nginx",
-    "php7.0-fpm"
-  ],
+  "services": [],
   "arguments": {
-    "install": [
-      {
-        "name": "domain",
-        "type": "domain",
-        "ask": {
-          "en": "Choose a domain for the web administration",
-          "fr": "Choisissez un domaine pour l'administration web"
+      "install": [
+          {
+            "name": "disclaimer1",
+            "type": "display_text",
+            "style": "warning",
+            "ask": {
+                "en": "Please note that this application only interfaces with **dedicated, public IP VPNs accepting inbound traffic**, preferably with an associated `.cube` (or `.ovpn/.conf`) configuration file. **Do not** expect that any VPN you randomly bought on the Internet can be used! Checkout the [list of known compatible providers](https://yunohost.org/providers/vpn) for more info.",
+                "fr": "Notez que cette application est prévue pour fonctionner avec des **VPN dédiés et à IP publique qui acceptent le traffic entrant**, et de préférence avec un fichier de configuration `.cube` (ou `.ovpn/.conf`) associé. Un VPN acheté au hasard sur Internet ne fonctionnera sans doute pas ! Consultez [la liste des fournisseurs connus et compatibles](https://yunohost.org/providers/vpn) pour plus d'infos."
+            }
         },
-        "example": "domain.org"
-      },
-      {
-        "name": "path",
-        "type": "path",
-        "ask": {
-          "en": "Choose a path for the web administration",
-          "fr": "Choisissez un chemin pour l'administration web"
-        },
-        "example": "/vpnadmin",
-        "default": "/vpnadmin"
-      }
+        {
+            "name": "disclaimer2",
+            "type": "display_text",
+            "style": "info",
+            "ask": {
+                "en": "After installation, you will be able to configure the application from YunoHost's webadmin in Applications > VPNclient > Configuration.",
+                "fr": "Après l'application, vous pourrez configurer l'application depuis la webadmin de YunoHost dans Applications > VPNclient > Configuration."
+            }
+        }
     ]
   }
 }

+ 1 - 40
scripts/_common.sh

@@ -3,8 +3,6 @@
 # Common variables and helpers
 #
 
-YNH_PHP_VERSION="7.3"
-
 pkg_dependencies="sipcalc dnsutils openvpn curl fake-hwclock"
 
 service_name="ynh-vpnclient"
@@ -20,60 +18,23 @@ function vpnclient_deploy_files_and_services()
     ynh_system_user_create ${app}
   fi
 
-  # Ensure the system user has enough permissions
-  install -b -o root -g root -m 0440 ../conf/sudoers.conf /etc/sudoers.d/${app}_ynh
-  ynh_replace_string "__VPNCLIENT_SYSUSER__" "${app}" /etc/sudoers.d/${app}_ynh
-
-  # Install IPv6 scripts
-  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/
-
   # Install command-line cube file loader
   install -o root -g root -m 0755 ../conf/$service_name-loadcubefile.sh /usr/local/bin/
 
   # Copy confs
-  mkdir -pm 0755 /var/log/nginx/
   chown root:${app} /etc/openvpn/
   chmod 775 /etc/openvpn/
   mkdir -pm 0755 /etc/yunohost/hooks.d/post_iptable_rules/
 
-  install -b -o root -g ${app} -m 0664 ../conf/openvpn_client.conf.tpl /etc/openvpn/client.conf.tpl
-  install -o root -g root -m 0644 ../conf/openvpn_client.conf.tpl /etc/openvpn/client.conf.tpl.restore
+  install -b -o root -g ${app} -m 0644 ../conf/openvpn_client.conf.tpl /etc/openvpn/client.conf.tpl
   install -b -o root -g root -m 0755 ../conf/hook_post-iptable-rules /etc/yunohost/hooks.d/90-vpnclient.tpl
   install -b -o root -g root -m 0644 ../conf/openvpn@.service /etc/systemd/system/
 
-  # Copy web sources
-  mkdir -pm 0755 /var/www/${app}/
-  cp -a ../sources/* /var/www/${app}/
-
-  chown -R root: /var/www/${app}/
-  chmod -R 0644 /var/www/${app}/*
-  find /var/www/${app}/ -type d -exec chmod +x {} \;
-
   # Create certificates directory
   mkdir -pm 0770 /etc/openvpn/keys/
   chown root:${app} /etc/openvpn/keys/
 
   #=================================================
-  # NGINX CONFIGURATION
-  #=================================================
-  ynh_print_info "Configuring nginx web server..."
-
-  ynh_add_nginx_config
-
-  #=================================================
-  # PHP-FPM CONFIGURATION
-  #=================================================
-  ynh_print_info "Configuring PHP-FPM..."
-
-  # Create a dedicated PHP-FPM config
-  ynh_add_fpm_config --phpversion=$YNH_PHP_VERSION
-  phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
-
-  #=================================================
-
-  # Fix sources
-  ynh_replace_string "__PATH__" "${path_url%%/}" "/var/www/${app}/config.php"
 
   # Copy init script
   install -o root -g root -m 0755 ../conf/$service_name /usr/local/bin/

+ 0 - 25
scripts/backup

@@ -23,10 +23,6 @@ ynh_print_info "Loading installation settings..."
 
 app=$YNH_APP_INSTANCE_NAME
 
-final_path=$(ynh_app_setting_get $app final_path)
-domain=$(ynh_app_setting_get $app domain)
-phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
-
 #=================================================
 # STANDARD BACKUP STEPS
 #=================================================
@@ -34,38 +30,17 @@ phpversion=$(ynh_app_setting_get --app=$app --key=phpversion)
 #=================================================
 ynh_print_info "Backing up the main app directory..."
 
-ynh_backup "$final_path"
-
-ynh_backup "/etc/sudoers.d/${app}_ynh"
-
-ynh_backup "/usr/local/bin/ipv6_expanded"
-ynh_backup "/usr/local/bin/ipv6_compressed"
 ynh_backup "/usr/local/bin/$service_name-loadcubefile.sh"
 
 ynh_backup "/etc/yunohost/hooks.d/90-vpnclient.tpl"
 
 ynh_backup "/etc/openvpn/client.conf.tpl"
-ynh_backup "/etc/openvpn/client.conf.tpl.restore"
 ynh_backup "/etc/openvpn/keys/"
 
 ynh_backup "/usr/local/bin/$service_name"
 ynh_backup "/usr/local/bin/$service_checker_name.sh"
 
 #=================================================
-# BACKUP THE NGINX CONFIGURATION
-#=================================================
-ynh_print_info "Backing up NGINX web server configuration..."
-
-ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf"
-
-#=================================================
-# BACKUP THE PHP-FPM CONFIGURATION
-#=================================================
-ynh_print_info "Backing up PHP-FPM configuration..."
-
-ynh_backup "/etc/php/$phpversion/fpm/pool.d/$app.conf"
-
-#=================================================
 # SPECIFIC BACKUP
 #=================================================
 # BACKUP SYSTEMD

+ 363 - 0
scripts/config

@@ -0,0 +1,363 @@
+#!/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
+#=================================================
+
+set_permissions() {
+    local file="$1"
+    if [ -f $file ]
+    then
+        chown $app:$app $file
+        chmod go=--- $file
+    fi
+}
+
+#=================================================
+# SPECIFIC GETTERS FOR TOML SHORT KEY
+#=================================================
+
+BACKTICK='`'
+TRIPLEBACKTICKS='```'
+
+get__status() {
+    local service_enabled=$(ynh_app_setting_get $app service_enabled)
+
+    ipv4=$(ping -w3 -c1 ip.yunohost.org  >/dev/null 2>&1 && curl --max-time 5 https://ip.yunohost.org --silent)
+    ipv6=$(ping -w3 -c1 ip6.yunohost.org >/dev/null 2>&1 && curl --max-time 5 https://ip6.yunohost.org --silent)
+
+    if ip route get 1.2.3.4 | grep -q tun0 && [[ -n "$ipv4" ]]
+    then
+        if [ $service_enabled -eq 1 ]
+        then
+            cat << EOF
+style: success
+ask:
+  en: |-
+    The VPN is enabled and running ! :)
+
+    **IPv4:** $BACKTICK$ipv4$BACKTICK
+
+    **IPv6:** $BACKTICK$ipv6$BACKTICK
+EOF
+
+        else
+            cat << EOF
+style: warning
+ask:
+  en: The VPN is running, but it shouldn't !?
+EOF
+        fi
+    elif [ $service_enabled -eq 1 ]
+    then
+        cat << EOF
+style: danger
+ask:
+  en: |-
+    The VPN is down ! Here are errors logged in the last few minutes
+    $TRIPLEBACKTICKS
+$(journalctl -u ynh-vpnclient -o cat | sed 's/^/    /g' | tail -n 15)
+    $TRIPLEBACKTICKS
+EOF
+    else
+        cat << EOF
+style: info
+ask:
+  en: The VPN is not enabled
+EOF
+
+    fi
+}
+
+get__login_user() {
+    if [ -s /etc/openvpn/keys/credentials ]
+    then
+        echo "$(sed -n 1p /etc/openvpn/keys/credentials)"
+    else
+        echo ""
+    fi
+}
+
+get__login_passphrase() {
+    if [ -s /etc/openvpn/keys/credentials ]
+    then
+        echo "$(sed -n 2p /etc/openvpn/keys/credentials)"
+    else
+        echo ""
+    fi
+}
+
+
+#=================================================
+# SPECIFIC VALIDATORS FOR TOML SHORT KEYS
+#=================================================
+validate__login_user() {
+
+    if grep -q '^\s*auth-user-pass' ${config_file}
+    then
+        if [[ -z "${login_user}" ]]
+        then
+            echo 'A Username is needed with this configuration file'
+        fi
+    fi
+}
+
+validate__login_passphrase() {
+    if grep -q '^\s*auth-user-pass' ${config_file}
+    then
+        if [[ -z "${login_passphrase}" ]]
+        then
+            echo 'A Password is needed with this configuration file'
+        fi
+    fi
+}
+
+validate__crt_server_ca() {
+    if grep -q '^\s*ca\s' ${config_file}
+    then
+        if [[ ! -e "${crt_server_ca}" ]]
+        then
+            echo "A server CA certificate is needed"
+        fi
+    fi
+}
+
+validate__crt_client() {
+    if grep -q '^\s*cert\s' ${config_file}
+    then
+        if [[ ! -e "${crt_client}" ]]
+        then
+            echo "A Client certificate is needed with this configuration file"
+        fi
+    fi
+}
+
+validate__crt_client_key() {
+    if grep -q '^\s*key\s' ${config_file}
+    then
+        if [[ ! -e "${crt_client_key}" ]]
+        then
+            echo "A client private key is needed with this configuration file"
+        fi
+    fi
+}
+
+validate__crt_client_ta() {
+    if grep -q '^\s*tls-auth\s' ${config_file}
+    then
+        if [[ ! -e "${crt_client_ta}" ]]
+        then
+            echo "A TLS auth shared secret is needed with this configuration file"
+        fi
+    fi
+}
+
+validate__nameservers() {
+    if [[ "$dns_method" == "custom" ]] && [[ -z "$nameservers" ]]
+    then
+        echo "You need to choose DNS resolvers or select an other method to provide DNS resolvers"
+    fi
+}
+#=================================================
+# SPECIFIC SETTERS FOR TOML SHORT KEYS
+#=================================================
+set__login_user() {
+    if [ -n "${login_user}" ]
+    then
+        echo "${login_user}\n${login_passphrase}" > /etc/openvpn/keys/credentials
+        set_permissions /etc/openvpn/keys/credentials
+    else
+        echo "" > /etc/openvpn/keys/credentials
+    fi
+}
+
+set__login_passphrase() {
+    :
+}
+
+#=================================================
+# OVERWRITING VALIDATE STEP
+#=================================================
+read_cube() {
+    tmp_dir=$(dirname "$1")
+    setting_value="$(jq --raw-output ".$2" "$1")"
+    if [[ "$setting_value" == "null" ]]
+    then
+        setting_value=''
+    # Save file in tmp dir
+    elif [[ "$2" == "crt_"* ]]
+    then
+        if [ -n "${setting_value}" ]
+        then
+            echo "${setting_value}" | sed 's/|/\n/g' > $tmp_dir/$2
+            setting_value="$tmp_dir/$2"
+        fi
+    fi
+    echo $setting_value
+}
+ynh_app_config_validate() {
+    # At this moment this var is not already set with the old value
+    if [ -z ${config_file+x} ]
+    then
+        config_file="${old[config_file]}"
+
+    # Overwrite form response with cube files data before validation process
+
+    # We don't have the extension, so we use this ugly hack to check that this is a json-like
+    # (i.e. it starts with { ..)
+    elif [ -f "${config_file}" ] && [[ "$(cat ${config_file} | tr -d ' ' | grep -v "^$" | head -c1)" == "{" ]]
+    then
+        ynh_print_info --message="Transforming .cube into OVPN file"
+        server_name="$(read_cube $config_file server_name)"
+        server_port="$(read_cube $config_file server_port)"
+        server_proto="$(read_cube $config_file server_proto)"
+        ip6_net="$(read_cube $config_file ip6_net)"
+        ip6_addr="$(read_cube $config_file ip6_addr)"
+        login_user="$(read_cube $config_file login_user)"
+        login_passphrase="$(read_cube $config_file login_passphrase)"
+        dns0="$(read_cube $config_file dns0)"
+        dns1="$(read_cube $config_file dns1)"
+        crt_server_ca="$(read_cube $config_file crt_server_ca)"
+        crt_client="$(read_cube $config_file crt_client)"
+        crt_client_key="$(read_cube $config_file crt_client_key)"
+        crt_client_ta="$(read_cube $config_file crt_client_ta)"
+        dns_method="custom"
+        nameservers="$dns0,$dns1"
+
+        # Build specific OVPN template
+        tmp_dir=$(dirname "${config_file}")
+        cp -f /etc/openvpn/client.conf.tpl $tmp_dir/client.conf.tpl
+        # Remove some lines
+        for rm_regex in "$(jq --raw-output '.openvpn_rm[]' "${config_file}")"
+        do
+            if [ ! -z "${rm_regex}" ] ; then
+                sed -i "/$rm_regex/di" $tmp_dir/client.conf.tpl
+            fi
+        done
+
+        # Add some other lines
+        echo "# Custom additions from .cube" >> $tmp_dir/client.conf.tpl
+        jq --raw-output ".openvpn_add[]" "${config_file}" >> $tmp_dir/client.conf.tpl
+
+        # Temporarily tweak sever_proto for template hydratation
+        [ "$server_proto" == tcp ] && server_proto=tcp-client
+
+        # Define other needed vars for template hydratation
+        [ -e "$crt_client_key" ] && cert_comment="" || cert_comment="#"
+        [ -e "$crt_client_ta" ] && ta_comment="" || ta_comment="#"
+        [[ "$server_proto" =~ udp ]] && udp_comment="" || udp_comment="#"
+        [ -n "$login_user" ] && login_comment="" || login_comment="#"
+
+        # Actually generate/hydrate the final configuration
+        ynh_add_config --template="$tmp_dir/client.conf.tpl" --destination="${config_file}"
+
+        [ "$server_proto" == tcp-client ] && server_proto=tcp
+
+
+    # Othewise, assume that it's a .ovpn / .conf
+    elif [ -f "${config_file}" ]
+    then
+        tmp_dir=$(dirname "${config_file}")
+        ynh_print_info --message="Extracting TLS keys from .ovpn file"
+        if grep -q '^\s*<ca>' ${config_file}
+        then
+            grep -Poz '(?<=<ca>)(.*\n)*.*(?=</ca>)' ${config_file} | sed '/^$/d'  > $tmp_dir/crt_server_ca
+            crt_server_ca=$tmp_dir/crt_server_ca
+            sed -i '/^\s*<ca>/,/\s*<\/ca>/d' ${config_file}
+            sed -i '/^\s*ca\s/d' ${config_file}
+            echo "ca /etc/openvpn/keys/ca-server.crt" >> ${config_file}
+        fi
+        if grep -q '^\s*<cert>' ${config_file}
+        then
+            grep -Poz '(?<=<cert>)(.*\n)*.*(?=</cert>)' ${config_file} | sed '/^$/d'  > $tmp_dir/crt_client
+            crt_client=$tmp_dir/crt_client
+            sed -i '/^\s*<cert>/,/\s*<\/cert>/d' ${config_file}
+            sed -i '/^\s*cert\s/d' ${config_file}
+            echo "cert /etc/openvpn/keys/user.crt" >> ${config_file}
+        elif ! grep -q '^\s*cert\s' ${config_file}
+        then
+            crt_client=""
+        fi
+        if grep -q '^\s*<key>' ${config_file}
+        then
+            grep -Poz '(?<=<key>)(.*\n)*.*(?=</key>)' ${config_file} | sed '/^$/d' > $tmp_dir/crt_client_key
+            crt_client_key=$tmp_dir/crt_client_key
+            sed -i '/^\s*<key>/,/\s*<\/key>/d' ${config_file}
+            sed -i '/^\s*key\s/d' ${config_file}
+            echo "key /etc/openvpn/keys/user.key" >> ${config_file}
+        elif ! grep -q '^\s*key\s' ${config_file}
+        then
+            crt_client_key=""
+        fi
+        if grep -q '^\s*<tls-auth>' ${config_file}
+        then
+            grep -Poz '(?<=<tls-auth>)(.*\n)*.*(?=</tls-auth>)' ${config_file} | sed '/^$/d' > $tmp_dir/crt_client_ta
+            crt_client_ta=$tmp_dir/crt_client_ta
+            sed -i '/^\s*<tls-auth>/,/\s*<\/tls-auth>/d' ${config_file}
+            sed -i '/^\s*tls-auth\s/d' ${config_file}
+            echo "tls-auth /etc/openvpn/keys/user_ta.key 1" >> ${config_file}
+        elif ! grep -q '^\s*tls-auth\s' ${config_file}
+        then
+            crt_client_ta=""
+        fi
+        sed -i 's@^\s*ca\s.*$@ca /etc/openvpn/keys/ca-server.crt@g' ${config_file}
+        sed -i 's@^\s*cert\s.*$@cert /etc/openvpn/keys/user.crt@g' ${config_file}
+        sed -i 's@^\s*key\s.*$@key /etc/openvpn/keys/user.key@g' ${config_file}
+        sed -i 's@^\s*tls-auth\s.*$@tls-auth /etc/openvpn/keys/user-ta.key@g' ${config_file}
+    fi
+
+    # Currently we need root priviledge to create tun0
+    if [ -f "${config_file}" ]
+    then
+        sed -i '/^\s*user\s/d' ${config_file}
+        sed -i '/^\s*group\s/d' ${config_file}
+    fi
+
+    _ynh_app_config_validate
+}
+
+#=================================================
+# OVERWRITING APPLY STEP
+#=================================================
+ynh_app_config_apply() {
+
+    # Stop vpn client
+    ynh_print_info --message="Stopping vpnclient in order to edit files"
+    touch /tmp/.ynh-vpnclient-stopped
+    /usr/local/bin/ynh-vpnclient stop
+
+    chown $app:$app /etc/openvpn/keys
+    chmod go=--- /etc/openvpn/keys
+
+    _ynh_app_config_apply
+
+    set_permissions /etc/openvpn/client.conf
+    set_permissions /etc/openvpn/keys/ca-server.crt
+    set_permissions /etc/openvpn/keys/user.crt
+    set_permissions /etc/openvpn/keys/user.key
+    set_permissions /etc/openvpn/keys/user_ta.key
+
+    # Start vpn client
+    ynh_print_info --message="Starting vpnclient service if needed"
+    /usr/local/bin/ynh-vpnclient start
+    rm -f /tmp/.ynh-vpnclient-stopped
+
+}
+
+ynh_app_config_run $1

+ 6 - 16
scripts/install

@@ -38,29 +38,19 @@ ynh_abort_if_errors
 #=================================================
 
 # Retrieve arguments
-domain=$YNH_APP_ARG_DOMAIN
-path_url=$YNH_APP_ARG_PATH
 app=$YNH_APP_INSTANCE_NAME
-final_path="/var/www/$app"
-
-#=================================================
-# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS
-#=================================================
-ynh_script_progression "Validating installation parameters..."
-
-# Check destination directory
-test ! -e "$final_path" || ynh_die "Path is already in use: ${final_path}."
-
-# Register (book) web path
-ynh_webpath_register "$app" "$domain" "$path_url"
 
 #=================================================
 # STORE SETTINGS FROM MANIFEST
 #=================================================
 ynh_script_progression "Storing installation settings..."
 
-ynh_app_setting_set "$app" domain "$domain"
-ynh_app_setting_set "$app" final_path "$final_path"
+# Default values for config panel
+ynh_app_setting_set "$app" service_enabled 0
+ynh_app_setting_set "$app" dns_method "yunohost"
+ynh_app_setting_set "$app" nameservers ""
+ynh_app_setting_set "$app" ip6_addr ""
+ynh_app_setting_set "$app" ip6_net ""
 
 #=================================================
 # STANDARD MODIFICATIONS

+ 6 - 24
scripts/remove

@@ -32,17 +32,16 @@ source /usr/share/yunohost/helpers
 ynh_print_info "Loading installation settings..."
 
 app=$YNH_APP_INSTANCE_NAME
-domain=$(ynh_app_setting_get $app domain)
 
 #=================================================
 # STOP AND REMOVE SERVICES
 #=================================================
 ynh_print_info "Stopping and removing services"
 
-systemctl stop $service_checker_name
-systemctl disable $service_checker_name --quiet
 systemctl stop $service_checker_name.timer && sleep 1
 systemctl disable $service_checker_name.timer --quiet
+systemctl stop $service_checker_name
+systemctl disable $service_checker_name --quiet
 
 if ynh_exec_warn_less yunohost service status $service_name >/dev/null
 then
@@ -57,22 +56,6 @@ do
 done
 
 #=================================================
-# REMOVE NGINX CONFIGURATION
-#=================================================
-ynh_print_info "Removing NGINX web server configuration"
-
-# Remove the dedicated NGINX config
-ynh_remove_nginx_config
-
-#=================================================
-# REMOVE PHP-FPM CONFIGURATION
-#=================================================
-ynh_print_info "Removing PHP-FPM configuration"
-
-# Remove the dedicated PHP-FPM config
-ynh_remove_fpm_config
-
-#=================================================
 # SPECIFIC REMOVE
 #================================================
 ynh_print_info "Removing openvpn configuration"
@@ -80,7 +63,6 @@ ynh_print_info "Removing openvpn configuration"
 # Remove openvpn configurations
 ynh_secure_remove /etc/openvpn/client.conf
 ynh_secure_remove /etc/openvpn/client.conf.tpl
-ynh_secure_remove /etc/openvpn/client.conf.tpl.restore
 
 # Remove YunoHost hook
 ynh_secure_remove /etc/yunohost/hooks.d/90-vpnclient.tpl
@@ -94,15 +76,16 @@ ynh_secure_remove /etc/openvpn/keys
 # Reload systemd configuration
 systemctl daemon-reload
 
+# Make sure to reload the firewall now that the post_iptables_rules ain't there anymore
+ynh_print_info "Reloading firewall"
+yunohost firewall reload
+
 #=================================================
 # REMOVE DEPENDENCIES
 #=================================================
 ynh_print_info "Removing dependencies"
 ynh_remove_app_dependencies
 
-# Remove sources
-ynh_secure_remove "/var/www/${app}"
-
 #=================================================
 # REMOVE DEDICATED USER
 #=================================================
@@ -111,7 +94,6 @@ ynh_print_info "Removing the dedicated system user"
 
 # Delete a system user
 ynh_system_user_delete ${app}
-ynh_secure_remove "/etc/sudoers.d/${app}_ynh"
 
 #=================================================
 # END OF SCRIPT

+ 1 - 50
scripts/restore

@@ -23,46 +23,16 @@ ynh_print_info "Loading settings..."
 
 app=$YNH_APP_INSTANCE_NAME
 
-domain=$(ynh_app_setting_get $app domain)
-path_url=$(ynh_app_setting_get $app path)
-final_path=$(ynh_app_setting_get $app final_path)
-phpversion=$(ynh_app_setting_get $app phpversion)
-
-#=================================================
-# CHECK IF THE APP CAN BE RESTORED
-#=================================================
-ynh_print_info "Validating restoration parameters..."
-
-ynh_webpath_available $domain $path_url \
-	|| ynh_die "Path not available: ${domain}${path_url}"
-test ! -d $final_path \
-	|| ynh_die "There is already a directory: $final_path "
-
-#=================================================
-# STANDARD RESTORATION STEPS
-#=================================================
-# RESTORE THE NGINX CONFIGURATION
-#=================================================
-
-ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf"
-
 #=================================================
 # RESTORE THE APP MAIN DIR
 #=================================================
-ynh_print_info "Restoring the app main directory..."
-
-ynh_restore_file "$final_path"
+ynh_print_info "Restoring the app files..."
 
-ynh_restore_file "/etc/sudoers.d/${app}_ynh"
-
-ynh_restore_file "/usr/local/bin/ipv6_expanded"
-ynh_restore_file "/usr/local/bin/ipv6_compressed"
 ynh_restore_file "/usr/local/bin/$service_name-loadcubefile.sh"
 
 ynh_restore_file "/etc/yunohost/hooks.d/90-vpnclient.tpl"
 
 ynh_restore_file "/etc/openvpn/client.conf.tpl"
-ynh_restore_file "/etc/openvpn/client.conf.tpl.restore"
 ynh_restore_file "/etc/openvpn/keys/"
 
 ynh_restore_file "/usr/local/bin/$service_name"
@@ -77,19 +47,6 @@ ynh_print_info "Recreating the dedicated system user..."
 ynh_system_user_create $app
 
 #=================================================
-# RESTORE USER RIGHTS
-#=================================================
-
-# Restore permissions on app files
-chown -R $app: $final_path
-
-#=================================================
-# RESTORE THE PHP-FPM CONFIGURATION
-#=================================================
-
-ynh_restore_file "/etc/php/$phpversion/fpm/pool.d/$app.conf"
-
-#=================================================
 # SPECIFIC RESTORATION
 #=================================================
 # REINSTALL DEPENDENCIES
@@ -122,12 +79,6 @@ yunohost service add $service_name --description "Tunnels the internet traffic t
 #=================================================
 # GENERIC FINALIZATION
 #=================================================
-# RELOAD NGINX AND PHP-FPM
-#=================================================
-ynh_print_info "Reloading NGINX web server and PHP-FPM..."
-
-systemctl reload php$phpversion-fpm
-systemctl reload nginx
 
 #=================================================
 # END OF SCRIPT

+ 45 - 22
scripts/upgrade

@@ -9,6 +9,8 @@
 source _common.sh
 source /usr/share/yunohost/helpers
 
+ynh_abort_if_errors
+
 #=================================================
 # LOAD SETTINGS
 #=================================================
@@ -16,40 +18,61 @@ ynh_print_info "Loading installation settings..."
 
 app=$YNH_APP_INSTANCE_NAME
 
-domain=$(ynh_app_setting_get $app domain)
-path_url=$(ynh_app_setting_get $app path)
-is_public=$(ynh_app_setting_get $app is_public)
-final_path=$(ynh_app_setting_get $app final_path)
+dns_method=$(ynh_app_setting_get $app dns_method)
+nameservers=$(ynh_app_setting_get $app nameservers)
 
 #=================================================
 # SPECIAL UPGRADE FOR VERSIONS < 1.2.0
 #=================================================
 
 # Removing configuration files with naming that occured in versions < 1.2.0 ("vpnadmin" instead off "$app")
-rm -f /etc/nginx/conf.d/${domain}.d/vpnadmin.conf 2>/dev/null 
-rm -f /etc/php/*/fpm/pool.d/vpnadmin.conf 2>/dev/null 
-
 if [ -d /var/www/vpnadmin ]; then
-  mv /var/www/vpnadmin /var/www/${app}
+  ynh_secure_remove /var/www/vpnadmin
+fi
+
+#=================================================
+# SPECIAL UPGRADE FOR VERSIONS < 2.0
+#=================================================
+
+# Old stuff
+
+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
+
+if [ -d /var/www/$app ]; then
+	ynh_secure_remove /var/www/$app
+fi
+
+[ -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 is_public)" ] || ynh_app_setting_delete $app is_public
+[ -z "$(ynh_app_setting_get $app final_path)" ] || ynh_app_setting_delete $app final_path
+
+if [ -e "/etc/sudoers.d/${app}_ynh" ]; then
+  ynh_secure_remove "/etc/sudoers.d/${app}_ynh"
+fi
+
+# New stuff
+
+if [ -z "$dns_method" ]; then
+    ynh_app_setting_set --app=$app --key=dns_method --value=custom
+fi
+if [ -z "$nameservers" ]; then
+    nameservers="$(grep -o -P '\s*nameserver\s+\K[abcdefabcdef\d.:]+' /etc/resolv.dnsmasq.conf | sort | uniq | paste -s -d, -)"
+    ynh_app_setting_set --app=$app --key=nameservers --value="$nameservers"
 fi
 
-## Versions known to have a buggy backup script
-#buggy_versions="1.0.0 1.0.1 1.1.0"
-#curr_version=$(read_manifest version)
-#if echo $buggy_versions | grep -w $curr_version > /dev/null; then
-#  echo "Your current version of ${app} is very old: ${curr_version}. Please ignore the next warning." >&2
-#fi
-#
 ##=================================================
 ## BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
 ##=================================================
-#
-#ynh_backup_before_upgrade
-#ynh_clean_setup () {
-#    ynh_restore_upgradebackup
-#}
-## Exit if an error occurs during the execution of the script
-ynh_abort_if_errors
+
+# Not done because vpnclient backup ain't so relevant I guess ?
 
 #=================================================
 # DO UPGRADE

+ 0 - 73
sources/config.php

@@ -1,73 +0,0 @@
-<?php
-
-/* VPN Client app for YunoHost
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/vpnclient_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 = dirname(__FILE__).'/i18n';
-
-  bindtextdomain($textdomain, $locales_dir);
-  bind_textdomain_codeset($textdomain, 'UTF-8');
-  textdomain($textdomain);
-
-  set('locale', $lang);
-}
-
-// After routing
-function after($output, $route) {
-  return $output;
-}

+ 0 - 366
sources/controller.php

@@ -1,366 +0,0 @@
-<?php
-
-/* VPN Client app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/vpnclient_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/vpnclient/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 vpnclient '.escapeshellarg($setting).' -v '.escapeshellarg($value));
-}
-
-function stop_service() {
-  touch('/tmp/.ynh-vpnclient-stopped');
-  exec('sudo systemctl stop ynh-vpnclient');
-}
-
-function start_service() {
-  exec('sudo systemctl start ynh-vpnclient', $output, $retcode);
-  unlink('/tmp/.ynh-vpnclient-stopped');
-
-  return $retcode;
-}
-
-function service_status() {
-  exec('sudo ynh-vpnclient status', $output);
-
-  return $output;
-}
-
-function service_faststatus() {
-  exec('ip link show tun0', $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 noneValue($str) {
-  return ($str == 'none') ? '' : $str;
-}
-
-function readAutoConf($file) {
-  $json = file_get_contents($file);
-  $config = json_decode($json, true);
-
-  if(!empty($config['crt_server_ca'])) {
-    $config['crt_server_ca'] = str_replace('|', "\n", $config['crt_server_ca']);
-  }
-
-  if(!empty($config['crt_client'])) {
-    $config['crt_client'] = str_replace('|', "\n", $config['crt_client']);
-  }
-
-  if(!empty($config['crt_client_key'])) {
-    $config['crt_client_key'] = str_replace('|', "\n", $config['crt_client_key']);
-  }
-
-  if(!empty($config['crt_client_ta'])) {
-    $config['crt_client_ta'] = str_replace('|', "\n", $config['crt_client_ta']);
-  }
-
-  return $config;
-}
-
-dispatch('/', function() {
-  $ip6_net = noneValue(ynh_setting_get('ip6_net'));
-  $raw_openvpn = file_get_contents('/etc/openvpn/client.conf.tpl');
-
-  set('service_enabled', ynh_setting_get('service_enabled'));
-  set('server_name', noneValue(ynh_setting_get('server_name')));
-  set('server_port', ynh_setting_get('server_port'));
-  set('server_proto', ynh_setting_get('server_proto'));
-  set('login_user', ynh_setting_get('login_user'));
-  set('login_passphrase', ynh_setting_get('login_passphrase'));
-  set('ip6_net', $ip6_net);
-  set('crt_client_exists', file_exists('/etc/openvpn/keys/user.crt'));
-  set('crt_client_key_exists', file_exists('/etc/openvpn/keys/user.key'));
-  set('crt_client_ta_exists', file_exists('/etc/openvpn/keys/user_ta.key'));
-  set('crt_server_ca_exists', file_exists('/etc/openvpn/keys/ca-server.crt'));
-  set('faststatus', service_faststatus() == 0);
-  set('raw_openvpn', $raw_openvpn);
-  set('dns0', ynh_setting_get('dns0'));
-  set('dns1', ynh_setting_get('dns1'));
-
-  return render('settings.html.php');
-});
-
-dispatch_put('/settings', function() {
-
-  if(!isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
-    throw new Exception('CSRF protection');
-  }
-
-  $service_enabled = isset($_POST['service_enabled']) ? 1 : 0;
-
-  if($service_enabled == 1) {
-    $crt_client_exists = file_exists('/etc/openvpn/keys/user.crt');
-    $crt_client_key_exists = file_exists('/etc/openvpn/keys/user.key');
-    $crt_server_ca_exists = file_exists('/etc/openvpn/keys/ca-server.crt');
-
-    $config = $_POST;
-    $autoconf = false;
-
-    try {
-      if($_FILES['cubefile']['error'] == UPLOAD_ERR_OK) {
-        $config = readAutoConf($_FILES['cubefile']['tmp_name']);
-
-        if(is_null($config)) {
-          throw new Exception(_('Json Syntax Error, please check your dot cube file'));
-        }
-
-        $autoconf = true;
-      }
-  
-      $ip6_net = empty($config['ip6_net']) ? 'none' : $config['ip6_net'];
-      $ip6_addr = 'none';
-
-      if(empty($config['server_name']) || empty($config['server_port']) || empty($config['server_proto'])) {
-        throw new Exception(_('The Server Address, the Server Port and the Protocol cannot be empty'));
-      }
-    
-      if(!preg_match('/^\d+$/', $config['server_port'])) {
-        throw new Exception(_('The Server Port must be only composed of digits'));
-      }
-    
-      if($config['server_proto'] != 'udp' && $config['server_proto'] != 'tcp') {
-        throw new Exception(_('The Protocol must be "udp" or "tcp"'));
-      }
-
-      if(empty($config['dns0']) || empty($config['dns1'])) {
-        throw new Exception(_('You need to define two DNS resolver addresses'));
-      }
-
-      if(empty($config['login_user']) xor empty($config['login_passphrase'])) {
-        throw new Exception(_('A Password is needed when you suggest a Username, or vice versa'));
-      }
-
-      if((!$autoconf && (($_FILES['crt_client']['error'] == UPLOAD_ERR_OK && $_FILES['crt_client_key']['error'] != UPLOAD_ERR_OK && (!$crt_client_key_exists || $_POST['crt_client_key_delete'] == 1))
-        || ($_FILES['crt_client_key']['error'] == UPLOAD_ERR_OK && $_FILES['crt_client']['error'] != UPLOAD_ERR_OK && (!$crt_client_exists || $_POST['crt_client_delete'] == 1))))
-        || ($autoconf && (empty($config['crt_client']) xor empty($config['crt_client_key'])))) {
-      
-        throw new Exception(_('A Client Certificate is needed when you suggest a Key, or vice versa'));
-      } 
- 
-      if((!$autoconf && $_FILES['crt_server_ca']['error'] != UPLOAD_ERR_OK && !$crt_server_ca_exists) || ($autoconf && empty($config['crt_server_ca']))) {
-        throw new Exception(_('You need a Server CA.'));
-      }
-      
-      if(((!$autoconf && $_FILES['crt_client_key']['error'] != UPLOAD_ERR_OK && (!$crt_client_key_exists || $_POST['crt_client_key_delete'] == 1)) || ($autoconf && empty($config['crt_client_key']))) && empty($config['login_user'])) {
-        throw new Exception(_('You need either a Client Certificate, either a Username, or both'));
-      }
-    
-      if($ip6_net != 'none') {
-        $ip6_net = ipv6_expanded($ip6_net);
-    
-        if(empty($ip6_net)) {
-          throw new Exception(_('The IPv6 Delegated Prefix format looks bad'));
-        }
-    
-        $ip6_blocs = explode(':', $ip6_net);
-        $ip6_addr = "${ip6_blocs[0]}:${ip6_blocs[1]}:${ip6_blocs[2]}:${ip6_blocs[3]}:${ip6_blocs[4]}:${ip6_blocs[5]}:${ip6_blocs[6]}:42";
-    
-        $ip6_net = ipv6_compressed($ip6_net);
-        $ip6_addr = ipv6_compressed($ip6_addr);
-      }
-
-    } catch(Exception $e) {
-      flash('error', $e->getMessage().' ('._('configuration not updated').').');
-      goto redirect;
-    }
-  }
-  
-  stop_service();
-  
-  ynh_setting_set('service_enabled', $service_enabled);
-
-  if($service_enabled == 1) {
-    ynh_setting_set('server_name', $config['server_name']);
-    ynh_setting_set('server_port', $config['server_port']);
-    ynh_setting_set('server_proto', $config['server_proto']);
-    ynh_setting_set('dns0', $config['dns0']);
-    ynh_setting_set('dns1', $config['dns1']);
-    ynh_setting_set('login_user', $config['login_user']);
-    ynh_setting_set('login_passphrase', $config['login_passphrase']);
-    ynh_setting_set('ip6_net', $ip6_net);
-    ynh_setting_set('ip6_addr', $ip6_addr);
-
-    if($autoconf) {
-      copy('/etc/openvpn/client.conf.tpl.restore', '/etc/openvpn/client.conf.tpl');
-
-      if(!empty($config['openvpn_rm'])) {
-        $raw_openvpn = explode("\n", file_get_contents('/etc/openvpn/client.conf.tpl'));
-        $fopenvpn = fopen('/etc/openvpn/client.conf.tpl', 'w');
-
-        foreach($raw_openvpn AS $opt) {
-          $filtered = false;
-
-          if(!preg_match('/^#/', $opt) && !preg_match('/<TPL:/', $opt)) {
-            foreach($config['openvpn_rm'] AS $filter) {
-              if(!empty($filter) && preg_match("/$filter/i", $opt)) {
-                $filtered = true;
-              }
-            }
-          }
-
-          if(!$filtered) {
-            fwrite($fopenvpn, "$opt\n");
-          }
-        }
-
-        fclose($fopenvpn);
-      }
-
-      if(!empty($config['openvpn_add'])) {
-        $raw_openvpn = file_get_contents('/etc/openvpn/client.conf.tpl');
-        $raw_openvpn .= "\n# Custom\n".implode("\n", $config['openvpn_add']);
-
-        file_put_contents('/etc/openvpn/client.conf.tpl', $raw_openvpn);
-      }
-
-      if(empty($config['crt_client'])) {
-        if(file_exists('/etc/openvpn/keys/user.crt')) {
-          unlink('/etc/openvpn/keys/user.crt');
-        }
-      } else {
-        file_put_contents('/etc/openvpn/keys/user.crt', $config['crt_client']);
-      }
-
-      if(empty($config['crt_client_key'])) {
-        if(file_exists('/etc/openvpn/keys/user.key')) {
-          unlink('/etc/openvpn/keys/user.key');
-        }
-      } else {
-        file_put_contents('/etc/openvpn/keys/user.key', $config['crt_client_key']);
-      }
-
-      if(empty($config['crt_client_ta'])) {
-        if(file_exists('/etc/openvpn/keys/user_ta.key')) {
-          unlink('/etc/openvpn/keys/user_ta.key');
-        }
-      } else {
-        file_put_contents('/etc/openvpn/keys/user_ta.key', $config['crt_client_ta']);
-      }
-
-      if(empty($config['crt_server_ca'])) {
-        if(file_exists('/etc/openvpn/keys/ca-server.crt')) {
-          unlink('/etc/openvpn/keys/ca-server.crt');
-        }
-      } else {
-        file_put_contents('/etc/openvpn/keys/ca-server.crt', $config['crt_server_ca']);
-      }
-
-    } else {
-
-      file_put_contents('/etc/openvpn/client.conf.tpl', $_POST['raw_openvpn']);
-
-      if($_FILES['crt_client']['error'] == UPLOAD_ERR_OK) {
-        move_uploaded_file($_FILES['crt_client']['tmp_name'], '/etc/openvpn/keys/user.crt');
-      } elseif($_POST['crt_client_delete'] == 1) {
-        unlink('/etc/openvpn/keys/user.crt');
-      }
-      
-      if($_FILES['crt_client_key']['error'] == UPLOAD_ERR_OK) {
-        move_uploaded_file($_FILES['crt_client_key']['tmp_name'], '/etc/openvpn/keys/user.key');
-      } elseif($_POST['crt_client_key_delete'] == 1) {
-        unlink('/etc/openvpn/keys/user.key');
-      }
-  
-      if($_FILES['crt_client_ta']['error'] == UPLOAD_ERR_OK) {
-        move_uploaded_file($_FILES['crt_client_ta']['tmp_name'], '/etc/openvpn/keys/user_ta.key');
-      } elseif($_POST['crt_client_ta_delete'] == 1) {
-        unlink('/etc/openvpn/keys/user_ta.key');
-      }
-      
-      if($_FILES['crt_server_ca']['error'] == UPLOAD_ERR_OK) {
-        move_uploaded_file($_FILES['crt_server_ca']['tmp_name'], '/etc/openvpn/keys/ca-server.crt');
-      }
-    }
-    
-    if(!empty($config['login_user'])) {
-      file_put_contents('/etc/openvpn/keys/credentials', "${config['login_user']}\n${config['login_passphrase']}");
-    } else {
-      file_put_contents('/etc/openvpn/keys/credentials', '');
-    }
-
-    $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):
-```
-/vpnadmin/?/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 - 336
sources/i18n/fr_FR/LC_MESSAGES/localization.po

@@ -1,336 +0,0 @@
-# French translations for data package
-# Traductions françaises du paquet data.
-# Copyright (C) 2015 THE data'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the data package.
-# Automatically generated, 2015.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: data 2\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-29 14:09+0200\n"
-"PO-Revision-Date: 2015-09-29 14:10+0200\n"
-"Last-Translator: samy boutayeb <samy@langues-etcetera.fr>\n"
-"Language-Team: none\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:130
-msgid "Json Syntax Error, please check your dot cube file"
-msgstr "Error de syntaxe Json, merci de vérifier votre fichier .cube"
-
-#: sources/controller.php:140
-msgid "The Server Address, the Server Port and the Protocol cannot be empty"
-msgstr ""
-"L'adresse du serveur, le port du serveur et le protocole ne peuvent pas être "
-"vides"
-
-#: sources/controller.php:144
-msgid "The Server Port must be only composed of digits"
-msgstr "Le port du serveur ne peut correspondre qu'à des chiffres"
-
-#: sources/controller.php:148
-msgid "The Protocol must be \"udp\" or \"tcp\""
-msgstr "Le protocole ne peut correspondre qu'à \"udp\" ou \"tcp\""
-
-#: sources/controller.php:152
-msgid "You need to define two DNS resolver addresses"
-msgstr "Vous devez définir deux adresses de résolveur DNS"
-
-#: sources/controller.php:156
-msgid "A Password is needed when you suggest a Username, or vice versa"
-msgstr ""
-"Un mot de passe est nécessaire si vous proposez un nom d'utilisateur, et "
-"inversement"
-
-#: sources/controller.php:163
-msgid "A Client Certificate is needed when you suggest a Key, or vice versa"
-msgstr ""
-"Un certificat client est nécessaire si vous proposez une clé, et inversement"
-
-#: sources/controller.php:167
-msgid "You need a Server CA."
-msgstr "Vous ne pouvez pas ne pas avoir de CA de serveur"
-
-#: sources/controller.php:171
-msgid "You need either a Client Certificate, either a Username, or both"
-msgstr ""
-"Vous devez avoir soit un certificat client, soit un nom d'utilisateur, soit "
-"les deux"
-
-#: sources/controller.php:178
-msgid "The IPv6 Delegated Prefix format looks bad"
-msgstr "Le format du préfixe IPv6 délégué semble incorrect"
-
-#: sources/controller.php:189
-msgid "configuration not updated"
-msgstr "configuration non-mise à jour"
-
-#: sources/controller.php:310
-msgid "Configuration updated and service successfully reloaded"
-msgstr "Configuration mise à jour et service correctement rechargé"
-
-#: sources/controller.php:312
-msgid "Configuration updated but service reload failed"
-msgstr "Configuration mise à jour mais le rechargement du service a échoué"
-
-#: sources/controller.php:316
-msgid "Service successfully disabled"
-msgstr "Service désactivé avec succès"
-
-#: sources/views/layout.html.php:27
-msgid "VPN Client"
-msgstr "Client VPN"
-
-#: sources/views/layout.html.php:49
-msgid "Error"
-msgstr "Erreur"
-
-#: sources/views/layout.html.php:54 sources/views/settings.html.php:124
-#: sources/views/settings.html.php:138
-msgid "Notice"
-msgstr "Notice"
-
-#: sources/views/layout.html.php:66
-msgid "Any problem? Contribute!"
-msgstr "Un problème ? Contribuez !"
-
-#: sources/views/settings.html.php:20
-msgid "VPN Client Configuration"
-msgstr "Configuration du client VPN"
-
-#: sources/views/settings.html.php:22 sources/views/settings.html.php:24
-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:22
-msgid "Running"
-msgstr "En cours d'exécution"
-
-#: sources/views/settings.html.php:24
-msgid "Not Running"
-msgstr "Éteint"
-
-#: sources/views/settings.html.php:27
-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:27
-msgid "More details"
-msgstr "Plus de détails"
-
-#: sources/views/settings.html.php:43
-msgid "Service"
-msgstr "Service"
-
-#: sources/views/settings.html.php:48
-msgid "VPN Enabled"
-msgstr "VPN activé"
-
-#: sources/views/settings.html.php:60
-msgid "Manual"
-msgstr "Manuel"
-
-#: sources/views/settings.html.php:61
-msgid "Automatic"
-msgstr "Automatique"
-
-#: sources/views/settings.html.php:67
-msgid "VPN"
-msgstr "VPN"
-
-#: sources/views/settings.html.php:72
-msgid "Server Address"
-msgstr "Adresse du serveur"
-
-#: sources/views/settings.html.php:79
-msgid "Server Port"
-msgstr "Port du serveur"
-
-#: sources/views/settings.html.php:81
-msgid "With restricted access, you should use 443 (TCP) or 53 (UDP)"
-msgstr "En cas d'accès restreint, utiliser 443 (TCP) ou 53 (UDP)"
-
-#: sources/views/settings.html.php:86
-msgid "Protocol"
-msgstr "Protocole"
-
-#: sources/views/settings.html.php:89
-msgid "UDP"
-msgstr "UDP"
-
-#: sources/views/settings.html.php:92
-msgid ""
-"UDP is more efficient than TCP (but more filtered in case of restrictive "
-"access)"
-msgstr ""
-"UDP est plus performant que TCP (mais plus filtré en cas d'accès restreint)"
-
-#: sources/views/settings.html.php:93
-msgid "TCP"
-msgstr "TCP"
-
-#: sources/views/settings.html.php:99
-msgid "Delegated prefix (IPv6)"
-msgstr "Préfixe délégué (IPv6)"
-
-#: sources/views/settings.html.php:101
-msgid ""
-"Leave empty if your Internet Service Provider does not give you a delegated "
-"prefix"
-msgstr ""
-"Laissez vide si votre Fournisseur d'Accès à Internet ne vous fournit pas de "
-"préfixe délégué."
-
-#: sources/views/settings.html.php:108
-msgid "Edit the raw configuration only if you know what you do!"
-msgstr "N'éditez la configuration brute que si vous savez ce que vous faites !"
-
-#: sources/views/settings.html.php:108 sources/views/settings.html.php:113
-msgid "Advanced"
-msgstr "Avancé"
-
-#: sources/views/settings.html.php:124
-msgid ""
-"You need to upload a Client Certificate, or define a Username (or both) for "
-"starting your VPN Client."
-msgstr ""
-"Vous devez téléverser le certificat du client, ou définir un nom "
-"d'utilisateur (ou les deux) pour démarrer votre client VPN."
-
-#: sources/views/settings.html.php:130
-msgid "Authentication"
-msgstr "Authentification"
-
-#: sources/views/settings.html.php:138
-msgid "You need to upload a Server CA for starting your VPN Client."
-msgstr "Vous devez transférer un CA de serveur pour démarrer votre client VPN."
-
-#: sources/views/settings.html.php:142
-msgid "Update Server CA"
-msgstr "Actualiser le CA du serveur"
-
-#: sources/views/settings.html.php:142
-msgid "Upload Server CA"
-msgstr "Transférer le CA du serveur"
-
-#: sources/views/settings.html.php:145
-msgid "You cannot have no server CA"
-msgstr "Vous ne pouvez pas ne pas avoir de CA de serveur"
-
-#: sources/views/settings.html.php:150 sources/views/settings.html.php:163
-#: sources/views/settings.html.php:176 sources/views/settings.html.php:189
-#: sources/views/settings.html.php:244
-msgid "Browse"
-msgstr "Parcourir"
-
-#: sources/views/settings.html.php:155
-msgid "Update Client Cert."
-msgstr "Actualiser le certificat client"
-
-#: sources/views/settings.html.php:155
-msgid "Upload Client Cert."
-msgstr "Téléverser un certificat client"
-
-#: sources/views/settings.html.php:158 sources/views/settings.html.php:171
-#: sources/views/settings.html.php:184
-msgid "Delete this certificate"
-msgstr "Supprimer ce certificat"
-
-#: sources/views/settings.html.php:168
-msgid "Update Client Key"
-msgstr "Actualiser la clé client"
-
-#: sources/views/settings.html.php:168
-msgid "Upload Client Key"
-msgstr "Téléverser un clé client"
-
-#: sources/views/settings.html.php:174 sources/views/settings.html.php:187
-msgid "Make sure your browser is able to read the key file before uploading"
-msgstr ""
-"Assurez-vous que votre navigateur peut lire le fichier contenant la clé "
-"avant de le téléverser"
-
-#: sources/views/settings.html.php:176 sources/views/settings.html.php:189
-msgid "make sure your browser is able to read the key file before uploading"
-msgstr ""
-"assurez-vous que votre navigateur peut lire le fichier contenant la clé "
-"avant de le téléverser"
-
-#: sources/views/settings.html.php:181
-msgid "Update Shared-Secret"
-msgstr "Actualiser le secret partagé"
-
-#: sources/views/settings.html.php:181
-msgid "Upload Shared-Secret"
-msgstr "Téléverser un secret partagé"
-
-#: sources/views/settings.html.php:194
-msgid "Username"
-msgstr "Nom d'utilisateur"
-
-#: sources/views/settings.html.php:196 sources/views/settings.html.php:203
-msgid "Leave empty if not necessary"
-msgstr "Laisser vide si non nécessaire"
-
-#: sources/views/settings.html.php:201
-msgid "Password"
-msgstr "Mot de passe"
-
-#: sources/views/settings.html.php:211
-msgid "DNS"
-msgstr "DNS"
-
-#: sources/views/settings.html.php:216
-msgid "First resolver"
-msgstr "Premier résolveur"
-
-#: sources/views/settings.html.php:218 sources/views/settings.html.php:225
-msgid "IPv6 or IPv4"
-msgstr "IPv6 ou IPv4"
-
-#: sources/views/settings.html.php:223
-msgid "Second resolver"
-msgstr "Second résolveur"
-
-#: sources/views/settings.html.php:235
-msgid "Auto Configuration"
-msgstr "Configuration automatique"
-
-#: sources/views/settings.html.php:240
-msgid "Upload Config"
-msgstr "Téléverser une configuration"
-
-#: sources/views/settings.html.php:247
-msgid "What is a dot cube file?"
-msgstr "Qu'est-ce qu'un fichier .cube ?"
-
-#: sources/views/settings.html.php:255
-msgid "Reloading may take a few minutes. Be patient."
-msgstr "Le rechargement peut prendre quelques minutes. Soyez patient."
-
-#: sources/views/settings.html.php:255
-msgid "Save and reload"
-msgstr "Sauvegarder et recharger"
-
-#~ msgid "ta.key"
-#~ msgstr "ta.key"
-
-#~ msgid "IPv6"
-#~ msgstr "IPv6"
-
-#~ msgid "Delegated prefix"
-#~ msgstr "Préfixe délégué"
-
-#~ msgid "Certificates"
-#~ msgstr "Certificats"
-
-#~ msgid "Login"
-#~ msgstr "Identifiant"

+ 0 - 301
sources/i18n/localization.pot

@@ -1,301 +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 14:09+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:130
-msgid "Json Syntax Error, please check your dot cube file"
-msgstr ""
-
-#: sources/controller.php:140
-msgid "The Server Address, the Server Port and the Protocol cannot be empty"
-msgstr ""
-
-#: sources/controller.php:144
-msgid "The Server Port must be only composed of digits"
-msgstr ""
-
-#: sources/controller.php:148
-msgid "The Protocol must be \"udp\" or \"tcp\""
-msgstr ""
-
-#: sources/controller.php:152
-msgid "You need to define two DNS resolver addresses"
-msgstr ""
-
-#: sources/controller.php:156
-msgid "A Password is needed when you suggest a Username, or vice versa"
-msgstr ""
-
-#: sources/controller.php:163
-msgid "A Client Certificate is needed when you suggest a Key, or vice versa"
-msgstr ""
-
-#: sources/controller.php:167
-msgid "You need a Server CA."
-msgstr ""
-
-#: sources/controller.php:171
-msgid "You need either a Client Certificate, either a Username, or both"
-msgstr ""
-
-#: sources/controller.php:178
-msgid "The IPv6 Delegated Prefix format looks bad"
-msgstr ""
-
-#: sources/controller.php:189
-msgid "configuration not updated"
-msgstr ""
-
-#: sources/controller.php:310
-msgid "Configuration updated and service successfully reloaded"
-msgstr ""
-
-#: sources/controller.php:312
-msgid "Configuration updated but service reload failed"
-msgstr ""
-
-#: sources/controller.php:316
-msgid "Service successfully disabled"
-msgstr ""
-
-#: sources/views/layout.html.php:27
-msgid "VPN Client"
-msgstr ""
-
-#: sources/views/layout.html.php:49
-msgid "Error"
-msgstr ""
-
-#: sources/views/layout.html.php:54 sources/views/settings.html.php:124
-#: sources/views/settings.html.php:138
-msgid "Notice"
-msgstr ""
-
-#: sources/views/layout.html.php:66
-msgid "Any problem? Contribute!"
-msgstr ""
-
-#: sources/views/settings.html.php:20
-msgid "VPN Client Configuration"
-msgstr ""
-
-#: sources/views/settings.html.php:22 sources/views/settings.html.php:24
-msgid ""
-"This is a fast status. Click on More details to show the complete status."
-msgstr ""
-
-#: sources/views/settings.html.php:22
-msgid "Running"
-msgstr ""
-
-#: sources/views/settings.html.php:24
-msgid "Not Running"
-msgstr ""
-
-#: sources/views/settings.html.php:27
-msgid "Loading complete status may take a few minutes. Be patient."
-msgstr ""
-
-#: sources/views/settings.html.php:27
-msgid "More details"
-msgstr ""
-
-#: sources/views/settings.html.php:43
-msgid "Service"
-msgstr ""
-
-#: sources/views/settings.html.php:48
-msgid "VPN Enabled"
-msgstr ""
-
-#: sources/views/settings.html.php:60
-msgid "Manual"
-msgstr ""
-
-#: sources/views/settings.html.php:61
-msgid "Automatic"
-msgstr ""
-
-#: sources/views/settings.html.php:67
-msgid "VPN"
-msgstr ""
-
-#: sources/views/settings.html.php:72
-msgid "Server Address"
-msgstr ""
-
-#: sources/views/settings.html.php:79
-msgid "Server Port"
-msgstr ""
-
-#: sources/views/settings.html.php:81
-msgid "With restricted access, you should use 443 (TCP) or 53 (UDP)"
-msgstr ""
-
-#: sources/views/settings.html.php:86
-msgid "Protocol"
-msgstr ""
-
-#: sources/views/settings.html.php:89
-msgid "UDP"
-msgstr ""
-
-#: sources/views/settings.html.php:92
-msgid ""
-"UDP is more efficient than TCP (but more filtered in case of restrictive "
-"access)"
-msgstr ""
-
-#: sources/views/settings.html.php:93
-msgid "TCP"
-msgstr ""
-
-#: sources/views/settings.html.php:99
-msgid "Delegated prefix (IPv6)"
-msgstr ""
-
-#: sources/views/settings.html.php:101
-msgid ""
-"Leave empty if your Internet Service Provider does not give you a delegated "
-"prefix"
-msgstr ""
-
-#: sources/views/settings.html.php:108
-msgid "Edit the raw configuration only if you know what you do!"
-msgstr ""
-
-#: sources/views/settings.html.php:108 sources/views/settings.html.php:113
-msgid "Advanced"
-msgstr ""
-
-#: sources/views/settings.html.php:124
-msgid ""
-"You need to upload a Client Certificate, or define a Username (or both) for "
-"starting your VPN Client."
-msgstr ""
-
-#: sources/views/settings.html.php:130
-msgid "Authentication"
-msgstr ""
-
-#: sources/views/settings.html.php:138
-msgid "You need to upload a Server CA for starting your VPN Client."
-msgstr ""
-
-#: sources/views/settings.html.php:142
-msgid "Update Server CA"
-msgstr ""
-
-#: sources/views/settings.html.php:142
-msgid "Upload Server CA"
-msgstr ""
-
-#: sources/views/settings.html.php:145
-msgid "You cannot have no server CA"
-msgstr ""
-
-#: sources/views/settings.html.php:150 sources/views/settings.html.php:163
-#: sources/views/settings.html.php:176 sources/views/settings.html.php:189
-#: sources/views/settings.html.php:244
-msgid "Browse"
-msgstr ""
-
-#: sources/views/settings.html.php:155
-msgid "Update Client Cert."
-msgstr ""
-
-#: sources/views/settings.html.php:155
-msgid "Upload Client Cert."
-msgstr ""
-
-#: sources/views/settings.html.php:158 sources/views/settings.html.php:171
-#: sources/views/settings.html.php:184
-msgid "Delete this certificate"
-msgstr ""
-
-#: sources/views/settings.html.php:168
-msgid "Update Client Key"
-msgstr ""
-
-#: sources/views/settings.html.php:168
-msgid "Upload Client Key"
-msgstr ""
-
-#: sources/views/settings.html.php:174 sources/views/settings.html.php:187
-msgid "Make sure your browser is able to read the key file before uploading"
-msgstr ""
-
-#: sources/views/settings.html.php:176 sources/views/settings.html.php:189
-msgid "make sure your browser is able to read the key file before uploading"
-msgstr ""
-
-#: sources/views/settings.html.php:181
-msgid "Update Shared-Secret"
-msgstr ""
-
-#: sources/views/settings.html.php:181
-msgid "Upload Shared-Secret"
-msgstr ""
-
-#: sources/views/settings.html.php:194
-msgid "Username"
-msgstr ""
-
-#: sources/views/settings.html.php:196 sources/views/settings.html.php:203
-msgid "Leave empty if not necessary"
-msgstr ""
-
-#: sources/views/settings.html.php:201
-msgid "Password"
-msgstr ""
-
-#: sources/views/settings.html.php:211
-msgid "DNS"
-msgstr ""
-
-#: sources/views/settings.html.php:216
-msgid "First resolver"
-msgstr ""
-
-#: sources/views/settings.html.php:218 sources/views/settings.html.php:225
-msgid "IPv6 or IPv4"
-msgstr ""
-
-#: sources/views/settings.html.php:223
-msgid "Second resolver"
-msgstr ""
-
-#: sources/views/settings.html.php:235
-msgid "Auto Configuration"
-msgstr ""
-
-#: sources/views/settings.html.php:240
-msgid "Upload Config"
-msgstr ""
-
-#: sources/views/settings.html.php:247
-msgid "What is a dot cube file?"
-msgstr ""
-
-#: sources/views/settings.html.php:255
-msgid "Reloading may take a few minutes. Be patient."
-msgstr ""
-
-#: sources/views/settings.html.php:255
-msgid "Save and reload"
-msgstr ""

+ 0 - 27
sources/index.php

@@ -1,27 +0,0 @@
-<?php
-
-/* VPN Client app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/vpnclient_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();

Fichier diff supprimé car celui-ci est trop grand
+ 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 */

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 1
sources/public/bootstrap/css/bootstrap-theme.css.map


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 5
sources/public/bootstrap/css/bootstrap-theme.min.css


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 6358
sources/public/bootstrap/css/bootstrap.css


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 1
sources/public/bootstrap/css/bootstrap.css.map


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 5
sources/public/bootstrap/css/bootstrap.min.css


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


Fichier diff supprimé car celui-ci est trop grand
+ 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


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 2276
sources/public/bootstrap/js/bootstrap.js


Fichier diff supprimé car celui-ci est trop grand
+ 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 - 107
sources/public/css/style.css

@@ -1,107 +0,0 @@
-/* VPN Client app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/vpnclient_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, div#raw_openvpn_panel {
-  color: #D9534F;
-}
-
-li.status-success {
-  color: #5CB85C;
-}
-
-img#status-loading {
-  display: none;
-  margin-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;
-}
-
-a.btn-danger span {
-  color: #eee;
-}
-
-a.btn-danger:hover span {
-  color: #fff;
-}
-
-a.not-allowed {
-  cursor: not-allowed;
-}
-
-input.allowed {
-  cursor: default;
-}
-
-a.btn-disabled, a.btn-disabled:hover, a.btn-disabled:active {
-  background-color: #999;
-  background-image: none;
-  border-color: #888;
-}
-
-a.btn-disabled:hover span {
-  color: #eee;
-}
-
-div#github {
-  margin: -10px 0 20px 20px;
-  background: url(../img/github.png) no-repeat 0 4px;
-}
-
-div#github a {
-  margin-left: 17px;
-}
-
-div#raw_openvpn_panel {
-  display: none;
-}
-
-textarea#raw_openvpn {
-  height: 300px;
-  border: 1px solid #D9534F;
-}
-
-ul.nav {
-  margin-top: 30px;
-  margin-bottom: 20px;
-}
-
-ul.nav a {
-  outline: none;
-}

BIN
sources/public/img/github.png


BIN
sources/public/img/loading.gif


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 4
sources/public/jquery/jquery-2.1.1.min.js


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 9
sources/public/js/bootstrap-toggle.min.js


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

@@ -1,133 +0,0 @@
-/* VPN Client app for YunoHost 
- * Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
- * Contribute at https://github.com/labriqueinternet/vpnclient_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 tabsClick() {
-  var tab = $(this).parent().attr('data-tab');
-
-  $('.nav').find('li.active').removeClass('active');
-  $(this).parent().addClass('active');
-
-  $('.tabs').hide();
-  $('.tab' + tab).show();
-
-  return false;
-}
-
-function ready() {
-  $('.btn-group').button();
-  $('[data-toggle="tooltip"]').tooltip();
-
-  $('.switch').bootstrapToggle();
-  $('.nav-tabs a').click(tabsClick);
-
-  $('.fileinput').click(function() {
-    if(!$(this).hasClass('btn-danger')) {
-      var realinputid = '#' + $(this).attr('id').replace(/_chooser.*/, '');
-
-      $(realinputid).click();
-    }
-  });
-
-  $('.deletefile').click(function() {
-    var chooserbtnid = '#' + $(this).attr('id').replace(/_deletebtn$/, '_chooserbtn');
-    var choosertxtid = '#' + $(this).attr('id').replace(/_deletebtn$/, '_choosertxt');
-    var fileinputid = '#' + $(this).attr('id').replace(/_deletebtn$/, '');
-    var deleteinputid = '#' + $(this).attr('id').replace(/btn$/, '');
-
-    $(deleteinputid).click();
-    $(chooserbtnid).toggleClass('btn-danger');
-    $(chooserbtnid).toggleClass('not-allowed');
-    $(choosertxtid).toggleClass('btn-danger');
-    $(choosertxtid).val($(choosertxtid).hasClass('btn-danger') ? 'Removal requested' : '');
-    $(fileinputid).val('');
-
-    if($(this).attr('id').search('_key') >= 0) {
-      if($(choosertxtid).hasClass('btn-danger') != $('#crt_client_choosertxt').hasClass('btn-danger')) {
-        $('#crt_client_deletebtn').click();
-      }
-    } else if($(this).attr('id').search('_ta') < 0) {
-      if($(choosertxtid).hasClass('btn-danger') != $('#crt_client_key_choosertxt').hasClass('btn-danger')) {
-        $('#crt_client_key_deletebtn').click();
-      }
-    }
-  });
-
-  $('input[type="file"]').change(function() {
-    var choosertxtid = '#' + $(this).attr('id') + '_choosertxt';
-
-    $(choosertxtid).val($(this).val().replace(/^.*[\/\\]/, ''));
-  });
-
-  $('#form').on("submit", function(event) {
-    event.preventDefault()
-    $('#save').prop('disabled', true);
-    $('#save-loading').show();
-    $.ajax({
-        url: this.action,
-        type: this.method,
-        contentType: false,
-        processData: false,
-        cache: false,
-        data: new FormData(this),
-        headers: {
-          'X-Requested-With': 'jQuery',
-        },
-        timeout: 5000,
-        dataType: "html",
-        // success: function() {}, // XXX will never happen because the VPN connection will be restarted after the form is posted.
-        complete: function() {
-          console.log("Forcing page reload after a few seconds...");
-          setTimeout(function() {document.location.reload();}, 45000)
-        },
-    });
-  })
-
-  $('#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');
-      });
-    }
-  });
-
-  $('#raw_openvpn_btn').click(function() {
-    $('#raw_openvpn_btnpanel').hide();
-    $('#raw_openvpn_panel').show('low');
-  });
-
-  $('#service_enabled').change(function() {
-    if($('#service_enabled').parent().hasClass('off')) {
-      $('.enabled').hide('slow');
-    } else {
-      $('.enabled').show('slow');
-    }
-  });
-}
-
-$(document).ready(ready)

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

@@ -1,70 +0,0 @@
-<!doctype html>
-
-<!--
-  VPN Client app for YunoHost 
-  Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-  Contribute at https://github.com/labriqueinternet/vpnclient_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><?= _("VPN Client") ?><?= 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'] ?><!-- RETURN_MSG -->
-      </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'] ?><!-- RETURN_MSG -->
-      </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'] ?><!-- RETURN_MSG -->
-      </div>
-    <?php endif; ?>
-
-    <?= $content ?>
-
-    <hr />
-    <div id="github"><a href="https://github.com/labriqueinternet/vpnclient_ynh"><?= _('Any problem? Contribute!') ?></a> - AGPL 3.0</div>
-  </div>
-</body>
-
-</html>

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

@@ -1,260 +0,0 @@
-<!--
-  VPN Client app for YunoHost 
-  Copyright (C) 2015 Julien Vaubourg <julien@vaubourg.com>
-  Contribute at https://github.com/labriqueinternet/vpnclient_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/>.
--->
-
-<h2><?= _("VPN Client 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"><?= _('VPN 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>
-      </div>
-
-      <div class="enabled" <?= $service_enabled == 0 ? 'style="display: none"' : '' ?>>
-        <ul class="nav nav-tabs nav-justified">
-          <li role="presentation" data-tab="manualconfig" class="active"><a href="#"><?= _("Manual") ?></a></li>
-          <li role="presentation" data-tab="autoconfig"><a href="#"><?= _("Automatic") ?></a></li>
-        </ul>
-
-        <div class="tabs tabmanualconfig">
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h3 class="panel-title"><?= _("VPN") ?></h3>
-            </div>
-
-            <div style="padding: 14px 14px 0 10px">
-              <div class="form-group">
-                <label for="server_name" class="col-sm-3 control-label"><?= _('Server Address') ?></label>
-                <div class="col-sm-9">
-                  <input type="text" class="form-control" name="server_name" id="server_name" placeholder="vpn.example.net" value="<?= $server_name ?>" />
-                </div>
-              </div>
-    
-              <div class="form-group">
-                <label for="server_port" class="col-sm-3 control-label"><?= _('Server Port') ?></label>
-                <div class="col-sm-9">
-                  <input type="text" data-toggle="tooltip" data-title="<?= _('With restricted access, you should use 443 (TCP) or 53 (UDP)') ?>" class="form-control" name="server_port" id="server_port" placeholder="1194" value="<?= $server_port ?>" />
-                </div>
-              </div>
-    
-              <div class="form-group">
-                <label for="server_proto" class="col-sm-3 control-label"><?= _('Protocol') ?></label>
-                <div class="btn-group col-sm-9" data-toggle="buttons">
-                  <label class="btn btn-default <?= $server_proto == 'udp' ? 'active' : '' ?>">
-                    <input type="radio" name="server_proto" value="udp" <?= $server_proto == 'udp' ? 'checked="cheked"' : '' ?> /> <?= _('UDP') ?>
-                  </label>
-    
-                  <label class="btn btn-default <?= $server_proto == 'tcp' ? 'active' : '' ?>" data-toggle="tooltip" data-title="<?= _('UDP is more efficient than TCP (but more filtered in case of restrictive access)') ?>">
-                    <input type="radio" name="server_proto" value="tcp" <?= $server_proto == 'tcp' ? 'checked="cheked"' : '' ?> /> <?= _('TCP') ?>
-                  </label>
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="ip6_net" class="col-sm-3 control-label"><?= _('Delegated prefix (IPv6)') ?></label>
-                <div class="col-sm-9">
-                  <input type="text" data-toggle="tooltip" data-title="<?= _('Leave empty if your Internet Service Provider does not give you a delegated prefix') ?>" class="form-control" name="ip6_net" id="ip6_net" placeholder="2001:db8:42::" value="<?= $ip6_net ?>" />
-                </div>
-              </div>
-
-              <div class="form-group" id="raw_openvpn_btnpanel">
-                <label class="col-sm-3 control-label"></label>
-                <div class="col-sm-9">
-                  <span class="glyphicon glyphicon-cog"></span> <a href="javascript:" id="raw_openvpn_btn" data-toggle="tooltip" data-title="<?= _('Edit the raw configuration only if you know what you do!') ?>"><?= _('Advanced') ?></a>
-                </div>
-              </div>
-
-              <div class="form-group" id="raw_openvpn_panel">
-                <label for="raw_openvpn" class="col-sm-3 control-label"><?= _('Advanced') ?></label>
-                <div class="col-sm-9">
-                  <pre><textarea class="form-control" name="raw_openvpn" id="raw_openvpn"><?= $raw_openvpn ?></textarea></pre>
-                </div>
-              </div>
-            </div>
-          </div>
-
-          <?php if(!$crt_client_key_exists && empty($login_user)): ?>
-            <div class="alert alert-dismissible alert-warning fade in" style="margin: 2px 0px 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> <?= _("You need to upload a Client Certificate, or define a Username (or both) for starting your VPN Client.") ?>
-            </div>
-          <?php endif; ?>
-
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h3 class="panel-title"><?= _("Authentication") ?></h3>
-            </div>
-
-            <div style="padding: 14px 14px 0 10px">
-              <div class="form-group">
-                <?php if(!$crt_server_ca_exists): ?>
-                  <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> <?= _("You need to upload a Server CA for starting your VPN Client.") ?>
-                  </div>
-                <?php endif; ?>
-
-                <label for="crt_server_ca" class="col-sm-3 control-label"><?= $crt_server_ca_exists ? _('Update Server CA') : _('Upload Server CA') ?></label>
-                <div class="input-group col-sm-9" style="padding: 0 15px">
-                  <?php if($crt_server_ca_exists): ?>
-                    <a class="btn btn-danger not-allowed btn-disabled input-group-addon" id="crt_server_ca_deletebtn" data-toggle="tooltip" data-title="<?= _('You cannot have no server CA') ?>"><span class="glyphicon glyphicon-remove"></span></a>
-                    <input id="crt_server_ca_delete" name="crt_server_ca_delete" type="checkbox" value="1" style="display: none" />
-                  <?php endif; ?>
-                  <input type="text" class="form-control fileinput" id="crt_server_ca_choosertxt" placeholder="-----BEGIN CERTIFICATE-----" readonly="readonly" />
-                  <input id="crt_server_ca" name="crt_server_ca" type="file" style="display: none" />
-                  <a class="btn input-group-addon fileinput" id="crt_server_ca_chooserbtn" data-toggle="tooltip" data-title="<?= _('Browse') ?>"><span class="glyphicon glyphicon-search"></span></a>
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="crt_client" class="col-sm-3 control-label"><?= $crt_client_exists ? _('Update Client Cert.') : _('Upload Client Cert.') ?></label>
-                <div class="input-group col-sm-9" style="padding: 0 15px">
-                  <?php if($crt_client_exists): ?>
-                    <a class="btn btn-danger input-group-addon deletefile" id="crt_client_deletebtn" data-toggle="tooltip" data-title="<?= _('Delete this certificate') ?>"><span class="glyphicon glyphicon-remove"></span></a>
-                    <input id="crt_client_delete" name="crt_client_delete" type="checkbox" value="1" style="display: none" />
-                  <?php endif; ?>
-                  <input type="text" class="form-control fileinput" id="crt_client_choosertxt" placeholder="-----BEGIN CERTIFICATE-----" readonly="readonly" />
-                  <input id="crt_client" name="crt_client" type="file" style="display: none" />
-                  <a class="btn input-group-addon fileinput" id="crt_client_chooserbtn" data-toggle="tooltip" data-title="<?= _('Browse') ?>"><span class="glyphicon glyphicon-search"></span></a>
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="crt_client_key" class="col-sm-3 control-label"><?= $crt_client_key_exists ? _('Update Client Key') : _('Upload Client Key') ?></label>
-                <div class="input-group col-sm-9" style="padding: 0 15px">
-                  <?php if($crt_client_key_exists): ?>
-                    <a class="btn btn-danger input-group-addon deletefile" id="crt_client_key_deletebtn" data-toggle="tooltip" data-title="<?= _('Delete this certificate') ?>"><span class="glyphicon glyphicon-remove"></span></a>
-                    <input id="crt_client_key_delete" name="crt_client_key_delete" type="checkbox" value="1" style="display: none" />
-                  <?php endif; ?>
-                  <input type="text" class="form-control fileinput" id="crt_client_key_choosertxt" data-toggle="tooltip" data-title="<?= _('Make sure your browser is able to read the key file before uploading') ?>" placeholder="-----BEGIN PRIVATE KEY-----" readonly="readonly" />
-                  <input id="crt_client_key" name="crt_client_key" type="file" style="display: none" />
-                  <a class="btn input-group-addon fileinput" id="crt_client_key_chooserbtn" data-toggle="tooltip" data-title="<?= _('Browse') ?> (<?= _('make sure your browser is able to read the key file before uploading') ?>)"><span class="glyphicon glyphicon-search"></span></a>
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="crt_client_ta" class="col-sm-3 control-label"><?= $crt_client_ta_exists ? _('Update Shared-Secret') : _('Upload Shared-Secret') ?></label>
-                <div class="input-group col-sm-9" style="padding: 0 15px">
-                  <?php if($crt_client_ta_exists): ?>
-                    <a class="btn btn-danger input-group-addon deletefile" id="crt_client_ta_deletebtn" data-toggle="tooltip" data-title="<?= _('Delete this certificate') ?>"><span class="glyphicon glyphicon-remove"></span></a>
-                    <input id="crt_client_ta_delete" name="crt_client_ta_delete" type="checkbox" value="1" style="display: none" />
-                  <?php endif; ?>
-                  <input type="text" class="form-control fileinput" id="crt_client_ta_choosertxt" data-toggle="tooltip" data-title="<?= _('Make sure your browser is able to read the key file before uploading') ?>" placeholder="ta.key" readonly="readonly" />
-                  <input id="crt_client_ta" name="crt_client_ta" type="file" style="display: none" />
-                  <a class="btn input-group-addon fileinput" id="crt_client_ta_chooserbtn" data-toggle="tooltip" data-title="<?= _('Browse') ?> (<?= _('make sure your browser is able to read the key file before uploading') ?>)"><span class="glyphicon glyphicon-search"></span></a>
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="login_user" class="col-sm-3 control-label"><?= _('Username') ?></label>
-                <div class="col-sm-9">
-                  <input type="text" data-toggle="tooltip" data-title="<?= _('Leave empty if not necessary') ?>" class="form-control" name="login_user" id="login_user" placeholder="michu" value="<?= $login_user ?>" />
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="login_passphrase" class="col-sm-3 control-label"><?= _('Password') ?></label>
-                <div class="col-sm-9">
-                  <input type="password" data-toggle="tooltip" data-title="<?= _('Leave empty if not necessary') ?>" class="form-control" name="login_passphrase" id="login_passphrase" placeholder="XVCwSbDkxnqQ" value="<?= $login_passphrase ?>" />
-                </div>
-              </div>
-            </div>
-          </div>
-
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h3 class="panel-title"><?= _("DNS") ?></h3>
-            </div>
-
-            <div style="padding: 14px 14px 0 10px">
-              <div class="form-group">
-                <label for="dns0" class="col-sm-3 control-label"><?= _('First resolver') ?></label>
-                <div class="col-sm-9">
-                  <input type="text" data-toggle="tooltip" data-title="<?= _('IPv6 or IPv4') ?>" class="form-control" name="dns0" id="dns0" placeholder="89.234.141.66" value="<?= $dns0 ?>" />
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="dns1" class="col-sm-3 control-label"><?= _('Second resolver') ?></label>
-                <div class="col-sm-9">
-                  <input type="text" data-toggle="tooltip" data-title="<?= _('IPv6 or IPv4') ?>" class="form-control" name="dns1" id="dns1" placeholder="2001:913::8" value="<?= $dns1 ?>" />
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-
-        <div class="tabs tabautoconfig" style="display: none">
-          <div class="panel panel-default">
-            <div class="panel-heading">
-              <h3 class="panel-title"><?= _("Auto Configuration") ?></h3>
-            </div>
-
-            <div style="padding: 14px 14px 0 10px">
-              <div class="form-group">
-                <label for="cubefile" class="col-sm-3 control-label"><?= _('Upload Config') ?></label>
-                <div class="input-group col-sm-9" style="padding: 0 15px">
-                  <input type="text" class="form-control fileinput" id="cubefile_choosertxt" placeholder="config.cube" readonly="readonly" />
-                  <input id="cubefile" name="cubefile" type="file" style="display: none" />
-                  <a class="btn input-group-addon fileinput" id="cubefile_chooserbtn" data-toggle="tooltip" data-title="<?= _('Browse') ?>"><span class="glyphicon glyphicon-search"></span></a>
-                </div>
-              </div>
-              <p style="text-align: center"><a href="http://internetcu.be/dotcubefiles.html"><?= _('What is a dot cube file?') ?></a></p>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <div class="form-group">
-        <div style="text-align: center">
-          <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..." />
-        </div>
-      </div>
-    </form>
-  </div>
-</div>