HttpUploadedFile: bug; při safe_mode nemá oprávnění při přesunu souboru

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Honza Kuchař
Člen | 1662
+
0
-

Z toho co je zde:
https://forum.nette.org/…iewtopic.php?…
https://forum.nette.org/…iewtopic.php?…

Je v současné metodě HttpUploadedFile bug.

Proto navrhuji změnu a to na:

/**
 * Move uploaded file to new location.
 * @param  string
 * @return bool
 */
public function move($dest)
{
        if (move_uploaded_file($this->tmpName, $dest)) {
                $this->tmpName = $dest;
                return TRUE;

        } else {
		@unlink($dest); // needed in PHP < 5.3 & Windows; intentionally @
                if(rename($this->tmpName, $dest)) {
                        $this->tmpName = $dest;
                        return TRUE;

                } else {
                        if(copy($this->tmpName, $dest)){
                            unlink($this->tmpName);
                            $this->tmpName = $dest;
                            return TRUE;
                        }
                        return FALSE;
                }
        }
}

Vím, že toto sice není tak elegantní, jako to co je teď v Nette, ale:

  1. Pomocí rename nebo copy většinou nemám přístup do tempů.

http://cz2.php.net/…ded-file.php Note: move_uploaded_file() is both safe mode and open_basedir aware. However, restrictions are placed only on the destination path as to allow the moving of uploaded files in which filename may conflict with such restrictions. move_uploaded_file() ensures the safety of this operation by allowing only those files uploaded through PHP to be moved.

  1. rename nefunguje mezi disky (alespoň na Windows – já mám třeba php na C a data na D)
  2. pouze copy a unlink je pomalé

Tzn. ideální postup je:
zkusit move_uploded_file – který nebude mít problém s oprávněními
poté zkusit rename – protože je nesrovnatelně rychlejší než copy, ale nefuguje mezi disky
poté zkusit copy a unlink – pomalé, ale funkční i mezi disky

David Grudl
Nette Core | 8227
+
0
-

Když tak nad tím přemýšlím – co by se stalo, kdyby tam bylo prostě jen move_uploaded_file()? Soubor by sice šlo přesunout jen jednou, ale vadí to něčemu?

Honza Kuchař
Člen | 1662
+
0
-

U normální uploadu to pravda skoro nedává smysl.
Ale u uploadu pomocí flashe (Uploadify nebo cokoli jiného) se ten soubor nejříve pošle na server, tam se musí přesunout do nějaké dočasné složky toho skriptu (->move()), protože PHP svoje uploadnute soubory maže. A poté až se nashromáždí všechny soubory v temp složce app se předá objekt HttpUploadedFile s již jednou přesunutým souborem užvateli a ten si zavolá podruhé ->move(). Jinak by musel uploader používat nějaký svůj objekt souboru, ale to mi připadá jako zbytečné, když má toto Nette přímo v sobě.

David Grudl
Nette Core | 8227
+
0
-

Rozumím.

Jelikož potřebuju mít před dalším vývojem stabilní verzi, tak jsem tam dal dočasně samotný move_uploaded_file() a pokusíme se najít nějaké řešení pro flash.

David Grudl
Nette Core | 8227
+
0
-

HttpUploadedFile nyní použije move_uploaded_file() nebo rename(). Podporu pro copy() a unlink() přidávat nechci, protože taková situace by na hostingu v podstatě nikdy nastat neměla.

Honza Kuchař
Člen | 1662
+
0
-

Takhle je to fajn. Protože nejdříve to přesune z C:/php/temp na D:/data/www/já_nevím_co (pomocí move_uploaded_file) a poté už přesouvám jen pomocí rename v rámci složek Nette aplikace. Takhle je to naprosto dostatečné. Díky!