Armin: Pfadangaben in PHP für Linux und Windows

Hallo, ich möchte eine PHP Anwendung unter allen Betriebssysteme zum laufen bringen. Es werden viele Operationen auf dem Filesystem vorgenommen, es werden z.B. XML Datein geladen die irgendwo auf dem Server liegen, oder es werden .txt Dateien irgendwohin geschrieben.

Diese festen Pfade werden über Konstanten definiert, z.B.:

define("TMP_DIR", "var/html/db/");
define("XML_DIR", "var/XML/");

im Code wird das Verzeichnis dann z.B. als Basisverzeichnis verwendet weil die Unterverzeicnise ab dann variabel sein könen:

$fp1 = fopen(TMP_DIR . "/tmp1/".$datname1.".txt","wb");
$fp2 = fopen(TMP_DIR . "/tmp2/".$datname2.".txt","wb");

$xmlfile_query = XML_DIR.'/template/query/'.$active_msconfig.'.xml');
$xmlfile_edit = XML_DIR.'/template/edit/'.$active_msconfig.'.xml');

Wie muss ich diese Pfadangaben nutzen damit das auch zuverlässig unter Windows läuft? Muss ich hier alles mit Backslashes abhandeln bzw. was mache ich wenn ein User in der Konfiguration es mal mit Slash mal mit Backslash einträgt? Oder mal mit Doppel Backslah etc. Ich habe es ausprobiert, es läuft ja anscheinend auch gemischt, aber ist das zuverlässig?

z.B.

define("TMP_DIR", "C:\\Inetpub\db\\");
define("XML_DIR", "C:\Inetpub\\xml\\");

