hannes: Dateiupload

0 78

Dateiupload

hannes
  • php
  1. 0
    dedlfix
    1. 0
      hannes
      1. 0
        Shadowcrow
      2. 0
        dedlfix
      3. 0
        Vinzenz Mai
  2. 0
    Der Martin
    1. 0
      hannes
      1. 0
        dedlfix
        1. 0
          hannes
          1. 0
            Shadowcrow
            1. 0
              hannes
              1. 0
                dedlfix
                1. 0
                  hannes
                  1. 0
                    dedlfix
                    1. 0
                      Shadowcrow
                    2. 0
                      Tom
                      1. 0
                        dedlfix
                        1. 0
                          hannes
                          1. 0
                            dedlfix
                            1. 0
                              hannes
                              1. 0
                                dedlfix
                                1. 0
                                  hannes
                                  1. 0
                                    dedlfix
                          2. 0
                            Der Martin
                            1. 0
                              hannes
                              1. 0
                                Shadowcrow
                                1. 0
                                  Shadowcrow
                                  1. 0
                                    hannes
                                    1. 0
                                      Tom
                              2. 0
                                Tom
                              3. 0
                                Der Martin
                                1. 0
                                  Shadowcrow
                                  1. 0
                                    Der Martin
                                    1. 0
                                      Shadowcrow
                                      1. 0
                                        hannes
                                        1. 0
                                          Tom
                                          1. 0
                                            hannes
                                          2. 0
                                            hannes
                                            1. 0
                                              Tom
                                              1. 0
                                                Tom
                                              2. 0
                                                hannes
                                                1. 0
                                                  Tom
                                                  1. 0
                                                    hannes
                                                    1. 0

                                                      Dateiupload und Typüberprüfung

                                                      Shadowcrow
                                                      1. 0
                                                        Tom
                              4. 2
                                ChrisB
                        2. 0
                          Tom
                          1. 0
                            dedlfix
                            1. 0
                              Tom
                              1. 0
                                dedlfix
                                1. 0
                                  Tom
                                  1. 0
                                    dedlfix
                                    1. 0
                                      Tom
                          2. 0
                            Der Martin
                            1. 0
                              Tom
                              1. 0
                                Der Martin
                                1. 0
                                  Tom
                            2. 0

                              Dateiupload, was tut move_uploaded_file() wirklich?

                              Tom
                              1. 0
                                dedlfix
                                1. 0
                                  Tom
                                  1. 0
                                    dedlfix
                                    1. 0
                                      Tom
                                      1. 0
                                        dedlfix
                                        1. 1

                                          Bin hetzt heftig beleidigt [... :-) ...]

                                          Tom
                                          • menschelei
                                          1. 0

                                            du doch nicht

                                            dedlfix
                              2. 0

                                Komme da nicht weiter...

                                Tom
                                1. 0
                                  Der Martin
                                  1. 0
                                    Tom
                  2. 0
                    Tom
          2. 0
            dedlfix
            1. 0
              Tom
  3. 0
    Felix Riesterer
    1. 2
      dedlfix
      1. 0
        Felix Riesterer
  4. 0
    Tom
    1. 0
      hannes
    2. 0
      hannes

Hallo,
ich kann einfach die Lösung nicht finden! Mir scheint der Code korrekt, jedoch bleibt die Variable $userfile leer.

Hier das Formular:

<form name="form1" method="post" enctype="multipart/form-data" action="<? echo htmlspecialchars ($_SERVER['PHP_SELF']); ?>">  
		<table width="55%" cellspacing="0" border="1"> <!--cellspacing für Safari-->  
		<tr>  
			<td colspan='3' class="intern"><div  style='margin-top:8px;margin-left:5px'>&nbsp;&nbsp;Artikel hochladen</div></td>  
		</tr>  
		  <tr>  
			<td colspan='3' class='intern' height='30'><div id='hr_intern'></td>  
		  </tr>  
		<tr>  
			<td class="intern"><div style="margin-left:12px;">w&auml;hle die Datei (Artikel), die du hochladen willst:</div>  
			<input type='hidden' name='MAX_FILE_SIZE' value='.ini_get('upload_max_filesize').'> <!-- 409600 = 800kB; 614400 = 1200kB -->  
			<input type='file' name='userfile' style='margin:5px 0 20px 12px; width:280px;'><!-- gewählte Datei bekommt diesen Namen -->  
			</td>  
		</tr>  
		<tr>  
		  <td colspan='3' class="intern"><div style='margin-left:12px;'>Artikelbezeichnung:<br>  
			  Gib einen aussagekr&auml;ftigen  
			  Namen an, unter welchem der Artikel auf dem Server abgelegt und auf dem Bildschirm angezeigt werden soll (tonform_....).<br></div>  
			 <input type='text' name='artikelName' style='margin:5px 0 20px 12px;'></td>  
		</tr>  
		<tr>  
		  <td colspan='3' class="intern"><div style='margin-left:12px;'>Preis:<br>  
			  Gib den Preis dieses Artikels an (ohne Versandkosten).<br></div>  
			 <input type="text" name="preis" style='margin:5px 0 20px 12px;' value='z.Bsp.: 420'></td>  
		</tr>  
		<tr>  
			<td class="intern"><input style="margin:5px 0 5px 12px;" name='submit' type='submit' value='abschicken'></td>  
		</tr>  
		<tr>  
			<td  class="intern"><div style='margin:12px;'><a href='shop.php' style='font-size:11px;' class='back' title='zum Shop'>zum Shop</a></div></td>  
		</tr>  
		<tr>  
			<td  class="intern"><div style='margin:12px;'>Wenn du keine Artikel mehr hochladen willst, kannst du dich hier <a href="logout.php" class="fwd">abmelden</a></div></td>  
		</tr>  
		</table>  
		</form>

Die PHP-Auswertung sieht folgendermassen aus:

@session_start();  
if (isset($_POST['userfile'])) $userfile=$_POST['userfile'];  
  
/************************************************************************************************/  
if (($_SESSION['myusername'] == "") OR ($_SESSION['mypassword'] == "")) {  
	include ("login.php");  
}  
/************************************************************************************************/  
  
include("db_vars.php");  
  
mysql_connect("$dbserver", "$dbuser", "$dbpass")or die("Keine Verbindung zum Server möglich!");  
mysql_select_db("$dbname")or die("Keine Datenbankverbindung möglich!");  
  
  
$speicherdatum = date("d. M Y - H:i:s");  
$unix_time = time();  
$dir = "shop";  
$subdir = "pics";  
  
