6B Logo

Schöner Downloaden

In den grauen frühen Tagen, als das Internet noch als Tummelplatz für mehr oder minder Eingeweihte herhalten musste, in jenen Tagen war ein Download eine klare Sache. Das herunterzuladende Objekt lag auf einem FTP-Server, wurde (durchaus bereits im ordinären Web-Browser) mittels ftp://ftp.download_url angesprochen und jedem Beteiligten – insbesondere dem besagten Web-Browser – war zweifelsfrei klar: hier wird jetzt nicht herumgekaspert, sondern heruntergeladen. Dazu kam, dass ohnehin höchst selten etwas zum Herunterladen angeboten wurde, das nicht zu irgendeiner Art von Archiv zusammengepackt war, schließlich war Webspace noch ein knappes Gut und die Bandbreiten bescheiden.

Einen FTP-Server im eigentlichen Sinne betreibt heute fast niemand mehr, und wer Daten zum Download zur Verfügung stellt, verfügt sie auf den Server und spricht sie mit einem ganz normalen http://download_url an. Auch Daten in Archive zu packen, kommt nur noch wenigen in den Sinn, schließlich ist Webspace längst ein inflationär verfügbares Gut und die Bandbreiten endlos.

Die Kombination aus beiden Gepflogenheiten hat leider einige Unwägbarkeiten zur Folge. Beispielsweise kann sich keiner sicher sein, was passiert, wenn er eine offene Word-Datei oder ein PDF zur Verfügung stellt. Je nach Umgebung bzw. Einstellung ist es gut möglich, dass der Browser versucht, die Datei selbst abzubilden (und losquäkt, wenn er irgendwann merkt, dass er es nicht hinbekommt) oder er startet eifrig Word (oder Acrobat oder irgendein anderes »Hilfsprogramm«), was nicht jeden Downloadwilligen vor Freude taumeln lassen wird. Häufig anzutreffen sind auch downloadbare JPG-Bilder, die sich nach dem Klick auf die Vorschau in voller Pracht in Zusatzfenstern öffnen und von weitschweifigen Erklärungen à la »Klicken Sie mit der rechten Maustaste auf das Bild und wählen Sie ›Sichern unter …‹ im Kontextmenu etc.« begleitet werden. Solange wir über eine Datei reden, mag das noch angehen, spätestens bei mittleren Listen wird der Geduldsfaden freilich bald reißen.

Wer aus irgendwelchen Gründen keine ZIP-Archive o. ä. anbieten will (z. B. weil Google sie im Gegensatz zu PDFs nicht auswerten kann) der kann sich mit einem kleinen PHP-Skript behelfen, das einen Download erzwingt – unabhängig von der Art der Datei und dem verwendeten Web-Browser.

Das Skript kann als normale PHP-Datei irgendwo auf dem Server abgelegt werden. Statt nun wie bislang mit

<a href="http://download_url">Runterladen</a>

zu starten, wird das Skript angesprochen und der URL als Parameter mitgegeben:

<a href="http://skript_url.php?file=datei_name">Runterladen</a>

Das Skript wertet den empfangenen Parameter aus und schreibt einen http-Header, der den sofortigen Download des Files bewirkt. Hier das komplette Skript zum Abgreifen:

<?php

// Pfad empfangen, ansonsten abbrechen
if ($_GET["file"]) $file = $_GET["file"]; else exit();

// eventuell eingegebene Slashes entfernen
$file = preg_replace("/\//", "", $file);

// Download-Pfad zusammensetzen
$dl_pfad = "pfad_zum_downloadverzeichnis/";
$dl_url = $dl_pfad.$file;

// Existenz der Datei überprüfen
if(is_file($dl_url)) {

   // Dateiname u. -größe für den Header ermitteln
   $file_name = basename($dl_url);
   $file_size = filesize($dl_url);

   // Header schreiben
   header("Content-Type: application/octet-stream");
   header("Content-Disposition: attachment; filename=$file_name");
   header("Content-Transfer-Encoding: binary");
   header("Content-Length: $file_size");
   readfile($dl_url);
	
} else exit();

?> 

