diff --git a/README.md b/README.md index 746f6a4..0496909 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,6 @@ Leed est un agrégateur de flux RSS/ATOM dit KISS : minimaliste, simple, léger http://leed.idleman.fr/ **Mise à jour du package:** -sudo yunohost app upgrade -u https://github.com/YunoHost-Apps/leed_ynh +sudo yunohost app upgrade leed -u https://github.com/YunoHost-Apps/leed_ynh **Multi-utilisateur:** Non, une instance par utilisateur. diff --git a/check_process b/check_process new file mode 100644 index 0000000..7c6b877 --- /dev/null +++ b/check_process @@ -0,0 +1,27 @@ +;; Test complet + auto_remove=1 + ; Manifest + domain="domain.tld" (DOMAIN) + path="/leed" (PATH) + admin="john" (USER) + password="pass" (PASSWORD) + language="fr" + market="Yes" + is_public="Yes" (PUBLIC|public=Yes|private=No) + ; Checks + pkg_linter=1 + setup_sub_dir=1 + setup_root=1 + setup_nourl=0 + setup_private=1 + setup_public=1 + upgrade=1 + backup_restore=1 + multi_instance=1 + wrong_user=1 + wrong_path=1 + incorrect_path=1 + corrupt_source=0 + fail_download_source=0 + port_already_use=0 + final_path_already_use=0 diff --git a/conf/nginx.conf b/conf/nginx.conf index c484a37..506ea33 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,5 +1,5 @@ location __PATH__ { - alias __FINALPATH__ ; + alias __FINALPATH__/ ; if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; } diff --git a/manifest.json b/manifest.json index 4f0a880..23a6392 100644 --- a/manifest.json +++ b/manifest.json @@ -1,90 +1,93 @@ { - "name": "Leed", - "id": "leed", - "packaging_format": 1, - "requirements": { - "yunohost": ">= 2.4" - }, - "description": { - "en": "Leed is a minimalistic RSS feed aggregator which allows quick and non-intrusive reading of feeds.", - "fr": "Leed est un agrégateur RSS minimaliste qui permet la consultation de flux RSS de manière rapide et non intrusive." - }, - "version": "1.6", + "name": "Leed", + "id": "leed", + "packaging_format": 1, + "requirements": { + "yunohost": ">= 2.4" + }, + "description": { + "en": "Leed is a minimalistic RSS feed aggregator which allows quick and non-intrusive reading of feeds.", + "fr": "Leed est un agrégateur RSS minimaliste qui permet la consultation de flux RSS de manière rapide et non intrusive." + }, + "version": "1.7", "url": "http://leed.idleman.fr/", - "licence": "free", - "maintainer": { - "name": "Maniack Crudelis", - "email": "maniackc_dev@crudelis.fr" - }, - "multi_instance": "true", - "services": [ - "nginx", - "php5-fpm", - "mysql" - ], - "arguments": { - "install" : [ - { - "name": "domain", - "ask": { - "en": "Choose a domain for Leed", - "fr": "Choisissez un domaine pour Leed" - }, - "example": "domain.org" - }, - { - "name": "path", - "ask": { - "en": "Choose a path for Leed", - "fr": "Choisissez un chemin pour Leed" - }, - "example": "/leed", - "default": "/leed" - }, - { - "name": "admin", - "ask": { - "en": "Choose the Leed administrator (must be an existing YunoHost user)", - "fr": "Choisissez un administrateur Leed (doit être un utilisateur YunoHost)" - }, - "example": "john" - }, - { - "name": "password", - "type": "password", - "ask": { - "en": "Set the administrator password Leed", - "fr": "Définissez le mot de passe administrateur de Leed" - }, - "example": "Choose a password" - }, - { - "name": "language", - "ask": { - "en": "Choose your agregator's language", - "fr": "Choisissez la langue de votre agrégateur" - }, - "choices" : ["en", "fr", "es"], - "default" : "en" - }, - { - "name": "market", - "ask": { - "en": "Do you want to activate the Leed Market?", - "fr": "Voulez-vous activer le Leed Market ?" - }, - "choices": ["Yes", "No"], - "default": "No" - }, - { - "name": "is_public", - "ask": { - "en": "Is it a public website ?", - "fr": "Est-ce un site public ?" - }, - "choices": ["Yes", "No"], - "default": "No" - } - ] - } + "license": "free", + "maintainer": { + "name": "Maniack Crudelis", + "email": "maniackc_dev@crudelis.fr" + }, + "multi_instance": true, + "services": [ + "nginx", + "php5-fpm", + "mysql" + ], + "arguments": { + "install" : [ + { + "name": "domain", + "type": "domain", + "ask": { + "en": "Choose a domain for Leed", + "fr": "Choisissez un domaine pour Leed" + }, + "example": "domain.org" + }, + { + "name": "path", + "type": "path", + "ask": { + "en": "Choose a path for Leed", + "fr": "Choisissez un chemin pour Leed" + }, + "example": "/leed", + "default": "/leed" + }, + { + "name": "admin", + "type": "user", + "ask": { + "en": "Choose the Leed administrator (must be an existing YunoHost user)", + "fr": "Choisissez un administrateur Leed (doit être un utilisateur YunoHost)" + }, + "example": "john" + }, + { + "name": "password", + "type": "password", + "ask": { + "en": "Set the administrator password Leed", + "fr": "Définissez le mot de passe administrateur de Leed" + }, + "example": "Choose a password" + }, + { + "name": "language", + "ask": { + "en": "Choose your agregator's language", + "fr": "Choisissez la langue de votre agrégateur" + }, + "choices" : ["en", "fr", "es"], + "default" : "en" + }, + { + "name": "market", + "ask": { + "en": "Do you want to activate the Leed Market?", + "fr": "Voulez-vous activer le Leed Market ?" + }, + "choices": ["Yes", "No"], + "default": "Yes" + }, + { + "name": "is_public", + "ask": { + "en": "Is it a public website ?", + "fr": "Est-ce un site public ?" + }, + "choices": ["Yes", "No"], + "default": "No" + } + ] + } } diff --git a/manifest2.2.json b/manifest2.2.json index 3bd7897..acaa060 100644 --- a/manifest2.2.json +++ b/manifest2.2.json @@ -71,7 +71,7 @@ "fr": "Voulez-vous activer le Leed Market ?" }, "choices": ["Yes", "No"], - "default": "No" + "default": "Yes" }, { "name": "is_public", diff --git a/scripts/.fonctions b/scripts/.fonctions new file mode 100755 index 0000000..ab08197 --- /dev/null +++ b/scripts/.fonctions @@ -0,0 +1,185 @@ +#!/bin/bash + +ynh_version="2.4" + +YNH_VERSION () { # Renvoi le numéro de version de la moulinette Yunohost + ynh_version=$(sudo yunohost -v | grep "moulinette:" | cut -d' ' -f2 | cut -d'.' -f1,2) +} + +CHECK_VAR () { # Vérifie que la variable n'est pas vide. +# $1 = Variable à vérifier +# $2 = Texte à afficher en cas d'erreur + test -n "$1" || (echo "$2" >&2 && false) +} + +EXIT_PROPERLY () { # Provoque l'arrêt du script en cas d'erreur. Et nettoye les résidus. + trap '' ERR + echo -e "\e[91m \e[1m" # Shell in light red bold + echo -e "!!\n $app install's script has encountered an error. Installation was cancelled.\n!!" >&2 + + CLEAN_SETUP # Appel la fonction de nettoyage spécifique du script install. + + # Compense le bug de ssowat qui ne supprime pas l'entrée de l'app en cas d'erreur d'installation. + sudo sed -i "\@\"$domain$path/\":@d" /etc/ssowat/conf.json + + if [ "$ynh_version" = "2.2" ]; then + /bin/bash $script_dir/remove # Appel le script remove. En 2.2, ce comportement n'est pas automatique. + fi + + exit 1 +} + +TRAP_ON () { # Activate signal capture + trap EXIT_PROPERLY ERR # Capturing exit signals on error +} + +TRAP_OFF () { # Ignoring signal capture until TRAP_ON + # Pour une raison que j'ignore, la fonction TRAP_ON fonctionne très bien. + # Mais pas la fonction TRAP_OFF... + # Utiliser directement `trap '' ERR` dans le code pour l'utiliser, à la place de la fonction. + trap '' ERR # Ignoring exit signals +} + +CHECK_USER () { # Vérifie la validité de l'user admin +# $1 = Variable de l'user admin. + sudo yunohost user list --json | grep -q "\"username\": \"$1\"" || (echo "Wrong admin" >&2 && false) +} + +CHECK_PATH () { # Vérifie la présence du / en début de path. Et son absence à la fin. + if [ "${path:0:1}" != "/" ]; then # Si le premier caractère n'est pas un / + path="/$path" # Ajoute un / en début de path + fi + if [ "${path:${#path}-1}" == "/" ] && [ ${#path} -gt 1 ]; then # Si le dernier caractère est un / et que ce n'est pas le seul caractère. + path="${path:0:${#path}-1}" # Supprime le dernier caractère + fi +} + +CHECK_DOMAINPATH () { # Vérifie la disponibilité du path et du domaine. + sudo yunohost app checkurl $domain$path -a $app +} + +CHECK_FINALPATH () { # Vérifie que le dossier de destination n'est pas déjà utilisé. + final_path=/var/www/$app + if [ -e "$final_path" ] + then + echo "This path already contains a folder" >&2 + false + fi +} + +GENERATE_DB () { # Créer une base de données et un utilisateur dédié au nom de l'app. +# $1 = Nom de la base de donnée + # Génère un mot de passe aléatoire. + db_user=$1 + db_pwd=$(head -n20 /dev/urandom | tr -c -d 'A-Za-z0-9' | head -c20) + CHECK_VAR "$db_pwd" "db_pwd empty" + # Utilise '$app' comme nom d'utilisateur et de base de donnée + # Initialise la base de donnée et stocke le mot de passe mysql. + ynh_mysql_create_db $db_user $db_user $db_pwd + sudo yunohost app setting $app mysqlpwd -v $db_pwd +} + +SETUP_SOURCE () { # Télécharge la source, décompresse et copie dans $final_path +# $1 = Nom de l'archive téléchargée. + wget -nv --show-progress -i ../sources/source_url -O $1 + # Vérifie la somme de contrôle de la source téléchargée. + md5sum -c ../sources/source_md5 --status || (echo "Corrupt source" >&2 && false) + # Décompresse la source + if [ "$(echo ${1##*.})" == "gz" ]; then + tar -x -f $1 + elif [ "$(echo ${1##*.})" == "zip" ]; then + unzip -q $1 + else + false # Format d'archive non pris en charge. + fi + # Copie les fichiers sources + sudo cp -a $(cat ../sources/source_dir)/. "$final_path" + # Copie les fichiers additionnels ou modifiés. + sudo cp -a ../sources/ajouts/. "$final_path" +} + +POOL_FPM () { # Créer le fichier de configuration du pool php-fpm et le configure. + sed -i "s@__NAMETOCHANGE__@$app@g" ../conf/php-fpm.conf + sed -i "s@__FINALPATH__@$final_path@g" ../conf/php-fpm.conf + finalphpconf=/etc/php5/fpm/pool.d/$app.conf + sudo cp ../conf/php-fpm.conf $finalphpconf + sudo chown root: $finalphpconf + finalphpini=/etc/php5/fpm/conf.d/20-$app.ini + sudo cp ../conf/php-fpm.ini $finalphpini + sudo chown root: $finalphpini + sudo service php5-fpm reload +} + +STORE_MD5_CONFIG () { # Enregistre la somme de contrôle du fichier de config +# $1 = Nom du fichier de conf pour le stockage dans settings.yml +# $2 = Nom complet et chemin du fichier de conf. + sudo yunohost app setting $app $1_file_md5 -v $(md5sum "$2" | cut -d' ' -f1) +} + +CHECK_MD5_CONFIG () { # Créé un backup du fichier de config si il a été modifié. +# $1 = Nom du fichier de conf pour le stockage dans settings.yml +# $2 = Nom complet et chemin du fichier de conf. + if [ "$(sudo yunohost app setting $app $1_file_md5)" != $(md5sum "$2" | cut -d' ' -f1) ]; then + sudo cp -a "$2" "$2.backup.$(date '+%d.%m.%y_%Hh%M,%Ss')" # Si le fichier de config a été modifié, créer un backup. + fi +} + +FIND_PORT () { # Cherche un port libre. +# $1 = Numéro de port pour débuter la recherche. + port=$1 + while ! sudo yunohost app checkport $port ; do + port=$((port+1)) + done + CHECK_VAR "$port" "port empty" +} + + +### REMOVE SCRIPT + +REMOVE_NGINX_CONF () { # Suppression de la configuration nginx + if [ -e "/etc/nginx/conf.d/$domain.d/$app.conf" ]; then # Delete nginx config + echo "Delete nginx config" + sudo rm "/etc/nginx/conf.d/$domain.d/$app.conf" + sudo service nginx reload + fi +} + +REMOVE_FPM_CONF () { # Suppression de la configuration du pool php-fpm + if [ -e "/etc/php5/fpm/pool.d/$app.conf" ]; then # Delete fpm config + echo "Delete fpm config" + sudo rm "/etc/php5/fpm/pool.d/$app.conf" + fi + if [ -e "/etc/php5/fpm/conf.d/20-$app.ini" ]; then # Delete php config + echo "Delete php config" + sudo rm "/etc/php5/fpm/conf.d/20-$app.ini" + fi + sudo service php5-fpm reload +} + +REMOVE_LOGROTATE_CONF () { # Suppression de la configuration de logrotate + if [ -e "/etc/logrotate.d/$app" ]; then + echo "Delete logrotate config" + sudo rm "/etc/logrotate.d/$app" + fi +} + +REMOVE_APP_DIR () { # Suppression du dossier de l'application + if test -n "$app" + then # Supprime le dossier seulement si $app n'est pas vide. + if [ -e "/var/www/$app" ]; then # Delete final_path + echo "Delete app dir" + sudo rm -r "/var/www/$app" + fi + fi +} + +REMOVE_BDD () { # Suppression de la base de donnée et de l'utilisateur associé. +# $1 = Nom de la base de donnée + # Utilise '$app' comme nom d'utilisateur et de base de donnée + db_user=$1 + if mysqlshow -u root -p$(sudo cat $MYSQL_ROOT_PWD_FILE) | grep -q "^| $db_user"; then + echo "Delete db" + ynh_mysql_drop_db $db_user + ynh_mysql_drop_user $db_user + fi +} diff --git a/scripts/backup b/scripts/backup index 5e72260..a73c193 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,10 +1,8 @@ #!/bin/bash # Récupère les infos de l'application. -version=$(sudo yunohost -v | grep "moulinette:" | cut -d' ' -f2 | cut -d'.' -f1,2) -if [ $version = "2.4" ]; then - app=$YNH_APP_INSTANCE_NAME -else +app=$YNH_APP_INSTANCE_NAME +if [ -z "$app" ]; then app=leed fi final_path=$(sudo yunohost app setting $app final_path) @@ -26,3 +24,7 @@ sudo cp -a /etc/nginx/conf.d/$domain.d/$app.conf $backup_dir/nginx.conf # Copy dedicated php-fpm process to backup folder sudo cp -a /etc/php5/fpm/pool.d/$app.conf $backup_dir/php-fpm.conf sudo cp -a /etc/php5/fpm/conf.d/20-$app.ini $backup_dir/php-fpm.ini + +# Backup db +root_pwd=$(sudo cat /etc/yunohost/mysql) +sudo mysqldump -u root -p$root_pwd --no-create-db $app --result-file="$backup_dir/db.sql" diff --git a/scripts/install b/scripts/install index 542b30e..8e0253f 100644 --- a/scripts/install +++ b/scripts/install @@ -1,6 +1,16 @@ #!/bin/bash -ynh_version=$(sudo yunohost -v | grep "moulinette:" | cut -d' ' -f2 | cut -d'.' -f1,2) +source .fonctions # Charge les fonctions génériques habituellement utilisées dans le script + +YNH_VERSION # Récupère le numéro de version de Yunohost. + +CLEAN_SETUP () { +# Nettoyage des résidus d'installation non pris en charge par le script remove. + # Clean hosts + sudo sed -i '/#leed/d' /etc/hosts +} +TRAP_ON # Active trap pour arrêter le script si une erreur est détectée. + # Retrieve arguments if [ $ynh_version = "2.4" ] then @@ -15,7 +25,7 @@ then app=$YNH_APP_INSTANCE_NAME # Source app helpers - . /usr/share/yunohost/helpers + source /usr/share/yunohost/helpers else domain=$1 path=$2 @@ -27,66 +37,16 @@ else app=leed fi - -# Delete files and db if exit with an error -EXIT_PROPERLY () { - trap '' ERR - echo -e "\e[91m \e[1m" # Shell in light red bold - echo -e "!!\n $app install's script has encountered an error. Installation was cancelled.\n!!" - - echo -e "\e[22m" # Remove bold - - # Clean hosts - sudo sed -i '/#leed/d' /etc/hosts - - if [ $ynh_version = "2.2" ]; then - /bin/bash ./remove # Appel le script remove. En 2.2, ce comportement n'est pas automatique. - fi - exit 1 -} -TRAP_ON () { # Activate signal capture - trap EXIT_PROPERLY ERR # Capturing exit signals on error -} -TRAP_OFF () { # Ignoring signal capture until TRAP_ON -# Pour une raison que j'ignore, la fonction TRAP_ON fonctionne très bien. -# Mais pas la fonction TRAP_OFF... -# Utiliser directement `trap '' ERR` dans le code pour l'utiliser, à la place de la fonction. - trap '' ERR # Ignoring exit signals -} -TRAP_ON +# Vérifie que les variables ne sont pas vides. +CHECK_VAR "$app" "app name not set" -# Vérifie la validité de l'user admin -sudo yunohost user list --json | grep -q "\"username\": \"$admin\"" -if [[ ! $? -eq 0 ]]; then - echo "Wrong admin" - touch /force_stop -fi +CHECK_USER "$admin" # Vérifie la validité de l'user admin -# Vérifie la disponibilité du path et du domaine. -sudo yunohost app checkurl $domain$path -a $app -if [[ ! $? -eq 0 ]]; then - touch /force_stop -fi +CHECK_PATH # Vérifie et corrige la syntaxe du path. +CHECK_DOMAINPATH # Vérifie la disponibilité du path et du domaine. -# Vérifie que le mot de passe n'est pas vide. -if [[ -z $user_pwd ]]; then - echo "Mot de passe incorrect" - touch /force_stop -fi - -# Vérifie que le dossier de destination n'est pas déjà utilisé. -final_path=/var/www/$app -if [ -e "$final_path" ] -then - echo "This path already contains a folder" - touch /force_stop -fi - -# Vérifie la présence du / en début de path -if [ $(echo $path | cut -c1) != "/" ]; then - path="/$path" -fi +CHECK_FINALPATH # Vérifie que le dossier de destination n'est pas déjà utilisé. # Enregistre les infos dans la config YunoHost @@ -94,29 +54,15 @@ sudo yunohost app setting $app admin -v $admin sudo yunohost app setting $app language -v $language sudo yunohost app setting $app domain -v $domain -# Génère un mot de passe aléatoire. -db_pwd=$(head -n20 /dev/urandom | tr -c -d 'A-Za-z0-9' | head -c20) -# Utilise '$app' comme nom d'utilisateur et de base de donnée -db_user=$app -# Initialise la base de donnée et stocke le mot de passe mysql. -if [ $ynh_version = "2.4" ]; then - ynh_mysql_create_db $db_user $db_user $db_pwd -else - sudo yunohost app initdb $db_user -p $db_pwd -fi -sudo yunohost app setting $app mysqlpwd -v $db_pwd +GENERATE_DB $app # Créer une base de données et un utilisateur dédié au nom de l'app. # Crée le repertoire de destination et stocke son emplacement. sudo mkdir "$final_path" sudo yunohost app setting $app final_path -v $final_path -# Décompresse la source -tar -x -f ../sources/leed.tar.gz -# Copie les fichiers sources -sudo cp -a leed/. "$final_path" -# Copie les fichiers additionnels ou modifiés. -# sudo cp -a ../sources/ajouts/. "$final_path" +SETUP_SOURCE "leed.tar.gz" # Télécharge la source, décompresse et copie dans $final_path + # Et copie le fichier de config nginx sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf @@ -126,16 +72,7 @@ sudo sed -i "s@__PATH__@$path@g" /etc/nginx/conf.d/$domain.d/$app.conf sudo sed -i "s@__FINALPATH__@$final_path@g" /etc/nginx/conf.d/$domain.d/$app.conf sudo sed -i "s@__NAMETOCHANGE__@$app@g" /etc/nginx/conf.d/$domain.d/$app.conf -# Créer le fichier de configuration du pool php-fpm et le configure. -sed -i "s@__NAMETOCHANGE__@$app@g" ../conf/php-fpm.conf -sed -i "s@__FINALPATH__@$final_path@g" ../conf/php-fpm.conf -finalphpconf=/etc/php5/fpm/pool.d/$app.conf -sudo cp ../conf/php-fpm.conf $finalphpconf -sudo chown root: $finalphpconf -finalphpini=/etc/php5/fpm/conf.d/20-$app.ini -sudo cp ../conf/php-fpm.ini $finalphpini -sudo chown root: $finalphpini -sudo service php5-fpm reload +POOL_FPM # Créer le fichier de configuration du pool php-fpm et le configure. # Set right permissions for curl install @@ -158,7 +95,7 @@ sudo yunohost app setting $app market -v "$market" if [ "$market" = "Yes" ]; then sudo rm -R $final_path/plugins - sudo git clone https://github.com/ldleman/Leed-market.git $final_path/plugins + sudo git clone https://github.com/ldleman/Leed-market.git "$final_path/plugins" fi @@ -170,13 +107,14 @@ sudo find $final_path -type d | xargs sudo chmod 755 # Les fichiers appartiennent à root sudo chown -R root: $final_path -# www-data doit avoir les droits d'écriture dans plugins et cache +# www-data doit avoir les droits d'écriture dans plugins, cache et updates sudo mkdir $final_path/cache -sudo chown -R www-data $final_path/cache $final_path/plugins +sudo chown -R www-data $final_path/cache $final_path/plugins $final_path/updates # Récupération du code de synchronisation code_sync=$(mysql -h localhost -u $db_user -p$db_pwd -s $db_user -e 'SELECT value FROM leed_configuration WHERE `key`="synchronisationCode"' | sed -n 1p) +CHECK_VAR "$code_sync" "code_sync empty" # Mise en place du cron pour la synchronisation sed -i "s@__ADMIN__@$admin@g" ../conf/cron_leed @@ -198,6 +136,3 @@ fi # Clean hosts sudo sed -i '/#leed/d' /etc/hosts - -# Recharge la configuration php5-fpm -# sudo service php5-fpm reload diff --git a/scripts/remove b/scripts/remove index 105333b..ccd2794 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,54 +1,27 @@ #!/bin/bash +source .fonctions # Charge les fonctions génériques habituellement utilisées dans le script + # Récupère les infos de l'application. -ynh_version=$(sudo yunohost -v | grep "moulinette:" | cut -d' ' -f2 | cut -d'.' -f1,2) +YNH_VERSION # Récupère le numéro de version de Yunohost. if [ $ynh_version = "2.4" ]; then app=$YNH_APP_INSTANCE_NAME # Source app helpers - . /usr/share/yunohost/helpers + source /usr/share/yunohost/helpers else app=leed MYSQL_ROOT_PWD_FILE="/etc/yunohost/mysql" fi domain=$(sudo yunohost app setting $app domain) -# Suppression de la base de donnée et de l'utilisateur associé. -# Utilise '$app' comme nom d'utilisateur et de base de donnée -db_user=$app -if mysqlshow -u root -p$(sudo cat $MYSQL_ROOT_PWD_FILE) | grep -q "^| $db_user"; then - echo "Delete db" - if [ $ynh_version = "2.4" ]; then - ynh_mysql_drop_db $db_user - ynh_mysql_drop_user $db_user - else - mysql -u root -p$(sudo cat $MYSQL_ROOT_PWD_FILE) -e "DROP DATABASE $db_user ; DROP USER $db_user@localhost ;" - fi -fi +REMOVE_BDD $app # Suppression de la base de donnée et de l'utilisateur associé. -# Suppression du dossier de l'application -if [ -e "/var/www/$app" ]; then # Delete final_path - echo "Delete app dir" - sudo rm -r "/var/www/$app" -fi +REMOVE_APP_DIR # Suppression du dossier de l'application -# Suppression de la configuration nginx -if [ -e "/etc/nginx/conf.d/$domain.d/$app.conf" ]; then # Delete nginx config - echo "Delete nginx config" - sudo rm "/etc/nginx/conf.d/$domain.d/$app.conf" - sudo service nginx reload -fi +REMOVE_NGINX_CONF # Suppression de la configuration nginx -# Suppression de la configuration du pool php-fpm -if [ -e "/etc/php5/fpm/pool.d/$app.conf" ]; then # Delete fpm config - echo "Delete fpm config" - sudo rm "/etc/php5/fpm/pool.d/$app.conf" -fi -if [ -e "/etc/php5/fpm/conf.d/20-$app.ini" ]; then # Delete php config - echo "Delete php config" - sudo rm "/etc/php5/fpm/conf.d/20-$app.ini" -fi -sudo service php5-fpm reload +REMOVE_FPM_CONF # Suppression de la configuration du pool php-fpm # Retirer le cron if [ -e "/etc/cron.d/$app" ]; then diff --git a/scripts/restore b/scripts/restore index 2e5e2b6..386b8fd 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,10 +1,11 @@ #!/bin/bash +# Source app helpers +source /usr/share/yunohost/helpers + # Récupère les infos de l'application. -version=$(sudo yunohost -v | grep "moulinette:" | cut -d' ' -f2 | cut -d'.' -f1,2) -if [ $version = "2.4" ]; then - app=$YNH_APP_INSTANCE_NAME -else +app=$YNH_APP_INSTANCE_NAME +if [ -z "$app" ]; then app=leed fi final_path=$(sudo yunohost app setting $app final_path) @@ -16,6 +17,12 @@ backup_dir=$1/apps/$app # Restore sources & data sudo cp -a $backup_dir/sources/. $final_path +# Créer la base de donnée et la restaure +db_pwd=$(sudo yunohost app setting $app mysqlpwd) +db_user=$app +ynh_mysql_create_db $db_user $db_user $db_pwd +mysql --debug-check -u $db_user -p$db_pwd $db_user < ${backup_dir}/db.sql + # Restore Nginx and YunoHost parameters sudo cp -a $backup_dir/yunohost/. /etc/yunohost/apps/$app sudo cp -a $backup_dir/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf diff --git a/scripts/upgrade b/scripts/upgrade index 1905f9b..06058c2 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,8 +1,10 @@ #!/bin/bash +source .fonctions # Charge les fonctions génériques habituellement utilisées dans le script + # Récupère les infos de l'application. -version=$(sudo yunohost -v | grep "moulinette:" | cut -d' ' -f2 | cut -d'.' -f1,2) -if [ $version = "2.4" ]; then +YNH_VERSION # Récupère le numéro de version de Yunohost. +if [ "$version" = "2.4" ]; then app=$YNH_APP_INSTANCE_NAME else app=leed @@ -11,14 +13,18 @@ domain=$(sudo yunohost app setting $app domain) path=$(sudo yunohost app setting $app path) admin=$(sudo yunohost app setting $app admin) is_public=$(sudo yunohost app setting $app is_public) +final_path=$(sudo yunohost app setting $app final_path) +db_pwd=$(sudo yunohost app setting $app mysqlpwd) +if [ -z $final_path ]; then # Si final_path n'est pas renseigné dans app setting + final_path=/var/www/$app + sudo yunohost app setting $app final_path -v $final_path +fi + +CHECK_PATH # Vérifie et corrige la syntaxe du path. + +SETUP_SOURCE "leed.tar.gz" # Télécharge la source, décompresse et copie dans $final_path -# Décompresse la source -tar -x -f ../sources/leed.tar.gz -# Copie les fichiers sources -sudo cp -a leed/. "$final_path" -# Copie les fichiers additionnels ou modifiés. -# sudo cp -a ../sources/ajouts/. "$final_path" # Et copie le fichier de config nginx sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf @@ -28,7 +34,7 @@ sudo chown -R www-data: $final_path # Change variables in Leed configuration sudo sed -i "s@__PATH__@$path@g" /etc/nginx/conf.d/$domain.d/$app.conf sudo sed -i "s@__FINALPATH__@$final_path@g" /etc/nginx/conf.d/$domain.d/$app.conf -sudo sed -i "s@NAMETOCHANGE@$app@g" /etc/nginx/conf.d/$domain.d/$app.conf +sudo sed -i "s@__NAMETOCHANGE__@$app@g" /etc/nginx/conf.d/$domain.d/$app.conf # Créer le fichier de configuration du pool php-fpm et le configure. sed -i "s@__NAMETOCHANGE__@$app@g" ../conf/php-fpm.conf @@ -49,9 +55,9 @@ sudo find $final_path -type d | xargs sudo chmod 755 # Les fichiers appartiennent à root sudo chown -R root: $final_path -# www-data doit avoir les droits d'écriture dans plugins et cache -sudo mkdir $final_path/cache -sudo chown -R www-data $final_path/cache $final_path/plugins +# www-data doit avoir les droits d'écriture dans plugins, cache et updates +sudo mkdir -p $final_path/cache +sudo chown -R www-data $final_path/cache $final_path/plugins $final_path/updates # Récupération du code de synchronisation @@ -65,16 +71,23 @@ sed -i "s@__PATH__@$path@g" ../conf/cron_leed sed -i "s@__CODESYNC__@$code_sync@g" ../conf/cron_leed sudo cp ../conf/cron_leed /etc/cron.d/$app +# Vide le cache de leed pour la mise à jour +sudo rm -rf $final_path/cache/* +# Laisse un accès libre pour curl. +sudo yunohost app setting $app unprotected_uris -v "/" +# Régénère la configuration de SSOwat +sudo yunohost app ssowatconf +# Lance la procédure de mise à jour de leed. +curl -kL https://$domain$path + # Make app private if necessary sudo yunohost app setting $app is_public -v "$is_public" if [ "$is_public" = "No" ]; then - # Retire l'autorisation d'accès de la page d'install. + # Retire l'autorisation d'accès à leed sudo yunohost app setting $app unprotected_uris -d # Rend la page d'actualisation accessible pour le script cron. sudo yunohost app setting $app skipped_uris -v "/action.php" -else # Si l'app est publique - sudo yunohost app setting $app unprotected_uris -v "/" fi # Recharge la configuration Nginx diff --git a/sources/ajouts/.gitignore b/sources/ajouts/.gitignore new file mode 100644 index 0000000..f0ff6f7 --- /dev/null +++ b/sources/ajouts/.gitignore @@ -0,0 +1,3 @@ +*.swp +*~ +Notes diff --git a/sources/ajouts/Functions.class.php b/sources/ajouts/Functions.class.php new file mode 100644 index 0000000..26c761b --- /dev/null +++ b/sources/ajouts/Functions.class.php @@ -0,0 +1,378 @@ + variable a sécuriser + * @param niveau de securisation + * @return variable securisée + */ + + public static function secure($var,$level = 1){ + $var = htmlspecialchars($var, ENT_QUOTES, "UTF-8"); + if($level<1)$var = mysqli_real_escape_string($var); + if($level<2)$var = addslashes($var); + return $var; + } + + + /** + * Return l'environnement/serveur sur lequel on se situe, permet de changer les + * connexions bdd en fonction de la dev, la préprod ou la prod + */ + public static function whereImI(){ + + $maps = array ( + 'LOCAL'=>array('localhost','127.0.0.1','0.0.0.1','::0.0.0.0'), + 'LAN'=>array('192.168.10.','valentin'), + 'PWAN'=>array('test.sys1.fr'), + 'WAN'=>array('www.sys1.fr'), + ); + + + $return = 'UNKNOWN'; + foreach($maps as $map=>$values){ + + foreach($values as $ip){ + $pos = strpos(strtolower($_SERVER['HTTP_HOST']),$ip); + if ($pos!==false){ + $return = $map; + } + } + } + return $return; + } + + public static function isLocal($perimeter='LOCAL'){ + $return = false; + + $localTab = array('localhost','127.0.0.1','0.0.0.1','::0.0.0.0'); + $lanTab = array('192.168.10.','valentin'); + + switch($perimeter){ + case 'LOCAL': + foreach($localTab as $ip){ + $pos = strpos(strtolower($_SERVER['HTTP_HOST']),$ip); + if ($pos!==false){ + $return = true; + } + } + break; + case 'LAN': + foreach($lanTab as $ip){ + $pos = strpos(strtolower($_SERVER['HTTP_HOST']),$ip); + if ($pos!==false){ + $return = true; + } + } + break; + case 'ALL': + foreach($localTab as $ip){ + $pos = strpos(strtolower($_SERVER['HTTP_HOST']),$ip); + if ($pos!==false){ + $return = true; + } + } + foreach($lanTab as $ip){ + $pos = strpos(strtolower($_SERVER['HTTP_HOST']),$ip); + if ($pos!==false){ + $return = true; + } + } + break; + } + + return $return; + } + + + /** + * Convertis la chaine passée en timestamp quel que soit sont format + * (prend en charge les formats type dd-mm-yyy , dd/mm/yyy, yyyy/mm/ddd...) + */ + public static function toTime($string){ + $string = str_replace('/','-',$string); + $string = str_replace('\\','-',$string); + + $string = str_replace('Janvier','Jan',$string); + $string = str_replace('Fevrier','Feb',$string); + $string = str_replace('Mars','Mar',$string); + $string = str_replace('Avril','Apr',$string); + $string = str_replace('Mai','May',$string); + $string = str_replace('Juin','Jun',$string); + $string = str_replace('Juillet','Jul',$string); + $string = str_replace('Aout','Aug',$string); + $string = str_replace('Septembre','Sept',$string); + $string = str_replace('Octobre','Oct',$string); + $string = str_replace('Novembre','Nov',$string); + $string = str_replace('Decembre','Dec',$string); + return strtotime($string); + } + + /** + * Recupere l'ip de l'internaute courant + * @author Valentin + * @return ip de l'utilisateur + */ + + public static function getIP(){ + if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ + $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];} + elseif(isset($_SERVER['HTTP_CLIENT_IP'])){ + $ip = $_SERVER['HTTP_CLIENT_IP'];} + else{ $ip = $_SERVER['REMOTE_ADDR'];} + return $ip; + } + + /** + * Retourne une version tronquée au bout de $limit caracteres de la chaine fournie + * @author Valentin + * @param message a tronquer + * @param limite de caracteres + * @return chaine tronquée + */ + public static function truncate($msg,$limit){ + if(mb_strlen($msg)>$limit){ + $fin='…' ; + $nb=$limit-mb_strlen($fin) ; + }else{ + $nb=mb_strlen($msg); + $fin=''; + } + return mb_substr($msg, 0, $nb).$fin; + } + + + function getExtension($fileName){ + $dot = explode('.',$fileName); + return $dot[sizeof($dot)-1]; + } + + /** + * Definis si la chaine fournie est existante dans la reference fournie ou non + * @param unknown_type $string + * @param unknown_type $reference + * @return false si aucune occurence du string, true dans le cas contraire + */ + public static function contain($string,$reference){ + $return = true; + $pos = strpos($reference,$string); + if ($pos === false) { + $return = false; + } + return strtolower($return); + } + + /** + * Définis si la chaine passée en parametre est une url ou non + */ + public static function isUrl($url){ + $return =false; + if (preg_match('/^(http|https|ftp)://([A-Z0-9][A-Z0-9_-]*(?:.[A-Z0-9][A-Z0-9_-]*)+):?(d+)?/?/i', $url)) { + $return =true; + } + return $return; + } + + /** + * Définis si la chaine passée en parametre est une couleur héxadécimale ou non + */ + public static function isColor($color){ + $return =false; + if (preg_match('/^#(?:(?:[a-fd]{3}){1,2})$/i', $color)) { + $return =true; + } + return $return; + } + + /** + * Définis si la chaine passée en parametre est un mail ou non + */ + public static function isMail($mail){ + $return =false; + if (filter_var($mail, FILTER_VALIDATE_EMAIL)) { + $return =true; + } + return $return; + } + + /** + * Définis si la chaine passée en parametre est une IP ou non + */ + public static function isIp($ip){ + $return =false; + if (preg_match('^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$',$ip)) { + $return =true; + } + return $return; + } + + public static function sourceName($string){ + $name = strtolower($string); + $name = str_replace(' ','-',$name); + $name = str_replace(''','-',$name); + $name = str_replace('\'','-',$name); + $name = str_replace(',','-',$name); + $name = str_replace(':','-',$name); + $name = str_replace('à','a',$name); + $name = trim($name); + $name = html_entity_decode($name,null,'UTF-8'); + return $name; + } + + public static function makeCookie($name, $value, $expire='') { + if($expire == '') { + setcookie($name, $value, mktime(0,0,0, date("d"), + date("m"), (date("Y")+1)),'/'); + }else { + setcookie($name, '', mktime(0,0,0, date("d"), + date("m"), (date("Y")-1)),'/'); + } + } + + public static function destroyCookie($name){ + Fonction::makeCookie($name,'',time()-3600); + unset($_COOKIE[$name]); + } + + public static function wordwrap($str, $width = 75, $break = "\n", $cut = false) + { + $str = html_entity_decode($str); + $str = htmlentities (wordwrap($str,$width,$break,$cut)); + $str = str_replace('<br/>','
',$str); + $str = str_replace('&','&',$str); + return $str; + } + + public static function createFile($filePath,$content){ + $fichier = fopen($filePath,"w+"); + $fwriteResult = fwrite($fichier,$content); + fclose($fichier); + } + + + + public static function convertFileSize($bytes) + { + if($bytes<1024){ + return round(($bytes / 1024), 2).' o'; + }elseif(1024<$bytes && $bytes<1048576){ + return round(($bytes / 1024), 2).' ko'; + }elseif(1048576<$bytes && $bytes<1073741824){ + return round(($bytes / 1024)/1024, 2).' Mo'; + }elseif(1073741824<$bytes){ + return round(($bytes / 1024)/1024/1024, 2).' Go'; + } + } + + + public static function hexaValue($str){ + $code = dechex(crc32($str)); + $code = substr($code, 0, 6); + return $code; + } + + public static function scanRecursiveDir($dir){ + $files = scandir($dir); + $allFiles = array(); + foreach($files as $file){ + if($file!='.' && $file!='..'){ + if(is_dir($dir.$file)){ + $allFiles = array_merge($allFiles,Fonction::scanRecursiveDir($dir.$file)); + }else{ + $allFiles[]=str_replace('//','/',$dir.'/'.$file); + } + } + } + return $allFiles; + } + + /** Permet la sortie directe de texte à l'écran, sans tampon. + Source : http://php.net/manual/fr/function.flush.php + */ + public static function triggerDirectOutput() { + // La ligne de commande n'en a pas besoin. + if ('cli'==php_sapi_name()) return; + if (function_exists('apache_setenv')) { + /* Selon l'hébergeur la fonction peut être désactivée. Alors Php + arrête le programme avec l'erreur : + "PHP Fatal error: Call to undefined function apache_setenv()". + */ + @apache_setenv('no-gzip', 1); + } + @ini_set('zlib.output_compression', 0); + @ini_set('implicit_flush', 1); + for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); } + ob_implicit_flush(1); + } + + public static function relativePath($from, $to, $ps = '/') { + $arFrom = explode($ps, rtrim($from, $ps)); + $arTo = explode($ps, rtrim($to, $ps)); + while(count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0])) { + array_shift($arFrom); + array_shift($arTo); + } + return str_pad("", count($arFrom) * 3, '..'.$ps).implode($ps, $arTo); + } + + + // Nettoyage de l'url avant la mise en base + public static function clean_url( $url ) { + $url = str_replace('&', '&', $url); + return $url; + } + + + + /** + * Méthode de test de connexion. + * @return true si ok + * @param server + * @param login + * @param pass + * @param db facultatif, si précisé alors tente de la séléctionner + */ + public static function testDb($server, $login, $pass, $db=null) { + /* Méthode hors des classes dédiées aux BDD afin de supporter le moins + de dépendances possibles. En particulier, pas besoin que le fichier + de configuration existe. */ + $link = mysqli_connect($server, $login, $pass, $db); + if (false===$link) return false; + mysqli_close($link); + return true; + } + + /** + * @return les langues acceptées par le navigateur + */ + public static function getBrowserLanguages() { + /* http://www.w3.org/International/questions/qa-lang-priorities.en.php + * ex: da, en-gb;q=0.8,en;q=0.7 --> array('da','en'); + */ + if (!array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) return array(); + $languages = array(); + $chunks = preg_split('/,\s*/', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + foreach($chunks as $chunk) $languages []= substr($chunk, 0, 2); + return array_unique($languages); + } + + /** + * @return boolean + */ + public static function isAjaxCall() { + return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'; + } +} +?> diff --git a/sources/ajouts/Update.class.php b/sources/ajouts/Update.class.php new file mode 100644 index 0000000..2340506 --- /dev/null +++ b/sources/ajouts/Update.class.php @@ -0,0 +1,113 @@ +connection; + //on sépare chaque requête par les ; + $sql_array = explode (";",$sql); + foreach ($sql_array as $val) { + $val = preg_replace('#([-].*)|(\n)#','',$val); + if ($val != '') { + //remplacement des préfixes de table + $val = str_replace('##MYSQL_PREFIX##',MYSQL_PREFIX,$val); + $result = $conn->query($val); + $ficlog = dirname(__FILE__).Update::FOLDER.'/'.substr($file,0,strlen($file)-3).'log'; + if (false===$result) { + file_put_contents($ficlog, date('d/m/Y H:i:s').' : SQL : '.$val."\n", FILE_APPEND); + file_put_contents($ficlog, date('d/m/Y H:i:s').' : '.$conn->error."\n", FILE_APPEND); + } else { + file_put_contents($ficlog, date('d/m/Y H:i:s').' : SQL : '.$val."\n", FILE_APPEND); + file_put_contents($ficlog, date('d/m/Y H:i:s').' : '.$conn->affected_rows.' rows affected'."\n", FILE_APPEND); + } + } + } + unset($conn); + } + $_SESSION = array(); + session_unset(); + session_destroy(); + } + // quand toutes les requêtes ont été executées, on insert le sql dans le json + Update::addUpdateFile(array($newFilesForUpdate)); + + return true; + } + +} + +?> \ No newline at end of file diff --git a/sources/leed.tar.gz b/sources/leed.tar.gz deleted file mode 100644 index cbe3490..0000000 Binary files a/sources/leed.tar.gz and /dev/null differ diff --git a/sources/source_dir b/sources/source_dir new file mode 100644 index 0000000..b4085d3 --- /dev/null +++ b/sources/source_dir @@ -0,0 +1 @@ +Leed-1.7 \ No newline at end of file diff --git a/sources/source_md5 b/sources/source_md5 new file mode 100644 index 0000000..8fd724b --- /dev/null +++ b/sources/source_md5 @@ -0,0 +1 @@ +f54a18cef71704be85e7b963cff19357 leed.tar.gz \ No newline at end of file diff --git a/sources/source_url b/sources/source_url new file mode 100644 index 0000000..a8cbbff --- /dev/null +++ b/sources/source_url @@ -0,0 +1 @@ +https://github.com/ldleman/Leed/archive/v1.7.tar.gz \ No newline at end of file