Moin!
Dein Code ist allerdings noch deutlich verbesserungswürdig!
Natürlich ist er das, aber er funktioniert muss nur
individalisiert werden. Die wesentlichen Sachen sind aber enthalten.
Das ist leider sehr häufig das Problem: Es wird nur entwickelt, bis es funktioniert, und auch nur geprüft, dass es funktioniert, wenn alles korrekt läuft. Fehlerkonditionen geraten gerne aus dem Blickfeld.
######################
$hier = $_SERVER['PHP_SELF'];
// Wozu sinnlos kopieren?
Jeder hat seinen Stil und je nach späterer Verwendung
ist das für mich so komfortabler.
Extrem nervig, wie ich finde. Verseucht den globalen Variablenraum mit unnötigen Variablen, deren sinnvolle Neubezeichnung man sich auch noch ausdenken muß - und an die man sich an anderer Stelle, wo es um den gleichen Wert geht, wieder erinnern muß.
$bildpfad = $_SERVER['DOCUMENT_ROOT'];
// Wieder eine sinnlose Kopie.
Wie ich schon sagte, aufgeräumter und komfortabler
Undurchsichtiger, ressourcenverschwendender. Etwas weniger Tipparbeit.
$bildpfad = str_replace('\','/',$bildpfad);
// Wozu das? In $_SERVER['DOCUMENT_ROOT']; sind keine Backslashes enthalten, die man in Slashes wandeln müßte. Wenn doch, dann kann das verwendete XAMP-System damit auch umgehen. Ansonsten würde der Apache nämlich streiken müssen.
Hier irrst du, hatte schon etliche Proble deswegen.
Nun ja, für die korrekte Serverkonfiguration ist der Admin zuständig. Und Windows-Maschinen sollte man ja sowieso nicht ins Internet lassen[TM]. ;)
$bildpfad = substr($bildpfad,0,strrpos($bildpfad,'/'));
// Eine undurchsichtige Stringoperation, die von unsicheren Annahmen ausgeht. $_SERVER['DOCUMENT_ROOT'] endet nicht zwingend mit einem Slash, was dir hier dann mehr abschneidet, als du willst...
$bildpfad = $bildpfad.'/'.$bildverz;
// ...nur um am Ende dann zu einem absoluten Pfad zu kommen, der dann doch innerhalb des DOCUMTENT_ROOT liegt, aber einfacher und sinnvoller so definiert würde:
$bildpfad = "/pfad/zum/bild/dir/";
// Das ist einfach und klar verständlich. Und funktioniert immer.
NEIN, man landet oberhalb vom root. Bei deiner Version nicht.
Wie gesagt: Undurchsichtige Stringoperation, die in Abhängigkeit von DOCUMENT_ROOT eben mal mehr, mal weniger abschneidet. Auf einem konkreten System wird man zwar immer im gleichen Verzeichnis landen - für ein Beispielskript ist der Code aber deswegen unbrauchbar.
Bei meiner Version landet man überall, wo man will:
$bildpfad = "/";
$bildpfad = "/home/benutzer/meine_bilder/";
$bildpfad = "/var/www/localhost/htdocs/bilder/";
if (isset($_GET['pic']) // besser so fragen, ob Variablen definiert sind.
In diesem Fall ja, aber oft will man auch dass was drin steht
und dann ist es einfacher wie ich es mache, trotz notice.
Was ist, wenn in $_GET['pic'] etwas drinsteht, was PHP zu "false" evaluiert? Der String "0" beispielsweise fällt darunter.
$pic = stripslashes($pic);
// Das darf nur passieren, wenn magic_quotes_gpc auf ON steht.
Ok, könnte man auch noch abfragen.
Ersetze "könnte man" durch "muß man".
register_globals ist schon lange "out", magic_quotes_gpc ist als nächstes am Aussterben.
// Der Aufruf von clearstatcache() an dieser Stelle ist mehr als sinnlos - er kostet bei Dateimetadatenoperationen (die du nicht benutzt) auch richtig Performance, wenn man ihn unbedacht anwendet.
Wusste ich nicht, im Manual wird konkret darauf bestanden,
nach jeder file_exists() Abfrage.
Quelle? Die englische Version sagt nichts von "muß man". Und das fragliche Szenario hielte ich auch nicht für relevant.
Besser wäre allerdings, auf file_exists() zu verzichten (und damit auf die Abhängigkeit von diesem Cache), und stattdessen fopen() und fpassthru() zu verwenden. fopen() wird scheitern, wenn die Datei nicht existiert oder aus sonst einem Grunde nicht gelesen werden kann - das kann man dann genauso abfangen.
// Durch die ungeprüfte Weiterreichung von $pic ergibt sich an dieser Stelle ggf. Angriffspotential auf den Benutzerbrowser.
»»
Wüsste jetzt nicht was ich da noch prüfen sollte ?
Aus der Doku zu header():
"Note: Since PHP 4.4.2 and PHP 5.1.2 this function prevents more than one header to be sent at once as a protection against header injection attacks."
Das bedeutet, dass header() durch in $pic eingeschleppte Zeilenschaltungen in früheren Versionen zum Absenden zusätzlicher Header gebracht werden konnte.
Gewiß ist es unwahrscheinlich, dass man in $pic sowohl einen manipulierten zusätzlichen Header als auch gleichzeitig einen gültigen Dateinamen haben kann, die Anmerkung sollte daher allgemein als Warnung verstanden werden. Man hat schon Pferde vor der Apotheke kotzen sehen.
readfile($bildpfad.$pic);
exit(); // keine weitere Ausgabe
// Das Skript wird nur dann abgebrochen, wenn tatsächlich erfolgreich ein Bild gefunden und ausgegeben wurde. In allen anderen Fällen läuft das Skript bei einem Request nach einem Bild weiter in den HTML-generierenden Teil.
Nein soll es nicht, Habe da schon die verrücktesten Sachen
bei den Vor zurück und reload Funktionen des Browsers erlebt.
Worauf bezieht sich das "Nein, soll es nicht"? Das Skript läuft in den HTML-Teil, wenn der gesetzte Parameter kein existierendes Bild beschreibt. Ist eine Unschönheit.
- Sven Rautenberg
--
"Love your nation - respect the others."