PHP header Problem

PHP:
<?php
$datei = "test.mp3";

$action = $_GET['action'];
if ($action == "dlnow") {
 $datei = $_GET['file'];
 header("Content-type: application/octet-stream");
 header("Content-Disposition: attachment; filename=".$datei."");
 header("Content-Length: ".filesize($datei)."");
 readfile($datei);
 exit();
}
?>
<a href="dl.php?action=dlnow">Download</a>

Vielleicht hilft die Übermittlung von Content-Length.
Weiterhin habe ich ein paar unnötige Anführungszeichen entfernt (bei readfile).
Außerdem entfehle ich dir, die Datei unbedingt zu validieren, denn sonst könnte man versuchen externe Dateien einzubinden, die du eigentlich gar nicht zum Download anbieten willst.
 
Außerdem entfehle ich dir, die Datei unbedingt zu validieren, denn sonst könnte man versuchen externe Dateien einzubinden, die du eigentlich gar nicht zum Download anbieten willst.
Was meinst Du genau damit

Edit
Nein, das mit der header("Content-Length: ".filesize($datei).""); hat leider auch nicht geholfen :(

[10-Aug-2007 20:52:59] PHP Warning: readfile(test.mp3) [<a href='function.readfile'>function.readfile</a>]: failed to open stream: No such file or directory in c:\webserver\dl.php on line 27
 
Zuletzt bearbeitet:
Im schlimmsten Fall könnte er dir Passwortdateien stehlen:

dl.php?action=dlnow&file=./../../../../etc/passwd

Sowas könnte versucht werden und auch funktionieren, falls PHP den Zugriff auf Ordner außerhalb des htdocs zulässt.

Eine mögliche Validierung könnte so aussehen:
PHP:
<?php
$file = $_GET['file'];
if(!empty($file) && strpos($file, '/') === false)
{
  # Download
} 
else 
{
  # Fehlermeldung
}
?>

/ Nachtrag:
Naja, die Fehlermeldung heißt, dass die Datei test.mp3 nicht existiert.
Ergo scheint es dort ein Problem zu geben oder du befindest dich vielleicht im falschen Verzeichnis.
 
:rolleyes: jetzt wird's peinlich.

Ja, die Dateien liegen in einem extra Ordner den ich via while auslesen lasse.
Der Ordner heisst "temp"


Wäre das denn so zu verstehen ?
PHP:
$ordner = "./temp";

header("Content-Disposition: attachment; filename=".$ordner/$datei."");
header("Content-Length: ".filesize($ordner/$datei)."");
readfile($ordner/$datei);
 
PHP:
$ordner = "./temp";
header("Content-Disposition: attachment; filename=".$ordner/$datei."");
header("Content-Length: ".filesize($ordner/$datei)."");
readfile($ordner/$datei);

Seit wann kann man Strings dividieren? ;)

PHP:
header('Content-Transfer-Encoding: binary');
Sollte sicherstellen, dass die Daten korrekt ankommen - Ist kein Muss aber kann.

Um auf dein oben beschriebenes Problem noch einen Lösungsansatz zu bieten: Die Output Buffering Funktionen können dazu genutzt werden um nach dem Senden der Filecontents die Ausgabe zu buffern und nicht mehr auszuliefern.

Um Probleme mit nicht vorhandene Dateien oder nicht zu lesenden Dateien zu vermeiden, ist die Funktion
PHP:
is_readable($path)
sehr nützlich. Die Downloadsteuerung könnte dann folgendermaßen aussehen:
PHP:
$pfad = realpath("{$ordner}/{$datei}");
// diese Pfadangabe muss in $pfad, beginnend bei $pfad{0}, gefunden werden (schützt vor Zugriffen auf höhere Verzeichnisse
$erlaubt = '/srv/www/domain/httpdocs/downloads/';

if (@ob_get_level() > 0) {
    @ob_end_clean();
}

if (strpos($pfad, $erlaubt) === 0 AND is_readable($pfad) AND is_file($pfad)) {
    header("Content-Disposition: attachment; Filename=\"{$datei}\"");
    header('Content-Type: application/octet-stream');
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . (string) filesize($pfad));
    @readfile($pfad);
} else {
    header('Content-Type: text/plain');
    echo "Datei konnte nicht gefunden werden unter '{$pfad}'";
}

