Matze: Problem mit move_uploaded_file()

Guten Morgen!

Ich hab grad ein, eigentlich triviales, Problem :(
Ich versuche eine Datei auf den Server zu laden. Das klappt aber nicht.
Ich bekomme auch keinen Error/Warning/Notice angezeigt deshalb steh ich grad irgendwie auf dem Schlauch.
Kann mir jemand einen Hinweis geben was ich falsch mache?

$upload_path = '/';  
$file_name = 'test';  
$file_type = '.txt';  
if(move_uploaded_file($_FILES['file_input']['name'], $upload_path.$file_name.$file_type)){  
    echo '<p>Upload Successful!</p>';  
}else{  
    echo '<p>ERROR</p>';  
}

Wie gesagt, bekomme ich von PHP keinen Fehler angezeigt, nur meine Ausgabe "ERROR" erscheint immer.
Ich habe auch herausgefunden, dass ich $upload_path irgendwelche Werte geben kann, ohne dass sich etwas ändert. Also wird dort wohl ein Fehler sein. Aber welcher?

Am HTML-Teil liegt es nicht, das Formular ist multipart/form-data und das Element besitzt auch den richtigen Namen.

Danke für Hilfe!

Grüße, Matze

  1. Hi,

    Ich versuche eine Datei auf den Server zu laden. Das klappt aber nicht.
    Ich bekomme auch keinen Error/Warning/Notice angezeigt

    Lass das komplette $_FILES-Array mittels print_r ausgeben.

    MfG ChrisB

    --
    Light travels faster than sound - that's why most people appear bright until you hear them speak.
    1. Guten Morgen Chris!

      Lass das komplette $_FILES-Array mittels print_r ausgeben.

      Array (
          [file_input] =>
          Array (
              [name] =>
              [type] =>
              [tmp_name] =>
              [error] => 4
              [size] => 0
          )
      )

      Mh, wo finde ich denn Angaben zu dem error 4?
      Und wieso tritt er auf?

      Danke und Grüße, Matze

      1. Mh, wo finde ich denn Angaben zu dem error 4?

        "UPLOAD_ERR_NO_FILE
            Value: 4; No file was uploaded."

        Ok, gefunden :)

        Aber

        Und wieso tritt er auf?

        das frag ich mich jetzt erst recht.

        Danke und Grüße, Matze

        1. Also der Fehler (error 4) tritt nur auf wenn ich keine Datei ausgewählt habe. Logisch.
          Das Dateifeld des Affenformulars war nach einer Fehlermeldung wieder leer. Hatte ich vergessen/übersehn.

          Wenn ich eine Datei auswähle erhalte ich bei z.B. einem Bild:

          Array (
              [file_input] => Array (
                  [name] => wine.jpg
                  [type] => image/jpeg
                  [tmp_name] => /var/www/web30/phptmp/phpRcickf
                  [error] => 0
                  [size] => 65614
              )
          )

          Danke und Grüße, Matze

          1. Hello,

            Also der Fehler (error 4) tritt nur auf wenn ich keine Datei ausgewählt habe. Logisch.
            Das Dateifeld des Affenformulars war nach einer Fehlermeldung wieder leer. Hatte ich vergessen/übersehn.

            Wenn ich eine Datei auswähle erhalte ich bei z.B. einem Bild:

            Array (
                [file_input] => Array (
                    [name] => wine.jpg
                    [type] => image/jpeg
                    [tmp_name] => /var/www/web30/phptmp/phpRcickf
                    [error] => 0
                    [size] => 65614
                )
            )

            Woran DU siehst, dass Du als erstes den Error auswerten solltest, bevor Du irgendetwas anderes machst:

            if(isset($_FILES[$file_element_name]['error']) and $_FILES[$file_element_name]['error'] === 0)
                {
                    ## File hochgeladen, weitermachen
                    ## z.B. Prüffunktion aufrufen
                    ## ...
                }
                else
                {
                    ## Fehler aufgetreten
                }

            Und achte bitte darauf, dass Dir niemand PHP-Files auf den Server hochladen kann. Da die aber je nach System unterschiedlich heißen können (Endungen php, phps, phtml, usw.) ist es ratsam, das Verzeichnis, in dem die Files gelagert werden, entweder ausßerhalb der Document Root anzulegen, oder aber den Parser für dieses Verzeichnis auszuschalten.

            Außerdem musst Du darauf achten, dass Dir niemand eine .htaccess oder eine php.ini (beim CGI) in ein per http erreichbares Verzeichnis hochläd. Das geht immer dann besonders einfach, wenn man Dateien unter dem vom Client gelieferten Namen abspeichert.

            Deshalb solltest Du sicherstellen, dass Du den Namen genauestens untersuchst, wenn Du Dateien unter einem vom Client geleiferten Namen abspeicherst. Es könnte sich auch ein Pfad darin verstecken. Dann wäre es dem Client möglich, die Dateien überal im vom PHP beschreibbaren Dateisystem unterzubringen.

            Fileupload-Scripte sind gefährlich!

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Hallo Tom,

              ja genauso hab ich es gemacht.
              Also if(isset(..['error']) && ... === '0')...
              Die Dateien werden aber vorher schon auf den Mimi-Typ geprüft, wobei das natürlich auch nicht 'sicher' ist. Dann sind bis jetzt nur 5 Dateitypen erlaubt (pdf, doc, jpg, gif, png) und die Dateien werden auf dem Server umbennant.

              Alles gut?

              Grüße, Matze

              1. Hello,

                ja genauso hab ich es gemacht.
                Also if(isset(..['error']) && ... === '0')...
                Die Dateien werden aber vorher schon auf den Mimi-Typ geprüft, wobei das natürlich auch nicht 'sicher' ist. Dann sind bis jetzt nur 5 Dateitypen erlaubt (pdf, doc, jpg, gif, png) und die Dateien werden auf dem Server umbennant.

                Bilder kannst Du mit Hilfe von getimagesize()
                http://de.php.net/manual/en/function.getimagesize.php
                relativ sicher erkennen. Ich habe es bisher noch nicht geschafft, ein Nicht-Bild durchzubringen.

                Es können in den Bildern aber immer noch Daten/Viren versteckt sein.

                Den MIME (Multipurpose Internet Mail Extension)-Typ einer Datei musst Du auf dem Server selber feststellen. Der vom Client mitgelieferte kann gelogen sein. Und da wird es spätestens schwierig. Dir gute alte Funktion mime_content_type() http://de.php.net/manual/en/function.mime-content-type.php ist angeblich angekündigt für spätere PHP-Versionen. Sie hat auf LINUX-Plattformen immer ausreichend zuverlässig den Typ ermittelt. Die als Ersatz genannte PECL extension Fileinfo ist sehr viel fehlerträchtiger und außerdem komplizierter in der Benutzung.

                Es ist also immer ratsam, die Dateien auf jeden Fall in einem Verzeichnis abzulegen, dass von PHP (und anderen Parsern) nicht geparst wird.

                Also

                1. ['error'] prüfen
                2. MIME-Type feststellen
                3. Dateinamen untersuchen und ggf. bereinigen.
                   Besser noch, unter einem eingenen Namen ablegen und
                   den mitgelieferten Wunschnamen in der Datenbank oder einer Datei dazu merken
                4. Namen, wie .htaccess, php.ini, usw, auf jeden Fall verhindern
                5. Ablegen der Datei nur in einem nicht geparsten Verzeichnis veranlassen

                6. Zu den Dateien immer eine Referenz bilden, WER sie hochgeladen hat
                7. keine anonymen Uploads zulassen
                8. IP, Zeitpunkt und Forwarder-IP (falls vorhanden) für den Upload speichern in einem
                   für normale User unerreichbaren Logfile, am besten auf einem gesonderten Logserver

                Liebe Grüße aus dem schönen Oberharz

                Tom vom Berg

                --
                Nur selber lernen macht schlau
                http://bergpost.annerschbarrich.de
                1. Hallo Tom!

                  Ich fange gerade an mich mit PHP zu beschäftigen und da interessiert mich das Thema Sicherheit ganz besonders. Darum meine folgende Nachfrage:

                  Also

                  1. ['error'] prüfen
                  2. MIME-Type feststellen
                  3. Dateinamen untersuchen und ggf. bereinigen.
                       Besser noch, unter einem eingenen Namen ablegen und
                       den mitgelieferten Wunschnamen in der Datenbank oder einer Datei dazu merken
                  4. Namen, wie .htaccess, php.ini, usw, auf jeden Fall verhindern
                  5. Ablegen der Datei nur in einem nicht geparsten Verzeichnis veranlassen

                  bis hierher nachvollziehbar

                  aber was nutzen dir die Punkte:

                  1. Zu den Dateien immer eine Referenz bilden, WER sie hochgeladen hat
                  2. keine anonymen Uploads zulassen
                  3. IP, Zeitpunkt und Forwarder-IP (falls vorhanden) für den Upload speichern in einem
                       für normale User unerreichbaren Logfile, am besten auf einem gesonderten Logserver

                  was kann man mit diesen Daten anfangen?

                  FG Ulysses

                  1. Hello Ulysses,

                    [...]

                    bis hierher nachvollziehbar

                    aber was nutzen dir die Punkte:

                    1. Zu den Dateien immer eine Referenz bilden, WER sie hochgeladen hat
                    2. keine anonymen Uploads zulassen
                    3. IP, Zeitpunkt und Forwarder-IP (falls vorhanden) für den Upload speichern in einem
                          für normale User unerreichbaren Logfile, am besten auf einem gesonderten Logserver

                    was kann man mit diesen Daten anfangen?

                    Man schaut sich seine hochgeladenen Dateien doch regelmäßig und möglichst zeitnah an. Wenn da nun plötzlich Hakenkreuze, Kinderpornos oder Ministerbilder auftauchen, obwohl dies vielleicht ungesetzlich oder zumindest ekelerregend ist, dann möchte man den "Schuldigen" doch wenigstens ermitteln können und zur Rechenschaft ziehen.

                    Das geht am einfachsten, wenn man gleich an der Datei eine Kennung anbringt, wer die erzeugen lassen hat. Die Usernummer also an leicht extrahierbarer Stelle im Dateinamen unterzubringen, wäre ein praktikabler weg.

                    Wenn man dies nicht kann oder will, oder sogar anonymen Upload zulassen will, sollte man zumindest die notwendigen Ermittlungsdaten (IP, Forwarder-IP und exacten zeitpunkt des Uploads) speichern zum Objekt. Das kann in einer referenzierenden Tabelle stattfinden.

                    Liebe Grüße aus dem schönen Oberharz

                    Tom vom Berg

                    --
                    Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
                    1. Hi!

                      Man schaut sich seine hochgeladenen Dateien doch regelmäßig und möglichst zeitnah an. Wenn da nun plötzlich Hakenkreuze, Kinderpornos oder Ministerbilder auftauchen, obwohl dies vielleicht ungesetzlich oder zumindest ekelerregend ist, dann möchte man den "Schuldigen" doch wenigstens ermitteln können und zur Rechenschaft ziehen.

                      Ok, d.h. die Daten sind eher rechts- als sicherheitsrelevant.

                      FG Ulysses

                      1. Hello,

                        Man schaut sich seine hochgeladenen Dateien doch regelmäßig und möglichst zeitnah an. Wenn da nun plötzlich Hakenkreuze, Kinderpornos oder Ministerbilder auftauchen, obwohl dies vielleicht ungesetzlich oder zumindest ekelerregend ist, dann möchte man den "Schuldigen" doch wenigstens ermitteln können und zur Rechenschaft ziehen.

                        Ok, d.h. die Daten sind eher rechts- als sicherheitsrelevant.

                        Genau, deshalb auch der Absatz ;-)

                        Liebe Grüße aus dem schönen Oberharz

                        Tom vom Berg

                        --
                        Nur selber lernen macht schlau
                        http://bergpost.annerschbarrich.de
    2. Also ich hab den kleinen Fehler jetzt wohl gefunden. Schon blöd manchmal.
      Es heißt nicht
      move_uploaded_file($_FILES['file_input']['name']
      sondern
      move_uploaded_file($_FILES['file_input']['tmp_name']
                                                ^^^^

      Das wars eigentlich schon.
      Den Ordner in den die Dateien geschoben werden habe ich per FTP erstellt und die Rechte 0747 gegeben. Die Dateien selbst haben 0644.

      Funktioniert alles bestens, aber ich bin mir bei 0747 für den Ordner nicht sicher. 0777 geht auch, ist wohl aber zu viel des Guten.

      Danke und Grüße, Matze

      1. echo $begrüßung;

        Funktioniert alles bestens, aber ich bin mir bei 0747 für den Ordner nicht sicher. 0777 geht auch, ist wohl aber zu viel des Guten.

        Die Zahlen allein sind noch nicht besonders aussagekräftig. Es kommt beim fraglichen Objekt auf die Besitzverhältnisse an, besonders die Gruppe. Und bei der Gruppenberechtigung ist wichtig, wer alles zur Gruppe gehört. Erst dann weiß man, wer unter alle anderen zu zählen ist. Wenn du also die Rechte bewerten willst, musst du die Besitzverhältnisse und die Gruppenzugehörigkeiten mit in Betracht ziehen.

        echo "$verabschiedung $name";

        1. Hello,

          Die Zahlen allein sind noch nicht besonders aussagekräftig. Es kommt beim fraglichen Objekt auf die Besitzverhältnisse an, besonders die Gruppe. Und bei der Gruppenberechtigung ist wichtig, wer alles zur Gruppe gehört. Erst dann weiß man, wer unter alle anderen zu zählen ist. Wenn du also die Rechte bewerten willst, musst du die Besitzverhältnisse und die Gruppenzugehörigkeiten mit in Betracht ziehen.

          Und die geringsten Rechte zählen.
          Wenn also jemand zu einer Gruppe gehört und dieser Gruppe wurden alle Rechte entzogen, dann kann OTHERS ruhig auf rwx stehen, derjenige darf trotzdem nicht lesen.

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de