Aktuelles Verzeichnis in php
Siegfried
- php
0 Robert B.
0 Rolf B
0 Felix Riesterer
0 Robert B.
0 Siegfried0 Siegfried
Guten Tag zusammen,
ich habe folgende Konstellationen:
/index.php
/de/seitex.php
/-test/us/seitey.php
................
d.h. php-dateien in den unterschiedlichsten Verzeichnissen.
Wie kann ich die Verzeichnisnamen in einer php-Datei erhalten?
Moin Siegfried,
ich habe folgende Konstellationen:
/index.php
/de/seitex.php
/-test/us/seitey.php
................
d.h. php-dateien in den unterschiedlichsten Verzeichnissen.
Wie kann ich die Verzeichnisnamen in einer php-Datei erhalten?
Es gibt die „magische Konstante“ __DIR__
, die genau Deinen Anwendungsfall abzudecken scheint.
Viele Grüße
Robert
Hallo Robert,
nur, wenn der Pfad zur Datei im Filesystem des Servers wissen möchte.
Wenn man den Pfad zum Script in der URL wissen möchte, über die das Script aufgerufen wurde, muss man auf die Einträge in $_SERVER zugreifen. Diese sind zwar in RFC 3275 standardisiert, aber zumindest unser Wiki vertraut dem nicht.
Ob dieses Misstrauen gegenüber den CGI-Metas aus RFC3275 gerechtfertigt ist, weiß ich nicht. Ich weiß jedenfalls, dass es einige Unterschiede in den $_SERVER-Einträgen gibt, je nachdem, welche Webserver-Software zum Einsatz kommt.
Ein weiterer Aspekt, den man beachten muss, sind URL-Rewrites. Wenn der Anwender https://example.com/foo/bar/dings.php
abruft und der Apache daraus per mod_rewrite ein /muh/bums.php
macht, dann muss man schon gut überlegen, ob einem das weiterhilft. Ich habe hier und jetzt keinen Überblick über die Einträge, die der Apache macht und in welchen Szenarien sie was enthalten. Unser Wiki leider auch nicht. Ich weiß auch nicht, ob alle Apaches ein gemeinsames Basisset von $_SERVER-Einträgen bereitstellen oder ob das wiederum an der Version oder an aktivierten Modulen hängt.
TL;DR: $_SERVER['SCRIPT_NAME'] ist ein in RFC3275 genannter Eintrag und sollte für https://example.com/foo/bar/dings.php den String "foo/bar/dings.php" enthalten (kein / am Anfang). Wenn man darauf dann dirname() anwendet, bekommt man den Pfad.
Meine Empfehlung wäre jedenfalls, sich den tatsächlichen Inhalt von $_SERVER['SCRIPT_NAME'] anzeigen zu lassen, bevor man anfängt, damit herumzumachen.
Wenn Rewrites im Spiel sind, bekommt man die URL vor dem Rewrite mit $_SERVER['REQUEST_URI']
. Diese URL zerlegt man mit parse_url in ihre Bestandteile und findet im Ergebnis unter dem Schlüssel 'path' das Gewünschte.
Rolf
Lieber Rolf,
Wenn Rewrites im Spiel sind, bekommt man die URL vor dem Rewrite mit
$_SERVER['REQUEST_URI']
. Diese URL zerlegt man mit parse_url in ihre Bestandteile und findet im Ergebnis unter dem Schlüssel 'path' das Gewünschte.
warum verwendet man es nur dann, wenn Rewrite im Spiel ist? Meine Devise: Immer genau $_SERVER['REQUEST_URI']
verwenden. $_SERVER['SCRIPT_NAME']
birgt dagegen genau in diesem Szenario ein Sicherheitsrisiko. Habe aber gerade keine Quelle für diese Aussage zur Hand.
Liebe Grüße
Felix Riesterer
Hallo Felix,
Sicherheitsrisiko
Welches Risiko soll bestehen, wenn ich mir von dort den Pfad besorge? Ich habe versucht, dazu etwas zu finden, aber die Sicherheitshinweise, auf die ich gestoßen bin, beziehen sich vor allem auf HTTP_HOST und SERVER_NAME. PHP_SELF ist auch so eine Sache, weil PHP_SELF auch den Pfadrest hinter dem Script enthält (z.B. bei /foo/script.php/dings/bums) und dieser Pfadrest beliebig böse sein kann. Bei SCRIPT_NAME ist es dem Server aber bereits erfolgreich gelungen, das Script darüber zu finden, da kann so viel Müll also nicht mehr drin sein.
Was man nicht tun sollte, ist, den erhaltenen Pfad zum navigieren im Filesystem des Servers zu verwenden. Er kann Verzeichnisakrobatik enthalten (foo/../../../../../etc/) und damit ggf. aus dem Document-Root ausbrechen. Ich denke, dass das aber auch für REQUEST_URI gilt.
immer verwenden
"Immer" ist ein großes Wort. REQUEST_URI zeigt bei Rewrites woanders hin als SCRIPT_NAME. Es hängt von der konkreten Anwendung ab, welches von den beiden das gewünschte Ergebnis liefert. Eine Prise Salz auf dem Immer sollte daher erforderlich sein.
Rolf
Lieber Rolf,
Was man nicht tun sollte, ist, den erhaltenen Pfad zum navigieren im Filesystem des Servers zu verwenden. Er kann Verzeichnisakrobatik enthalten (foo/../../../../../etc/) und damit ggf. aus dem Document-Root ausbrechen. Ich denke, dass das aber auch für REQUEST_URI gilt.
sehr richtig. Deswegen sollte der REQUEST_URI auch niemals als Pfad des Dateisystems verstanden werden, auch wenn er das manchmal sein mag. Aus Sicht des Scripts ist es ein String, nichts weiter. Davon aber Pfade im Dateisystem abzuleiten ist prinzipiell gefährlich und sollte nur von denjenigen gemacht werden, die wirklich wissen, was sie da wirklich tun und was das wirklich bedeutet.
Es hängt von der konkreten Anwendung ab, welches von den beiden [SCRIPT_NAME oder REQUEST_URI] das gewünschte Ergebnis liefert.
Wenn Du REQUEST_URI verwendest, dann gehst Du offensichtlich weniger von einem Verzeichnispfad aus, weil so ein String prinzipiell alles sein kann. Bei SCRIPT_NAME ist das nicht so offensichtlich. Und wenn Du in einer Anwendung auf das Dateisystem zugreifen willst, solltest Du insbesondere die automagischen Konstanten wie __DIR__
und __FILE__
verwenden, weil die nicht von entsprechend manipulierten Request-Parametern beeinflusst werden können.
Liebe Grüße
Felix Riesterer
Moin Rolf,
nur, wenn der Pfad zur Datei im Filesystem des Servers wissen möchte.
im Kontext der Ausgangsfrage muss dieser Satz hervorgehoben werden:
Wenn man den Pfad zum Script in der URL wissen möchte, über die das Script aufgerufen wurde, muss man auf die Einträge in
$_SERVER
zugreifen.
Bei inkludierten Dateien müsste $_SERVER
überall gleich sein, weil es ja der gleiche Request ist, während die magische Konstante __FILE__
den Namen der jeweiligen PHP-Datei spezifiziert bzw. __DIR__
deren Verzeichnis.
Ob dieses Misstrauen gegenüber den CGI-Metas aus RFC 3875 gerechtfertigt ist, weiß ich nicht. Ich weiß jedenfalls, dass es einige Unterschiede in den $_SERVER-Einträgen gibt, je nachdem, welche Webserver-Software zum Einsatz kommt.
Ich könnte mir vorstellen, dass PATH_INFO
oder das Format der Pfadangaben unterschiedlich sein können …
Viele Grüße
Robert
Hallo Robert,
Siegfried war ja offenbar am Serverpfad interessiert und nicht am URL-Pfad. Insofern lagst Du mit Deiner Antwort richtig.
Bei inkludierten Dateien will ich eigentlich gar nicht wissen, wie ich sie per URL erreiche. Da soll eigentlich gar keiner wissen, ob und wie man sie per URL erreichen kann.
Rolf
Hi,
Bei inkludierten Dateien will ich eigentlich gar nicht wissen, wie ich sie per URL erreiche.
die sollten gar nicht per URL erreichbar sein.
cu,
Andreas a/k/a MudGuard
Hallo MudGuard,
da hast Du natürlich auch wieder recht.
Aber Mediawiki und Wordpress sind das beste Beispiel, dass es nicht immer so gemacht wird, denn längst nicht jeder Webspace bietet Speicherplatz außerhalb von DocumentRoot an.
Möglicherweise hätte man unsere Selfhtml Mediawiki-Installation so anpassen können, dass die vendor- und include-Ordner nicht im Webspacen liegen. Ist aber unterblieben, ob aus Sachzwang oder aus Zeitmangel, weiß ich nicht.
Der Access-Log vom Wiki zeigt, dass täglich hunderte von Script-Kiddies nach bekannten Fehlern im Vendor-Verzeichnis des Composers suchen. Weshalb das Verzeichnis sicherlich besser außerhalb vom DocumentRoot läge. Ich weiß nur nicht, ob das so trivial ist, da fehlt mir Detailkenntnis zu Mediawiki.
Rolf
Hi,
Aber Mediawiki und Wordpress sind das beste Beispiel, dass es nicht immer so gemacht wird, denn längst nicht jeder Webspace bietet Speicherplatz außerhalb von DocumentRoot an.
man kann auch Verzeichnisse unterhalb von DocumentRoot mit deny all
per url unzugänglich machen …
cu,
Andreas a/k/a MudGuard
Lieber MudGuard,
man kann auch Verzeichnisse unterhalb von DocumentRoot mit
deny all
per url unzugänglich machen …
und dann gibt es noch die Möglichkeit auf Apachen eine entsprechende .htaccess
einzusetzen.
Liebe Grüße
Felix Riesterer
Danke Robert,
das war es.
Hallo Siegfried,
hast Du es schon mal mit der Funktion realpath() probiert: siehe
Hallo zusammen,
nachdem ich mich etwas mit DIR befasst habe, habe ich folgendes gefunden
// Verwende __DIR__ um den absoluten Pfad des aktuellen Verzeichnisses zu erhalten
$baseDir = __DIR__;
// Erstelle einen Link zu einer Datei im gleichen Verzeichnis
$linkToFile = $baseDir . '/datei.txt';
// Erstelle einen Link zu einer Datei in einem Unterverzeichnis
$linkToSubdirectoryFile = $baseDir . '/unterverzeichnis/datei.txt';
Was mich jetzt noch interessieren würde:
Wie erhält man einen Link zu einer Datei 'datei.txt' im übergeordneten Verzeichnis (Vaterverzeichnis?)?
Schönen Gruß
Siegfried
Lieber Siegfried,
es ist keine gute Idee, die Herkunft von Daten zu verschleiern:
// Verwende __DIR__ um den absoluten Pfad des aktuellen Verzeichnisses zu erhalten $baseDir = __DIR__;
Warum sollte der Variablenname $baseDir
überhaupt verwendet werden? Was er beutet, muss man sich aus dem Programmverlauf heraus ableiten. Besser wäre die direkte Verwendung der magischen Konstante __DIR__
selbst an dessen Stelle:
// Erstelle einen Link zu einer Datei im gleichen Verzeichnis
$linkToFile = __DIR__ . '/datei.txt';
// Erstelle einen Link zu einer Datei in einem Unterverzeichnis
$linkToSubdirectoryFile = __DIR__ . '/unterverzeichnis/datei.txt';
Wie erhält man einen Link zu einer Datei 'datei.txt' im übergeordneten Verzeichnis (Vaterverzeichnis?)?
Warum liest Du die Dir gegebenen Hilfen nicht genau genug, wo die Antwort schon enthalten war?
Liebe Grüße
Felix Riesterer
Hallo Felix,
Wie erhält man einen Link zu einer Datei 'datei.txt' im übergeordneten Verzeichnis (Vaterverzeichnis?)?
Warum liest Du die Dir gegebenen Hilfen nicht genau genug, wo die Antwort schon enthalten war?
Aus der dortigen Antwort von Rolf an Dich kann ich nicht entnehmen, wie ich das übergeordnete Verzeichnis erhalte. Ich lese dort nur was man nicht tun sollte.
Schönen Gruß
Siegfried
Hallo Siegfried,
dir war die Bedeutung von ..
nicht bekannt?
Mit __DIR__ . "/../datei.txt"
gehst du von __DIR__
aus eine Ebene hoch und dann auf datei.txt
Wenn du ../
mehrfach verwendest, gehst du entsprechend viele Ebenen hoch.
Rolf