if(isset($_POST['submit']) && $_POST['submit']=="abschicken"){  
  
	if($userfile == "") {  
	 /*echo "<head><META HTTP-EQUIV='refresh' content='1;URL={$_SERVER['PHP_SELF']}'><link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
	 <table class='error'>  
	 <tr>  
		<td class='error'>du musst die Datei zum hochladen {$_POST['userfile']} ausw&auml;hlen!</td>  
	 </tr>  
	 </table>";exit;*/  
	 echo "temporärer Dateiname: $userfile<br>";  
	 echo "Pfad und Name der temporären Datei, wie sie im Filesystem des Servers zu finden ist: {$_FILES['thefile']['tmp_name']}<br>";  
	 echo "Original-Dateiname: $userfile_name<br>";  
	 echo "Grösse der Datei in Byte: $userfile_size<br>";  
	 echo "MIME-Typ der Datei: $userfile_type<br><br>";  
	 $_FILES['userfile']['error'];  
	 copy ($userfile, $userfile_name);  
	}  
	  
	if($artikelName == "")  
	{  
	 echo "<head><META HTTP-EQUIV='refresh' content='100;URL={$_SERVER['PHP_SELF']}'><link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
	 <table class='error'>  
	 <tr>  
		<td class='error'>du musst eine Artikelbezeichnung eingeben!</td>  
	 </tr>  
	 </table>";exit;  
	}  
	  
	if($preis == "")  
	{  
	 echo "<head><META HTTP-EQUIV='refresh' content='100;URL={$_SERVER['PHP_SELF']}'><link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
	 <table class='error'>  
	 <tr>  
		<td class='error'>du musst einen Preis eingeben!</td>  
	 </tr>  
	 </table>";exit;  
	}  
  
	if($userfile != "")  
	{  
		$userfile_name = str_replace("ä","ae",$userfile_name);  
		$userfile_name = str_replace("ö","oe",$userfile_name);  
		$userfile_name = str_replace("ü","ue",$userfile_name);	  
  
		if (file_exists("shop/pics/".$userfile_name)) {  
			echo ("<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>  
			 <link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
			 <table class='info'>  
			 <tr>  
				<td class='info'>Der Artikel existiert schon !</td>  
			 </tr>  
			 </table>");exit;  
		}  
		else {  
		    move_uploaded_file($userfile, "shop/pics/".$userfile_name);  
		}  
	}  
  
	if(mysql_query("INSERT INTO artikel (dateiName,artikelName,preis,dir,mime,speicherdatum,unix_time) VALUES ('$userfile_name', '$artikelName', '$preis', '$subdir', '$userfile_type', '$speicherdatum', '$unix_time')")) {  
			echo "<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>  
			 <link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
			 <table class='info'>  
			 <tr>  
				<td class='info'>Der Artikel wurde erfolgreich hochgeladen !</td>  
			 </tr>  
			 </table>";  
	}  
	else {  
			echo "<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>  
			<link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
			 <table class='error'>  
			 <tr>  
				<td class='error'>Der Artikel konnte nicht hochgeladen werden !</td>  
			 </tr>  
			 </table>";  
	}  
	exit;  
  
}

Sorry für den umfangreichen Code, aber ich denke, es braucht diese Angaben.
Kann mir jemand helfen?

  1. Hi!

    ich kann einfach die Lösung nicht finden! Mir scheint der Code korrekt, jedoch bleibt die Variable $userfile leer.

    Anstatt vom Anschein auszugehen, wäre es besser, sich zu überzeugen. Dazu braucht man nicht nur die Augen zum Code-Lesen, sondern grundlegendes Wissen zum Debugging. Üblicherweise reicht für den Anfang, sich die Werte der beteiligten Variablen mit var_dump() ausgeben zu lassen und diese Werte mit der eigenen Vorstellung zu vergleichen. Manchmal muss dann die eigene Vorstellung korrigiert werden, manchmal den Code, der für die Werteerzeugung zuständig ist.

    Sorry für den umfangreichen Code, aber ich denke, es braucht diese Angaben.

    Nein. Es ist viel zu viel unnötiges Zeug. Den HTML-Code für ein funktionierendes Upload-Formular bekommt man so klein hin wie beim Beispiel im PHP-Handbuch. Wenn du ein Problem hast, das du trotz Debugging nicht findest, erstell eine Kopie vom aktuellen Stand und kürze den Code auf das Minimum ein, das zur Nachstellung des Problems notwendig ist. Darin lässt sich wesentlich einfacher weitere Fehlersuche betreiben, und für den, der es nachvollziehen soll ist es auch keine Zumutung mehr.

    Lo!

    1. Hallo,
      echo var_dump($userfile); ergibt NULL, was ich ja vorher schon wusste.
      Das mit der Menge Code ist mir nicht recht, ich glaubte aber, es brauche den ganzen Code.
      Soll ich jetzt das Minimum an notwendigem Code nochmals posten, oder finde ich so Hilfe?

      1. 'ǝɯɐu$ ıɥ

        echo var_dump($userfile); ergibt NULL, was ich ja vorher schon wusste.
        Das mit der Menge Code ist mir nicht recht, ich glaubte aber, es brauche den ganzen Code.
        Soll ich jetzt das Minimum an notwendigem Code nochmals posten, oder finde ich so Hilfe?

        Der Martin schrieb dir doch schon woran es hängt...

        ssnɹƃ
        ʍopɐɥs

        --
        “A computer lets you make more mistakes faster than any invention in human history–with the possible exceptions of handguns and tequila.”
        - Mitch Radcliffe
      2. Hi!

        echo var_dump($userfile); ergibt NULL, was ich ja vorher schon wusste.

        Und wo kommt der Wert her? Warum prüfst du nicht var_dump($_POST), stellst dann fest, dass da gar kein Eintrag für userfile drin ist und fragst dich dann, warum das so ist? Und wenn du nicht auf die Lösung kommst, kannst du nun zumindest konkret nachfragen, warum ein Upload nicht in $_POST zu finden ist.

        Soll ich jetzt das Minimum an notwendigem Code nochmals posten, oder finde ich so Hilfe?

        Posten musst du ihn nicht mehr, aber zum Üben kannst du gern mal diese Herangehensweise probieren.

        Lo!

      3. Hallo,

        echo var_dump($userfile); ergibt NULL, was ich ja vorher schon wusste.

        Du packst zu spät an. Schau' Dir zuallererst die Inhalte der superglobalen Variablen $_POST und $_FILES an.

        Freundliche Grüße

        Vinzenz

  2. Hi,

    ich kann einfach die Lösung nicht finden! Mir scheint der Code korrekt, jedoch bleibt die Variable $userfile leer.

    ja, woher soll sie auch kommen?

    @session_start();

    if (isset($_POST['userfile'])) $userfile=$_POST['userfile'];

      
    Hochgeladene Dateien findet man bekanntlich nicht in $\_POST, sondern im temp-Verzeichnis - und die Metainformationen dazu wie Angaben über Erfolg oder Misserfolg, Dateinamen und ggf. Dateigröße in $\_FILES.  
      
    
    > mysql\_connect("$dbserver", "$dbuser", "$dbpass")or die("Keine Verbindung zum Server möglich!");  
    > mysql\_select\_db("$dbname")or die("Keine Datenbankverbindung möglich!");  
      
    Was soll der Unfug, Stringvariablen nochmal in Strings einzubetten?  
      
    
    > 	 echo "Pfad und Name der temporären Datei, wie sie im Filesystem des Servers zu finden ist: {$\_FILES['thefile']['tmp\_name']}<br>";  
      
    Ach? Hier weißt du auf einmal, dass du in $\_FILES nachsehen musst ...  
      
    
    > Sorry für den umfangreichen Code, aber ich denke, es braucht diese Angaben.  
      
    In diesem Fall nicht; aber das ist immer noch besser, als Informationen zurückzuhalten und erst durch mehrmaliges Nachfragen den entscheidenden Hinweis zu geben.  
      
    Übrigens habe ich den Eindruck, dass dein gesamter Code ziemlich konfus ist. Blickst du da noch durch? Ich würde mich beim dem Gewurschtel schwer tun. Möchtest du da nicht mal ein bisschen Ordnung reinbringen?  
      
    So long,  
     Martin  
    
    -- 
    "Mutti, hier steht, das Theater sucht Statisten. Was sind Statisten?" - "Das sind Leute, die nur rumstehen und nichts zu sagen haben." - "So wie Papa?"  
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    
    1. Hallo Der Martin,

      if (isset($_POST['userfile'])) $userfile=$_POST['userfile'];[/code]

      diesen Code habe ich enfernt.

      Was soll der Unfug, Stringvariablen nochmal in Strings einzubetten?

      das hatte ich übersehen, ist jetzt bereinigt.

      Ach? Hier weißt du auf einmal, dass du in $_FILES nachsehen musst ...

      Ich hab ja auch eine Weile verbracht, den Fehler zu finden. Wenn auch ohne Ergebnis.

      Sorry für den umfangreichen Code, aber ich denke, es braucht diese Angaben.

      In diesem Fall nicht; aber das ist immer noch besser, als Informationen zurückzuhalten und erst durch mehrmaliges Nachfragen den entscheidenden Hinweis zu geben.

      dedlfix sieht das anders.

      Übrigens habe ich den Eindruck, dass dein gesamter Code ziemlich konfus ist. Blickst du da noch durch? Ich würde mich beim dem Gewurschtel schwer tun. Möchtest du da nicht mal ein bisschen Ordnung reinbringen?

      Das verstehe ich wirklich nicht.
      Gruss
      hannes

      1. Hi!

        Sorry für den umfangreichen Code, aber ich denke, es braucht diese Angaben.
        In diesem Fall nicht; aber das ist immer noch besser, als Informationen zurückzuhalten und erst durch mehrmaliges Nachfragen den entscheidenden Hinweis zu geben.
        dedlfix sieht das anders.

        Das Problem muss nachvollziehbar sein - nicht mehr und nicht weniger. Es ist nicht hilfreich, so wenig Informationen zu liefern, dass man das Problem nicht nachvollziehen kann. Es ist aber auch nicht hilfreich, zu viel Unnötiges zu posten, denn dann sinkt die Bereitschaft, sich damit genau auseinanderzusetzen.

        Lo!

        1. Das Problem muss nachvollziehbar sein - nicht mehr und nicht weniger. Es ist nicht hilfreich, so wenig Informationen zu liefern, dass man das Problem nicht nachvollziehen kann. Es ist aber auch nicht hilfreich, zu viel Unnötiges zu posten, denn dann sinkt die Bereitschaft, sich damit genau auseinanderzusetzen.

          Vorerst mal Danke für die Tipps. Aber zu wissen, was nötig oder unnötig ist, setzt schon voraus, das Problem soweit eingegrenzt zu haben, dass man der Lösung nahe ist. Bei mir herrscht eher Verzweiflung, als Lösungsschimmerhoffnung.

          Wenn ich die bisherigen postings richtig verstanden habe, kann ich jetzt das Problem eingrenzen:
          echo var_dump($_POST); ergibt, dass es keinen Eintrag $userfile gibt; das wusste ich ja schon. Aber ich weiss nicht weshalb (ich habe ja beim upload-Versuch mittels Dialog-Fenster eine Datei ausgewählt).

          Und ich weiss es noch nicht.

          Gruss
          hannes

          1. 'ǝɯɐu$ ıɥ

            Wenn ich die bisherigen postings richtig verstanden habe, kann ich jetzt das Problem eingrenzen:
            echo var_dump($_POST); ergibt, dass es keinen Eintrag $userfile gibt; das wusste ich ja schon. Aber ich weiss nicht weshalb (ich habe ja beim upload-Versuch mittels Dialog-Fenster eine Datei ausgewählt).

            Herr im Himmel: Martin schrieb dir das die gesuchten Infos in $_FILES zu finden sind und dedlfix sagte dir du sollst in beiden Arrays nachschauen...

            ssnɹƃ
            ʍopɐɥs

            --
            “A computer lets you make more mistakes faster than any invention in human history–with the possible exceptions of handguns and tequila.”
            - Mitch Radcliffe
            1. Herr im Himmel: Martin schrieb dir das die gesuchten Infos in $_FILES zu finden sind und dedlfix sagte dir du sollst in beiden Arrays nachschauen...

              Das hab ich ja gemacht, mit

                
              if(isset($_POST['submit']) && $_POST['submit']=="abschicken"){  
                
              	if($userfile == "") {  
              ...	  
              	 echo var_dump($_POST); echo "Metainformationen zu Erfolg oder Misserfolg: var_dump($_POST);<br>";  
              	 echo var_dump($_FILES); echo "Metainformationen zu Dateinamen und ggf. Dateigröße in var_dump($_FILES);<br>";  
              	}
              

              ...
              }

              Das Ergebnis ist:

              array(4) { ["MAX_FILE_SIZE"]=> string(9) ".ini_get(" ["artikelName"]=> string(0) "" ["preis"]=> string(11) "z.Bsp.: 420" ["submit"]=> string(10) "abschicken" } Metainformationen zu Erfolg oder Misserfolg: var_dump(Array);
              array(1) { ["userfile"]=> array(5) { ["name"]=> string(8) "back.gif" ["type"]=> string(9) "image/gif" ["tmp_name"]=> string(28) "C:\xampplite\tmp\php33A7.tmp" ["error"]=> int(0) ["size"]=> int(51) } } Metainformationen zu Dateinamen und ggf. Dateigröße in var_dump(Array);

              Aber damit kann ich nichts anfangen. Ich sehe lediglich, dass $userfile in $_FILES enthalten ist. Aber wieso gibt es keinen Eintrag in $_POST, resp. wieso wird es nicht hochgeladen?

              Gruss
              hannes

              1. Hi!

                array(1) { ["userfile"]=> array(5) { ["name"]=> string(8) "back.gif" ["type"]=> string(9) "image/gif" ["tmp_name"]=> string(28) "C:\xampplite\tmp\php33A7.tmp" ["error"]=> int(0) ["size"]=> int(51) } } Metainformationen zu Dateinamen und ggf. Dateigröße in var_dump(Array);

                Übersichtlicher wird es übrigens, wenn du im Browser die Quelltextansicht wählst, oder die Kontrollausgaben von Arrays mit einem <pre> einleitest.

                Aber damit kann ich nichts anfangen. Ich sehe lediglich, dass $userfile in $_FILES enthalten ist. Aber wieso gibt es keinen Eintrag in $_POST, resp. wieso wird es nicht hochgeladen?

                File-Uploads sind immer in $_FILES zu finden. Und es wurde hochgeladen, denn in diesem Array findest du die nötigen Informationen, um an die Datei zu gelangen. Ich hab dir ja schon die Handbuchseite zum Upload-Formular verlinkt. Dort stehen auch die Einträge von $_FILES erklärt.

                Lo!

                1. Hallo dedlfix,

                  Übersichtlicher wird es übrigens, wenn du im Browser die Quelltextansicht wählst, oder die Kontrollausgaben von Arrays mit einem <pre> einleitest.

                  okay, nicht gewusst. Werd ich in Zukunft machen.

                  File-Uploads sind immer in $_FILES zu finden. Und es wurde hochgeladen,

                  hier C:\xampplite\tmp\php33A7.tmp gibt es keine solche Datei.

                  Ich hab dir ja schon die Handbuchseite zum Upload-Formular verlinkt. Dort stehen auch die Einträge von $_FILES erklärt.

                  Da verstehe ich nicht alles, was ich verstehe ist erfüllt.

                  Mein einfaches (?) Problem des Dateiuploads ist mit all den bisherigen neuen Informationen noch nicht gelöst. Es geht einfach nicht!

                  Gruss
                  hannes

                  1. Hi!

                    File-Uploads sind immer in $_FILES zu finden. Und es wurde hochgeladen,
                    hier C:\xampplite\tmp\php33A7.tmp gibt es keine solche Datei.

                    Sie wird am Script-Ende weggeräumt. Du musst die Datei noch während der Script-Laufzeit mit move_uploded_file() wegkopieren.

                    Ich hab dir ja schon die Handbuchseite zum Upload-Formular verlinkt. Dort stehen auch die Einträge von $_FILES erklärt.
                    Da verstehe ich nicht alles, was ich verstehe ist erfüllt.
                    Mein einfaches (?) Problem des Dateiuploads ist mit all den bisherigen neuen Informationen noch nicht gelöst. Es geht einfach nicht!

                    Dann such dir mal ein funktionierendes Beispiel im Netz, probier es bei dir aus und pass es dann an deine Wünsche an.

                    Lo!

                    1. 'ǝɯɐu$ ıɥ

                      File-Uploads sind immer in $_FILES zu finden. Und es wurde hochgeladen,
                      hier C:\xampplite\tmp\php33A7.tmp gibt es keine solche Datei.

                      Sie wird am Script-Ende weggeräumt. Du musst die Datei noch während der Script-Laufzeit mit move_uploded_file() wegkopieren.

                      macht er ja, nur an der falschen stelle, er hat sich da mit seinen ifs und der umkopiererei total verfranst, er sollte sich vorallem den rückgabewert von move_uploded_file() anzeigen lassen.

                      *g* ich hatte auch so meine probleme mit meinem ersten upload formular...

                      ssnɹƃ
                      ʍopɐɥs

                      --
                      “A computer lets you make more mistakes faster than any invention in human history–with the possible exceptions of handguns and tequila.”
                      - Mitch Radcliffe
                    2. Hello,

                      Sie wird am Script-Ende weggeräumt. Du musst die Datei noch während der Script-Laufzeit mit move_uploded_file() wegkopieren.

                      Dann will ich hier jetzt auch nochmal einhaken, denn die Frage, was move_uploaded_file() wirklich tut, konnte ich bisher immer noch nicht klären. Woher nimmt die Funktion die Information "uploaded"?.

                      Wen soll es eigentlich schützen?

                      Liebe Grüße aus dem schönen Oberharz

                      Tom vom Berg

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

                        Dann will ich hier jetzt auch nochmal einhaken, denn die Frage, was move_uploaded_file() wirklich tut, konnte ich bisher immer noch nicht klären. Woher nimmt die Funktion die Information "uploaded"?.

                        So wie es dokumentiert ist. Sie sorgt dafür, dass es sich wirklich um eine hochgeladene Datei handelt und nicht etwa um /etc/passwd, falls es jemandem gelingt, diesen Namen an die Stelle des zu kopierenden Dateinamens zu bringen. Ein einfaches copy() prüft das nicht.

                        Wen soll es eigentlich schützen?

                        Den Werserver.

                        Lo!

                        1. Ich bin total entnervt!

                          Zu einem frühen Zeitpunkt wurde gerügt, ich sollte nicht so viel Code posten.
                          Nun macht es den Anschein, dass (fast) niemand den Code liest, sonst hätte man ja gesehen, dass move_uploaded_file und auch anderes gemacht wurde. (ich habe die angegebenen Links verfolgt, und soweit ich verstanden habe, die dortigen Infos verwertet; ich habe selbst in php.ini nachgeschaut, ob file_uploads=On ist etc. etc.)
                          Nichts hat geholfen.

                          Die Diskussion ist mittlerweile 2m über meinem Kopf (und meinem Verständnis) angelangt. Ich habe zwar einige Tipps erhalten, die ich auch gerne beachten werde.

                          Nur mein eigentliches Problem heisst:
                          Der upload funktioniert einfach nicht, obwohl ich keinen Fehler im Code finden kann.

                          Und es kann/will mir niemand sagen, wo der Knopf ist.

                          Gruss
                          hannes

                          1. Hi!

                            Zu einem frühen Zeitpunkt wurde gerügt, ich sollte nicht so viel Code posten.
                            Nun macht es den Anschein, dass (fast) niemand den Code liest, sonst hätte man ja gesehen, dass move_uploaded_file und auch anderes gemacht wurde.

                            Genau das ist das Problem bei zu viel unnützem Zeug: nicht nur du siehst nicht mehr durch, auch die Helfer haben nicht immer Lust, sich da durchzuwühlen.

                            Nichts hat geholfen.

                            Hast du nun den Dateinamen der Datei, die PHP beim Upload in Emfang genommen und in sein Temp-Verzeichnis abgelegt hat, aus $_FILES extrahieren können? Dieser Name muss der erste Parameter von move_uploaded_file() sein. Es ist nicht der Name der ursprünglichen Datei sondern ein willkürlich festgelegter. In deiner Kontrollausgabe hieß er C:\xampplite\tmp\php33A7.tmp. Und wenn du dir die Kontrollausgabe nochmal anschaust, siehst du, dass er in $_FILES['userfile']['tmp_name'] steht.

                            Nur mein eigentliches Problem heisst:
                            Der upload funktioniert einfach nicht, obwohl ich keinen Fehler im Code finden kann.
                            Und es kann/will mir niemand sagen, wo der Knopf ist.

                            Dein Code hat noch viel mehr Fehler drin, als das falsche Nachsehen in $_POST['userfile']. Da gibt es eine beispielsweise eine Stelle, da greifst du auf $_FILES['thefile'] zu, was gar nicht existiert. Der nicht beachtete Kontextwechsel beim Erstellen des SQL-Statements ist ein weiterer Fehler, der zu Lasten der Sicherheit deines Servers geht.

                            Und stell mal das error_reporting auf E_ALL (und display_errors auf on), dann bekommst du Zugriffe auf nicht vorhandene Variablen angezeigt, was oftmals ein Hinweis auf einen Fehler ist.

                            Lo!

                            1. Hallo dedlfix,

                              Hast du nun den Dateinamen der Datei, die PHP beim Upload in Emfang genommen und in sein Temp-Verzeichnis abgelegt hat, aus $_FILES extrahieren können?

                              Der Dateiname wird richtig (in meinem Beispiel als 'back.gif') als Kontrollausgabe angezeigt. s. mein Posting mein posting (sorry: weiss leider nicht, wie sonst auf mein posting zu verweisen.

                              Dieser Name muss der erste Parameter von move_uploaded_file() sein.

                              mein erster Parameter ist die Variable $userfile selbst. In anderen Formularen, die ich erstellt habe, funktioniert das

                              Dein Code hat noch viel mehr Fehler drin, als das falsche Nachsehen in $_POST['userfile']. Da gibt es eine beispielsweise eine Stelle, da greifst du auf $_FILES['thefile'] zu, was gar nicht existiert.

                              Diese $_FILES-Abfrage habe ich später (als Reaktion auf eure Tipps) gemacht (ist also nicht im ursprünglichen Code, und wurde bereits schon angepasst. 'thefile' ist natürlich 'userfile'.)

                              Der nicht beachtete Kontextwechsel beim Erstellen des SQL-Statements ist ein weiterer Fehler, der zu Lasten der Sicherheit deines Servers geht.

                              Auch die mysql-Abfrage wurde angepasst zu:

                              mysql_connect($dbserver, $dbuser, $dbpass)or die("Keine Verbindung zum Server möglich!");  
                              mysql_select_db($dbname)or die("Keine Datenbankverbindung möglich!");  
                              
                              

                              Gruss
                              hannes

                              1. Hi!

                                Hast du nun den Dateinamen der Datei, die PHP beim Upload in Emfang genommen und in sein Temp-Verzeichnis abgelegt hat, aus $_FILES extrahieren können?
                                Der Dateiname wird richtig (in meinem Beispiel als 'back.gif') als Kontrollausgabe angezeigt. s. mein Posting mein posting (sorry: weiss leider nicht, wie sonst auf mein posting zu verweisen.
                                Dieser Name muss der erste Parameter von move_uploaded_file() sein.
                                mein erster Parameter ist die Variable $userfile selbst. In anderen Formularen, die ich erstellt habe, funktioniert das

                                Wenn da drin der Inhalt von $_FILES['userfile']['tmp_name'] steht, dann greifst du auf die richtige Datei zu. Du kannst übrigens auch gleich $_FILES['userfile']['tmp_name'] als ersten Parameter übergeben, ohne noch eine weitere Variable anzulegen.

                                Der nicht beachtete Kontextwechsel beim Erstellen des SQL-Statements ist ein weiterer Fehler, der zu Lasten der Sicherheit deines Servers geht.
                                Auch die mysql-Abfrage wurde angepasst zu:

                                mysql_connect($dbserver, $dbuser, $dbpass)or die("Keine Verbindung zum Server möglich!");

                                mysql_select_db($dbname)or die("Keine Datenbankverbindung möglich!");

                                  
                                Es geht nicht um die Verbindung zum MySQL-Server sondern um den Zusammenbau des SQL-Statements (INSERT INTO ...).  
                                  
                                  
                                Lo!
                                
                                1. Hallo dedlfix,

                                  Du kannst übrigens auch gleich $_FILES['userfile']['tmp_name'] als ersten Parameter übergeben, ohne noch eine weitere Variable anzulegen.

                                  Auch das habe ich ohne Erfolg versucht.

                                  Es geht nicht um die Verbindung zum MySQL-Server sondern um den Zusammenbau des SQL-Statements (INSERT INTO ...).

                                  Das sieht jetzt so aus:

                                  if(mysql_query("INSERT INTO artikel (dateiName,artikelName,preis,dir,mime,speicherdatum,unix_time) VALUES ('" . mysql_real_escape_string($userfile_name) . "', '" . mysql_real_escape_string($artikelName) . "', '" . mysql_real_escape_string($preis) . "', '" . mysql_real_escape_string($subdir) . "', '" . mysql_real_escape_string($userfile_type) . "', '" . mysql_real_escape_string($speicherdatum) . "', '" . mysql_real_escape_string($unix_time) . "')")) {...}  
                                  
                                  

                                  Vielen Dank für den Tipp.

                                  Gruss
                                  hannes

                                  1. Hi!

                                    Du kannst übrigens auch gleich $_FILES['userfile']['tmp_name'] als ersten Parameter übergeben, ohne noch eine weitere Variable anzulegen.
                                    Auch das habe ich ohne Erfolg versucht.

                                    Du hast auch immer schön mit var_dump() nachgeschaut, dass in den verwendeten Variablen das drin ist, was drin sein soll? Bei verzweigten Programmen (sprich: if-else) ist es auch sinnvoll, sich davon zu überzeugen, dass der richtige Pfad gewählt wurde. Das geht einfach mit einem kleinen echo 'bin im if'; oder echo 'bin bei else';, falls das nicht sowieso schon durch signifikante Ausgabe-Anweisungen klar ist, wie die Abarbeitung den Code entlangläuft.

                                    Weiterhin ist es immer richtig, von den verwendeten Funktionen den Rückgabewert auszuwerten. Sehr oft gibt der bekannt, ob die Ausführung fehlerfrei war oder nicht. Dazu muss man im Handbuch nachlesen, was für ein Ergebnis im Gut- und was im Fehlerfall kommt. Eigentlich müsste das nicht nur eine Kontrollausgabe fürs Debugging werden, sondern der ganze Programmfluss ist ideal so gestaltet, dass auf beide Fälle angemessen reagiert wird. Die einfachste und anwenderunfreundlichste Reaktion ist ein "or die('meldung');". Der Patient hat zwar nur mal gehustet, wurde aber trotzdem erschossen. Besser ist, bei Funktionen, die false im Fehlerfall und im Gutfall etwas das zu true evaluiert zurückgeben, kann man das so lösen:

                                    if (move_uploaded_file(...)) {
                                        // tun, was zu tun ist, wenn erfolgreich
                                      } else {
                                        // Reaktion im Fehlerfall
                                      }

                                    Und ja, durch eine solche Fehlerbehandlung wird der Code teilweise um ein Vielfaches länger als reiner Geradeaus-Code, dafür aber auch um ein Vielfaches robuster.

                                    Es geht nicht um die Verbindung zum MySQL-Server sondern um den Zusammenbau des SQL-Statements (INSERT INTO ...).
                                    Das sieht jetzt so aus:
                                    if(mysql_query("INSERT INTO artikel (dateiName,artikelName,preis,dir,mime,speicherdatum,unix_time) VALUES ('" . mysql_real_escape_string($userfile_name) . "', '" . mysql_real_escape_string($artikelName) . "', '" . mysql_real_escape_string($preis) . "', '" . mysql_real_escape_string($subdir) . "', '" . mysql_real_escape_string($userfile_type) . "', '" . mysql_real_escape_string($speicherdatum) . "', '" . mysql_real_escape_string($unix_time) . "')")) {...}

                                    Schon besser. Noch eine Runde übersichtlicher, finde ich, wird es, wenn du die Funktion sprintf() verwendest - siehe zweites Beispiel. Der INSERT-INTO-String kann dann in einem Rutsch notiert werden, ohne dass er immer wegen der Funktionsaufrufe unterbrochen und zusammengefügt werden muss.

                                    Lo!

                          2. Hallo,

                            Ich bin total entnervt!

                            wir auch, weil du nicht erkennen lässt, dass du den Hinweisen überhaupt nachgehst.

                            Zu einem frühen Zeitpunkt wurde gerügt, ich sollte nicht so viel Code posten.
                            Nun macht es den Anschein, dass (fast) niemand den Code liest

                            Das ist die Gefahr, wenn man zuviel davon hinschmeißt - noch dazu so unübersichtlich.

                            Nur mein eigentliches Problem heisst:
                            Der upload funktioniert einfach nicht

                            Doch, er funktioniert - das hast du selbst schon nachgewiesen (ich habe mir mal erlaubt, die Ausgabe von var_dump() lesbar zu formatieren):

                            array(1)
                            { ["userfile"]=> array(5)
                                { ["name"]=> string(8) "back.gif"
                                  ["type"]=> string(9) "image/gif"
                                  ["tmp_name"]=> string(28) "C:\xampplite\tmp\php33A7.tmp"
                                  ["error"]=> int(0)
                                  ["size"]=> int(51)
                                }
                            }

                            Da steht, dass eine Datei mit dem Namen back.gif hochgeladen wurde, dass sie vermutlich den MIME-Typ image/gif hat, dass sie eine Größe von 51 Bytes hat, dass der Upload fehlerfrei verlief (Code 0), und dass die Datei temporär als C:\xampplite\tmp\php33A7.tmp abgelegt wurde. Von dort musst du sie nur noch wegkopieren oder -verschieben (sinnigerweise mit move_uploaded_file(), das ist dafür gedacht), bevor das Script beendet wird.

                            Und es kann/will mir niemand sagen, wo der Knopf ist.

                            Wie oft willst du es denn noch lesen?!

                            Ciao,
                             Martin

                            --
                            Das einzige Problem beim Nichtstun: Man weiß nie, wann man damit fertig ist.
                            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                            1. Hallo Der Martin,

                              wir auch, weil du nicht erkennen lässt, dass du den Hinweisen überhaupt nachgehst.

                              Ich bin jeder einzelnen Antwort von euch nachgegangen und habe angepasst/reagiert/kommentiert.

                              Der upload funktioniert einfach nicht
                              Doch, er funktioniert ...

                              Ja, ins tmp-Verzeichnis

                              Von dort musst du sie nur noch wegkopieren oder -verschieben (sinnigerweise mit move_uploaded_file(), das ist dafür gedacht), bevor das Script beendet wird.

                              das mache ich ja mit:
                              move_uploaded_file($userfile, "$dir/$subdir/".$userfile_name);
                              ich habe erfolglos auch dies versucht:
                              move_uploaded_file($userfile, "./shop/pics/".$userfile_name);

                              Wie oft willst du es denn noch lesen?!

                              Ich habe jedes posting gelesen, versucht die Tipps umzusetzen und die Erfolge/Misserfolge in weiteren postings bekannt zu geben. Was soll ich noch lesen?

                              Gruss
                              hannes

                              1. 'ǝɯɐu$ ıɥ

                                Wie oft willst du es denn noch lesen?!
                                Ich habe jedes posting gelesen, versucht die Tipps umzusetzen und die Erfolge/Misserfolge in weiteren postings bekannt zu geben. Was soll ich noch lesen?

                                Meins? Gehe mal deine ifs durch, soweit ich das sehe ist das move_uploaded_files() an der falschen Stelle...

                                ssnɹƃ
                                ʍopɐɥs

                                --
                                “A computer lets you make more mistakes faster than any invention in human history–with the possible exceptions of handguns and tequila.”
                                - Mitch Radcliffe
                                1. 'ǝɯɐu$ ıɥ

                                  Meins? Gehe mal deine ifs durch, soweit ich das sehe ist das move_uploaded_files() an der falschen Stelle...

                                  genauer gesagt, ich denke hier liegt der Hund begraben:

                                  if($userfile != "")  
                                          {  
                                                  $userfile_name = str_replace("ä","ae",$userfile_name);  
                                                  $userfile_name = str_replace("ö","oe",$userfile_name);  
                                                  $userfile_name = str_replace("ü","ue",$userfile_name);  
                                    
                                                  if (file_exists("shop/pics/".$userfile_name)) {  
                                                          echo ("<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>  
                                                           <link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
                                                           <table class='info'>  
                                                           <tr>  
                                                                  <td class='info'>Der Artikel existiert schon !</td>  
                                                           </tr>  
                                                           </table>");exit;  
                                                  }  
                                                  else {  
                                                      move_uploaded_file($userfile, "shop/pics/".$userfile_name);  
                                                  }  
                                          }
                                  

                                  ssnɹƃ
                                  ʍopɐɥs

                                  --
                                  “A computer lets you make more mistakes faster than any invention in human history–with the possible exceptions of handguns and tequila.”
                                  - Mitch Radcliffe
                                  1. Hallo Shadowcrow,

                                    der Code sieht jetzt so aus:

                                      
                                    if(isset($_POST['submit']) && $_POST['submit']=="abschicken"){  
                                      
                                    	if($userfile == "") {  
                                    	 ...  
                                    	}  
                                    	else {  
                                    		$userfile_name = str_replace("ä","ae",$userfile_name);  
                                    		$userfile_name = str_replace("ö","oe",$userfile_name);  
                                    		$userfile_name = str_replace("ü","ue",$userfile_name);	  
                                      
                                    		if (file_exists("$dir/$subdir/".$userfile_name)) {  
                                    			echo ("<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>  
                                    			 <link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
                                    			 <table class='info'>  
                                    			 <tr>  
                                    				<td class='info'>Der Artikel existiert schon !</td>  
                                    			 </tr>  
                                    			 </table>");exit;  
                                    		}  
                                    		else {  
                                    		    move_uploaded_file($userfile, "./shop/pics/".$userfile_name);  
                                    		}  
                                    	}  
                                      
                                    	  
                                    	if($artikelName == ""){ usw.
                                    

                                    hat aber nichts gebracht

                                    Gruss
                                    hannes

                                    1. Hello Hannes,

                                      der Code sieht jetzt so aus:

                                      [...]

                                      hat aber nichts gebracht

                                      Wie wäre es denn mal mit dem Error-Log des Webservers und eventuell auch dem Access-Log? Hast Du dort schon mal reingeschaut?

                                      Hast Du eigentlich 'open_basedir', 'upload_tmp_dir', usw. mal angeschaut, wie die gesetzt sind?

                                      Liebe Grüße aus dem schönen Oberharz

                                      Tom vom Berg

                                      --
                                       ☻_
                                      /▌
                                      / \ Nur selber lernen macht schlau
                                      http://bergpost.annerschbarrich.de
                              2. Hello,

                                Von dort musst du sie nur noch wegkopieren oder -verschieben (sinnigerweise mit move_uploaded_file(), das ist dafür gedacht), bevor das Script beendet wird.
                                das mache ich ja mit:
                                move_uploaded_file($userfile, "$dir/$subdir/".$userfile_name);
                                ich habe erfolglos auch dies versucht:
                                move_uploaded_file($userfile, "./shop/pics/".$userfile_name);

                                Die Verwendung des ['name']-Elementes im Pfad ist nicht ungefährlich. Da kann auch move_uloaded_file() nicht helfen, wenn der Client einen gefährlichen Wert schickt.

                                Es sollte auf jeden Fall die Funktion basename()
                                http://de2.php.net/manual/en/function.basename.php
                                vorher auf den Wert angewendet werden

                                Liebe Grüße aus dem schönen Oberharz

                                Tom vom Berg

                                --
                                 ☻_
                                /▌
                                / \ Nur selber lernen macht schlau
                                http://bergpost.annerschbarrich.de
                              3. Hallo,

                                Von dort musst du sie nur noch wegkopieren oder -verschieben (sinnigerweise mit move_uploaded_file(), das ist dafür gedacht), bevor das Script beendet wird.
                                das mache ich ja mit:
                                move_uploaded_file($userfile, "$dir/$subdir/".$userfile_name);
                                ich habe erfolglos auch dies versucht:
                                move_uploaded_file($userfile, "./shop/pics/".$userfile_name);

                                und was ist $userfile? Wo kommt das mittlerweile her? Was steht da drin?

                                Ciao,
                                 Martin

                                --
                                Ein Patriot ist jemand, der bereit ist, sein Land gegen seine Regierung zu verteidigen.
                                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                1. 'ǝɯɐu$ ıɥ

                                  und was ist $userfile? Wo kommt das mittlerweile her? Was steht da drin?

                                  es kam mal daher: if (isset($_POST['userfile'])) $userfile=$_POST['userfile'];

                                  ich denke das hier das problem liegt:

                                  if($userfile != "")  
                                          {  
                                                  $userfile_name = str_replace("ä","ae",$userfile_name);  
                                                  $userfile_name = str_replace("ö","oe",$userfile_name);  
                                                  $userfile_name = str_replace("ü","ue",$userfile_name);  
                                    
                                                  if (file_exists("shop/pics/".$userfile_name)) {  
                                                          echo ("<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>  
                                                           <link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>  
                                                           <table class='info'>  
                                                           <tr>  
                                                                  <td class='info'>Der Artikel existiert schon !</td>  
                                                           </tr>  
                                                           </table>");exit;  
                                                  }  
                                                  else {  
                                                      move_uploaded_file($userfile, "shop/pics/".$userfile_name);  
                                                  }  
                                          }  
                                  
                                  

                                  ssnɹƃ
                                  ʍopɐɥs

                                  --
                                  “A computer lets you make more mistakes faster than any invention in human history–with the possible exceptions of handguns and tequila.”
                                  - Mitch Radcliffe
                                  1. Hallo,

                                    und was ist $userfile? Wo kommt das mittlerweile her? Was steht da drin?
                                    es kam mal daher: if (isset($_POST['userfile'])) $userfile=$_POST['userfile'];

                                    dann wäre es also undefined; warum, haben wir hannes nun schon ungefähr (n+1)mal erklärt.
                                    Vielleicht hat er das auch schon korrigiert; das geht aus seiner ganz besonderen Art des Berichtens ja leider nicht hervor.

                                    ich denke das hier das problem liegt:

                                    if($userfile != "")

                                    {
                                                    $userfile_name = str_replace("ä","ae",$userfile_name);
                                                    $userfile_name = str_replace("ö","oe",$userfile_name);
                                                    $userfile_name = str_replace("ü","ue",$userfile_name);

                                    if (file_exists("shop/pics/".$userfile_name)) {
                                                            echo ("<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>
                                                             <link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>
                                                             <table class='info'>
                                                             <tr>
                                                                    <td class='info'>Der Artikel existiert schon !</td>
                                                             </tr>
                                                             </table>");exit;
                                                    }
                                                    else {
                                                        move_uploaded_file($userfile, "shop/pics/".$userfile_name);
                                                    }
                                            }

                                      
                                    Da wird zunächst ein weiterer Name bearbeitet (wo auch immer der herkommt), dann wird geprüft, ob eine Datei mit diesem Namen in ./shop/pics/ schon existiert. Falls ja, wird ein wenig HTML-Gerümpel ausgegeben, andernfalls die hochgeladene Datei unter dem eben erzeugten Namen nach ./shop/pics/ kopiert. Wenn $userfile korrekt wäre ...  
                                    An diesem Programmabschnitt ist AFAIS nichts grob falsch, wenn nur die dort verwendeten Variablen $userfile und $userfile\_name sinnvolle Werte haben.  
                                      
                                    Ciao,  
                                     Martin  
                                    
                                    -- 
                                    Zwei Mäuse treiben's miteinander. Sagt der Mäuserich: "Hoffentlich ist nicht wieder alles für die Katz."  
                                    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                    
                                    1. 'ǝɯɐu$ ıɥ

                                      und was ist $userfile? Wo kommt das mittlerweile her? Was steht da drin?
                                      es kam mal daher: if (isset($_POST['userfile'])) $userfile=$_POST['userfile'];

                                      dann wäre es also undefined; warum, haben wir hannes nun schon ungefähr (n+1)mal erklärt.
                                      Vielleicht hat er das auch schon korrigiert; das geht aus seiner ganz besonderen Art des Berichtens ja leider nicht hervor.

                                      das weiß nur er selbst....

                                      ich denke das hier das problem liegt:

                                      if($userfile != "")

                                      {
                                                      $userfile_name = str_replace("ä","ae",$userfile_name);
                                                      $userfile_name = str_replace("ö","oe",$userfile_name);
                                                      $userfile_name = str_replace("ü","ue",$userfile_name);

                                      if (file_exists("shop/pics/".$userfile_name)) {
                                                              echo ("<head><META HTTP-EQUIV='refresh' content='2;URL={$_SERVER['PHP_SELF']}'>
                                                               <link href='../../Seiten/style.css' rel='stylesheet' type='text/css'></head>
                                                               <table class='info'>
                                                               <tr>
                                                                      <td class='info'>Der Artikel existiert schon !</td>
                                                               </tr>
                                                               </table>");exit;
                                                      }
                                                      else {
                                                          move_uploaded_file($userfile, "shop/pics/".$userfile_name);
                                                      }
                                              }

                                      
                                      >   
                                      > Da wird zunächst ein weiterer Name bearbeitet (wo auch immer der herkommt), dann wird geprüft, ob eine Datei mit diesem Namen in ./shop/pics/ schon existiert. Falls ja, wird ein wenig HTML-Gerümpel ausgegeben, andernfalls die hochgeladene Datei unter dem eben erzeugten Namen nach ./shop/pics/ kopiert. Wenn $userfile korrekt wäre ...  
                                      > An diesem Programmabschnitt ist AFAIS nichts grob falsch, wenn nur die dort verwendeten Variablen $userfile und $userfile\_name sinnvolle Werte haben.  
                                      
                                      wohl eher nicht denn:  
                                      ~~~php
                                        
                                      copy ($userfile, $userfile_name);
                                      

                                      ssnɹƃ
                                      ʍopɐɥs

                                      --
                                      “A computer lets you make more mistakes faster than any invention in human history–with the possible exceptions of handguns and tequila.”
                                      - Mitch Radcliffe
                                      1. Hallo Shadowcrow,

                                        Da wird zunächst ein weiterer Name bearbeitet (wo auch immer der herkommt), ...

                                        Dein Hinweis hat mich auf die Lösung geführt! $userfile_name war nicht definiert. Bei einem anderen script, das einwandfrei funktionierte, hatte ich eine fremde Datei mit Variablen-Definitionen inkludiert. Dort war $userfile_name definiert. Diese  Datei brauchte ich für dieses script nicht (glaubte ich). Was ein Irrtum war.

                                        Sorry, tut mir echt leid, dass ich so viel Wirbel um nichts (!?) gemacht habe, und soviel von eurer Zeit in Anspruch genommen habe.

                                        Ich hab mich wohl auch etwas von den vielen anderen Tipps zu weiterführenden Schritten verleiten lassen. Habe dabei aber viel gelernt!

                                        Gruss
                                        hannes

                                        1. Hello,

                                          Sorry, tut mir echt leid, dass ich so viel Wirbel um nichts (!?) gemacht habe, und soviel von eurer Zeit in Anspruch genommen habe.

                                          Ich hab mich wohl auch etwas von den vielen anderen Tipps zu weiterführenden Schritten verleiten lassen. Habe dabei aber viel gelernt!

                                          Na dann! ;-)

                                          Es wäre wahrscheinlich sehr hilfreich für Dich, wenn Du dir dein Endergebnis dann nochmal hier zerpflücken lässt. Auch, wenn es "funktioniert". Es waren schließlich noch diverse Sicherheitslücken vorhanden!

                                          Wir werden dann auch versuchen, dich nicht zu demotivieren sondern nur wichtige Hinweise zu geben, was Du noch einbauen oder ändern solltest... (hoffe ich doch *g*)

                                          Liebe Grüße aus dem schönen Oberharz

                                          Tom vom Berg

                                          --
                                           ☻_
                                          /▌
                                          / \ Nur selber lernen macht schlau
                                          http://bergpost.annerschbarrich.de
                                          1. Es wäre wahrscheinlich sehr hilfreich für Dich, wenn Du dir dein Endergebnis dann nochmal hier zerpflücken lässt. Auch, wenn es "funktioniert". Es waren schließlich noch diverse Sicherheitslücken vorhanden!

                                            Vielen Dank für das Angebot. Das mache ich gerne. Ich komme aber erst nächsten Samstag/Montag wieder dazu, diese Arbeit aufzunehmen. (Bin wie gesagt, kein Profi, mache noch andere Dinge).
                                            Ich werde mich dann aber gerne wieder melden, und sehen, wie's weitergeht.

                                            Gruss
                                            hannes

                                          2. Hallo Tom,

                                            hier also der bereinigte Code

                                              
                                            <?  
                                            @session_start();  
                                              
                                            /************************************************************************************************/  
                                            if (($_SESSION['myusername'] == "") OR ($_SESSION['mypassword'] == "")) {  
                                            	include ("login.php");  
                                            }  
                                            /************************************************************************************************/  
                                              
                                            include("./include/db_vars.php");  
                                            include("./include/db_connect.php");  
                                              
                                            $speicherdatum = date("d. M Y - H:i:s");  
                                            $unix_time = time();  
                                            $updir = "..";  
                                            $dir = "shop";  
                                            $subdir = "articles";  
                                              
                                            if(isset($_POST['submit']) && $_POST['submit']=="hochladen"){  
                                              
                                            	if($_FILES['userfile']['tmp_name'] == ""){  
                                            	 	header("Location: article_upload_antw.php?flag=userfile");  
                                            		exit;  
                                            	}  
                                            	  
                                            	if($_POST['artikelName'] == ""){  
                                            	 	header("Location: article_upload_antw.php?flag=artikelName");  
                                            		exit;  
                                            	}	  
                                            					  
                                            	if($_POST['Preis'] != ""){  
                                              
                                            		if(is_numeric($_POST['Preis'])){  
                                            			 $_POST['preis'] = intval($_POST['Preis']);  
                                            		}  
                                            		else {  
                                            	 	header("Location: article_upload_antw.php?flag=nonumeric");  
                                            		exit;  
                                            		}  
                                            	}  
                                              
                                            	if($_POST['Preis'] == ""){  
                                            	 	header("Location: article_upload_antw.php?flag=preis");  
                                            		exit;  
                                            	}	  
                                              
                                            	if($_POST['Versandkosten'] != ""){  
                                              
                                            		if(is_numeric($_POST['Versandkosten'])){  
                                            			 $_POST['Versandkosten'] = intval($_POST['Versandkosten']);  
                                            		}  
                                            		else {  
                                            	 	header("Location: article_upload_antw.php?flag=nonumeric");  
                                            		exit;  
                                            		}  
                                            	}  
                                              
                                            	if($_POST['Versandkosten'] == ""){  
                                            	 	header("Location: article_upload_antw.php?flag=versandkosten");  
                                            		exit;  
                                            	}	  
                                              
                                            	if($_POST['Breite'] == ""){  
                                            	 	header("Location: article_upload_antw.php?flag=breite");  
                                            		exit;  
                                            	}	  
                                            	if($_POST['Hoehe'] == ""){  
                                            	 	header("Location: article_upload_antw.php?flag=hoehe");  
                                            		exit;  
                                            	}	  
                                            	if($_POST['Tiefe'] == ""){  
                                            	 	header("Location: article_upload_antw.php?flag=tiefe");  
                                            		exit;  
                                            	}	  
                                              
                                            	else {  
                                            		$_FILES['userfile']['name'] = str_replace("ä","ae",$_FILES['userfile']['name']);  
                                            		$_FILES['userfile']['name'] = str_replace("ö","oe",$_FILES['userfile']['name']);  
                                            		$_FILES['userfile']['name'] = str_replace("ü","ue",$_FILES['userfile']['name']);  
                                              
                                            		if (file_exists($updir."/".$dir."/".$subdir."/".mysql_real_escape_string($_FILES['userfile']['name']))) {  
                                            			header("Location: article_upload_antw.php?flag=already");  
                                            			exit;  
                                            		}  
                                            		  
                                            		if (!@move_uploaded_file($_FILES['userfile']['tmp_name'], $updir."/".$dir."/".$subdir."/".mysql_real_escape_string($_FILES['userfile']['name']))){  
                                            			header("Location: article_upload_antw.php?flag=nosaved");  
                                            			exit;  
                                            		}  
                                              
                                            		if(!mysql_query("INSERT INTO artikel (dateiName,artikelName,Breite,Hoehe,Tiefe,currency,Preis,centimes,Versandkosten,Ordner,mime,speicherdatum,unix_time) VALUES ('" . mysql_real_escape_string($_FILES['userfile']['name']) . "', 'tonform_" . mysql_real_escape_string($_POST['artikelName']) . "','" . mysql_real_escape_string($_POST['Breite']) . "','" . mysql_real_escape_string($_POST['Hoehe']) . "','" . mysql_real_escape_string($_POST['Tiefe']) . "','CHF', '" . mysql_real_escape_string($_POST['Preis']) . "', '.--','" . mysql_real_escape_string($_POST['Versandkosten']) . "', '" . mysql_real_escape_string($subdir) . "', '" . mysql_real_escape_string($_FILES['userfile']['type']) . "', '" . mysql_real_escape_string($speicherdatum) . "', '" . mysql_real_escape_string($unix_time) . "')")){  
                                            			unlink("../shop/pics/".$_FILES['userfile']['name']);  
                                            			header("Location: article_upload_antw.php?flag=noDB");  
                                            		    exit;  
                                            		}  
                                            		  
                                            		else {  
                                            			mysql_query("UPDATE artikel SET total=Preis+Versandkosten");  
                                              
                                            			header("Location: article_upload_antw.php?flag=io");  
                                            		    exit;  
                                            		}	  
                                            	}  
                                            	exit;  
                                              
                                            }  
                                              
                                            ?>
                                            

                                            Wenn du mal Zeit und Gelegenheit hast, reinzuschauen, bin ich dir dankbar. Keine Eile!
                                            Gruss
                                            hannes

                                            1. Hello,

                                              Hallo Tom,

                                              hier also der bereinigte Code
                                              [code lang=php]
                                              <?
                                              @session_start();

                                              /************************************************************************************************/
                                              if (($_SESSION['myusername'] == "") OR ($_SESSION['mypassword'] == "")) {
                                              include ("login.php");
                                              }
                                              /************************************************************************************************/

                                              if (empty($_SESSION['myusername'] == "") OR empty($_SESSION['mypassword'])
                                              {
                                                  include ("login.php");
                                                  exit;
                                              }

                                              include("./include/db_vars.php");
                                              include("./include/db_connect.php");

                                              $speicherdatum = date("d. M Y - H:i:s");
                                              $unix_time = time();
                                              $updir = "..";
                                              $dir = "shop";
                                              $subdir = "articles";

                                              if(isset($_POST['submit']) && $_POST['submit']=="hochladen"){

                                              hier zuerst auf Fehler prüfen:

                                              achte auf den Identitätsvergleich mit ===

                                              if ($_FILES['userfile']['error'] === UPLOAD_ERR_OK)
                                              {

                                              dann die weiteren Prüfungen

                                              ($_FILES['userfile']['tmp_name'])

                                              tmp_name kann nicht mehr leer sein, wenn der Error-Wert === 0 (UPLOAD_ERR_OK) ist

                                              http://de.php.net/manual/en/features.file-upload.errors.php

                                              if($_POST['artikelName'] == ""){
                                              header("Location: article_upload_antw.php?flag=artikelName");
                                              exit;
                                              }

                                              if($_POST['Preis'] != ""){

                                                if(is\_numeric($\_POST['Preis'])){  
                                                	 $\_POST['preis'] = intval($\_POST['Preis']);  
                                                }  
                                                else {  
                                                header("Location: article\_upload\_antw.php?flag=nonumeric");  
                                                exit;  
                                                }  
                                              

                                              }

                                              if($_POST['Preis'] == ""){
                                              header("Location: article_upload_antw.php?flag=preis");
                                              exit;
                                              }

                                              if($_POST['Versandkosten'] != ""){

                                                if(is\_numeric($\_POST['Versandkosten'])){  
                                                	 $\_POST['Versandkosten'] = intval($\_POST['Versandkosten']);  
                                                }  
                                                else {  
                                                header("Location: article\_upload\_antw.php?flag=nonumeric");  
                                                exit;  
                                                }  
                                              

                                              }

                                              if($_POST['Versandkosten'] == ""){
                                              header("Location: article_upload_antw.php?flag=versandkosten");
                                              exit;
                                              }

                                              if($_POST['Breite'] == ""){
                                              header("Location: article_upload_antw.php?flag=breite");
                                              exit;
                                              }
                                              if($_POST['Hoehe'] == ""){
                                              header("Location: article_upload_antw.php?flag=hoehe");
                                              exit;
                                              }
                                              if($_POST['Tiefe'] == ""){
                                              header("Location: article_upload_antw.php?flag=tiefe");
                                              exit;
                                              }

                                              Ich würde die Übertragung der Postparameter von der Übertragung des Bildes trennen, also einen eigenen Zyklus dafür aufbauen. Es ist dabei ziemlich egal, ob Du zuerst das Bild hochladen lässt, ein Thumbnail daraus berechnest und dann erst die Beschreibungsdaten dazu hochladen lässt, oder umgekehrt. Das ist nur eine Frage deiner Geschäftslogik. Alle Bilder ohne vollständige Beschreibung würden in einem Zwischenverzeichnis liegen bleiben, bis der User mit der Arbeit fertig ist. Beschreibungen ohne Bilder könnten doch aber eventuell zulässig sein, oder? Das könnte man parametrisieren in einer INI-Datei. Dazu müssten die Vorgangszüge aber getrennt werden...

                                              else {
                                              $_FILES['userfile']['name'] = str_replace("ä","ae",$_FILES['userfile']['name']);
                                              $_FILES['userfile']['name'] = str_replace("ö","oe",$_FILES['userfile']['name']);
                                              $_FILES['userfile']['name'] = str_replace("ü","ue",$_FILES['userfile']['name']);

                                                if (file\_exists($updir."/".$dir."/".$subdir."/".mysql\_real\_escape\_string($\_FILES['userfile']['name']))) {  
                                                	header("Location: article\_upload\_antw.php?flag=already");  
                                                	exit;  
                                                }  
                                              

                                              mysql_real_escape_string() hat hier nichts zu suchen. Das behandelt das Argument nur genau für die SQL-Textschnittstelle, da diese einen gemischten Daten- und Befehlsstrom verwendet.

                                              Für das Dateisystem ist es viel wesentlicher, dass $_FILES['userfile']['name'] darauf geprüft wird, ob es nur einen Namen und auf gar keinen Fall einen (unerwünschten) Pfadanteil (auch '../../../' o.ä.) enthält. Dafür ist die Funktion basename() brauchbar.
                                              http://de.php.net/manual/en/function.basename.php

                                                if (!@move\_uploaded\_file($\_FILES['userfile']['tmp\_name'], $updir."/".$dir."/".$subdir."/".mysql\_real\_escape\_string($\_FILES['userfile']['name']))){  
                                                	header("Location: article\_upload\_antw.php?flag=nosaved");  
                                                	exit;  
                                                }  
                                              

                                              solange nicht geklärt ist, welchen Zusatznutzen move_uploaded_file() an dieser Stelle bietet, halte ich den Nachteil des TOCTTOU-Fehlers für überwiegend. Es wäre daher besser, das Kopieren der Daten generisch zu lösen und für das Eröffnen der neuen Datei im Zielverzeichnis

                                              fopen($ziel, 'xb+')
                                                  http://de.php.net/manual/en/function.fopen.php

                                              Die notwendige Absicherung für das Quellfile liefert move_uploaded_file() mMn nicht. Bei Verwendung von $_FILES['tmp_name'] kann es sich nur um ein hochgeladenes File handeln. Dieses könnte aber immer noch durch andere User manipuliert worden sein, wenn man nicht daran gedacht hat, 'upload_tmp_dir' auf einen eigenen, geschützten Bereich umzuschalten. Eben diese Absicherung, die durch eine Hashbildung des DateiINHALTES beim Serverupload möglich wäre, wird aber (vermutlich) gerad nicht vorgenommen. Der Hash wird nur über den Dateinamen (lt. Martin) gebildet. Dieser ist aber durch das gesicherte Array-Element $_FILES['tmp_name'] schon abgesichert.

                                              Hier habe ich erstmal aufgehört, weiterzulesen.

                                              Die Übertragung der Daten aus der Session in die MySQL-Tabelle ist ein eigener Vorgangszug, der erst dann durchgeführt werden sollte, wenn die beiden anderen (Bildupload, Beschreibungsdaten) ordnungsgemäß durchgeführt worden sind. Erst dann sollte auch das Bild vom persistenten Zwischenspeicher des Users in den allgemeinen Bildspeicher des Systems überführt werden.

                                              Wenn Du den Vorgang in drei Teile (Vorgangszüge) zerlegst (zuzüglich Bildverschiebung von USER nach ALLGEMEIN), dann sollte das eine sehr flexible und sichere Lösung werden.

                                              Liebe Grüße aus dem schönen Oberharz

                                              Tom vom Berg

                                              --
                                               ☻_
                                              /▌
                                              / \ Nur selber lernen macht schlau
                                              http://bergpost.annerschbarrich.de
                                              1. Hello,

                                                Das sollte allerdings so lauten:

                                                if (empty($_SESSION['myusername']) OR empty($_SESSION['mypassword'])
                                                {
                                                    include ("login.php");
                                                    exit;
                                                }

                                                Liebe Grüße aus dem schönen Oberharz

                                                Tom vom Berg

                                                --
                                                 ☻_
                                                /▌
                                                / \ Nur selber lernen macht schlau
                                                http://bergpost.annerschbarrich.de
                                              2. Hallo Tom,
                                                vielen Dank, dass du dir die Mühe gegeben hast, den code zu überprüfen.
                                                Meine Antwort etwas summarisch:

                                                • login hab ich angepasst
                                                • das mit dem UPLOAD_ERR_OK etc. muss ich bei Gelegenheit in Ruhe studieren
                                                • mysql_real_escape_string habe ich angepasst und kapiert.
                                                • auch das mit der Trennung der upload-Inhalte (das Aufteilen in die drei Vorgangszüge) will ich überlegen (dazu muss ich sagen, dass es sich um einen kleinen "online-shop" für meine Frau handelt; sie soll lediglich die Möglichkeit haben, in einem geschützten Bereich ihre Bilder/Artikel, die sie anbieten will, hochzuladen. Die CIA bleibt da wohl draussen vor ;-) Aber ich nehme deine Überlegungen grundsätzlich zur Kenntnis. "parametrisieren in einer INI-Datei" ist sowieso über meinem Horizont.
                                                  Nochmals vielen Dank.
                                                  Gruss
                                                  hannes

                                                NB: hab noch ein anderes Problem, weiss nicht, ob ich dies hier anführen soll (vielleicht siehst du die Lösung in einer Sekunde), oder ob ich einen neuen thread eröffnen soll.
                                                (ich habe ein script, das Preis,Versandkosten und tot anzeigt. Die Info sind aus DB. Ich möchte, dass Versandkosten und tot angepasst werden, wenn ein User im Formular des gleichen scripts die entspr. checkbox anwählt). Ich habe schon x Stunden damit verbracht und knete immer noch den gleichen Teig.
                                                (Code und genauere Beschreibung poste ich, wenn klar ist wo).

                                                1. Hello Hannes,

                                                  es fehlen ja noch mehr Sicherheitsmechanismen.

                                                  Wenn Du sicherstellen willst, dass nur Bilder hochgeladen werden können und keine Scripte, Texte, oder HTML-Seiten, dann müsstest Du das auch noch überprüfen. Dabei ist es sowohl wichtig, dass es sich tatsächlich um ein Bild handelt, als auch, die Dateiendung dazu passt. Über die Dateiendung wird bei PHP oft gekennzeichnet, dass die Datei zu parsen ist, also als PHP-Script behandelt werden soll.

                                                  Wenn nun jedermann hochladen darf, dann muss man nicht lange darauf warten, dass man als Bilder getarnte Scritpe auf dem Server hat...

                                                  Liebe Grüße aus dem schönen Oberharz

                                                  Tom vom Berg

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

                                                    ... überprüfen...dass es sich tatsächlich um ein Bild handelt

                                                    wie macht man das? (ausser der Dateiendung) Meinst du mit $_FILES['userfile']['type']?
                                                    Gruss hannes
                                                    what about NB meines letzten postings?

                                                    1. 'ǝɯɐu$ ıɥ

                                                      wie macht man das? (ausser der Dateiendung) Meinst du mit $_FILES['userfile']['type']?

                                                      Überprüfe das u.a. mit getimagesize(), beachte die hinweise hier und hier (bitte die Threads zu ende lesen.)

                                                      ssnɹƃ
                                                      ʍopɐɥs

                                                      --
                                                      HTML, was ist das? Ein neues Männermagazin? Css.., was es alles gibt!
                                                      1. Hello,

                                                        Überprüfe das u.a. mit getimagesize(), beachte die hinweise hier und hier (bitte die Threads zu ende lesen.)

                                                        Danke für die Unterstützung.
                                                        Die wesentlichen Dinge habe ich ja auch schon alle in den angefangenen Artikel im Wiki übernommen. Es müssen nun als nächstes ein paar sichere Beispiele erzeugt werden und dann der Rest nochmal geschliffen und lackiert ;-)

                                                        http://wiki.selfhtml.org/wiki/Artikel:PHP/File_Upload

                                                        Zum Schluss kann es dann um die größeren Lösungen gehen.

                                                        Ich war an der Frage der Sinnhaftigkeit von move_uploaded_file() und is_uploaded_file() hängen geblieben, die sich bisher nicht erwiesen hat...

                                                        Liebe Grüße aus dem schönen Oberharz

                                                        Tom vom Berg

                                                        --
                                                         ☻_
                                                        /▌
                                                        / \ Nur selber lernen macht schlau
                                                        http://bergpost.annerschbarrich.de
                              4. Hi,

                                Ich habe jedes posting gelesen, versucht die Tipps umzusetzen und die Erfolge/Misserfolge in weiteren postings bekannt zu geben. Was soll ich noch lesen?

                                Ein Grundlagen-Tutorial.

                                MfG ChrisB

                                --
                                RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
                        2. Hello,

                          Dann will ich hier jetzt auch nochmal einhaken, denn die Frage, was move_uploaded_file() wirklich tut, konnte ich bisher immer noch nicht klären. Woher nimmt die Funktion die Information "uploaded"?.

                          So wie es dokumentiert ist. Sie sorgt dafür, dass es sich wirklich um eine hochgeladene Datei handelt und nicht etwa um /etc/passwd, falls es jemandem gelingt, diesen Namen an die Stelle des zu kopierenden Dateinamens zu bringen. Ein einfaches copy() prüft das nicht.

                          *eins-zwei-drei-vier-fünf-sechs-sieben-acht-neun-zehn*

                          Meine Frage war doch nicht, was dokumentiert ist, sondern, wie die die Funktion das "uploaded" feststellt. Da der Temporärdateiname vom Server-System ausgewürfelt wird und die Einstellung für 'upload_tmp_dir' mit PHP_INI_SYSTEM gekennzeichnet ist, kann ich mir nicht vorstellen, welchen Einfluss der Client auf diese Namen bzw. den Pfad nehmen könnte.

                          Was macht also move_uploaded_file() zusätzlich, um die Sicherheit noch zu erhöhen?

                          Wen soll es eigentlich schützen?

                          Den Werserver.

                          *mmh*
                          Leuchtet mir nicht ein.

                          (Wo steht es im Quellcode? Wenn es jemand verlinken kann, brauch ich nicht erst lange zu suchen, sonst fang ich heute Nacht vielleicht damit an...)

                          Liebe Grüße aus dem schönen Oberharz

                          Tom vom Berg

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

                            Meine Frage war doch nicht, was dokumentiert ist, sondern, wie die die Funktion das "uploaded" feststellt. Da der Temporärdateiname vom Server-System ausgewürfelt wird und die Einstellung für 'upload_tmp_dir' mit PHP_INI_SYSTEM gekennzeichnet ist, kann ich mir nicht vorstellen, welchen Einfluss der Client auf diese Namen bzw. den Pfad nehmen könnte.

                            Nicht auf den Namen der hochgeladenen Datei, aber auf den String, den du bei copy() als ersten Parameter übergibst. Und die Funktion weiß natürlich, welche Datei hochgeladen wurde, weil PHP sie ja grad eben in Empfang genommen hat - genau die und nicht irgendwelche anderen, die andere Leute hochgeladen haben oder die schon auf dem System sind.

                            Was macht also move_uploaded_file() zusätzlich, um die Sicherheit noch zu erhöhen?

                            Es stellt sicher, dass ein Kopieren mit manipuliertem Dateinamen - sprich: anderer als der hochgeladener Dateien - nicht stattfinden kann.

                            Wen soll es eigentlich schützen?
                            Den Werserver.
                            *mmh*
                            Leuchtet mir nicht ein.

                            Ungewollte Offenlegung von Informationen auf dem Server wird verhindert.

                            Lo!

                            1. Hello,

                              Hi!

                              Meine Frage war doch nicht, was dokumentiert ist, sondern, wie die die Funktion das "uploaded" feststellt. Da der Temporärdateiname vom Server-System ausgewürfelt wird und die Einstellung für 'upload_tmp_dir' mit PHP_INI_SYSTEM gekennzeichnet ist, kann ich mir nicht vorstellen, welchen Einfluss der Client auf diese Namen bzw. den Pfad nehmen könnte.

                              Nicht auf den Namen der hochgeladenen Datei, aber auf den String, den du bei copy() als ersten Parameter übergibst. Und die Funktion weiß natürlich, welche Datei hochgeladen wurde, weil PHP sie ja grad eben in Empfang genommen hat - genau die und nicht irgendwelche anderen, die andere Leute hochgeladen haben oder die schon auf dem System sind.

                              Da kommen wir der Sache also schon näher. "Die Funktion weiß...". Woher weiß die das? Was weiß die mehr, als es $_FILES sowieso schon weiß?

                              Was macht also move_uploaded_file() zusätzlich, um die Sicherheit noch zu erhöhen?

                              Es stellt sicher, dass ein Kopieren mit manipuliertem Dateinamen - sprich: anderer als der hochgeladener Dateien - nicht stattfinden kann.

                              Wer sollte den denn manipulieren, wenn das Script, ihn aus $_FILES['???']['tmp_name'] oder $_FILES['???']['tmp_name'][x] (bei mehreren Files unter dem Namen ['???'] entnimmt.

                              Soll das heißen, dass in $_FILES 'nur so ungefähr' und 'manchmal' die richtigen Temporärdateinamen drinstehen?

                              Ich halte die Funktion (bei Verwendung von $_FILES) immer noch für Quatsch, solange mir niemand zeigen kann, was die mehr kann.

                              Wen soll es eigentlich schützen?
                              Den Werserver.
                              *mmh*
                              Leuchtet mir nicht ein.

                              Ungewollte Offenlegung von Informationen auf dem Server wird verhindert.

                              *grummel*

                              Das ist mir vollkommen klar. Ich frage mich nur, durch welche Maßnahme an welcher Stelle soll das verhindert werden? mMn kann hier nichts eingeschleppt werden. Und wenn der Scriptautor einen Fehler macht, kann er die Datei ggf. auch gleich selber klauen, wenn er dran kommt.

                              Liebe Grüße aus dem schönen Oberharz

                              Tom vom Berg

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

                                Und die Funktion weiß natürlich, welche Datei hochgeladen wurde, weil PHP sie ja grad eben in Empfang genommen hat - genau die und nicht irgendwelche anderen, die andere Leute hochgeladen haben oder die schon auf dem System sind.
                                Da kommen wir der Sache also schon näher. "Die Funktion weiß...". Woher weiß die das? Was weiß die mehr, als es $_FILES sowieso schon weiß?

                                Schrub ich doch, aber nochmal genauer: sie ist Bestandteil von PHP und hat somit auch Zugriff auf dessen interne Informationen. Du wirst sie sicher nicht mit einer Userland-Funktion nachbilden können. Eine dieser internen Information ist das Wissen um die soeben empfangene Datei.

                                Was macht also move_uploaded_file() zusätzlich, um die Sicherheit noch zu erhöhen?
                                Es stellt sicher, dass ein Kopieren mit manipuliertem Dateinamen - sprich: anderer als der hochgeladener Dateien - nicht stattfinden kann.
                                Wer sollte den denn manipulieren, wenn das Script, ihn aus $_FILES['???']['tmp_name'] oder $_FILES['???']['tmp_name'][x] (bei mehreren Files unter dem Namen ['???'] entnimmt.

                                Es geht nicht um den Wenn-Fall sondern un den Wenn-nicht-Fall. Niemand wird daran gehindert, noch Stringmanipulationen daran vorzunehmen, oder sich den Inhalt von $_FILES verändern zu lassen, oder es selbst zu tun - aus welchem Grund und mit welchem Vorgang auch immer.

                                Soll das heißen, dass in $_FILES 'nur so ungefähr' und 'manchmal' die richtigen Temporärdateinamen drinstehen?

                                Zum Scriptstart wird von Seiten PHPs aus das richtige drinstehen. Es ist aber nicht read-only.

                                Ich halte die Funktion (bei Verwendung von $_FILES) immer noch für Quatsch, solange mir niemand zeigen kann, was die mehr kann.

                                Das "mehr" ist die Prüfung auf wirklich Hochgeladenes.

                                Das ist mir vollkommen klar. Ich frage mich nur, durch welche Maßnahme an welcher Stelle soll das verhindert werden? mMn kann hier nichts eingeschleppt werden.

                                Sei doch mal ein wenig kreativer. So wirst du nie ein guter Angreifer und auch kein guter Verteidiger, wenn du dir die Angriffsvektoren nicht vorstellen kannst.

                                Und wenn der Scriptautor einen Fehler macht, kann er die Datei ggf. auch gleich selber klauen, wenn er dran kommt.

                                Wenn Script-Autoren (oder Programmierer im Allgemeinen) immer fehlerfrei arbeiten würden, bräuchte es eine ganze Menge anderer Sicherungsmaßnahmen ebenfalls nicht.

                                Lo!

                                1. Hello dedlfix,

                                  Es geht nicht um den Wenn-Fall sondern un den Wenn-nicht-Fall. Niemand wird daran gehindert, noch Stringmanipulationen daran vorzunehmen, oder sich den Inhalt von $_FILES verändern zu lassen, oder es selbst zu tun - aus welchem Grund und mit welchem Vorgang auch immer.

                                  Martin hat mich auf die sehr viel wahrscheinlichere Spur gebracht...

                                  Es scheint um eine (zusätzliche) Absicherung in Shared-Hosting-Umgebungen zu gehen. Wenn es so ist, wie wir in https://forum.selfhtml.org/?t=204544&m=1385376 vermuten, dann wird dadurch die Zwischenlagerung im /tmp-Verzeichnis abgesichert. Da könnten Andere die Datei manipulieren.

                                  Liebe Grüße aus dem schönen Oberharz

                                  Tom vom Berg

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

                                    Es geht nicht um den Wenn-Fall sondern un den Wenn-nicht-Fall. Niemand wird daran gehindert, noch Stringmanipulationen daran vorzunehmen, oder sich den Inhalt von $_FILES verändern zu lassen, oder es selbst zu tun - aus welchem Grund und mit welchem Vorgang auch immer.
                                    Martin hat mich auf die sehr viel wahrscheinlichere Spur gebracht...
                                    Es scheint um eine (zusätzliche) Absicherung in Shared-Hosting-Umgebungen zu gehen. Wenn es so ist, wie wir in https://forum.selfhtml.org/?t=204544&m=1385376 vermuten, dann wird dadurch die Zwischenlagerung im /tmp-Verzeichnis abgesichert. Da könnten Andere die Datei manipulieren.

                                    Mir scheint, du hast was anderes hineininterpretiert, als er gesagt hat. Er sagte, der hash wird über den Datei_namen_ berechnet, du stelltest du (dir) jedoch ein Szenario vor, bei dem ein Hash über den Datei_inhalt_ eine Rolle spielt. Das Handbuch verspricht auch nicht, dass die Funktion den Inhalt der Datei schützt.

                                    Lo!

                                    1. Hello,

                                      Es geht nicht um den Wenn-Fall sondern un den Wenn-nicht-Fall. Niemand wird daran gehindert, noch Stringmanipulationen daran vorzunehmen, oder sich den Inhalt von $_FILES verändern zu lassen, oder es selbst zu tun - aus welchem Grund und mit welchem Vorgang auch immer.
                                      Martin hat mich auf die sehr viel wahrscheinlichere Spur gebracht...
                                      Es scheint um eine (zusätzliche) Absicherung in Shared-Hosting-Umgebungen zu gehen. Wenn es so ist, wie wir in https://forum.selfhtml.org/?t=204544&m=1385376 vermuten, dann wird dadurch die Zwischenlagerung im /tmp-Verzeichnis abgesichert. Da könnten Andere die Datei manipulieren.

                                      Mir scheint, du hast was anderes hineininterpretiert, als er gesagt hat. Er sagte, der hash wird über den Datei_namen_ berechnet, du stelltest du (dir) jedoch ein Szenario vor, bei dem ein Hash über den Datei_inhalt_ eine Rolle spielt.

                                      Martin hat aber auch geschrieben, dass er das noch nicht vollends durchschaut hat, was da passiert. Und ich habe mir erlaubt, weiterzudenken ;-P

                                      Das Handbuch verspricht auch nicht, dass die Funktion den Inhalt der Datei schützt.

                                      Das gilt es eben noch herauszufinden.
                                      Also doch nachher Quellcode-Lesestunde. Jetzt habe ich nicht genug Ruhe dafür.

                                      Liebe Grüße aus dem sonnigen Oberharz
                                      (heute 14°C im Schatten, in der Sonne Sonnenbrandgarantie)

                                      Tom vom Berg

                                      --
                                       ☻_
                                      /▌
                                      / \ Nur selber lernen macht schlau
                                      http://bergpost.annerschbarrich.de
                          2. Hallo,

                            tief einatmen ...

                            *eins-zwei-drei-vier-fünf-sechs-sieben-acht-neun-zehn*

                            und ausatmen. Jetzt besser? :-)

                            Meine Frage war doch nicht, was dokumentiert ist, sondern, wie die die Funktion das "uploaded" feststellt.

                            War mir klar, dass du auf das "wie" hinaus wolltest. Deswegen habe ich nochmal im Quellcode gewühlt. So ganz bin ich noch nicht dahintergekommen, aber es scheint so, als ob beim eigentlichen Upload (also noch bevor das Script gestartet wird) über den Namen jeder Datei, die hochgeladen und mit einem Zufallsnamen im temp-Verzeichnis abgelegt wurde, ein Hash berechnet und abgelegt wird.
                            Und move_uploaded_file() überprüft dann genau wie is_uploaded_file(), ob die Datei mit dem angegebenen Namen existiert, ob ein Hash dazu existiert, und ob er mit dem Dateinamen zusammenpasst.
                            Wenn sich das jetzt ein wenig vage anhört, dann liegt es daran, dass ich den Ablauf auch noch nicht so ganz begriffen habe.

                            (Wo steht es im Quellcode? Wenn es jemand verlinken kann, brauch ich nicht erst lange zu suchen, sonst fang ich heute Nacht vielleicht damit an...)

                            In ./ext/standard/basic_functions.c ab Zeile 5787 (für PHP 5.3.6).

                            Ciao,
                             Martin

                            --
                            Wer barfuß geht, dem kann man nicht die Schuld in die Schuhe schieben.
                            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                            1. Hello Martin,

                              tief einatmen ...

                              *eins-zwei-drei-vier-fünf-sechs-sieben-acht-neun-zehn*

                              und ausatmen. Jetzt besser? :-)

                              Besser ;-)

                              Meine Frage war doch nicht, was dokumentiert ist, sondern, wie die die Funktion das "uploaded" feststellt.

                              War mir klar, dass du auf das "wie" hinaus wolltest. Deswegen habe ich nochmal im Quellcode gewühlt. So ganz bin ich noch nicht dahintergekommen, aber es scheint so, als ob beim eigentlichen Upload (also noch bevor das Script gestartet wird) über den Namen jeder Datei, die hochgeladen und mit einem Zufallsnamen im temp-Verzeichnis abgelegt wurde, ein Hash berechnet und abgelegt wird.
                              Und move_uploaded_file() überprüft dann genau wie is_uploaded_file(), ob die Datei mit dem angegebenen Namen existiert, ob ein Hash dazu existiert, und ob er mit dem Dateinamen zusammenpasst.
                              Wenn sich das jetzt ein wenig vage anhört, dann liegt es daran, dass ich den Ablauf auch noch nicht so ganz begriffen habe.

                              Jetzt dämmert es mir, was die sich dabei gedacht haben könnten. In einer Shared-Hosting-Umgebung wäre es denkbar, dass ein Administrator keine Ahnung hatte von PHP- und Domaineinrichtung, und das Upload-Tmp-Dir daher auf /tmp liegt - für alle Domains gemeinsam.

                              Da wäre es also möglich, dass jemand mein gerade hochgeladenes File im Temporärverzeichnis manipuliert, bevor ich es verschoben habe in meinen Account. Das geht aber nur bei der Modulversion. Bei der (Fast-)CGI-Version gehört die Datei einem getrennten Prozess pro Request und kann nur vom Eigentümer verändert werden (t-Flag) http://en.wikipedia.org/wiki/Sticky_bit (da steht allderings nichts von Schreibrechten, sondern nur vom Namen *?*).

                              Wenn der Hash nicht mehr zur Datei passt, hat jemand gefummelt.

                              Bei Linux-Systemen sollte das bei Verwendung der Standardeinstellungen nicht möglich sein

                              (Wo steht es im Quellcode? Wenn es jemand verlinken kann, brauch ich nicht erst lange zu suchen, sonst fang ich heute Nacht vielleicht damit an...)

                              In ./ext/standard/basic_functions.c ab Zeile 5787 (für PHP 5.3.6).

                              Da schaue ich nachher nochmal genauer nach, ob ich das verstehe. Ich muss auch immer etwas kämpfen. Wir sollten uns mal von Christian Seiler einen Crashkurs geben lassen. Der wäre mir auch etliche Euronen wert :-) Alternativ beantrage ich Gehirn-Cloning ;-P

                              Liebe Grüße aus dem schönen Oberharz

                              Tom vom Berg

                              --
                               ☻_
                              /▌
                              / \ Nur selber lernen macht schlau
                              http://bergpost.annerschbarrich.de
                              1. Hi,

                                Jetzt dämmert es mir, was die sich dabei gedacht haben könnten. In einer Shared-Hosting-Umgebung wäre es denkbar, dass ein Administrator keine Ahnung hatte von PHP- und Domaineinrichtung, und das Upload-Tmp-Dir daher auf /tmp liegt - für alle Domains gemeinsam.

                                das ist auch das einzige Szenario, wo ich mir irgendein Sicherheitsproblem vorstellen könnte. Denn sonst dürfte die Rechteverwaltung des OS (ansatzweise sogar unter Windows) ja sowieso den Zugriff auf alles verweigern, was nicht dem Apache/PHP-User gehört. Oder anders gesagt: Wenn ich mich allein auf das Rechtesystem des OS verlasse, kann ich mit den normalen Dateisystemfunktionen von PHP lustig hin- und herkopieren, soweit das OS mich lässt, so dass eine weitere Einschränkung, wie move_uploaded_file() sie anscheinend macht, nicht nötig wäre.
                                Shared-Hosting, wo alle virtuellen Hosts unter dem gleichen Benutzer laufen, ist die einzige Situation, bei der man zusätzlich aufpassen muss.

                                Da wäre es also möglich, dass jemand mein gerade hochgeladenes File im Temporärverzeichnis manipuliert, bevor ich es verschoben habe in meinen Account.

                                Genau.

                                Das geht aber nur bei der Modulversion.

                                Mag sein; mit der CGI-Variante kenne ich mich nicht so gut aus.

                                Wir sollten uns mal von Christian Seiler einen Crashkurs geben lassen. Der wäre mir auch etliche Euronen wert :-)

                                Könnte ich mir auch vorstellen - aber welchen konkreten Themenschwerpunkt meintest du jetzt?

                                Alternativ beantrage ich Gehirn-Cloning ;-P

                                Das ist nach dem heutigen Stand der Wissenschaft AFAIK immer noch problematisch. ;-)

                                Ciao,
                                 Martin

                                --
                                Finanztipp:
                                Leihen Sie sich Geld von einem Pessimisten.
                                Er rechnet sowieso nicht damit, dass er es zurückbekommt.
                                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                1. Hello,

                                  Wir sollten uns mal von Christian Seiler einen Crashkurs geben lassen. Der wäre mir auch etliche Euronen wert :-)

                                  Könnte ich mir auch vorstellen - aber welchen konkreten Themenschwerpunkt meintest du jetzt?

                                  PHP-Quellcode lesen und manipulieren, neu compilieren, usw.
                                  Nicht, dass ich das dann täglich tun wollte, aber es erleichtert die Recherche doch ganz gewaltig.

                                  Liebe Grüße aus dem schönen Oberharz

                                  Tom vom Berg

                                  --
                                   ☻_
                                  /▌
                                  / \ Nur selber lernen macht schlau
                                  http://bergpost.annerschbarrich.de
                            2. Hello Martin,

                              In ./ext/standard/basic_functions.c ab Zeile 5787 (für PHP 5.3.6).

                              Es geht also um diese beiden Funktions-Baumuster...
                              (die sind jetzt aus der 5.3-dev, die neuere habe ich noch nicht runtergeladen)

                              Das heißt also, wir müssen nach SG() suchen und ggf. noch nach zend_hash_exists()

                              #------------------

                              /* {{{ proto bool is_uploaded_file(string path)
                                 Check if file was created by rfc1867 upload */
                              PHP_FUNCTION(is_uploaded_file)
                              {
                              char *path;
                              int path_len;

                              if (!SG(rfc1867\_uploaded\_files)) {  
                              	RETURN\_FALSE;  
                              }  
                              
                              if (zend\_parse\_parameters(ZEND\_NUM\_ARGS() TSRMLS\_CC, "s", &path, &path\_len) == FAILURE) {  
                              	return;  
                              }  
                              
                              if (zend\_hash\_exists(SG(rfc1867\_uploaded\_files), path, path\_len + 1)) {  
                              	RETURN\_TRUE;  
                              } else {  
                              	RETURN\_FALSE;  
                              }  
                              

                              }
                              /* }}} */

                              #------------------------

                              /* {{{ proto bool move_uploaded_file(string path, string new_path)
                                 Move a file if and only if it was created by an upload */
                              PHP_FUNCTION(move_uploaded_file)
                              {
                              char *path, *new_path;
                              int path_len, new_path_len;
                              zend_bool successful = 0;

                              #ifndef PHP_WIN32
                              int oldmask; int ret;
                              #endif

                              if (!SG(rfc1867\_uploaded\_files)) {  
                              	RETURN\_FALSE;  
                              }  
                              
                              if (zend\_parse\_parameters(ZEND\_NUM\_ARGS() TSRMLS\_CC, "ss", &path, &path\_len, &new\_path, &new\_path\_len) == FAILURE) {  
                              	return;  
                              }  
                              
                              if (!zend\_hash\_exists(SG(rfc1867\_uploaded\_files), path, path\_len + 1)) {  
                              	RETURN\_FALSE;  
                              }  
                              
                              if (PG(safe\_mode) && (!php\_checkuid(new\_path, NULL, CHECKUID\_CHECK\_FILE\_AND\_DIR))) {  
                              	RETURN\_FALSE;  
                              }  
                              
                              if (php\_check\_open\_basedir(new\_path TSRMLS\_CC)) {  
                              	RETURN\_FALSE;  
                              }  
                              
                              VCWD\_UNLINK(new\_path);  
                              if (VCWD\_RENAME(path, new\_path) == 0) {  
                              	successful = 1;  
                              

                              #ifndef PHP_WIN32
                              oldmask = umask(077);
                              umask(oldmask);

                              	ret = VCWD\_CHMOD(new\_path, 0666 & ~oldmask);  
                              
                              	if (ret == -1) {  
                              		php\_error\_docref(NULL TSRMLS\_CC, E\_WARNING, "%s", strerror(errno));  
                              	}  
                              

                              #endif
                              } else if (php_copy_file_ex(path, new_path, STREAM_DISABLE_OPEN_BASEDIR TSRMLS_CC) == SUCCESS) {
                              VCWD_UNLINK(path);
                              successful = 1;
                              }

                              if (successful) {  
                              	zend\_hash\_del(SG(rfc1867\_uploaded\_files), path, path\_len + 1);  
                              } else {  
                              	php\_error\_docref(NULL TSRMLS\_CC, E\_WARNING, "Unable to move '%s' to '%s'", path, new\_path);  
                              }  
                              
                              RETURN\_BOOL(successful);  
                              

                              }
                              /* }}} */

                              Wenn es nicht um den Inhalt der Files gehen sollte, sondern nur um den Namen, dann halte ich diese Funktionen für nutzlosen Overhead. Denn das Array $_FILES sollte sicher sein und somit sollte zumindest der Name der Temporärdatei nicht manipuliert werden können, da dieser vom System kommt und das Array nur der jeweiligen Scriptinstanz zur Verfügung steht. Hingegen könnte das File in einem gemeinsam genutzten Bereich liegen und auch das t-flag bei Linux schützt nicht gegen Manipulation des Files, sondern nur gegen Löschen/Verschieben oder Namensänderung.

                              Move_uploaded_file() war genau der Punkt, an dem ich im Wiki-Artikel jetzt hängengeblieben war. Ohne Kenntnis der Zusammenhänge mag ich das nicht gebetsmühlenartig wieder zur Bentutzung vorschlagen. PHP hatte schon andere Designfehler (magic_quotes, PHP_SELF, usw), die später zu weit verbreiteten Sicherheitslücken geführt haben.

                              Mein Resümeé daraus ist also: für die Modulversion _unbedingt_ das upload_tmp_dir auf ein eigenes HTTP-geschütztes Verzeichnis setzen, usw...

                              Für Sessions gilt ja Ähnliches.

                              Liebe Grüße aus dem auch heute sonnigen Oberharz

                              Tom vom Berg

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

                                Wenn es nicht um den Inhalt der Files gehen sollte, sondern nur um den Namen, dann halte ich diese Funktionen für nutzlosen Overhead.

                                Es kommt mir so vor, als ob du ihren Sinn abstreitest, nur weil er dir verschlossen bleibt. Wenn du das genauer geklärt haben möchtest, solltest du auf einer PHP-Mailing-Liste (o.ä.) um Erklärung bitten. Oder du versuchst in die Historie abzutauchen und Dokumente zu finden, die dazu Diskussionen zur Zeit der Einführung der Funktion enthalten.

                                Denn das Array $_FILES sollte sicher sein und somit sollte zumindest der Name der Temporärdatei nicht manipuliert werden können, da dieser vom System kommt und das Array nur der jeweiligen Scriptinstanz zur Verfügung steht.

                                Woher nimmst du diese Sicherheit, bezweifelst aber andere Sicherheitseinrichtungen?

                                Hingegen könnte das File in einem gemeinsam genutzten Bereich liegen und auch das t-flag bei Linux schützt nicht gegen Manipulation des Files, sondern nur gegen Löschen/Verschieben oder Namensänderung.

                                Das ist nicht der Knackpunkt für die Funktionen is_uploaded_file()/move_uploaded_file(). Die Nichtnutzung von gemeinsamen Bereichen ist wegen der gemeinsamen Zugreifbarkeit an sich ein Sicherheitsrisiko. Das änderst du nicht durch Nutzung oder Nichtnutzung der beiden oder auch anderer Datei-Funktionen. Den Aspekt solltest du unabhängig davon betrachten.

                                Move_uploaded_file() war genau der Punkt, an dem ich im Wiki-Artikel jetzt hängengeblieben war. Ohne Kenntnis der Zusammenhänge mag ich das nicht gebetsmühlenartig wieder zur Bentutzung vorschlagen.

                                Was ist an den Alternativen besser?

                                PHP hatte schon andere Designfehler (magic_quotes, PHP_SELF, usw), die später zu weit verbreiteten Sicherheitslücken geführt haben.

                                Zumindest halfen die Design-Fehler Magic Quotes und Safe Mode allzu unbedarften Anwendern aus dem Gröbsten raus, auch wenn der Wissende sehr gut ohne sie auskommt, ja sie sogar in machen Situationen ungewolltes - aber kein unsicheres - Verhalten zeigen. Wenn is_uploaded_file() / move_uploaded_file() dem Anwender hier ebenfalls zumindest einen kleinen Nutzen und keinen Schaden bringen, sehe ich nicht, warum man sie nicht empfehlen sollte.

                                Lo!

                                1. Hello,

                                  Denn das Array $_FILES sollte sicher sein und somit sollte zumindest der Name der Temporärdatei nicht manipuliert werden können, da dieser vom System kommt und das Array nur der jeweiligen Scriptinstanz zur Verfügung steht.

                                  Woher nimmst du diese Sicherheit, bezweifelst aber andere Sicherheitseinrichtungen?

                                  Ja, wenn Du das so sagst. Sollte ich lieber den Superglobalen Arrays auch misstrauen? Naja, Du steckst da wohl tiefer drin. Was ist denn das Problem mit dem Array $_FILES?

                                  Mit dem Sinn der beiden Funktionen hat die Unsicherheit der superglobalen Arrays natürlich nichts zu tun. Nur weil die superglobalen Arrays auch unsicher sein könnten, müssen die Funktionen noch lange keinen Sinn haben.

                                  Liebe Grüße aus dem schönen Oberharz

                                  Tom vom Berg

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

                                    Denn das Array $_FILES sollte sicher sein und somit sollte zumindest der Name der Temporärdatei nicht manipuliert werden können, da dieser vom System kommt und das Array nur der jeweiligen Scriptinstanz zur Verfügung steht.

                                    Woher nimmst du diese Sicherheit, bezweifelst aber andere Sicherheitseinrichtungen?

                                    Ja, wenn Du das so sagst. Sollte ich lieber den Superglobalen Arrays auch misstrauen? Naja, Du steckst da wohl tiefer drin. Was ist denn das Problem mit dem Array $_FILES?

                                    Ich sehe kein Problem. Ich versuche nur herauszufinden, welche Probleme du mit den beiden Funktionen hast (oder sie (die Probleme) dir auszureden). Und ich sehe da dein typisches Vom-Hundersten-ins-Tausende-Problem und hab die Befürchtung, dass dein Artikel am Ende zwar sehr genau ist, aber ihn k(aum )einer mehr bis zum Ende lesen will. Lang wird er eh schon, so dass ich dir sowieso vorschlage, an den Anfang einen Extrakt der wichtigsten Punkte zu stellen.

                                    Mit dem Sinn der beiden Funktionen hat die Unsicherheit der superglobalen Arrays natürlich nichts zu tun. Nur weil die superglobalen Arrays auch unsicher sein könnten, müssen die Funktionen noch lange keinen Sinn haben.

                                    Wie gesagt, ich denke, es geht weniger um die Kombination *_uploaded_file() und $_FILES... als (erstem) Parameter, sondern wenn man statt $_FILES handgefüllte Variablen nimmt.

                                    Lo!

                                    1. Hello,

                                      Denn das Array $_FILES sollte sicher sein und somit sollte zumindest der Name der Temporärdatei nicht manipuliert werden können, da dieser vom System kommt und das Array nur der jeweiligen Scriptinstanz zur Verfügung steht.

                                      Woher nimmst du diese Sicherheit, bezweifelst aber andere Sicherheitseinrichtungen?

                                      Ja, wenn Du das so sagst. Sollte ich lieber den Superglobalen Arrays auch misstrauen? Naja, Du steckst da wohl tiefer drin. Was ist denn das Problem mit dem Array $_FILES?

                                      Ich sehe kein Problem.

                                      Na, das beruhigt mich doch schon mal.

                                      Ich versuche nur herauszufinden, welche Probleme du mit den beiden Funktionen hast (oder sie (die Probleme) dir auszureden).

                                      Mit welcher Berechtigung? das kommt mir dann so vor, wie "Kernkraftwerke sind sicher".

                                      Und ich sehe da dein typisches Vom-Hundersten-ins-Tausende-Problem

                                      Was ist an der Verfolgung einer Frage bis zur Wurzel auszusetzen?
                                      Wenn Du mir damit bescheinigen willst, dass ich solange nachfrage, bis jegliche Zweifel ausgeräumt sind, dann danke ich Dir dafür.

                                      und hab die Befürchtung, dass dein Artikel am Ende zwar sehr genau ist, aber ihn k(aum )einer mehr bis zum Ende lesen will. Lang wird er eh schon, so dass ich dir sowieso vorschlage, an den Anfang einen Extrakt der wichtigsten Punkte zu stellen.

                                      Das ist eine gute Idee. Das wichtigste zuerst: "Uploads sind böse!".

                                      Ich werde diese Aussage dann aber trotzdem hinterfragen. Schließlich wollen wir doch Updates, nur nicht zu dem Preis eines "GAUs", sondern zu überschaubaren und quantifizierbaren Risiken, nicht relativ, sondern absolut!

                                      Mit dem Sinn der beiden Funktionen hat die Unsicherheit der superglobalen Arrays natürlich nichts zu tun. Nur weil die superglobalen Arrays auch unsicher sein könnten, müssen die Funktionen noch lange keinen Sinn haben.

                                      Wie gesagt, ich denke, es geht weniger um die Kombination *_uploaded_file() und $_FILES... als (erstem) Parameter, sondern wenn man statt $_FILES handgefüllte Variablen nimmt.

                                      Wer nimmt denn handgefüllte Variablen? Dann könnte ich doch gleich Konstanten dafür benutzen, oder?

                                      Liebe Grüße aus dem schönen Oberharz

                                      Tom vom Berg

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

                                        Wer nimmt denn handgefüllte Variablen?

                                        Wer rahmt Variablen in "" ein? ... Bitte fortsetzen mit allen möglichen anderen unsinnigen Vorgehensweisen. Wir™ wissen mittlerweile, wie wir auf kürzestem und sinnvollstem Weg die Ziele erreichen. Wir wundern uns nur, auf welche wunderlichen Ideen die Anfänger so kommen.

                                        Versuch in der Historie zu stöbern, da findest du sicher Begründungen, warum diese Funktionen zusätzlich zu copy()/move() existieren.

                                        Lo!

                                        1. Hello,

                                          Wer nimmt denn handgefüllte Variablen?

                                          Wer rahmt Variablen in "" ein? ... Bitte fortsetzen mit allen möglichen anderen unsinnigen Vorgehensweisen.

                                          Daher habe ich vorhin gefragt, wer (warum) geschützt werden soll.

                                          Soll nun Fehlverhalten des Programmierers oder Angriffsverhalten des Clients abgefangen werden?

                                          Deine Aussage zielt doch nun eher auf Fehlverhalten des Programmierers. Das mit einer vom Programmierer optional einsetzbaren Funktion abfangen zu wollen, halte ich für wenig sinnvoll.

                                          Und das Angriffsverhalten des Clients abzufangen mit einer Doppelung der Sicherungsmaßnahmen, die aber beide dieselbe Lücke lassen, halte ich erst recht für gehirnamputiert.

                                          Was "WIR" hier empfehlen würden, steht noch auf einem ganz anderen Blatt. Und das versuche ich gerade zu formulieren. Dazu muss ich aber erst die Vorgänge bis ins Tausendstel untersucht haben...

                                          Setz doch Deine Kraft ganz einfach mal dafür ein, die aufgeworfenen Denkansätze zu verfolgen und zu hinterfüttern oder ad Absurdum zu führen, anstatt die Poster der Denkansätze ad Absurdum zu führen.

                                          Liebe Grüße aus dem schönen Oberharz

                                          Tom vom Berg

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

                                            Daher habe ich vorhin gefragt, wer (warum) geschützt werden soll.
                                            Soll nun Fehlverhalten des Programmierers oder Angriffsverhalten des Clients abgefangen werden?

                                            Wenn du den Programmierer vor sicherheitsrelevanten Fehlhandlungen schützt, schützt du damit den Server. Also ist immer der Schutz des Servers (inklusive dem darauf liegenden Zeug), der auf dem Spiel steht.

                                            Setz doch Deine Kraft ganz einfach mal dafür ein, die aufgeworfenen Denkansätze zu verfolgen und zu hinterfüttern oder ad Absurdum zu führen,

                                            Mit dem Verfolgen der Denkansätze kommst du aber nur zu einer Theorie, die vielleicht in sich stimmig erscheint, aber sonst nicht weiter anhand der Tatsachen geprüft wurde. Das sehe ich als Sackgasse an. Ich glaube nicht, dass man ohne damaliges Wissen herausfinden kann, was genau der Sinn der Funktionen ist. Wenn du den Quellcode liest, wirst du seine Wirkungsweise sehen. Zum Warum kannst du dann auch wieder nur Theorien erstellen, aber keine absolute Antwort finden können. Oder stand eine in den Kommentaren des PHP-Quellcodes?

                                            Immerhin ergaben meine Recherchen, dass is_uploaded_file() deutlich älter als move_uploaded_file() ist. is_ gab es seit 3.0.17 (außer zwischen 4.0 und 4.0.3), move_ seit 4.0.3. Damals wurde noch viel mit register_globals gearbeitet und man konnte damit seine eigenen Variablen von außen überschreiben lassen. Wenn man nun statt $HTTP_POST_FILES['foo'] auf $foo zugegriffen hat, und statt eines Uploads $foo[tmp_name] per Querystring übergeben hat, konnte man mit einem ungeprüften copy($foo['tmp_name'], ...) auch beliebige Dateien kopieren. Mit is_ konnte man vor dem copy() den Dateinnamen prüfen und mit move_ ohne explizite Prüfung sicher kopieren.

                                            Lo!

                              2. Hello,

                                In ./ext/standard/basic_functions.c ab Zeile 5787 (für PHP 5.3.6).

                                Es geht also um diese beiden Funktions-Baumuster...
                                (die sind jetzt aus der 5.3-dev, die neuere habe ich noch nicht runtergeladen)

                                Das heißt also, wir müssen nach SG() suchen und ggf. noch nach zend_hash_exists()

                                Also ich kann das "SG" in der ganzen Sammlung nicht finden (wo es deklariert und wo defininiert ist) und mein Textpad auch nicht...

                                Liebe Grüße aus dem schönen Oberharz

                                Tom vom Berg

                                --
                                 ☻_
                                /▌
                                / \ Nur selber lernen macht schlau
                                http://bergpost.annerschbarrich.de
                                1. Hi,

                                  Das heißt also, wir müssen nach SG() suchen und ggf. noch nach zend_hash_exists()
                                  Also ich kann das "SG" in der ganzen Sammlung nicht finden (wo es deklariert und wo defininiert ist) und mein Textpad auch nicht...

                                  hihi, könnte es daran liegen, dass das ein Macro ist und keine Funktion, und dass es daher in einer Headerdatei zu finden ist? Dass es keine Funktion sein KANN, sieht man schon daran, dass es ab und zu auch als linke Seite einer Zuweisung auftritt:
                                    SG(...) = ausdruck;
                                  Das wäre mit einer Funktion nicht möglich - selbst wenn sie einen Zeigertyp liefert, müsste man mindestens einmal dereferenzieren (oder indizieren, was auf dasselbe herauskäme), um ein LValue zu erhalten.

                                  Ach ja:  ./main/SAPI.h, Zeile 137ff.

                                  Es ist wohl ein Macro zum kontrollierten Zugriff auf globale Daten.

                                  Ciao,
                                   Martin

                                  --
                                  Zivilisation bedeutet, dass die Eskimos warme Wohnungen bekommen und dann arbeiten müssen, damit sie sich einen Kühlschrank leisten können.
                                  Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                                  1. Hello,

                                    hihi, könnte es daran liegen, dass das ein Macro ist und keine Funktion,

                                    Ach Sch...! Daran habe ich nicht gedacht.

                                    und dass es daher in einer Headerdatei zu finden ist? Dass es keine Funktion sein KANN, sieht man schon daran, dass es ab und zu auch als linke Seite einer Zuweisung auftritt:
                                      SG(...) = ausdruck;

                                    Das wäre mit einer Funktion nicht möglich - selbst wenn sie einen Zeigertyp liefert, müsste man mindestens einmal dereferenzieren (oder indizieren, was auf dasselbe herauskäme), um ein LValue zu erhalten.

                                    Ach ja:  ./main/SAPI.h, Zeile 137ff.

                                    Es ist wohl ein Macro zum kontrollierten Zugriff auf globale Daten.

                                    Na dann. Da werde ich nachher nochmal tätig werden.

                                    Das interessiert mich doch genauer, ob diese Funktionen nun obsolet sind, oder immer noch sinnvoll.

                                    Liebe Grüße aus dem schönen Oberharz

                                    Tom vom Berg

                                    --
                                     ☻_
                                    /▌
                                    / \ Nur selber lernen macht schlau
                                    http://bergpost.annerschbarrich.de
                  2. Hello,

                    File-Uploads sind immer in $_FILES zu finden. Und es wurde hochgeladen,
                    hier C:\xampplite\tmp\php33A7.tmp gibt es keine solche Datei.

                    Au weia! Wenn ich hier mitlese, dann fallen mir wieder alle meine Sünden ein.
                    Unter http://wiki.selfhtml.org/wiki/Artikel:PHP/File_Upload findest Du nämlich einen angefangenen Artikel zum Thema Fileupload. Leider ist das Ganze nämlich noch komplizierter, als man auf den ersten Blick denkt - nicht das Hochladen, sondern die Randeffekte, wie die Bewahrung der Sicherheit.

                    Die "Temporärdatei" ist nur solange vorhanden, wie das Script, dem sie zugeordnet wird, noch läuft. Sie ist also transient. Am Ende des Scriptes löscht PHP diese "temporärdatei" wieder aus dem Verzeichnis, damit das nicht vollgemüllt wird. Wenn Du die Datei also behalten willst, deren Temporärnamen Du in $_FILES['???']['tmp_name'] findest, musst Du sie innerhalb des Scriptes an einen persistenten Ort kopieren.

                    Liebe Grüße aus dem schönen Oberharz

                    Tom vom Berg

                    --
                     ☻_
                    /▌
                    / \ Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
          2. Hi!

            Vorerst mal Danke für die Tipps. Aber zu wissen, was nötig oder unnötig ist, setzt schon voraus, das Problem soweit eingegrenzt zu haben, dass man der Lösung nahe ist.

            Genau das ist der Weg, auf den ich dich zu schicken versuche. Ich habe gute Erfahrung damit gemacht, nicht nur alles Überflüssige wegzubekommen, so dass man sich auf das Wesentliche konzentrieren kann, sondern auch damit den entscheidenden letzten Schritt zur Problemlösung zu finden.

            Wenn ich die bisherigen postings richtig verstanden habe, kann ich jetzt das Problem eingrenzen:
            echo var_dump($_POST); ergibt, dass es keinen Eintrag $userfile gibt; das wusste ich ja schon. Aber ich weiss nicht weshalb (ich habe ja beim upload-Versuch mittels Dialog-Fenster eine Datei ausgewählt).
            Und ich weiss es noch nicht.

            Nun, weil - wie schon gesagt - Uploads nicht in $_POST sondern in $_FILES auftauchen. Aber abgesehen davon, könnte man in $GLOBALS nachschauen, da steht wirklich alles drin, was dem Programm an Variablen zur Verfügung steht. Wenn es da nicht drinsteht, ist es wirklich nicht da. Gut, ich gebe zu, die Idee mit dem $GLOBALS ist nicht gerade naheliegend. Aber vielleicht fällt dir das beim nächsten gleichgelagerten Problem als eine Ursachenforschungsmöglichkeit wieder ein.

            Lo!

            1. Hello,

              Nun, weil - wie schon gesagt - Uploads nicht in $_POST sondern in $_FILES auftauchen. Aber abgesehen davon, könnte man in $GLOBALS nachschauen, da steht wirklich alles drin, was dem Programm an Variablen zur Verfügung steht. Wenn es da nicht drinsteht, ist es wirklich nicht da.

              Das ist nicht ganz richtig und daher kann ein Blick in $GLOBALS auch ältere PHP-Hasen manchmal arg verwirren... Ich denke da speziell an die Environment-Variablen. Die werden (i.d.R. heute) erst dann in $GLOBALS aufgenommen, wenn sie benötigt wurden.

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
  3. Lieber hannes,

    <form action="<? echo htmlspecialchars ($_SERVER['PHP_SELF']); ?>">

    ich meine mal gelesen zu haben, dass das ein Angriffspunkt für XSS-Attacken ist...

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Hi!

      <form action="<? echo htmlspecialchars ($_SERVER['PHP_SELF']); ?>">
      ich meine mal gelesen zu haben, dass das ein Angriffspunkt für XSS-Attacken ist...

      Nein, htmlspecialchars() verhindert das. Nur das nackige $_SERVER['PHP_SELF'] wäre ein Schwachpunkt.

      Lo!

      1. Lieber dedlfix,

        Nein, htmlspecialchars() verhindert das. Nur das nackige $_SERVER['PHP_SELF'] wäre ein Schwachpunkt.

        danke für die Klarstellung. Wieder etwas gelernt. :-)

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
  4. Hello Hannes,

    stehen denn alle Codezeilen in einem einzigen PHP-File?

    Hier ist auf jeden Fall schon mal ein Fehler im Formular:

    <input type='hidden' name='MAX_FILE_SIZE' value='.ini_get('upload_max_filesize').'> <!-- 409600 = 800kB; 614400 = 1200kB -->

    Du benutzt hier eine PHP-Funktion im HTML-Kontext. Das funktioniert natürlich nicht. Da müsstest Du schon den PHP-Parser bemühen.

    Das Formular funktioniert aber sonst.

    Den Rest schaue ich mir nachher (heute Nacht) an, wenn bis dahin keiner den Fehler entdeckt hat.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

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

      stehen denn alle Codezeilen in einem einzigen PHP-File?

      ja

      Hier ist auf jeden Fall schon mal ein Fehler im Formular:

      <input type='hidden' name='MAX_FILE_SIZE' value='.ini_get('upload_max_filesize').'> <!-- 409600 = 800kB; 614400 = 1200kB -->

      Diesen Code-Teil hatte ich schon mal korrigiert mit:
      <input type='hidden' name='MAX_FILE_SIZE' value='614400'>
      hatte sich nichts geändert

      Den Rest schaue ich mir nachher (heute Nacht) an, wenn bis dahin keiner den Fehler entdeckt hat.

      Vielen Dank zum voraus, sorry für die Mühe
      Gruss
      hannes

    2. Hallo zusammen,
      das file ist hier zu sehen (weiss gar nicht, wo ich dieses posting im thread platzieren soll).

      Gruss
      hannes