La Freebox V6 disposent d'API qui permettent de faire un md5.
Chose étrange, cet API n'est pas exposé dans l'interface "Freebox OS".
Pourtant, pouvoir vérifier qu'un fichier a bien été copié sur la Freebox en récupérant un md5 est très intéressant, surtout quand on est à distance. En effet, en local on peut toujours relire le fichier copié et comparer/faire le md5, mais à distance, avec l'upload ADSL limité, cela s'avère bien vite limitant pour des gros fichiers.
J'ai donc construit un script qui vous permet de faire un md5 de fichiers sur la Freebox.
Le voici :
#! /bin/sh
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# Version 2, December 2004
# Copyright (C) 2014 Zakhar @ ubuntu.fr
# Everyone is permitted to copy and distribute verbatim or modified
# copies of this license document, and changing it is allowed as long
# as the name is changed.
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
# 0. You just DO WHAT THE FUCK YOU WANT TO.
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# http://www.wtfpl.net/ for more details.
#===========================================================
#
# Fonction :
# ----------
# Réalise un md5 du/des fichier(s) passé(s) en paramètre.
# Ce script fonctionne uniquement avec une Freebox V6 (Révolution).
#
# Important :
# -----------
# Vous devez avoir autorisé votre application et inscrite dans les
# variables ci-dessous app_id/app_token
#
# Usage :
# -------
# fb5sum Fichier [...Fichiers]
#
# Version : 1.0
# -------
#
# Tested : Ubuntu Precise, Synology DSM4.2 (+coreutils)
# ------
#
# Date : 2014-04-13
# -----
#
# Author : Zakhar
# ------
#
# History :
# -------
#
# TODO:
# Il faudrait automatiser l'autorisation de l'appli... mais comme c'est l'affaire d'une seule commande :
# curl http://mafreebox.freebox.fr/api/v1/login/authorize -d '{"app_id":"fbxmd5","app_name":"Freebox MD5","app_version":"1.0","device_name":"Terminal"}'
#
# TODO
# On pourrait aussi afficher le temps restant et la vitesse de traitement, comme c'est affiché dans le panneau des tâches.
freebox="http://mafreebox.freebox.fr" #IP de la freebox
app_id="fbxmd5" #Valeur indiquée lors de l'autorisation en local
app_token="Mettez votre app_token ici" #Valeur retournée par la freebox lors de l'autorisation en local
session_token=''
id=0
cleaning=0
status=0
################## Usage ##################
if [ -z "${1}" ]; then
echo "Usage : fb5sum Fichier [...Fichiers]"
echo "Fichier : chemin complet du fichier ex. /Disque dur/Téléchargement/fichier.txt"
exit 1
fi
################## Nettoyage à la sortie ##################
cleanup()
{
cleaning=1
if [ -n "${session_token}" ]; then
[ ${id} -ne 0 ] && deleteTask
################### Logout ###################
out="$(curl -i -s "${freebox}/api/v${version}/login/logout" -H "X-Fbx-App-Auth: ${session_token}" -d '')"
session_token=''
successIsTrue "${out}" 'Erreur au logout !'
fi
exit $status
}
trap cleanup HUP INT QUIT ABRT TERM EXIT
################## Test HTTP 200 ##################
## @param 1: output de curl
## @param 2: chaine à afficher en cas d'erreur
http200()
{
if ! printf '%s' "${1}" | head -n1 | grep -q 'HTTP/1.1 200 OK'; then
echo
echo "${2}"
echo "${1}"
status=1
[ ${cleaning} -eq 0 ] && exit 1
fi
}
################## Test JSON success ##################
## @param 1: output de curl
## @param 2: chaine à afficher en cas d'erreur
successIsTrue()
{
http200 "${1}" "${2}"
if ! printf '%s' "${1}" | grep -q '"success":true'; then
echo
echo "${2}"
echo "${1}"
status=1
[ ${cleaning} -eq 0 ] && exit 1
fi
}
################## Test chaine non vide ##################
## @param 1: chaine à tester
## @param 2: chaine à afficher en cas d'erreur
## @param 3: output de curl
notEmpty()
{
if [ -z "${1}" ]; then
echo
echo "${2}"
echo "${3}"
status=1
[ ${cleaning} -eq 0 ] && exit 1
fi
}
################### Suppression de la tâche ###############
deleteTask()
{
out="$(curl -i -s -X DELETE "${freebox}/api/v${version}/fs/tasks/${id}" -H "X-Fbx-App-Auth: ${session_token}")"
id=0
successIsTrue "${out}" "Erreur suppression de la tâche."
}
###########################################################
################## Début de la connexion ##################
###########################################################
################## Lecture de la version ##################
printf "Connexion ... 1/3"
out="$(curl -i -s "${freebox}/api_version")"
http200 "${out}" "Erreur HTTP."
version="$(printf "%s" "${out}" | sed '/api_version/ !d;s/.*api_version":"//;s/\([0-9]*\)\..*/\1/')"
notEmpty "${version}" "Impossible de lire la version." "${out}"
################## Obtention du challenge #################
printf "\b\b\b2/3"
out="$(curl -i -s "${freebox}/api/v${version}/login")"
successIsTrue "${out}" "Erreur, impossible d'initier un login."
challenge="$(printf "%s" "${out}" | sed '/"success"/ !d;s|.*"challenge":"||;s|",.*||;s|\\/|/|g')"
notEmpty "${challenge}" "Impossible d'obtenir le challenge." "${out}"
#### Création du password = hash($challenge,$app_token) ######
password="$(printf '%s' "${challenge}" | openssl dgst -sha1 -hmac $app_token | sed 's/(stdin)= //')"
################## Ouverture de la session ################
printf "\b\b\b3/3"
out="$(curl -i -s "${freebox}/api/v${version}/login/session/" -d "{\"app_id\":\"${app_id}\",\"password\":\"${password}\"}")"
successIsTrue "${out}" "Erreur, impossible d'ouvrir la session."
session_token="$(printf '%s' "${out}" | sed '/"success"/ !d;s|.*"session_token":"||;s|",.*||;s|\\/|/|g')"
notEmpty "${session_token}" 'Impossible de lire le token de session.' "${out}"
printf "\b\b\bOK \n"
###########################################################
################### fin de la connexion ###################
###########################################################
###########################################################
################## Calcul des MD5 ##################
###########################################################
for f in "$@"; do
################## Soumission de la tâche #################
out="$(curl -i -s "${freebox}/api/v${version}/fs/hash/" -H "X-Fbx-App-Auth: ${session_token}" -d "{\"src\":\"$(printf '%s' "${f}" | base64 -w0)\",\"hash_type\":\"md5\"}")"
successIsTrue "${out}" 'Soumission de la tâche impossible.'
id="$(printf '%s' "${out}" | sed '/"success"/ !d;s|.*"id":||;s|,.*||')"
notEmpty "${id}" "Impossible de lire l'ID de la tâche." "${out}"
while :; do
########### Récupération de l'avancement ###############
out="$(curl -i -s "${freebox}/api/v${version}/fs/tasks/${id}" -H "X-Fbx-App-Auth: ${session_token}")"
successIsTrue "${out}" "Lecture de l'avancement de la tâche impossible."
progress="$(printf '%s' "${out}" | sed '/"success"/ !d;s|.*"progress":||;s|}.*||')"
notEmpty "${progress}" 'Impossible de lire la progression de la tâche.' "${out}"
printf "\b\b\b%2u%%" $progress
state="$(printf '%s' "${out}" | sed '/"success"/ !d;s|.*"state":"||;s|",.*||')"
notEmpty "${state}" "Impossible de lire l'état de la tâche." "${out}"
case "${state}" in
'queued') printf "\rEn attente."
;;
'running') printf "\rEn cours : %2u%% " ${progress}
;;
'paused') printf "\rEn pause : %2u%% " ${progress}
;;
'done') printf "\rTerminé : 100%%"
break
;;
'failed') printf "\rEchoué. "
break
;;
*) printf "\rEtat inconnu : %s" "${state}"
break
esac
sleep 2
done
if [ "${state}" = 'done' ]; then
################## Lecture du résultat (md5) ###############
out="$(curl -i -s "${freebox}/api/v${version}/fs/tasks/${id}/hash" -H "X-Fbx-App-Auth: ${session_token}")"
successIsTrue "${out}" "Erreur lecture du hash."
hash="$(printf '%s' "${out}" | sed '/"success"/ !d;s|.*"result":"||;s|".*||')"
printf "\r%s %s\n" "${hash}" "${f}"
else
################## Lecture de la cause d'erreur ############
error="$(printf '%s' "${out}" | sed '/"success"/ !d;s|.*"error":"||;s|",.*||')"
printf "\rEchec: %s %s\n" "${error}" "${f}"
fi
deleteTask
done
L'usage est simple, une fois que vous avez récupéré le source et que vous l'avez rendu exécutable, vous lancez avec :
./fbxmd5.sh 'Disque dur/Téléchargement/mon_Fichier.iso'
IMPORTANT: au préalable, vous devez autoriser l'application et obtenir un 'token'.
Pour cela, exécutez la ligne de commande indiquée en commentaire dans les TODO, autorisez l'application, récupérez le token affiché et mettez le dans la variable app_token.
Au niveau des autorisations, vous pouvez restreindre l'application à l'accès aux fichiers seulement, cela suffit.
Testé sur Ubuntu et sur Synology (DSM4.2, nécessite l'installation des coreutils)