diff --git a/check_process b/check_process
new file mode 100644
index 0000000..c315f0d
--- /dev/null
+++ b/check_process
@@ -0,0 +1,33 @@
+;; Test complet
+ ; Manifest
+ domain="domain.tld" (DOMAIN)
+ path="/path" (PATH)
+ user="john" (USER)
+ ; Checks
+ pkg_linter=1
+ setup_sub_dir=1
+ setup_root=1
+ setup_nourl=0
+ setup_private=0
+ setup_public=0
+ upgrade=1
+ backup_restore=1
+ multi_instance=0
+ incorrect_path=1
+ port_already_use=1 (8081)
+ change_url=0
+;;; Levels
+ Level 1=auto
+ Level 2=auto
+ Level 3=auto
+# Level 4: Not relevant
+ Level 4=na
+ Level 5=auto
+ Level 6=auto
+ Level 7=auto
+ Level 8=0
+ Level 9=0
+ Level 10=0
+;;; Options
+Email=
+Notification=none
diff --git a/conf/app.src b/conf/app.src
new file mode 100644
index 0000000..0a7b75c
--- /dev/null
+++ b/conf/app.src
@@ -0,0 +1,6 @@
+SOURCE_URL=https://github.com/afaqurk/linux-dash/archive/59d4787d3147e79a816a5c88ed8af482a0661e88.zip
+SOURCE_SUM=9c3112c93bb20be8b719335b20bf161e11a8095ecf639baab6ea8c95ef289928
+SOURCE_SUM_PRG=sha256sum
+SOURCE_FORMAT=zip
+SOURCE_IN_SUBDIR=true
+SOURCE_FILENAME=
diff --git a/conf/app.src.2.0 b/conf/app.src.2.0
new file mode 100644
index 0000000..136f8ad
--- /dev/null
+++ b/conf/app.src.2.0
@@ -0,0 +1,6 @@
+SOURCE_URL=https://github.com/afaqurk/linux-dash/archive/2.0.tar.gz
+SOURCE_SUM=f7342807ecadd22410614336378311a356e04a18569f64935ea67b9bc27ccd56
+SOURCE_SUM_PRG=sha256sum
+SOURCE_FORMAT=tar.gz
+SOURCE_IN_SUBDIR=true
+SOURCE_FILENAME=
diff --git a/conf/nginx.conf b/conf/nginx.conf
index beea8dd..3ad0143 100644
--- a/conf/nginx.conf
+++ b/conf/nginx.conf
@@ -1,9 +1,14 @@
-location YNH_WWW_PATH/ {
- rewrite ^YNH_WWW_PATH$ YNH_WWW_PATH/ permanent;
- proxy_pass http://localhost:8081/;
- proxy_set_header Host $host;
- proxy_buffering off;
+#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent;
+location __PATH__/ {
- # Include SSOWAT user panel.
- include conf.d/yunohost_panel.conf.inc;
+ if ($scheme = http) {
+ rewrite ^ https://$server_name$request_uri? permanent;
+ }
+
+ proxy_pass http://localhost:__PORT__/;
+ proxy_set_header Host $host;
+ proxy_buffering off;
+
+ # Include SSOWAT user panel.
+ include conf.d/yunohost_panel.conf.inc;
}
diff --git a/conf/supervisor.conf b/conf/supervisor.conf
index 0c0655d..148e08d 100644
--- a/conf/supervisor.conf
+++ b/conf/supervisor.conf
@@ -1,5 +1,7 @@
-[program:linuxdash]
-directory=/var/www/linuxdash/
+[program:__APP__]
+directory=__FINALPATH__/
+;command=python app/server/index.py (v2.0)
command=python python-server.py
autostart=true
autorestart=true
+user=__USER__
diff --git a/manifest.json b/manifest.json
index 733d4f0..a8f2fd4 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,18 +1,23 @@
{
"name": "Linux-Dash",
"id": "linuxdash",
+ "packaging_format": 1,
"description": {
"en": "A drop-in, low-overhead monitoring web dashboard for GNU/linux machine.",
"fr": "Tableau de bord léger pour le monitoring d’un serveur GNU/linux."
},
+ "version": "2.0",
"url": "https://github.com/afaqurk/linux-dash",
- "license": "free",
+ "license": "MIT",
"maintainer": {
"name": "Moul",
"email": "moul@moul.re",
"url": "https://moul.re"
},
- "multi_instance": "false",
+ "requirements": {
+ "yunohost": ">= 2.7.2"
+ },
+ "multi_instance": false,
"services": [
"nginx"
],
@@ -20,7 +25,7 @@
"install" : [
{
"name": "domain",
- "type": "domain",
+ "type": "domain",
"ask": {
"en": "Choose a domain name for Linux-Dash",
"fr": "Choisissez un nom de domaine pour Linux-Dash"
@@ -29,7 +34,7 @@
},
{
"name": "path",
- "type": "path",
+ "type": "path",
"ask": {
"en": "Choose a path for Linux-Dash",
"fr": "Choisissez un chemin pour Linux-Dash"
@@ -39,7 +44,7 @@
},
{
"name": "user",
- "type": "user",
+ "type": "user",
"ask": {
"en": "Choose the YunoHost user which have access to Linux-Dash",
"fr": "Choisissez l’utilisateur YunoHost qui a accès à Linux-Dash"
diff --git a/scripts/_common.sh b/scripts/_common.sh
new file mode 100644
index 0000000..24bd7ba
--- /dev/null
+++ b/scripts/_common.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# ============= FUTURE YUNOHOST HELPER =============
+# Delete a file checksum from the app settings
+#
+# $app should be defined when calling this helper
+#
+# usage: ynh_remove_file_checksum file
+# | arg: file - The file for which the checksum will be deleted
+ynh_delete_file_checksum () {
+ local checksum_setting_name=checksum_${1//[\/ ]/_} # Replace all '/' and ' ' by '_'
+ ynh_app_setting_delete $app $checksum_setting_name
+}
diff --git a/scripts/backup b/scripts/backup
new file mode 100755
index 0000000..d192288
--- /dev/null
+++ b/scripts/backup
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+#=================================================
+# GENERIC START
+#=================================================
+# IMPORT GENERIC HELPERS
+#=================================================
+
+if [ ! -e _common.sh ]; then
+ # Get the _common.sh file if it's not in the current directory
+ cp ../settings/scripts/_common.sh ./_common.sh
+ chmod a+rx _common.sh
+fi
+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
+
+#=================================================
+# LOAD SETTINGS
+#=================================================
+
+app=$YNH_APP_INSTANCE_NAME
+
+final_path=$(ynh_app_setting_get $app final_path)
+domain=$(ynh_app_setting_get $app domain)
+
+#=================================================
+# STANDARD BACKUP STEPS
+#=================================================
+# BACKUP THE APP MAIN DIR
+#=================================================
+
+ynh_backup "$final_path"
+
+#=================================================
+# BACKUP THE NGINX CONFIGURATION
+#=================================================
+
+ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf"
+
+#=================================================
+# SPECIFIC BACKUP
+#=================================================
+# BACKUP SUPERVISOR CONFIG
+#=================================================
+
+ynh_backup "/etc/supervisor/conf.d/$app.conf"
diff --git a/scripts/install b/scripts/install
index 7f6b41b..8b6be88 100755
--- a/scripts/install
+++ b/scripts/install
@@ -1,48 +1,141 @@
#!/bin/bash
-app=linuxdash
+#=================================================
+# GENERIC START
+#=================================================
+# IMPORT GENERIC HELPERS
+#=================================================
-# Retrieve arguments
-domain=$1
-path=$2
-user=$3
+source _common.sh
+source /usr/share/yunohost/helpers
-# Check domain/path availability
-sudo yunohost app checkurl $domain$path -a $app
-if [[ ! $? -eq 0 ]]; then
- exit 1
-fi
+#=================================================
+# MANAGE SCRIPT FAILURE
+#=================================================
-# Check port availability
-sudo yunohost app checkport 8081
-if [[ ! $? -eq 0 ]]; then
- exit 1
-fi
+# Exit if an error occurs during the execution of the script
+ynh_abort_if_errors
+
+#=================================================
+# RETRIEVE ARGUMENTS FROM THE MANIFEST
+#=================================================
+
+domain=$YNH_APP_ARG_DOMAIN
+path_url=$YNH_APP_ARG_PATH
+user=$YNH_APP_ARG_USER
+
+app=$YNH_APP_INSTANCE_NAME
+
+#=================================================
+# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS
+#=================================================
-# Copy files to the right place
final_path=/var/www/$app
-sudo mkdir -p $final_path
-sudo cp -a ../sources/* $final_path
+test ! -e "$final_path" || ynh_die "This path already contains a folder"
-# Set permissions
-sudo chown -R www-data: $final_path
+# Normalize the url path syntax
+path_url=$(ynh_normalize_url_path $path_url)
+
+# Check web path availability
+ynh_webpath_available $domain $path_url
+# Register (book) web path
+ynh_webpath_register $app $domain $path_url
+
+#=================================================
+# STORE SETTINGS FROM MANIFEST
+#=================================================
+
+ynh_app_setting_set $app domain $domain
+ynh_app_setting_set $app path $path_url
+ynh_app_setting_set $app user $user
+
+#=================================================
+# STANDARD MODIFICATIONS
+#=================================================
+# INSTALL DEPENDENCIES
+#=================================================
+
+ynh_install_app_dependencies supervisor
+
+#=================================================
+# DOWNLOAD, CHECK AND UNPACK SOURCE
+#=================================================
+
+ynh_app_setting_set $app final_path $final_path
+# Download, check integrity, uncompress and patch the source from app.src
+ynh_setup_source "$final_path"
+
+#=================================================
+# FIND AND OPEN A PORT
+#=================================================
+
+# Find a free port
+port=$(ynh_find_port 8081)
+# Open this port
+yunohost firewall allow --no-upnp TCP $port 2>&1
+ynh_app_setting_set $app port $port
+
+# For v2.0 only
+# ynh_replace_string "default=80" "default=$port" "$final_path/app/server/index.py"
+ynh_replace_string "'localhost', 8081" "'localhost', $port" "$final_path/python-server.py"
+
+#=================================================
+# NGINX CONFIGURATION
+#=================================================
+
+# Create a dedicated nginx config
+if [ "$path_url" != "/" ]
+then
+ ynh_replace_string "^#sub_path_only" "" "../conf/nginx.conf"
+fi
+ynh_add_nginx_config
+
+#=================================================
+# CREATE DEDICATED USER
+#=================================================
+
+# Create a system user
+ynh_system_user_create $app
+
+#=================================================
+# SPECIFIC SETUP
+#=================================================
+# SET SUPERVISOR
+#=================================================
# Set as a service with supervisor
-sudo apt-get -y -qq install supervisor
-sudo cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf
-sudo supervisorctl update
-sudo supervisorctl start $app
+cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf
+ynh_replace_string "__APP__" "$app" "/etc/supervisor/conf.d/$app.conf"
+ynh_replace_string "__FINALPATH__" "$final_path" "/etc/supervisor/conf.d/$app.conf"
+ynh_replace_string "__USER__" "$app" "/etc/supervisor/conf.d/$app.conf"
-# Modify Nginx configuration file and copy it to Nginx conf directory
-sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
-nginxconf=/etc/nginx/conf.d/$domain.d/$app.conf
-sudo cp ../conf/nginx.conf $nginxconf
-sudo chown root: $nginxconf
-sudo chmod 600 $nginxconf
+supervisorctl update
+supervisorctl restart $app
-# Only give one user access to this app
-sudo yunohost app removeaccess $app
-sudo yunohost app addaccess $app -u $user
+#=================================================
+# REMOVE GOOGLE !!!
+#=================================================
-# Reload web server
-sudo service nginx reload
+sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html"
+
+#=================================================
+# GENERIC FINALIZATION
+#=================================================
+# SECURE FILES AND DIRECTORIES
+#=================================================
+
+# Set permissions to app files
+chown -R root: $final_path
+
+#=================================================
+# SETUP SSOWAT
+#=================================================
+
+# Restrict access to admin only
+yunohost app addaccess --users=$user $app
+
+#=================================================
+# RELOAD NGINX
+#=================================================
+
+systemctl reload nginx
diff --git a/scripts/remove b/scripts/remove
index 6d28ede..97e3c87 100755
--- a/scripts/remove
+++ b/scripts/remove
@@ -1,19 +1,72 @@
#!/bin/bash
-app=linuxdash
-domain=$(sudo yunohost app setting $app domain)
+#=================================================
+# GENERIC START
+#=================================================
+# IMPORT GENERIC HELPERS
+#=================================================
-# Remove sources and nginx configuration
-sudo rm -rf /var/www/$app
-sudo rm -f /etc/nginx/conf.d/$domain.d/$app.conf
+source _common.sh
+source /usr/share/yunohost/helpers
+
+#=================================================
+# LOAD SETTINGS
+#=================================================
+
+app=$YNH_APP_INSTANCE_NAME
+
+domain=$(ynh_app_setting_get $app domain)
+port=$(ynh_app_setting_get $app port)
+final_path=$(ynh_app_setting_get $app final_path)
+
+#=================================================
+# STANDARD REMOVE
+#=================================================
+# REMOVE APP MAIN DIR
+#=================================================
+
+# Remove the app directory securely
+ynh_secure_remove "$final_path"
+
+#=================================================
+# REMOVE NGINX CONFIGURATION
+#=================================================
+
+# Remove the dedicated nginx config
+ynh_remove_nginx_config
+
+#=================================================
+# CLOSE A PORT
+#=================================================
+
+if yunohost firewall list | grep -q "\- $port$"
+then
+ echo "Close port $port"
+ yunohost firewall disallow TCP $port 2>&1
+fi
+
+#=================================================
+# SPECIFIC REMOVE
+#=================================================
+# REMOVE SUPERVISOR
+#=================================================
# Remove service
-sudo supervisorctl stop $app
-sudo rm -f /etc/supervisor/conf.d/$app.conf
+supervisorctl stop $app
+ynh_secure_remove /etc/supervisor/conf.d/$app.conf
-# Remove supervisor package
-# Need to be manage with future manifest/moulinette Debian package management
-# sudo apt-get -y -qq remove supervisor
+#=================================================
+# REMOVE DEPENDENCIES
+#=================================================
-# Reload nginx configuration
-sudo service nginx reload
+# Remove metapackage and its dependencies
+ynh_remove_app_dependencies
+
+#=================================================
+# GENERIC FINALIZATION
+#=================================================
+# REMOVE DEDICATED USER
+#=================================================
+
+# Delete a system user
+ynh_system_user_delete $app
diff --git a/scripts/restore b/scripts/restore
new file mode 100755
index 0000000..0f7f62b
--- /dev/null
+++ b/scripts/restore
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+#=================================================
+# GENERIC START
+#=================================================
+# IMPORT GENERIC HELPERS
+#=================================================
+
+if [ ! -e _common.sh ]; then
+ # Get the _common.sh file if it's not in the current directory
+ cp ../settings/scripts/_common.sh ./_common.sh
+ chmod a+rx _common.sh
+fi
+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
+
+#=================================================
+# LOAD 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)
+
+#=================================================
+# CHECK IF THE APP CAN BE RESTORED
+#=================================================
+
+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_restore_file "$final_path"
+
+#=================================================
+# RECREATE THE DEDICATED USER
+#=================================================
+
+# Create the dedicated user (if not existing)
+ynh_system_user_create $app
+
+#=================================================
+# RESTORE USER RIGHTS
+#=================================================
+
+# Restore permissions on app files
+chown -R root: $final_path
+
+#=================================================
+# SPECIFIC RESTORATION
+#=================================================
+# REINSTALL DEPENDENCIES
+#=================================================
+
+# Define and install dependencies
+ynh_install_app_dependencies supervisor
+
+#=================================================
+# RESTORE THE SUPERVISOR CONFIGURATION
+#=================================================
+
+ynh_restore_file "/etc/supervisor/conf.d/$app.conf"
+
+supervisorctl update
+supervisorctl restart $app
+
+#=================================================
+# GENERIC FINALIZATION
+#=================================================
+# RELOAD NGINX
+#=================================================
+
+systemctl reload nginx
diff --git a/scripts/upgrade b/scripts/upgrade
index 90d4dca..33445c0 100644
--- a/scripts/upgrade
+++ b/scripts/upgrade
@@ -1,30 +1,122 @@
#!/bin/bash
-# Retrieve settings
-app=linuxdash
-domain=$(sudo yunohost app setting $app domain)
-path=$(sudo yunohost app setting $app path)
+#=================================================
+# GENERIC START
+#=================================================
+# IMPORT GENERIC HELPERS
+#=================================================
-# Remove trailing "/" for next commands
-path=${path%/}
+source _common.sh
+source /usr/share/yunohost/helpers
-# Copy files to the right place
-final_path=/var/www/$app
-sudo mkdir -p $final_path
-sudo cp -a ../sources/* $final_path
+#=================================================
+# LOAD SETTINGS
+#=================================================
-# Set permissions
-sudo chown -R www-data: $final_path
+app=$YNH_APP_INSTANCE_NAME
-# Modify Nginx configuration file and copy it to Nginx conf directory
-sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
-nginxconf=/etc/nginx/conf.d/$domain.d/$app.conf
-sudo cp ../conf/nginx.conf $nginxconf
-sudo chown root: $nginxconf
-sudo chmod 600 $nginxconf
+domain=$(ynh_app_setting_get $app domain)
+path_url=$(ynh_app_setting_get $app path)
+user=$(ynh_app_setting_get $app admin)
+final_path=$(ynh_app_setting_get $app final_path)
+port=$(ynh_app_setting_get $app port)
-# Restart Linux-dash service
-sudo supervisorctl restart $app
+#=================================================
+# ENSURE DOWNWARD COMPATIBILITY
+#=================================================
-# Reload web server & sso
-sudo service nginx reload
+# If final_path doesn't exist, create it
+if [ -z $final_path ]; then
+ final_path=/var/www/$app
+ ynh_app_setting_set $app final_path $final_path
+fi
+
+#=================================================
+# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
+#=================================================
+
+# Backup the current version of the app
+ynh_backup_before_upgrade
+ynh_clean_setup () {
+ # restore it if the upgrade fails
+ ynh_restore_upgradebackup
+}
+# Exit if an error occurs during the execution of the script
+ynh_abort_if_errors
+
+#=================================================
+# CHECK THE PATH
+#=================================================
+
+# Normalize the URL path syntax
+path_url=$(ynh_normalize_url_path $path_url)
+
+#=================================================
+# STANDARD UPGRADE STEPS
+#=================================================
+# DOWNLOAD, CHECK AND UNPACK SOURCE
+#=================================================
+
+# Download, check integrity, uncompress and patch the source from app.src
+ynh_setup_source "$final_path"
+
+#=================================================
+# NGINX CONFIGURATION
+#=================================================
+
+# Create a dedicated nginx config
+if [ "$path_url" != "/" ]
+then
+ ynh_replace_string "^#sub_path_only" "" "../conf/nginx.conf"
+fi
+ynh_add_nginx_config
+
+#=================================================
+# CREATE DEDICATED USER
+#=================================================
+
+# Create a system user
+ynh_system_user_create $app
+
+#=================================================
+# SPECIFIC UPGRADE
+#=================================================
+# UPGRADE SUPERVISOR
+#=================================================
+
+# Set as a service with supervisor
+cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf
+ynh_replace_string "__APP__" "$app" "/etc/supervisor/conf.d/$app.conf"
+ynh_replace_string "__FINALPATH__" "$final_path" "/etc/supervisor/conf.d/$app.conf"
+ynh_replace_string "__USER__" "$app" "/etc/supervisor/conf.d/$app.conf"
+
+supervisorctl update
+supervisorctl restart $app
+
+#=================================================
+# REMOVE GOOGLE !!!
+#=================================================
+
+sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html"
+
+#=================================================
+# GENERIC FINALIZATION
+#=================================================
+# SECURE FILES AND DIRECTORIES
+#=================================================
+
+# Set right permissions for curl installation
+chown -R root: $final_path
+
+#=================================================
+# SETUP SSOWAT
+#=================================================
+
+# Restrict access to admin only
+yunohost app addaccess --users=$user $app
+
+#=================================================
+# RELOAD NGINX
+#=================================================
+
+systemctl reload nginx
diff --git a/sources/.editorconfig b/sources/.editorconfig
deleted file mode 100755
index 4a7ea30..0000000
--- a/sources/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-root = true
-
-[*]
-indent_style = space
-indent_size = 2
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-
-[*.md]
-trim_trailing_whitespace = false
diff --git a/sources/.gitignore b/sources/.gitignore
deleted file mode 100644
index 91be243..0000000
--- a/sources/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-vendor
-node_modules
diff --git a/sources/LICENSE.md b/sources/LICENSE.md
deleted file mode 100644
index ec1c59a..0000000
--- a/sources/LICENSE.md
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 afaqurk
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/sources/README.md b/sources/README.md
deleted file mode 100644
index a6a8a51..0000000
--- a/sources/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
- - Demo | - Features | - - Installation | - Support - -
- -- - - -
- -- - - -
- -