Talynn: Standardverzeichnis für Uploads

Hallo, liebe Leute!

Wo wird bei einer Standard-XAMPP-Installation auf Windows eine hochgeladene Datei temporär zwischengespeichert? Wird sie nach Gebrauch durch das PHP-Script gelöscht? Und wo könnte man dieses temporäre Upload-Verzeichnis ändern?

Hier mein Upload-Script:
<form name="form1" method="post" action="<? $PHP_SELF ?>" enctype="multipart/form-data">
 <input name="userfile" type="file" /><br/>
 <input name="upload" type="submit" value="upload" />
</form>
<?
  echo $_FILES['userfile']['name'];
?>

Vielen Dank. :)

  1. Hi,

    Wo wird bei einer Standard-XAMPP-Installation auf Windows eine hochgeladene Datei temporär zwischengespeichert? Wird sie nach Gebrauch durch das PHP-Script gelöscht? Und wo könnte man dieses temporäre Upload-Verzeichnis ändern?

    RTFM: http://www.php.net/manual/en/features.file-upload.php

    MfG ChrisB

  2. Hello,

    Wo wird bei einer Standard-XAMPP-Installation auf Windows eine hochgeladene Datei temporär zwischengespeichert?

    in "upload_tmp_dir"
    Wenn kein Konfigurationswert eingestellt ist (z.B. in der php.ini oder den Conf-Dateien der Virtuellen Hosts), dann wird das /tmp-Verzeichnis des Servers benutzt.

    Jeder virtuelle Host sollte dein eigenes Upload-Verzeichnis bekommen

    Wird sie nach Gebrauch durch das PHP-Script gelöscht? Und wo könnte man dieses temporäre Upload-Verzeichnis ändern?

    Ja, der Name der Datei wird an das PHP-Script weitergereicht und wenn dieses endet, wird die Datei vom PHP-Runtime wieder beseitigt. Es handelt sich also nicht um eine echte temporäre Datei des Betriebssystems, sondern um eine statische, die aber von PHP kontgrolliert wird.

    Hier mein Upload-Script:
    <form name="form1" method="post" action="<? $PHP_SELF ?>" enctype="multipart/form-data">

    Nimm nicht $PHP_SELF, das ist ohnehin schon überaltert ("Register Globals" ist das Stichwort), sondern nimm $_SERVER['SCRIPT_NAME']. Mit $_SERVER['PHP_SELF'] könnte Dein Formular entführbar werden.

    <input name="userfile" type="file" /><br/>
    <input name="upload" type="submit" value="upload" />
    </form>

    <?
      echo $_FILES['userfile']['name'];
    ?>

    Der Name, der in ['name'] übermittelt wird, ist derjenoge, den der Client als Namen der Datei auf dem Client mitsendet. Er ist selbstverstänlich fälschbar und birgt, wenn man ihn unkontrolliert übernimmt, ggf. Gefahren. Alles, was vom Client kommt, ist potentiell gefährlich.

    Eine Mindestbehandlung des Namens kann man mit der Funktion basedir() vornehmen.

    Der Name der "temporären" Datei steht in $_FILES['userfile']['tmp_name'];

    Liebe Grüße

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    1. Hello,
      ...

      Liebe Grüße

      Tom vom Berg

      Hallo, Tom!

      Erst einmal Dankeschön für diese freundliche und umfangreiche Antwort. Nicht jeder konnte sich diesen Stil angewöhnen.

      Seltsamerweise beschreibt ein Gastautor einen Upload etwas anders. Mein Script mit $PHP_SELF funktioniert seltsamerweise auch ohne register_globals. (Ich habs trotzdem ausgetauscht.)

      Jetzt habe ich noch ein anderes Problem.

      if(isset($_POST['submit']))
        {
         echo "Die Datei wurde erfolgreich hochgeladen.";
        }

      ...der Text erscheint nicht.

      1. Hello,

        Seltsamerweise beschreibt ein Gastautor einen Upload etwas anders. Mein Script mit $PHP_SELF funktioniert seltsamerweise auch ohne register_globals. (Ich habs trotzdem ausgetauscht.)

        Jetzt habe ich noch ein anderes Problem.

        if(isset($_POST['submit']))

        Das Dilaogelement heißt in Deinem Script doch auch 'upload' und nicht 'submit'

        {
           echo "Die Datei wurde erfolgreich hochgeladen.";
          }

        ...der Text erscheint nicht.

        Dann sollten wir nun aber noch zu den Sicherheitslücken und zu den Fehlermöglichkeiten kommen.

        Nach einem Upload solltest Du auf jeden Fall als erstes

        if ($_FILES['formularfeldname']['error'] === 0)
          {
             ## Upload eines einzelnen Files ist OK
             ## weitermachen

        }
          else
          {
             ## Fehlerauswertung

        }

        prüfen.

        Außerdem solltest Du auch prüfen, WAS hochgeladen wurde. Wenn es eine ausführbare Datei, ein PHP-Script oder ähnliches ist, und Du das nicht erwartet hast, dann könnte der Server gefährdet sein.

        Liebe Grüße

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        1. if(isset($_POST['submit']))

          Das Dilaogelement heißt in Deinem Script doch auch 'upload' und nicht 'submit'

          Es heißt nicht "upload", der Wert value enthält nur die Beschriftung. (Ändere ich die If-Bedinung in 'upload', passiert genauso wenig.) Was soll ich also tun?

          Dann sollten wir nun aber noch zu den Sicherheitslücken und zu den Fehlermöglichkeiten kommen.

          Nach einem Upload solltest Du auf jeden Fall als erstes

          if ($_FILES['formularfeldname']['error'] === 0)
            {
               ## Upload eines einzelnen Files ist OK
               ## weitermachen

          }
            else
            {
               ## Fehlerauswertung

          }

          prüfen.

          Außerdem solltest Du auch prüfen, WAS hochgeladen wurde. Wenn es eine ausführbare Datei, ein PHP-Script oder ähnliches ist, und Du das nicht erwartet hast, dann könnte der Server gefährdet sein.

          Eins nach dem anderen. Ich bin PHP-Anfänger und muss so ein Script Schritt für Schritt aufbauen.

          1. Danke, ich habe das Problem gelöst.

            Das <input>-Element braucht einen Namen ("name="), auf den sich das Script beziehen kann. Den Hinweis brachte mir der unfreundliche ChrisB.

            Ich danke euch beiden für eure Hilfe. :)

          2. Hello,

            if(isset($_POST['submit']))

            Das Dilaogelement heißt in Deinem Script doch auch 'upload' und nicht 'submit'

            Es heißt nicht "upload", der Wert value enthält nur die Beschriftung.

            <input name="upload" type="submit" value="upload" />

            Und was für einen Wert enthält das Attribut "name"?

            Liebe Grüße

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            1. Und was für einen Wert enthält das Attribut "name"?

              Daran habe ich nicht gedacht, dir zu sagen, dass ich das Attribut "name" beim Ausprobieren bereits entfernt hatte und es immer noch nicht ging. Mit 'upload' hats leider auch nicht funktioniert, jetzt funktioniert es ja.

      2. Hi,

        Erst einmal Dankeschön für diese freundliche und umfangreiche Antwort. Nicht jeder konnte sich diesen Stil angewöhnen.

        Nicht jeder sieht ein, den Leuten das Lesen grundlegender Anleitungen abzunehmen, weil sie dafuer selbst zu faul sind.

        if(isset($_POST['submit']))
          {
           echo "Die Datei wurde erfolgreich hochgeladen.";
          }

        ...der Text erscheint nicht.

        Wenn dein Formular weiterhin so aussieht, wie eingangs gepostet, kein Wunder - es existiert kein Formularelement mit diesem Namen.

        MfG ChrisB

        1. Nicht jeder sieht ein, den Leuten das Lesen grundlegender Anleitungen abzunehmen, weil sie dafuer selbst zu faul sind.

          Und nicht jeder ist generell erst einmal freundlich zu Leuten, die sie nicht kennen. Was man als Kind gelernt hat, ist sowieso unwichtig...

          if(isset($_POST['submit']))
            {
             echo "Die Datei wurde erfolgreich hochgeladen.";
            }

          ...der Text erscheint nicht.

          Wenn dein Formular weiterhin so aussieht, wie eingangs gepostet, kein Wunder - es existiert kein Formularelement mit diesem Namen.

          MfG ChrisB

          Das ist wenigstens mal ein brauchbarer Vorschlag. Dankeschön. Trotzdem solltest du in Zukunft vielleicht nicht mehr mit Anfängern sprechen - du könntest sie durch deine Unfreundlichkeit abschrecken.

          MfG,
          Talynn

          1. Hi,

            Nicht jeder sieht ein, den Leuten das Lesen grundlegender Anleitungen abzunehmen, weil sie dafuer selbst zu faul sind.

            Und nicht jeder ist generell erst einmal freundlich zu Leuten, die sie nicht kennen.

            Stimmt.
            Leuten, die man nicht kennt, Fragen zu stellen, die man sich mit Leichtigkeit selbst haette beantworten koennen, in dem man nur mal an der passenden Stelle nachliest, halte ich fuer nicht sonderlich freundlich.
            Verhaelt sich uebrigens auch dann nicht anders, wenn man die Leute kennt.

            Trotzdem solltest du in Zukunft vielleicht nicht mehr mit Anfängern sprechen - du könntest sie durch deine Unfreundlichkeit abschrecken.

            Auch Anfaenger sollten sich daran gewoehnen, dass man erst mal versucht, sein Problem selber zu loesen, bevor man fragt - insb. dann, wenn sich die Fragen aeusserst leicht durch selber Nachlesen beantworten lassen.

            MfG ChrisB

            1. Stimmt.
              Leuten, die man nicht kennt, Fragen zu stellen, die man sich mit Leichtigkeit selbst haette beantworten koennen, in dem man nur mal an der passenden Stelle nachliest, halte ich fuer nicht sonderlich freundlich.

              Das ist ja schonmal falsch. Auf der von dir angegegebenen Seite habe ich nichts von einem temporären Speicherort, und wie man ihn einstellen könnte, gefunden. Und ich bezog mich auf deine Antwort, nicht auf meine Frage, die - wie ich finde - sehr freundlich war.

              Und jetzt bitte keine weitere Off-Topic-Diskussion.

              1. Hi,

                Das ist ja schonmal falsch. Auf der von dir angegegebenen Seite habe ich nichts von einem temporären Speicherort, und wie man ihn einstellen könnte, gefunden.

                Dann solltest du wirklich Lesen lernen:

                Files will, by default be stored in the server's default temporary directory, unless another location has been given with the upload_tmp_dir directive in php.ini. The server's default directory can be changed by setting the environment variable TMPDIR in the environment in which PHP runs.

                Und ich bezog mich auf deine Antwort, nicht auf meine Frage, die - wie ich finde - sehr freundlich war.

                Wie gesagt, fuer jeden Kleinscheiss nachfragen, ohne sich vorher selber zu unformieren, ist m.E. auch eine Art von Frechheit.

                MfG ChrisB

      3. Hi Talynn,

        Seltsamerweise beschreibt ein Gastautor einen Upload etwas anders. Mein Script mit $PHP_SELF funktioniert seltsamerweise auch ohne register_globals. (Ich habs trotzdem ausgetauscht.)

        So wie es dort im Beispielcode mit $_SERVER['PHP_SELF'] gemacht wird, sollte man es nicht machen. Ich habe das gerade im Bugtracker eingetragen, damit das jemand korrigiert. Gut, dass du aufgepasst hast :-)

        Viele Grüße,
          ~ Dennis.

        1. Hallo Dennis,

          »» So wie es dort im Beispielcode mit $_SERVER['PHP_SELF'] gemacht wird, sollte man es nicht machen. Ich habe das gerade im Bugtracker eingetragen, damit das jemand korrigiert. Gut, dass du aufgepasst hast :-)

          Danke für den Hinweis, ist korrigiert.

          Viele Grüße,
          Christian

          1. Hello Christian,

            »» So wie es dort im Beispielcode mit $_SERVER['PHP_SELF'] gemacht wird, sollte man es nicht machen. Ich habe das gerade im Bugtracker eingetragen, damit das jemand korrigiert. Gut, dass du aufgepasst hast :-)

            Danke für den Hinweis, ist korrigiert.

            Das Beispiel enthält allerdings noch mehr fragwürdige Stellen:

            $_FILES['thefile']['name']  Der Name der Datei, wie sie auf dem Clientsystem genannt wurde.
                                            Eventuelle Verzeichnisangaben werden nicht mitgesendet.

            $_FILES['thefile']['size']  Die Größe der Datei in Bytes

            $_FILES['thefile']['type']  Der Mime-Type der Datei, wie der Client sie lieferte (z.B. image/gif).

            Diese Angaben sind sämtlich fälschbar. In einem Musterscript auf SelfHTML dann damit weiterzuarbeiten,  ohne die passenden Hinweise zu geben, halte ich ich für nicht seriös.

            Die einzigen nicht fälschbaren Werte im Files-Array sind die Fehlernummer

            $_FILES['thefile']['error']

            und der temporäre Dateiname

            $_FILES['thefile']['tmp_name']

            da sie beide vom eigenen Server des Scriptes ermittelt/vergeben werden

            Speziell an dieser Passage störe ich mich:

              
            <?php  
            if(isset($_FILES['thefile']['tmp_name']) && $_FILES['thefile']['type']=="application/msword"){  
              // weiter mit der Verarbeitung  
            }else{  
             if(isset($_FILES['thefile']['tmp_name'])){  
                    die("Dieses File ist kein MS-Word Dokument sondern hat den Mime-Type ".$_FILES['thefile']['type']);  
             }else{  
                    die("Kein File übertragen")  
                    // man muss hier nicht zwingenderweise abbrechen,  
                    // das File kann auch freiwillig übermittelt worden sein,  
                    // je nach Anforderung  
             }  
            }  
            ?>  
            
            

            Es wird hier nicht als erstes nach dem Fehlerwert gefragt, wie es richtig wäre

              
            if (isset($_FILES[$myfieldname]) and $_FILES[$myfieldname]['error'] === 0)  
            {  
              ## weitermachen  
            }  
            else  
            {  
              ## Fehlerbehandlung  
            }  
            
            

            und es wird eine vermeintliche Sicherheit vorgegaukelt, was ich für BESONDERS SCHLIMM halte, indem man den vom Client mitgelieferten MIME-Type durch einen Stringvergleich "überprüft".

            Er wird eben hierdurch NICHT ÜBEPRÜFT, sondern es wird nur den Angaben des Client vertraut. Und diese Methode wird hier auch noch als Sicherheitsfeature des Scriptes dargestellt. Das ist unseriös und zwar deshalb, weil die Verantwortlichen es besser wissen.

            Ich möchte die generelle Überarbeitung des Scriptes daher nochmals hier im Forum zur Diskussion stellen, bevor ich selber dann den Bugtracker bemühe.
            Wie man einen Fileupload einigermaßen vernünftig absichert, habe ich hier oft genug ausfühlich beschrieben und auch erwähnt, dass ich mich sehr darüber ärgere, dass es (immer noch) keine (mehr) erprobte Funktion für die Feststellung des MIME-Types in PHP gibt.

            Liebe Grüße

            Tom vom Berg

            --
            Nur selber lernen macht schlau