Anmerkungen

  1. #1 | Klaus-Dieter | 26.03.08, 11:13

    Hoi,
    ich bin nicht sicher, aber: kommt man damit nicht per »?file=../../../datei.usw« sonstwo hin? Das wäre eine alternative Möglichkeit, Euer Skript runterzuladen :-)
    Grüße!

  2. #2 | Ralf Schmid | 26.03.08, 14:49

    Runterladen? Das bisschen Skript? Nächstes Mal vielleicht – aber nur vielleicht.

  3. #3 | Beate | 26.03.08, 21:04

    Ich glaube Klaus-Dieter meint was anderes, und hat damit nicht unrecht: Das ganze könnte schnell eine große Sicherheitslücke aufmachen…

    http://skript_url.php?file=/etc/passwd usw.

    Also lieber Finger weg davon.

  4. #4 | Ralf Schmid | 26.03.08, 21:52

    Ah, okay Beate, jetzt ist der Groschen gefallen. Die Finger würde ich deshalb nicht gleich davonlassen: Es ist ein Download-Verzeichnis angegeben ($dl_pfad), in dem natürlich keine sensiblen Daten herumliegen sollten. Die Ausführung vom Skript kann an die Bedingung gekoppelt werden, dass die Datei der Begierde in diesem Verzeichnis liegt, wenn nicht, wird das Skript abgebrochen – ich habe das Letztere mal ergänzt, das war in der Tat nicht so ganz glücklich.

    In jedem Fall danke an Euch beide für den Hinweis.

  5. #5 | Klaus-Dieter | 27.03.08, 07:56

    Guten Morgen, ich muß nochmal nach-nerven … hab das mal probiert und komme tatsächlich per Manipulation des $file in höhere Verzeichnisse, TROTZ is_file()-Bedingung, nämlich mit ../ 1 höher, mit ../../ 2 höher usw. und dann natürlich auch wieder »tiefer«, sofern Verzeichnisname bekannt. Wenn ich dann noch den Dateinamen kenne … Die Datei-Existenzprüfung reicht nicht, weil ich ja den kompletten $dl_pfad manipuliere. Der im Skript hinterlegte Download-Ordner ist dann sozusagen nur der Ausgangspunkt. Vielleicht würde ja Slashes entfernen das Problem lösen, weil ich dann zumindest per Variablen-Manipulation nicht mehr Verzeichnis wechseln kann: $file = preg_replace(”/\//”, “”, $file) oder so ähnlich. Grüße!!

  6. #6 | Ralf Schmid | 27.03.08, 09:04

    Guten Morgen Klaus-Dieter, das hört sich wirklich furchterregend an, aber für den Knackpunkt halte ich nach wie vor den Namen des DL-Verzeichnisses: der ist erstens nicht bekannt, und selbst wenn, wird er immer mit dem, was per ?file= übergeben wurde, mittels $dl_url = $dl_pfad.$file; zu einem Gesamtstring zusammengesetzt, der im Missbrauchsfall eine nicht existierende Pfadangabe bezeichnen wird.

    Mal angenommen, Du weißt, dass das Verzeichnis /download/ heißt, und gibst an ?file=was_auch_immer, dann wird $dl_url zu /download/was-auch-immer – wie man so in ein unstatthaftes Verzeichnis wechseln will, ist mir unklar, kann aber sein, dass ich gerade einem Denkfehler erliege.

    Als Vorsichtmaßnahme die Slashes zu entfernen, kostet natürlich nichts und schadet auch nichts, insofern kann man das als zusätzliche Sicherungsmaßnahme ja mitnehmen. Soll heißen: es ist mittlerweile drin.

  7. #7 | Klaus-Dieter | 27.03.08, 09:25

    Ahoihoi Ralf, meine Sorge war nur die: statt wie im href-Attribut vorgesehen downloadordner/dateiname könnte ein böswilliger User ja zB die Datei downloadordner/../nachbarordner/andererdateiname erreichen, indem er script.php?file=../nachbarordner/andererdateiname aufruft. Aber das setzt außer (mindestens einem) bekannten Ordner- und Dateinamen jedenfalls voraus, daß man Schrägstriche eingibt. Deswegen bin ich mit dem preg_replace glücklich :-) Ohne Schrägstrich keine Verzeichnis-Navigation.
    Viele Grüße

  8. #8 | Ralf Schmid | 27.03.08, 09:36

    Glücklich? Das ist schön. Dann will ich auch glücklich sein – dass sich soviel Glück bereits mit einem simplen preg_replace erreichen lässt, hätte ich nie vermutet …

Sie müssen alle Felder mit * ausfüllen, Ihre ggfls. eingetragene E-Mail-Adresse wird nicht veröffentlicht. HTML wird gelöscht, Eingeweihte können Textile benutzen.






Journal abonnieren