#!/bin/bash

if [ -z "${1}" ]; then
  echo "Keine Download-URL angegeben."
  exit 1
fi

# URL zerlegen
#
# Zunchst Protokoll entfernen, wenn vorhanden
Url=${1#ftp://}

# Servernamen und Dateipfad auftrennen
Server=${Url%%/*}
InFile=/${Url#*/}
OutFile=${InFile##*/}

# Benutzernamen und Passwort abtrennen, wenn vorhanden
if [ -z "${Server/*@*}" ]; then
  UserPass=${Server%@*}
  Hostname=${Server##*@}
else
  UserPass=""
  Hostname=${Server}
fi

# Benutzer und Passwort aufteilen
if [ -z "${UserPass/*:*}" ]; then
  User=${UserPass%%:*}
  Pass=${UserPass#*:}
else
  User=${UserPass}
fi

function GetResponseCode
{
  Response="   -"
  while
    read -ru 5 Response && [ "${Response:3:1}" = "-" ];
  do
    # echo ${Response} >&2
    :
  done
  # echo ${Response} >&2
  echo ${Response:0:3}
}

function SetPassive
{
  echo "PASV" >&5
  while
    read -ru 5 Response && [ "${Response:3:1}" = "-" ];
  do
    :
  done

  if [ "${Response:0:3}" = "227" ]; then
    # IP-Adresse und Port stehen in Klammern -- den Rest wegwerfen
    Response=${Response##*\(}
    Response=${Response%%\)*}
    # Die einzelnen Felder von Adresse und Port sind mit Kommas getrennt
    IFS=",{$IFS}"
    set -- $Response
    IP="${1}.${2}.${3}.${4}"
    PortHi=${5}
    PortLo=${6}
    # IP und Port-Nummer auswerten
    echo "/dev/tcp/${IP}/$((${PortHi}*256+${PortLo}))"
  else
    # Fehler, keine passive Verbindung mglich
    echo ""
  fi
}

exec 5<>/dev/tcp/${Hostname}/21

if [ "$?" != "0" ]; then
  echo "Keine Verbindung zum Server."
  exit 1
fi

# Zunchst Server-Greeting einlesen
if [ "$(GetResponseCode)" != "220" ]; then
  echo "Keine Begrung, kein FTP-Daemon? -- Abbruch."
  exit 1
fi

# Anmelden
echo "USER ${User:-anonymous}" >&5

while true; do
  ResponseCode=$(GetResponseCode)
  if [ "${ResponseCode}" = "331" ]; then
    # Passwort senden
    echo "PASS ${Pass:-nobody@nowhere.net}" >&5
  elif [ "${ResponseCode}" = "230" ]; then
    break
  else
    echo "Login fehlgeschlagen."
    exit 1
  fi
done

# Datenverbindung ffnen
DataCon=$(SetPassive)
exec 6<${DataCon}

# Datei herunterladen
echo "TYPE I" >&5
GetResponseCode >/dev/null

echo "RETR ${InFile}" >&5
if [ "$(GetResponseCode)" = "150" ]; then
  exec 7>${OutFile}
  IFS=""
  
  while read -rd "" -n 4096 -u 6 Data; do
    echo -n "${Data}" >&7
    if [ "${#Data}" -lt "4096" ]; then
      echo -en "\000" >&7
    fi
  done
  echo -n "${Data}" >&7

  exec 7>&-
fi

# Datenverbindung schlieen
if [ "$(GetResponseCode)" = "226" ]; then
  # Datentransfer abgeschlossen, Datenverbindung schlieen
  exec 6>&-
fi

# Ausloggen
echo "QUIT" >&5
GetResponseCode >/dev/null

# Verbindung schlieen
exec 5>&-