Danke + Gruß Armin

  1. hi

    Wie muss ich diese Pfadangaben nutzen damit das auch zuverlässig unter Windows läuft?

    Wie gehabt: mit dem einfachen Slash

    Und das Laufwerk muss nur dann angegeben werden, wenn die Daten auf einem anderen LW sind als die Anwendung. Also wenn alles auf d: laaft /path/file reicht da.

    Meistens läuft der Webserver auf c: Also wenn Du Pfad~Angaben in der httpd.conf oder .htaccess hast, müssen die entweder auf c: liegen oder mit LW: notiert sein.

    MfG

    1. Danke, das wäre ja einfach… Und was könnte passieren wenn der User dann doch die Backslashes bei der Definition eingibt? Gilt das auch für exec Befehle? Armin

      1. Danke, das wäre ja einfach… Und was könnte passieren wenn der User dann doch die Backslashes bei der Definition eingibt? Gilt das auch für exec Befehle?

        Wenn der Backslash zu notieren ist, muss er maskiert werden. Idr. mit einem Backslash vornedran. Oder nimm quotemeta das macht die Sache oftmals einfacher.

        MfG

      2. Hallo Armin,

        Danke, das wäre ja einfach…

        noch einfacher ist es natürlich, es 100% korrekt und portabel zu machen.

        Und was könnte passieren wenn der User dann doch die Backslashes bei der Definition eingibt?

        Dann musst du – wie von pl geschrieben – die Backslashes maskieren.

        Gilt das auch für exec Befehle?

        Das gilt für jeden String.

        Generell musst du bei Zugriffen aufs Dateisystem natürlich beachten, dass der Nutzer keinen Schindluder treibt.

        Viele Grüße
        Robert

      3. Tach!

        Danke, das wäre ja einfach… Und was könnte passieren wenn der User dann doch die Backslashes bei der Definition eingibt?

        Dann gibt es unter Linux nicht die gewünschten Ergebnisse. Während Windows mittlerweile oftmals mit \ und / klarkommt (zumindest die Pfadangaben, die die PHP-Funktionen ans Betriebssystem weitergeben sollten keine Probleme bereiten), gilt bei Linux nach wie vor nur der / als Verzeichnistrenner. Der \ hat dort die Funktion ein Zeichen zu maskieren.

        dedlfix.

  2. Hallo Armin,

    Diese festen Pfade werden über Konstanten definiert, z.B.:

    define("TMP_DIR", "var/html/db/");
    define("XML_DIR", "var/XML/");
    

    Kleiner Hinweis: Das ^^^^^^ sind relative Pfadangaben.

    $fp1 = fopen(TMP_DIR . "/tmp1/".$datname1.".txt","wb");
    $fp2 = fopen(TMP_DIR . "/tmp2/".$datname2.".txt","wb");
    
    $xmlfile_query = XML_DIR.'/template/query/'.$active_msconfig.'.xml');
    $xmlfile_edit = XML_DIR.'/template/edit/'.$active_msconfig.'.xml');
    

    Ich hoffe, dass du hier zuvor geprüft hast, ob die Variablen sinnvolle und gültige Zeichen enthalten.

    Wie muss ich diese Pfadangaben nutzen damit das auch zuverlässig unter Windows läuft?

    Der Slash funktioniert auch unter Windows. Absolut korrekt (es kann ja auch Dateisysteme geben, die weder / noch \ als Pfadtrenner verwenden) ist die Verwendung der PHP-Konstanten DIRECTORY_SEPARATOR.

    Muss ich hier alles mit Backslashes abhandeln bzw. was mache ich wenn ein User in der Konfiguration es mal mit Slash mal mit Backslash einträgt? Oder mal mit Doppel Backslah etc. Ich habe es ausprobiert, es läuft ja anscheinend auch gemischt, aber ist das zuverlässig?

    define("TMP_DIR", "C:\\Inetpub\db\\");
    define("XML_DIR", "C:\Inetpub\\xml\\");
    

    Im String-Kontext hat der Backslash eine besondere Bedeutung, die dir in deinem Beispiel zufällig nicht auffällt. Aber probier mal den Unterschied zwischen

    echo "C:\neuer ordner";
    echo "C:\\neuer ordner";
    

    Viele Grüße
    Robert

    1. Hallo Robert,

      die Sonderbedeutung von \ als Steuerzeichen für Sonderzeichen greift nur in Strings mit Doppel-Anführungszeichen " oder in Heredoc-Strings. Bei Strings mit einfachen Anführungszeichen ' oder Nowdoc-Strings nicht. Es gibt nur das klitzekleine Detail mit dem Backslash am Ende; $path = 'c:\hugo\'; gibt dann doch eine Überraschung.

      Die sicherste Lösung ist: DIRECTORY_SEPARATOR für alle!

      Rolf

      --
      sumpsi - posui - clusi
      1. Hallo @Rolf B,

        die Sonderbedeutung von \ als Steuerzeichen für Sonderzeichen greift nur in Strings mit Doppel-Anführungszeichen " oder in Heredoc-Strings. Bei Strings mit einfachen Anführungszeichen ' oder Nowdoc-Strings nicht.

        echo 'Ist\'s wirklich so?'
        

        😉

        Die sicherste Lösung ist: DIRECTORY_SEPARATOR für alle!

        d'accord – bzw. d\'accord!

        Viele Grüße
        Robert

      2. hi,

        Die sicherste Lösung ist: DIRECTORY_SEPARATOR für alle!

        Sicher hilfreich, stellt aber auch nicht sicher daß eine fehlerfreie Konfiguration eingespielt wird.

        MfG

        1. Tach!

          Die sicherste Lösung ist: DIRECTORY_SEPARATOR für alle!

          Sicher hilfreich, stellt aber auch nicht sicher daß eine fehlerfreie Konfiguration eingespielt wird.

          Was möchtest du damit sagen? Die Konstante ist jedenfalls nicht konfiguriert sondern von PHP in Abhängigkeit vom System vordefiniert.

          dedlfix.

  3. Hallo Armin,

    offiziell gibt es in PHP die vordefinierte Konstante DIRECTORY_SEPARATOR. Aber scheinbar funktioniert der Vorwärts-Schrägstrich auf allen OS, wo PHP läuft.

    Aber solltest mit den Verzeichnisseparatoren etwas vorsichtig sein.

    define("TMP_DIR", "var/html/db/");
    ...
    $fp1 = fopen(TMP_DIR . "/tmp1/".$datname1.".txt","wb");
    

    öffnet die Datei var/html/db//tmp1/foo.txt, was von PHP zwar verdichtet wird, aber trotzdem kein richtiger Pfadname ist.

    Insbesondere am Beginn eines Pfadnamens ist ein doppelter Directory-Separator semantisch etwas anderes als mittendrin; stell Dir vor, du würdest dies tun:

    define("ROOT_DIR", "/");
    ...
    $fp1 = fopen(ROOT_DIR . "/usr/".$datname1.".txt","wb");
    

    Das würde dann zu //usr/foo.txt führen, und unter Windows wäre das ein Zugriff auf einen UNC-Pfad, d.h. er würde die Netzwerk-Ressource usr suchen. Was Unix draus macht weiß ich nicht.

    Leider hat PHP keine definierte Funktion zum Kombinieren von Pfaden, d.h. entweder muss man sich da selbst was schreiben oder eben aufpassen, wenn man Pfade zusammenbaut.

    Rolf

    --
    sumpsi - posui - clusi
  4. hi again

    das da ist nicht zuverlässig:

    define("TMP_DIR", "C:\\Inetpub\db\\");
    define("XML_DIR", "C:\Inetpub\\xml\\");
    

    Das kann mächtig in die Hose gehen insofern als daß der Interpreter den Pfad nicht so versteht wie es der Autor meinte!

    Ein print qx(dir c:\\windows\temp); gibt mir ein "Datei nicht gefunden" und danach den Inhalt des Verzeichnisses /window aus obwohl ich eigentlich was ganz anderes wollte 😉

    Nämlich den Inhalt von /windows/temp und da steht genua eine Datei.

    Also Vorsicht!

    1. Hallo pl,

      Ein print qx(dir c:\\windows\temp); gibt mir ein "Datei nicht gefunden" und danach den Inhalt des Verzeichnisses /window aus obwohl ich eigentlich was ganz anderes wollte 😉

      Nämlich den Inhalt von /windows/temp und da steht genua eine Datei.

      hm, was könnte denn \t für eine Bedeutung haben? 😉

      Viele Grüße
      Robert

      1. hi

        Ein print qx(dir c:\\windows\temp); gibt mir ein "Datei nicht gefunden" und danach den Inhalt des Verzeichnisses /window aus obwohl ich eigentlich was ganz anderes wollte 😉

        Nämlich den Inhalt von /windows/temp und da steht genua eine Datei.

        hm, was könnte denn \t für eine Bedeutung haben? 😉

        Es hat die Bedeutung einer Überraschung!

        (Die immer dann voliegt wenn was ganz anderes kommt als das was man sich gewünscht hat)

        1. Hallo pl,

          hm, was könnte denn \t für eine Bedeutung haben? 😉

          Es hat die Bedeutung einer Überraschung!

          das möchte ich gerne um acht Zeichenpositionen zur Seite weisen.

          Viele Grüße
          Robert

        2. Hallo,

          (Die immer dann voliegt wenn was ganz anderes kommt als das was man sich gewünscht hat)

          Weshalb wir hier ja auch nicht bei „Wünsch dir was!“ sind…

          Gruß
          Kalk

      2. hi

        Ein print qx(dir c:\\windows\temp); gibt mir ein "Datei nicht gefunden" und danach den Inhalt des Verzeichnisses /window aus obwohl ich eigentlich was ganz anderes wollte 😉

        Nämlich den Inhalt von /windows/temp und da steht genua eine Datei.

        hm, was könnte denn \t für eine Bedeutung haben? 😉

        Bei mir greift \t in den Kommandozeilenpuffer. Da kann z.B. sowas drinstehen wie \$hf_mig$ was auch erklärt warum die Meldung 'Datei nicht gefunden' erscheint.

        Und bei Dir?

    2. Tach!

      Ein print qx(dir c:\\windows\temp); gibt mir ein "Datei nicht gefunden"

      Bei mir ergibt das einen Syntaxfehler. Thema ist übrigens PHP. Wenn du abweichend davon antwortest, wäre es sinnvoll, wenn du das zumindest klarstellst.

      dedlfix.

      1. Tach!

        Ein print qx(dir c:\\windows\temp); gibt mir ein "Datei nicht gefunden"

        Bei mir ergibt das einen Syntaxfehler. Thema ist übrigens PHP. Wenn du abweichend davon antwortest, wäre es sinnvoll, wenn du das zumindest klarstellst.

        print system("dir c:\\windows\temp"); Verhält sich bei mir mit PHP genauso wie mit Perl oben beschrieben. Es erzeugt also auch keine Fehlermeldung.

        MfG