@koy:
Ginge natürlich auch, wäre dann das angesprochene TR-064-Interface ... wenn ich es richtig verstehe, paßt da das Format nicht. Ansonsten stünde der Pfad zur Service-Description irgendwo oben schon.
@Theo Tintensich:
Ich brauche das zwar nicht, habe es aber jetzt doch einmal ausprobiert. Meine Vermutung zu multipart war wohl doch richtig, auch bei mir reagiert firmwarecfg nicht auf "application/x-www-url-encoded".
Das folgende bash(!)-Script lädt das Telefonbuch problemlos, den Teil mit dem Login und dem Post-Aufruf mußt Du eben substituieren durch wget-Aufrufe, da das "fritzbox"-Script nicht zum Download zur Verfügung gestellt wird. Das Prinzip sollte trotzdem erkennbar sein.
Entscheidend sind die Aufrufe von "form=$($CALL_MPFD new)" bis "postdata=$($CALL_MPFD postfile $form)", wo aus den angegebenen Formularfeldern eine Datei gebaut wird, die einen multipart/form-data-Request enthält. Der Name der Datei steht anschließend in $postdata, diese kann als "--post-file"-Argument beim 'wget' verwendet werden. $CALL_MFPD ist am Anfang der Datei definiert, da bei mir die Script-Files alles 'nx' sind, brauche ich den expliziten Aufruf über "bash". Wenn man das multipart_form-Script ausführbar irgendwo ablegt, ist natürlich der Aufruf von "multipart_form new" usw. möglich, dann aber in der ersten Zeile von multipart_form auch den SheBang anpassen.
Code:
#! /bin/bash
cleanup()
{
cleanup_file()
{
while [ $# -gt 0 ]; do
[ ${#1} -lt 6 ] && return # /tmp/. is min valid length
[ -d $1 -o -f $1 ] && rm -f $([ -d $1 ] && echo -n "-r") $1 2>/dev/null
shift
done
}
cleanup_file $configfile $envfile $phonebook $postdata $request
exit $1
}
CALL_FB="/bin/bash ./fritzbox"
CALL_MPFD="/bin/bash ./multipart_form"
configfile=$(mktemp)
if [ -z "$1" ]; then
echo "FRITZ_BOX=fritz.box\nFRITZ_USER=\nFRITZ_PASSWD=\n" >$configfile
else
cat $1 >$configfile
if [ $? -ne 0 ]; then
echo "Configuration file '$1' is not usable." 1>&2
exit $(cleanup 127)
fi
fi
envfile=$(mktemp)
$CALL_FB login --config-file=$configfile --environment-file=$envfile
rc=$?
if [ $rc -ne 0 ]; then
echo "Unable to login to your device." 1>&2
exit $(cleanup $rc)
fi
phonebook=$(mktemp)
. $envfile
form=$($CALL_MPFD new)
$CALL_MPFD addfield $form sid $FRITZ_SID
$CALL_MPFD addfield $form PhonebookId 1
$CALL_MPFD addfield $form PhonebookExportName PB2
$CALL_MPFD addfield $form PhonebookExport
postdata=$($CALL_MPFD postfile $form)
echo "Reading phonebook file file ..." 1>&2
$CALL_FB post --config-file=$configfile --environment-file=$envfile /cgi-bin/firmwarecfg $postdata >phonebook.xml
rc=$?
if [ $rc -ne 0 ]; then
$CALL_FB logout --config-file=$configfile --environment-file=$envfile
echo "Error $rc reading box configuration file." 1>&2
exit $(cleanup $rc)
fi
$CALL_MPFD cleanup $form
$CALL_FB logout --config-file=$configfile --environment-file=$envfile
cat phonebook.xml
exit $(cleanup 0)
Dieses Script wird als "multipart_form" zusätzlich benötigt (ist als Anhang auch noch mal vorhanden und läuft (vermutlich, lange nicht mehr getestet) sogar unter Busybox-ash, wenn es sein muß, wobei das wget der Box kein --post-file kennt und damit relativiert sich der Nutzen, aber es gibt (oder gab) ja auch noch 'nc'):
Code:
#! /bin/true
errmsg() { printf "%s\n" "$*" 1>&2; }
check_form()
{
local form="$1" rc=0
if [ -d $form ]; then
if [ ! -f $form/content ]; then
errmsg "The specified form directory '$form' does not contain a valid multipart form-data structure."
rc=1
else
if [ ! -w $form/content ]; then
errmsg "The specified form directory '$form' does not contain a valid multipart form-data structure."
rc=1
fi
fi
else
errmsg "The specified form directory '$form' is invalid."
rc=1
fi
return $rc
}
field_header()
{
local type
[ ${#2} -gt 0 ] && type="$(echo -e -n "\r\nContent-Type: $2")"
echo -n "Content-Disposition: form-data; name=\"$1\"$type"
}
content_length()
{
local form="$1" tab=$'\t' part name hdr boundary
boundary="$(cat $form/boundary)"
len=0
while read line; do
part="${line%%${tab}*}"
name="${line#*${tab}}"
type="${name#*${tab}}"
[ ${#type} -gt 0 ] && name="${name%%${tab}*}"
hdr="$(field_header "$name" "$type")"
len=$(( len + 2 + 2 + ${#boundary} + 2 + ${#hdr} + 4 + $(wc -c <$form/$part) ))
done <$form/content
echo $(( len + 2 + 2 + ${#boundary} ))
}
post_data()
{
local form="$1" tab=$'\t' field tf oifs="$IFS" fl
tf=$(mktemp)
boundary="$(cat $form/boundary)"
cat $form/content |
while read line; do
field=""
part="${line%%${tab}*}"
name="${line#*${tab}}"
type="${name#*${tab}}"
[ ${#type} -gt 0 ] && name="${name%%${tab}*}"
hdr="$(field_header "$name" "$type")"
echo -n -e "$fl--$boundary\r\n$hdr\r\n\r\n" >>$tf
fl="\r\n"
cat $form/$part >>$tf
done
echo -n -e "\r\n--$boundary--" >>$tf
echo -n -e "Content-Type: multipart/form-data; boundary=$boundary\r\n" >$form/formdata
echo -n -e "Content-Length: $(wc -c <$tf)\r\n\r\n" >>$form/formdata
cat $tf >>$form/formdata
rm $tf 2>/dev/null
echo -n -e "\r\n" >>$form/formdata
echo "$form/formdata"
}
op=$1
case $op in
"new")
if [ ${#2} -gt 0 ]; then
errmsg "No parameters allowed for new form creation."
rc=127
else
td=$(mktemp -d)
touch $td/content
echo -n -e "$(echo "$td$(date +%s)" | md5sum | sed -n -e "s/^\([0-9a-f]*\).*/\1/p")" >$td/boundary
echo $td
rc=0
fi
;;
"cleanup")
form="$2"
if check_form $form; then
rm -r $form 2>/dev/null
rc=0
else
rc=127
fi
;;
"addfield")
form="$2"
name="$3"
value="$4"
if check_form $form; then
if [ ${#name} -eq 0 ]; then
errmsg "Missing field name for 'addfield' operation."
rc=127
else
part="$name$(date +%s)"
echo -n -e "$value" >$form/$part
echo -e "$part\t$name" >>$form/content
rc=0
fi
else
rc=127
fi
;;
"addfile")
form="$2"
name="$3"
file="$4"
type="$5"
if check_form $form; then
if [ ${#name} -eq 0 ]; then
errmsg "Missing field name for 'addfile' operation."
rc=127
else
part="$name$(date +%s)"
cat $file >$form/$part
echo -e "$part\t$name\t$type" >>$form/content
rc=0
fi
else
rc=127
fi
;;
"length")
form="$2"
if check_form $form; then
content_length "$form"
rc=0
else
rc=127
fi
;;
"postdata")
form="$2"
if check_form $form; then
cat $(post_data "$form")
rc=0
else
rc=127
fi
;;
"postfile")
form="$2"
if check_form $form; then
post_data "$form"
rc=0
else
rc=127
fi
;;
*)
errmsg "Unknown operation '$op'."
rc=127
;;
esac
exit $rc
EDIT:
Eines habe ich glatt noch vergessen ... offenbar ist firmwarecfg auch etwas "wählerisch", was die Reihenfolge der Formularfelder im Request angeht. Der Download funktioniert bei mir nur, wenn "PhonebookExport" das letzte Feld ist.