@ob_start();
// ...
@ob_end_clean();

Hoffe, das hilft ein wenig ;)
 
öhm... wus ? :confused:


Also, ich habe eine Datei die eben dl.php und diese befindet sich auf dem Root Ordner (wo man auch u.a. die index.php hat)
Desweiteren gibt es einen Ordner der temp heisst.

- C:\Webserver -> dl.php
- C:\Webserver\temp -> Dateien

Ich lasse den Ordner temp mit einer While schleife auslesen.
PHP:
$order = "./temp";

$handle = opendir($ordner);
 while ($file = readdir ($handle)) {
  if ($file != "." && $file != "..") {
   echo "<img src=\"images/pfeil.gif\" border=\"0\">\n";
   echo "<a href=\"dl.php?action=dlnow&file=".$file."\"  >".$file."</a><br/>\n";
  }
 }

Danach übergebe ich mit dem Link den Dateinamen an eine Variable
PHP:
$action = $_GET['action'];
if(!empty($file) && strpos($file, '/') === false) { 
 if ($action == "dlnow") {
  header("Content-type: application/octet-stream");
  header("Content-Disposition: attachment; filename=".$datei."");
  header("Content-Length: ".filesize($datei)."");
  readfile($datei);
  exit();
 }
}


Kann sein das ich da nun gerade einen totalen Denkfehler drinne hab was die übergabe des Verzeichnisses betrifft.. .
 
Bevor ich dich falsch verstehe, frage ich lieber mal: Befinden sich beide Sachen - Also sowohl das Listing des Ordnerinhalts als auch der Force-Download Teil in einer Datei?
Wenn ja, dann ist das wohl die beste Lösung: Wenn die HTTP-GET 'action' gleich 'dlnow' ist, wird versucht, die $_GET['file'] zu übertragen. Wenn sie nicht gefunden wird oder ein anderer Teil der if-Bedingung nicht erfüllt wird, beginnt das Listing...

PHP:
/**
 * dl.php
 */
$order = "./temp";

if(isset($_GET['action']) AND $_GET['action'] == 'dlnow' AND !empty($_GET['file']) AND strpos($_GET['file'], '/') === false AND is_readable($ordner . '/' . $_GET['file']) { 
  header("Content-type: application/octet-stream");
  header("Content-Disposition: attachment; filename=" . $_$GET['file'] ."");
  header("Content-Length: ".filesize($ordner . '/' . $_GET['file'])."");
  readfile($ordner . '/' . $_GET['file']);
  exit;
} else {
  $handle = opendir($ordner);
  while ($file = readdir ($handle)) {
    if ($file != "." && $file != "..") {
      echo "<img src=\"images/pfeil.gif\" border=\"0\">\n";
      echo "<a href=\"dl.php?action=dlnow&file=".$file."\"  >".$file."</a><br/>\n";
    }
  }
  closedir($handle);
}

Danach übergebe ich mit dem Link den Dateinamen an eine Variable
PHP:
$action = $_GET['action'];
if(!empty($file) && strpos($file, '/') === false) { 
 if ($action == "dlnow") {
  header("Content-type: application/octet-stream");
  header("Content-Disposition: attachment; filename=".$datei."");
  header("Content-Length: ".filesize($datei)."");
  readfile($datei);
  exit();
 }
}

Bevor ich jetzt total an dir und deinem Problem vorbeirede, entschuldige ich mich schonmal - Aber ich verstehe deine Problematik gerade nicht so recht? :confused:
 
Ich glaube... es ist vollendet.

Ich hab einfach nicht begriffen wie ich das mit den Pfad und der Datei machen sollte..
Jetzt läufts aber und ich hab nochmal dieses dlnow entfernt.
<a href=\"dl.php?file=".$file."\" >".$file."</a><br/>

Entsprechend den Code mit der action hab ich natürlich auch geändert.


Ich muss mich vielmals bei dir bedanken für die Hilfe und die Geduld.. !!
 
Zurück