#!/bin/sh -e
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
# Version 2, December 2004
# Copyright (C) 2010-2013 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 :
# ----------
# - Télécharge automatiquement un lien ou une liste de liens free spécifiés dans
# un fichier passé en paramètre 1.
# NOTE: la liste de lien peut être une page web, le script extrait les liens
# qui ont un pattern correct correspondant à un lien dl.free
# Il ne s'agit cependant pas d'un "parsing", par ex. si les liens sont
# raccourcis par une balise le script ne
# trouvera pas. Cependant pour des liens postés dans des forums, ce genre
# de "truc" n'existe pas, et les liens sont en général trouvés.
# En cas de difficulté, la solution consiste alors à extraire les liens
# 'manuellement' avec un éditeur de texte.
# - Réessaye en cas d'erreurs du serveur (infini, CTRL+C pour stopper)
# - Le téléchargement peut être interrompu à tout moment. Il reprendra
# exactement où il avait été interrompu.
# - Lorsqu'on a passé un fichier contenant des liens et qu'on reprend le
# téléchargement, celui-ci saute les fichiers déjà téléchargés.
# - Les fichiers résultants possèdent le nom donnés par l'uploader.
# Si ce nom n'est pas récupérable, le nom du lien à la place.
# - On peut lancer plusieurs scripts de téléchargement en parallèle à
# condition qu'ils ne portent pas sur les mêmes liens à télécharger.
#
# Usage :
# -------
# Voir description dans la fonction usage()
#
# Remarque : ce script fonctionne que vous soyez chez Free ou pas
# ========== (sinon c'est juste BEAUCOUP plus long quand on n'est pas chez Free !)
# Rectificatif : Depuis la fin de Megaupload, pour lutter contre la surcharge et que
# =========== les freenautes puissent avoir un service décent, Free a mis en place
# un captcha pour les non Freenautes. Le script ne fonctionne donc plus
# si l'on n'est pas chez Free, et il n'y a rien qu'on puisse faire.
#
# Tested : Ubuntu Lucid, Precise, Synology DS413j
# ------
#
# Version : 2.5
# -------
#
# Date : 2013-04-19
# -----
#
# Author : Zakhar
# ------
#
# History :
# -------
# 2.5
# - Adaptations pour Synology. Affichage plus "propre" (sous screen de façon à
# pouvoir laisser tourner en "tâche de fond").
# Sur Synology, il faut rajouter 2 packages : coreutils et libcurl (pour curl)
# Adpatations pour ne pas se planter sur iconv (inexistant) ni sur file
# qui existe pour Synology mais provoque un segfault.
# 2.4
# - Rajout du CSRF (firmware 1.1.9) pour téléchargement par la Freebox.
# - La mention "Fichier déjà en cours de téléchargement" est réservée au
# téléchargement sur le PC lui-même. On ne l'affiche pas lorsqu'on vérifie
# où en est la Freebox (ie avec -rc ou -pc ou -mc)
# 2.3
# - La taille du fichier à télécharger est désormais indiquée lorsqu'on utilise
# l'option -c. Cela permet, lors de la vérification, d'éviter d'entamer un
# téléchargement si certains fichiers de la liste sont soupçonnés "incomplets".
# 2.2
# - Licence changée en WTFPL V2
# - Signalement d'un bug par netbja lors d'une utilisation avec screen
# (http://forum.ubuntu-fr.org/viewtopic.php?pid=12093101#p12093101)
# Désormais, lancé avec screen ou byobu, le script fonctionne correctement
# les ecritures à l'écran se font en monochrome.
# 2.1.1
# Les scripts lancés en parallèle tiennent désormais compte du marquage
# correctement. Le fichier de lien est marqué avec un lock, et relu à chaque
# item pour vérifier si un téléchargement parallèle a eu lieu et s'est terminé.
# 2.1.0
# - Le post de Lapogne71 (http://forum.ubuntu-fr.org/viewtopic.php?id=896681)
# m'a donné l'idée de rendre le script "parallèle". En réalité, pour ne pas
# rentrer dans cette complexité et aussi pour garder un affichage clair,
# vous pouvez désormais lancer le script sur une même liste dans plusieurs
# terminaux, si le fichier est déjà en cours de téléchargement (dans un
# autre terminal), cela vous sera indiqué, et on passe au fichier suivant.
# Et en réalité c'était très facile à faire... puisque Free nous dit lorsque
# on tente de charger 2 fois le même fichier (c'est une des limites posées
# par Free pour éviter les "accélérateurs de téléchargement).
# Donc si vous avez un liste de 15 fichiers et que vous voulez paralléliser
# il suffit de lancer le script avec le nom de la liste en paramètre sur
# plusieurs terminaux. Le maximum est 6, puisque au delà Free bloque au delà.
# 2.0.0
# - Version curl / dash + extraction intelligente de liens
#
# Contributor : // Ajouter votre nom si vous contribuez et redistribuez //
# -----------
# ======================================================================================
# Notes à l'attention des futurs contributeurs (et pour mémoire pour moi-même)!
# -----
#
# Particularités (bug ?) Free.
# - Pour obtenir le nom du fichier, il suffit d'avoir le header --content-disposition
# En principe on pourrait faire juste un HEAD mais cela échoue et dl.free.fr retourne
# une erreur 404 sur ce HEAD
# On utilise donc une "ruse", on fait un GET normal en demandant un "range"
# impossible. La réponse normale est alors 416 (Range impossible) si on est chez Free
# et sinon on obtient une page avec le lien vers le fichier à télécharger.
#
# Différences Freenautes/Non Freenautes.
# - Pour un Freenaute, l'activation du lien télécharge directement le fichier
# - Un non Freenaute va récupérer une page de formulaire dans laquelle figure
# le nom du fichier spécifié par l'uploader et un lien de téléchargment.
#
# - Les status header HTTP qui nous intéressent sont :
# 404 : là on arrête le script vu qu'un fichier est irrécupérable.
# 200 : OK
# 206 : dans le cas d'une reprise (contenu partiel) après un CTRL+C
# 416 : dans le cas du contournement expliqué plus haut. Cela peut aussi arriver si
# on a détruit réinitialisé le fichier des liens et que certains fichiers sont
# déjà complètement téléchargés. Dans ce cas on ira voir au serveur, et on
# constate que la longueur du fichier est la même que le fichier local, et le
# serveur rendra donc 416. Ce n'est donc pas une erreur à proprement parler
# pour ce qui nous concerne.
# 500 : cela signale une surcharge du serveur. Dans ce cas on temporise et
# on refait un essai.
#
# - Si curl rencontre une erreur, c'est de toute façon irrécupérable. Dans ce cas le
# script s'arrêtera car il est lancé avec l'option '-e'
#
# ======================================================================================
# --------------------------------------------------------------------------------------
# Variables et fonctions utilitaires (usage et trap) |
# --------------------------------------------------------------------------------------
SLEEP=30
fCHECK='n'
fFORCE='n'
fMARK='n'
fFBX='n'
fCPY='n'
fREN='n'
fMOVE='n'
fVERB='n'
FILTRE=''
LINKS=''
LIST=''
DEST=''
PATTERN='http://dl.free.fr/'
LOCK_FILE='/tmp/dlfree.lock'
LIST_FILE='/tmp/dlfree.list'
FBX_CONFIG_FILE="${HOME}/.config/mafreebox.conf"
FBX_IP_PORT='mafreebox.freebox.fr'
fbxCSRF=''
JSONRPC='{"jsonrpc":"2.0","method":'
# --------------------------------------------------------------------------------------
# Fonction de nettoyage final et trap en cas d'arrêt forcé du script |
# --------------------------------------------------------------------------------------
clean() { rm "${TMPLOG}" "${TMPLOG}".?; }
trap clean HUP INT QUIT ABRT TERM
# --------------------------------------------------------------------------------------
# Contournement permettant par exemple d'utiliser le script via phpshell qui lance |
# un terminal "basique" ne supportant pas tput. |
# --------------------------------------------------------------------------------------
if tput sgr0 2>/dev/null && tput setf 9 2>/dev/null; then
TPUT='tput'
hBAR='─────────────────────────────────────'
vStar='⬕'
else
TPUT='nop'
hBAR='-------------------------------------'
vStar='*'
fi
nop()
{
:
}
# --------------------------------------------------------------------------------------
# Diverses fonctions utilitaires |
# --------------------------------------------------------------------------------------
usage()
{
if [ -n "$1" ]; then ${TPUT} bold; printf "\n%s\n\n" "${1}"; ${TPUT} sgr0; fi
cat <, --sleep= Spécifie le temps d'attente en cas de problème serveur.
-v, --verbose Mode verbeux.
-V, --version Affiche la version du script.
EOF
if [ -n "${TMPLOG}" ]; then clean; fi
exit $#
}
vecho()
{
if [ "${fVERB}" = 'y' ]; then
printf "${vStar} %s\n" "${1}"
fi
}
cyan() { ${TPUT} setf 3; ${TPUT} bold; }
red() { ${TPUT} setf 4; ${TPUT} bold; }
yellow() { ${TPUT} setf 6; ${TPUT} bold; }
normal() { ${TPUT} setf 9; ${TPUT} sgr0; }
abort()
{
ERR=${1}
if [ ${1} -ne 0 ]; then red; fi
until shift && [ -z "${1}" ]; do
printf '%s\n' "${1}"
done
if [ -n "${TMPLOG}" ]; then clean; fi
normal
exit 1
}
jsoncatch()
{
if [ "${HTTP_CODE}" -ne 200 ] || grep ',"error":' "${TMPLOG}" >/dev/null; then
echo "\n** Erreur JSON avec la Freebox."
cat "${TMPLOG}"
clean
exit
fi
}
freebox_start_dl()
{
HTTP_CODE=$( curl "http://${FBX_IP_PORT}/download.cgi" \
-o "${TMPLOG}" \
-b "${TMPLOG}.f" \
-d "url=${IDENT}&user=freebox&method=download.http_add" \
--data-urlencode "csrf_token=${fbxCSRF}" \
-H 'X-Requested-With: XMLHttpRequest' \
-w "%{http_code}" \
-s)
jsoncatch
}
marklink()
{
if [ ${fMARK} = 'y' ]; then
(
flock 9
sed -i -e "s|${IDENT}|# &\|${NAME}|" "${LINKS}"
) 9>"/tmp/${LINKS}.lock"
rm -f "/tmp/${LINKS}.lock"
fi
}
checkform()
{
if [ "${fMARK}" = 'y' ]; then
vecho "-k ignoré dans cette forme"
fMARK='n'
fi
}
# Priorité : move / rename / copy / freebox
ignorefbx()
{
if [ "${fFBX}" = 'y' ]; then
vecho "-b est ignoré lorsque ${1} est spécifié"
fFBX='n'
fi
}
ignorecpy()
{
if [ "${fCPY}" = 'y' ]; then
vecho "-p est ignoré lorsque ${1} est spécifié"
fCPY='n'
fi
ignorefbx "${1}"
}
checkprio()
{
if [ "${fMOVE}" = 'y' ]; then
if [ "${fREN}" = 'y' ]; then
vecho "-r est ignoré lorsque -m est spécifié"
fREN='n'
fi
ignorecpy '-m'
else
if [ "${fREN}" = 'y' ]; then
ignorecpy '-r'
else
if [ "${fCPY}" = 'y' ]; then
ignorefbx '-p'
fi
fi
fi
}
checkmark()
{
if [ "${fCHECK}" = 'y' -a "${fMARK}" = 'y' ]; then
vecho "-k est ignoré lorsque -c est spécifié"
fMARK='n'
fi
}
checkforce()
{
if [ "${fCHECK}" = 'y' -a "${fFORCE}" = 'y' ]; then
vecho "-f est ignoré lorsque -c est spécifié"
fFORCE='n'
fi
}
param2()
{
printf '%s' "${1}" | cut -c "${2}"- | sed 's/[=|:]\?//'
}
# --------------------------------------------------------------------------------------
# Lecture et vérification des paramètres |
# --------------------------------------------------------------------------------------
echo
until [ -z "${1}" ]; do
case "${1}" in
--freebox ) fFBX='y'; checkprio ;;
--check ) fCHECK='y'; checkforce; checkmark ;;
--filtre ) FILTRE=$2; shift ;;
--filtre* ) FILTRE=$( param2 "${1}" 9 ) ;;
--force ) fFORCE='y'; checkforce ;;
--help ) usage ;;
--mark ) fMARK='y'; checkmark ;;
--move ) fMOVE='y'; checkprio ;;
--copy ) fCPY='y'; checkprio ;;
--rename ) fREN='y' ; checkprio ;;
--sleep ) SLEEP=$2; shift ;;
--sleep* ) SLEEP=$( param2 "${1}" 8 ) ;;
--verbose ) fVERB='y' ;;
--version ) printf "%s\n" "$( basename ${0} ): Version 2.5"; exit 0 ;;
- ) usage "Paramètre non spécifié : '-'" ;;
-* )
i=2
while [ ${i} -le ${#1} ]
do
case $( printf '%s' "${1}" | cut -c ${i} ) in
b ) fFBX='y'; checkprio ;;
c ) fCHECK='y'; checkforce; checkmark ;;
e ) if [ ${i} -eq ${#1} ]; then
FILTRE=$2; shift
else
FILTRE=$( param2 "${1}" ${i} )
fi
break
;;
f ) fFORCE='y'; checkforce ;;
h ) usage ;;
k ) fMARK='y'; checkmark ;;
m ) fMOVE='y'; checkprio ;;
p ) fCPY='y'; checkprio ;;
r ) fREN='y' ; checkprio ;;
s ) if [ ${i} -eq ${#1} ]; then
SLEEP=$2; shift
else
SLEEP=$( param2 "${1}" ${i} )
fi
break
;;
v ) fVERB='y' ;;
V ) printf "%s\n" "$( basename ${0} ): Version 2.5"; exit 0 ;;
* ) usage "Paramètre incorrect : '-$(printf '%s' ${1} | cut -c ${i})'" ;;
esac
i=$(( ${i} + 1 ))
done
;;
*) if [ -n "${LINKS}" ]; then
if [ -n "${DEST}" ]; then
usage "Argument en trop : '${1}'."
else
DEST="${LINKS}"
LINKS="${1}"
fi
else
LINKS="${1}"
fi
;;
esac
shift
done
vecho "Lecture des paramètres OK"
# --------------------------------------------------------------------------------------
# Si on est en 'copie/move' de la Freebox, le premier paramètre est la destination. |
# Si 2 paramètres avaient été donnés, c'est déjà OK, mais sinon il faut inverser. |
# Si aucun paramètre, on fixe DEST au répertoire courant : '.' |
# Sinon, on vérifie juste si on n'a pas donné trop de paramètres ou aucun ! |
# Dans le cas du rename, 0 param est OK, 1 est rename sur liste de filtrage |
# --------------------------------------------------------------------------------------
vecho "Détermination de la forme utilisée"
if [ "${fREN}" = 'y' ]; then
if [ -n "${DEST}" ]; then
usage "Argument en trop : '${DEST}'."
fi
if [ "${fFORCE}" = 'y' ]; then
vecho "-f sera ignoré dans cette forme"
fFORCE='n'
fi
if [ -z "${LINKS}" ]; then
vecho "Forme 4 : renommage total sur la Freebox"
if [ "${fMARK}" = 'y' ]; then
vecho "-k sera ignoré dans cette forme"
fMARK='n'
fi
else
vecho "Forme 4 : renommage sur la Freebox filtré par liste"
fi
else
if [ "${fCPY}" = 'y' -o "${fMOVE}" = 'y' ]; then
if [ -z "${DEST}" ]; then
vecho "Forme 4 : copie/déplacement total de la Freebox"
DEST="${LINKS}"
LINKS=''
if [ -z "${DEST}" ]; then
DEST='.'
fi
if [ "${fMARK}" = 'y' ]; then
vecho "-k sera ignoré dans cette forme"
fMARK='n'
fi
else
vecho "Forme 4 : copie/déplacement de la Freebox filtré par liste"
fi
if [ ! -d "${DEST}" ]; then
abort 1 "Erreur, le chemin spécifié n'est pas un répertoire : '${DEST}'"
fi
else
if [ -n "${DEST}" ]; then
usage "Argument en trop : '${DEST}'."
fi
if [ -z "${LINKS}" ]; then
usage "Pas de lien ni de fichier spécifié."
fi
fi
fi
# --------------------------------------------------------------------------------------
# Récupération des liens selon la forme utilisée |
# 1ère forme: un lien unique de type http://dl.free.fr/123456789 |
# 2ème forme: une page web contenant des liens de la forme ci-dessus |
# 3ème forme: un fichier contenant des liens de la forme ci-dessus |
# 4ème forme: idem aux 3 autres, mais facultatif |
# --------------------------------------------------------------------------------------
if [ -z ${TMPLOG} ]; then TMPLOG=$( mktemp ); fi
touch "${TMPLOG}.f"
if [ -n "${LINKS}" ]; then
SVG_LINKS="${LINKS}"
if printf '%s' "${LINKS}" | egrep "^http://|^https://|^ftp://" >/dev/null; then
if printf '%s' "${LINKS}" | grep "^${PATTERN}" >/dev/null; then
if [ ${#LINKS} -eq 27 ]; then
LIST="${LINKS}"
vecho "Forme 1 : lien unique dl.free.fr complet."
checkform
else
usage "Lien unique incorrect : '${LINKS}'"
fi
else
vecho "Forme 2 : lien vers une page web."
HTTP_CODE=$( curl "${LINKS}" -s -o "${TMPLOG}.f" -w '%{http_code}' )
if [ "${HTTP_CODE}" = "200" ]; then
vecho "Récupération de la page web réussie"
LINKS="${TMPLOG}.f"
checkform
else
abort "** Erreur récupération de la page contenant des liens : '${LINKS}'"
fi
fi
fi
if [ -z "${LIST}" ]; then
if [ -f "${LINKS}" ]; then
if [ "${LINKS}" = "${SVG_LINKS}" ]; then
vecho "Forme 3 : fichier contenant des liens"
fi
vecho "Extraction des liens dl.free.fr"
#
# Si file n'existe pas (sur Syno il fait un segfault) on prie que le lien soit OK!
#
which file >/dev/null && {
ENCODE=$( file "${LINKS}" --mime-encoding | sed 's/.*: //' )
if [ "${ENCODE}" = 'binary' ]; then
abort 1 "** Erreur, le fichier fourni est un fichier binaire : '${SVG_LINKS}'"
fi
}
LIST=$( sed "s|\(#\?[ |\t]*\)\?\(${PATTERN}.........\)|\2\1 \n|g" "${LINKS}" \
| { LANG="en_GB.${ENCODE}" && \
sed -n "s|.*\(${PATTERN}..........\)|\1|p" ; \
} | uniq -w 27 | sed '/#/d;s/ //' )
else
if [ ${#LINKS} -gt 27 -o ${#LINKS} -lt 9 ]; then
abort 1 "Erreur, fichier inexistant ou lien unique incorrect : '${LINKS}'"
fi
LIST="$( printf '%s' ${PATTERN} | cut -c -$(( 27 - ${#LINKS})) )${LINKS}"
if printf '%s' "${LIST}" | grep -v "^${PATTERN}" >/dev/null; then
abort 1 "Erreur, fichier inexistant ou lien unique incorrect : '${LINKS}'"
else
vecho "Forme 1 : lien unique dl.free.fr partiel."
checkform
fi
fi
fi
if [ -z "${LIST}" ]; then
abort 0 "Arrêt, aucun fichier dl.free.fr trouvé dans '${SVG_LINKS}'"
fi
vecho "Détermination de la forme d'usage réussie"
fi
# --------------------------------------------------------------------------------------
# Récupération du mot de passe de la Freebox (fichier config ou clavier) |
# --------------------------------------------------------------------------------------
if [ "${fCPY}" = 'y' -o "${fMOVE}" = 'y' -o "${fFBX}" = 'y' -o "${fREN}" = 'y' ]; then
vecho "Initialisation de la communication avec la Freebox"
if [ -f "${FBX_CONFIG_FILE}" ]; then
vecho "Fichier mot de passe trouvé"
. "${FBX_CONFIG_FILE}"
fi
if [ -z "${PASSWORD}" ]; then
stty_orig=`stty -g`
stty -echo
read -p "Mot de passe de votre FreeBox: " PASSWORD
stty $stty_orig
echo
fi
HTTP_CODE=$( curl "http://${FBX_IP_PORT}/login.php"\
-c "${TMPLOG}.f"\
-d "login=freebox&passwd=$PASSWORD"\
-o /dev/null \
-D "${TMPLOG}.e" \
-w "%{http_code}"\
-s )
# Quand le mot de passe est correct, on a 302, mais on veut juste le cookie
# donc on ne met pas d'option -L pour récupérer la page après login
# Sinon, un mot de passe incorrect rend une page qui l'indique + un HTTP_CODE à 200
if [ "${HTTP_CODE}" -ne 302 ]; then
abort 1 "** Mot de passe incorrect."
fi
fbxCSRF="$( sed -n -e '/X-FBX-CSRF-Token: /s/X-FBX-CSRF-Token: //p' "${TMPLOG}.e" | sed 's/\r//' )"
rm -rf "${TMPLOG}.e"
vecho "Initialisation communication Freebox réussie"
fi
# --------------------------------------------------------------------------------------
# 4ème forme, on veut récupérer des fichiers présents sur la Freebox |
# -1) Lecture du répertoire où sont téléchargés les fichiers |
# -2) Lecture de la liste des fichiers téléchargés depuis dl.free.fr |
# --------------------------------------------------------------------------------------
if [ "${fCPY}" = 'y' -o "${fMOVE}" = 'y' -o "${fREN}" = 'y' ]; then
vecho "Initialisations pour la Forme 4"
vecho "Récupération de répertoire de téléchargement"
HTTP_CODE=$(curl "http://${FBX_IP_PORT}/download.cgi"\
-o "${TMPLOG}" \
-b "${TMPLOG}.f" \
--data "${JSONRPC}\"download.config_get\"}" \
-H 'Content-Type: application/json; charset=utf-8' \
-w '%{http_code}'\
-s )
jsoncatch
DL_DIR=$( sed 's/.*,"download_dir":"//;s/","max_dl":.*//;s|\\/|/|g' "${TMPLOG}" )
vecho "Récupération de la liste des fichiers dans ce répertoire"
HTTP_CODE=$(curl "http://${FBX_IP_PORT}/fs.cgi"\
-o "${TMPLOG}" \
-b "${TMPLOG}.f" \
--data "${JSONRPC}\"fs.list\",\"id\":0.$(od -An -N8 -t fD /dev/urandom| sed 's/.*,//;s/e.*//'),\"params\":[\"${DL_DIR}\",{\"with_attr\":true}]}" \
-H 'Content-Type: application/json; charset=utf-8' \
-w '%{http_code}'\
-s )
jsoncatch
DL_DIR_LIST=$( sed -e 's|.*"jsonrpc":"2.0","result":\[\?||;s|\]\?}$||' -e 's/},/}\n/g' "${TMPLOG}" )
vecho "Récupération de la liste des téléchargements"
HTTP_CODE=$(curl "http://${FBX_IP_PORT}/download.cgi"\
-o "${TMPLOG}" \
-b "${TMPLOG}.f" \
--data "${JSONRPC}\"download.list\"}" \
-H 'Content-Type: application/json; charset=utf-8' \
-w '%{http_code}'\
-s )
jsoncatch
FBX_LIST=$( sed -e 's/^{"jsonrpc":"2.0","result":\[\?//;s/\]\?}$//' -e 's/},/}\n/g'\
<"${TMPLOG}" | sed -n '/"url":"http:\\\/\\\/dl.free.fr\\\//p')
if [ -z "${FBX_LIST}" ]; then
abort 0 "Pas de fichiers à traiter sur la Freebox."
fi
if [ -z "${LIST}" ]; then
LIST=$( printf '%s' "${FBX_LIST}" | sed 's/.*,"url":"//;s/","rx_rate.*//;s|\\/|/|g')
fi
fi
if [ "${fCHECK}" = 'y' ]; then
vecho "Mode vérification d'existence seulement (pas de téléchargement)"
if [ "${fCPY}" = 'y' ]; then
vecho "Fichiers seulement vérifiés sur la Freebox"
fi
if [ "${fMOVE}" = 'y' -o "${fREN}" = 'y' ]; then
vecho "Fichiers vérifiés et éventuellement réparés sur la Freebox"
fi
else
if [ "${fFORCE}" = 'y' ]; then
if [ "${fCPY}" = 'y' -o "${fMOVE}" = 'y' ]; then
vecho "Copie/déplacement avec écrasement si les fichiers existent déjà"
else
if [ "${fFBX}" = 'y' ]; then
vecho "-f est ignoré lorsque -b est spécifié"
fFORCE='n'
else
vecho "Téléchargement avec reprise si les fichiers existent déjà"
fi
fi
fi
fi
# --------------------------------------------------------------------------------------
# Boucle principale de téléchargement des fichiers |
# --------------------------------------------------------------------------------------
for IDENT in ${LIST}
do
printf "\n\n${hBAR}\nFichier : %s\n" ${IDENT}
BASE_IDENT=$( basename "${IDENT}" )
if grep -qs "# ${IDENT}" "${LINKS}"; then
echo "Déjà téléchargé en parallèle."
continue
fi
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Vérifie l'existence du fichier et trouve le nom de la destination |
while :
do
HTTP_CODE=$( curl "${IDENT}" -s -L --cookie-jar "${TMPLOG}.c" -D "${TMPLOG}.h"\
--header 'Range: bytes=-0' -o "${TMPLOG}" -w "%{http_code}" )
case ${HTTP_CODE} in
404) abort 1 "*!* Ficher inexistant : ${IDENT}"\
"Téléchargement impossible."
;;
200) echo "\n** Ce script ne fonctionne ainsi que si vous êtes chez Free !\n"
exit
;;
416) NAME=$( tr -d '\r' <"${TMPLOG}.h" |\
sed -n '/Content-disposition/s/.*filename=//p;s/^M//g' )
if [ -z "${NAME}" ]; then NAME="${BASE_IDENT}"; fi
break
;;
*) echo "\n** Erreur serveur (${HTTP_CODE}) : attente ${SLEEP}s\n"
sleep ${SLEEP} 2>/dev/null || sleep 30
;;
esac
done
#
# Dans le header, il n'y a rien qui indique l'encoding du nom de fichier. |
# On teste donc si le nom est valide en utf-8, et sinon on suppose que c'est de |
# l'iso-8859-1
# S'il n'y a pas iconv (Synology)... prions !..
which iconv >/dev/null && \
if [ $( printf '%s' "${NAME}" | iconv -f utf-8 -t utf-8 -c -s ) != "${NAME}" ]; then
NAME=$( printf '%s' "${NAME}" | iconv -f iso-8859-1 -t utf-8 -s )
fi
if [ "${NAME}" = "${BASE_IDENT}" ]; then
if [ "${fCPY}" != 'y' -a "${fMOVE}" != 'y' -a "${fREN}" != 'y' ]; then
echo "Fichier déjà en cours de téléchargement"
fi
else
printf "Cible : "; yellow; printf '%s\n' "${NAME}"; normal
if [ "${fCHECK}" = 'y' ]; then
printf 'Taille : %s\n' $(sed -n '/Content-Range/s|.*/||p' "${TMPLOG}.h")
fi
fi
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Filtrage si l'option --filtre a été spécifiée (et la chaine non nulle !) |
if [ -n "${FILTRE}" ]; then
if printf '%s' "${NAME}" | grep -vE "${FILTRE}"; then
printf "Fichier non traité (filtrage par option --filtre)"
continue
fi
fi
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Vérification d'existence si on n'a pas mis l'option --force |
if [ "${fFORCE}" = 'n' -a "${fCHECK}" = 'n' ]; then
if [ "${fCPY}" = 'y' -o "${fMOVE}" = 'y' ]; then
TARGET="${DEST}/${NAME}"
else
TARGET="${NAME}"
fi
if [ "${fFBX}" = 'n' -o "${fCPY}" = 'y' -o "${fMOVE}" = 'y' ]; then
if [ -f "${TARGET}" ]; then
abort 1 "*!* Fichier cible existe déjà : ${TARGET}" \
"Vous pouvez :" \
"- Supprimer le fichier au préalable ou" \
"- Utiliser l'option -f pour forcer la réécriture/reprise."
fi
fi
fi
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Télécharge le fichier si pas en mode vérification |
while [ "${fCHECK}" = 'n' -a "${fCPY}" = 'n' -a "${fMOVE}" = 'n' -a \
"${fREN}" = 'n' -a "${NAME}" != "${BASE_IDENT}" ]
do
if [ "${fFBX}" = 'y' ]; then
freebox_start_dl
else
HTTP_CODE=$( curl "$IDENT" -C - -o "$NAME" -w "%{http_code}" )
fi
case ${HTTP_CODE} in
200 |\
206 |\
416) # Marque le lien comme OK
if [ "${fFBX}" = 'y' ]; then
printf "Téléchargement soumis à la Freebox avec succès\n"
else
printf "Téléchargement terminé avec succès\n"
fi
marklink
break
;;
*) echo "** Erreur serveur (${HTTP_CODE}) : attente ${SLEEP}\n"
sleep $SLEEP 2>/dev/null
;;
esac
done
fFILE_OK='y'
if [ "${fCPY}" = 'y' -o "${fMOVE}" = 'y' -o "${fREN}" = 'y' ]; then
THIS=$( printf '%s' "${FBX_LIST}" | sed -n "/${BASE_IDENT}\",\"rx_rate/p" )
if [ -z "${THIS}" ]; then
abort 1 "Fichier absent sur la freebox ou a déjà été supprimé : '${IDENT}'"
fi
if ! echo "${DL_DIR_LIST}" |\
grep "\"type\":\"file\",\"name\":\"${BASE_IDENT}\"" >/dev/null; then
L1="Fichier '${BASE_IDENT}' présent dans la liste mais pas dans le répertoire"
fFILE_OK='n'
fi
FBX_FILE="${DL_DIR}/${BASE_IDENT}"
status=$( printf '%s' "${THIS}" | sed 's/.*"status":"//;s/","url":.*//' )
case ${status} in
'done' )
if [ ${fCHECK} = 'n' ]; then
if [ "${fFILE_OK}" = 'n' ]; then
abort 1 "${L1}"
fi
if [ "${fREN}" = 'y' ]; then
HTTP_CODE=$(curl "http://${FBX_IP_PORT}/fs.cgi"\
-o "${TMPLOG}" \
-b "${TMPLOG}.f" \
--data "${JSONRPC}\"fs.move\",\"params\":[\"${FBX_FILE}\",\"${DL_DIR}/${NAME}\"]}" \
-H 'Content-Type: application/json; charset=utf-8' \
-w '%{http_code}'\
-s )
jsoncatch
printf "Fichier renommé sur la Freebox avec succès\n"
marklink
else
HTTP_CODE=$( curl "http://${FBX_IP_PORT}/get.php" \
-o "${DEST}/${NAME}" \
-w "%{http_code}" \
-b "${TMPLOG}.f"\
-d "filename=${FBX_FILE}" )
if [ "${HTTP_CODE}" -eq 200 ]; then
printf "Copie du fichier depuis la Freebox terminée avec succès\n"
marklink
else
abort 1 "Erreur téléchargement depuis la Freebox de '${FBX_FILE}'"
fi
fi
else
if [ "${fFILE_OK}" = 'n' ]; then
red; echo "${L1}"; normal
fi
fi
;;
'running')
size=$( printf '%s' "${THIS}" | sed 's/.*,"size"://;s/}//' )
trnf=$( printf '%s' "${THIS}" | sed 's/.*,"transferred"://;s/,"name":.*//' )
if [ ${trnf} -eq 0 ]; then
pourcent=0
else
pourcent=$(( ${trnf} * 100 / ${size} ))
fi
cyan; printf "Téléchargement en cours : %2u%%\n" ${pourcent}; normal
;;
*) errmsg=$(printf '%s' "${THIS}"|sed 's/.*"errmsg":"//;s/","status":.*//')
red
printf "Etat inattendu ou erreur :\n"
printf " status=%s\n" "${status}";
printf " errmsg=%s\n" "${errmsg}";
normal
esac
if [ \( "${fMOVE}" = 'y' -o "${fREN}" = 'y' \) -a "${status}" != 'running' ]; then
if [ "${status}" = 'done' -a \( ${fCHECK} = 'n' -o "${fFILE_OK}" = 'n' \) -o \
"${status}" != 'done' -a ${fCHECK} = 'y' ]; then
# Suppression dans la liste des téléchargements
ID=$( printf '%s' "${THIS}" | sed 's/.*,"id"://;s/,"transferred":.*//' )
HTTP_CODE=$(curl "http://${FBX_IP_PORT}/download.cgi"\
-o "${TMPLOG}" \
-b "${TMPLOG}.f" \
--data "${JSONRPC}\"download.remove\",\"params\":[\"http\",${ID}]}" \
-H 'Content-Type: application/json; charset=utf-8' \
-w '%{http_code}'\
-s )
jsoncatch
if [ "${fMOVE}" = 'y' ]; then
# Suppression des fichiers
if echo "${DL_DIR_LIST}" |\
grep "\"type\":\"file\",\"name\":\"${BASE_IDENT}\"" >/dev/null; then
HTTP_CODE=$(curl "http://${FBX_IP_PORT}/fs.cgi"\
-o "${TMPLOG}" \
-b "${TMPLOG}.f" \
--data "${JSONRPC}\"fs.remove\",\"params\":[[\"${FBX_FILE}\"]]}" \
-H 'Content-Type: application/json; charset=utf-8' \
-w '%{http_code}'\
-s )
jsoncatch
fi
printf "Suppression du fichier sur la Freebox réussie\n"
else
printf "Suppression du fichier de la liste des téléchargements réussie\n"
fi
fi
if [ "${status}" != 'done' -a ${fCHECK} = 'y' ]; then
freebox_start_dl
printf "Réparation OK : téléchargement re-soumis à la Freebox\n"
fi
fi
fi
if [ "${fCHECK}" = 'y' -a "${fFILE_OK}" = 'y' ]; then
printf "Vérification OK"
fi
# _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
done
# --------------------------------------------------------------------------------------
# Fin correcte du traitement |
# --------------------------------------------------------------------------------------
if [ "${TPUT}" = "nop" ]; then
printf "\n\n\nLes traitements sont terminés avec succès\n"
else
printf "\n\n\n╔═══════════════════════════════════════════╗\n"
printf "║ Les traitements sont terminés avec succès ║\n"
printf "╚═══════════════════════════════════════════╝\n"
fi
clean