Lars: Upload: Problem mit den Berechtigungen

Hey ihr,

ich habe ein Problem mit meinem Upload-Script. Es soll eine Datei hochladen und in einem anderen Verzeichnis speichern.

Ich erhalte jedoch folgenden Fehler:

Warning: move_uploaded_file(../../login/Lars) [function.move-uploaded-file]: failed to open stream: Permission denied in C:\xampp\htdocs\site\admin\include\login.php on line 246

Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move 'C:\xampp\tmp\php98EA.tmp' to '../../login/Lars' in C:\xampp\htdocs\site\admin\include\login.php on line 246

Hier mal der Code, mit dem ich es versuche. Die Zeilennummern hab ich mal dazu geschrieben, damit die Zeile 246 gleich ausfindig machen kann:

244 // Kopiervorgang durchführen, bei Fehler melden
245 $ziel = '../../login/lars;
246 if(!move_uploaded_file($_FILES['datei']['tmp_name'], $ziel)) {
247 $error = 'copy';
248 }
249 // Berechtigungen festlegen
250 if(!chmod($ziel, 0644)) {
251 $error = 'chmod';
252 }

Das dürften wohl die entscheidenden Zeilen sein. Hat jemand eine Idee?

Grüße
Lars

  1. Hello Lars,

    ist das Verzeichnis überhaupt vorhanden?

    C:\xampp\tmp\php98EA.tmp
               -----

    Und lies dir mal das Kapitel im PHP-Handbuch durch
    http://de.php.net/manual/de/features.file-upload.php

    Harzliche Grüße vom Berg
    http://bergpost.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

    1. Und lies dir mal das Kapitel im PHP-Handbuch durch
      http://de.php.net/manual/de/features.file-upload.php

      Hey, Danke für deine Antwort erstmal. Es lag an der Variable $ziel. Ich hab versehentlich dort den Dateinamen gar nicht mit angegeben... hatte ich irgendwie verdrängt. Jetzt gehts ;-)

      Falls du (oder jemand anderes) hier nochmal reinguckst: Hast du den Hinweis auf das Kapitel im PHP-Handbuch rein aus Routine gegeben, oder weisen die Codeschnippsel schon grobe Fahrlässigkeiten oder ähnliches auf?

      Ich werds natürlich nochmal durchackern, wollte ich eh tun... bin noch nicht so fit, wie du an der Frage sicher schon bemerkt hast ;-)

      Grüße
      Lars

      1. Hello,

        Und lies dir mal das Kapitel im PHP-Handbuch durch
        http://de.php.net/manual/de/features.file-upload.php

        Hey, Danke für deine Antwort erstmal. Es lag an der Variable $ziel. Ich hab versehentlich dort den Dateinamen gar nicht mit angegeben... hatte ich irgendwie verdrängt. Jetzt gehts ;-)

        Falls du (oder jemand anderes) hier nochmal reinguckst: Hast du den Hinweis auf das Kapitel im PHP-Handbuch rein aus Routine gegeben, oder weisen die Codeschnippsel schon grobe Fahrlässigkeiten oder ähnliches auf?

        Da steht auch nicth alles drin. Ist aber schon mal ein Einsatzpunkt.
        Üblicherweise fehlt auf einem Windows-Rechner das Upload-Tmp-Dir, da dies bei Windows TEMP heißt und nicht TMP. Kommt immer darauf an, welche XAMMP-Out-of-the-box-version man erwischt hat. Ich glaube mich zu erinnern, dass sie das in den neueren Installationen korrigiert haben.

        Und je nach Windows müssen auch die Rechte gestzt werden. Was auf einem Win98SE ncoh alles direkt nach der Installation funktionierte (bis auf TEMP/TMP), das geht auf einem WinXP nicht mehr ohne weiteres.

        Wichtig beim Upload ist, dass

        1. Als erstes das Error-Feld abgefragt wird

        if (isset($_FILES[$formfeldname]['error']) and $_FILES[$formfeldname]['error'] === 0)

        Also erst vergewissern, ob PHP einen Uploadversuch erkannt hat und die $_FILES-Variablen
           auch angelegt hat, dann schauen, ob das Error-Feld identisch 0 ist, nur dann wurde ein
           fehlerfreier Single-File-Upload durchgeführt
           Bei einem Mehrfach-Upload ist dieses Feld ein Array und mann muss dann für jedes
           einzelne File die Frage stellen. Insgesamt also:

        if (isset($_FILES[$formfeldname]['error']))
           {
             if ($_FILES[$formfeldname]['error'] === 0)
             {
               ## einzelnes File weiterverarbeiten
               ## Prüfung auf die zulässigen MIME-Types
               ## Kopieren in permantentes Verzeichnis

        }
             elseif (is_array($_FILES[$formfeldname]['error'])
             {
               ## mehrere Files hochgeladen
               foreach($_FILES[$formfeldname]['error'] as $fileno => $fileerror)
               {
                 if ($fileerror === 0)
                 {
                   ## File unter Nummer $fileno ist sauber angekommen
                   ## Prüfung auf die zulässigen MIME-Types
                   ## Kopieren in permantentes Verzeichnis
                 }
                 else
                 {
                   ## Fehler $fileerror beim Upload von File $fileno
                 }
               }
             }
             else
             {
               ## Fehler beim Upload, mehr Info gbit die Fehlernummer
             }
           }
           else
           {
             ## kein Upload stattfefunden
           }

        Die Prüfung auf den MIME-Type darf nicht mit dem vom Client mitgelieferten Wert geschehen, sondern mit einer Prüffunktion auf dem Server. Sie hierzu
        http://de3.php.net/manual/de/function.mime-content-type.php und
        http://de3.php.net/manual/de/ref.fileinfo.php

        Wenn Du den Namen bildest für das Ziel, verlasse Dich bitte auch nicht auf den vom Client gelieferten. Bei einer Verwaltung mit Datenbank kannst Du ohnehin einen translateion-Table zwischenschalten und einen Namen auswürfeln. Bewährt hat sich bei Uploads, die durch vorgemerkte User stattfinden, die $usernummer mit reinzunehmen, sodass man auch nach einem Datenbankabsturz noch die Files den Usern zuordnen kann.
        Wenn der Name angelenht an das sein soll, was der Client mitliefert, auf jeden fall die Funktion

        basename()  http://de.php.net/manual/de/function.basename.php oder
           pathinfo()  [http://de.php.net/manual/de/function.pathinfo.php]

        oder eine ähnliche eigene Funktion bemühen. Der Client könnte hier nämlich auch

        ../../../etc/passwd

        mitliefern. Das sollte üblicherweise für den PHP-Prozess zwar schreibgeschützt sein, aber man weiß ja nicht, welcher "chmod 777 / -R" Künstler auf dem Host am Werke war...

        Harzliche Grüße vom Berg
        http://bergpost.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

        1. Hello,
          [sehr viel Text]

          Hey Tom! Vielen Dank für die ausführlichen Infos, damit hatte ich nicht gerechnet! ;-) Hast mir sehr geholfen, damit werde ich mein Upload-Script auf jedenfall verbessern. :-)

          Grüße
          Lars