Pokud v aplikaci máme nasazené automatické odhlašování uživatelů, tak se může stát, že k odhlášení dojde v době mezi stažením a odeslání formuláře. Slušností je do přihlašovacího formuláře doplnit do skrytých polí data, která uživatel vyplnil, aby je nemusel zadávat znovu. Pro skalární data to je triviální, pokud však formulář může obsahovat pole (případně víceúrovňová), dá se použít následující řešení:
<?php $process = $_POST; while (list($key, $val) = each($process)) { if (is_array($val)) { foreach ($val as $k => $v) { $process[$key . "[$k]"] = $v; } } else { echo '<input type="hidden" name="' . htmlspecialchars($key) . '" value="' . htmlspecialchars($val) . '" />' . "\n"; } } ?>
Podobně jako u vypnutí magic_quotes_gpc se nepoužívá rekurze, aby se zabránilo útočníkovi její přílišnou hloubkou shodit PHP. Tento kód je možné vložit do přihlašovacího formuláře.
Pokud formulář obsahoval i vložené soubory, je možné do skrytých polí vložit i jejich původní jméno, typ a obsah, tím se z nich ale stanou běžná POST data. Aby aplikace mohla transparentně pracovat s polem $_FILES, musí přihlašovací skript data do tohoto pole opět vložit:
<?php // zakódování foreach ($_FILES as $key => $val) { if ($val['error'] == UPLOAD_ERR_OK) { echo '<input type="hidden" name="_files[' . htmlspecialchars($key) . '][name]" value="' . htmlspecialchars($val['name']) . '" />' . "\n"; echo '<input type="hidden" name="_files[' . htmlspecialchars($key) . '][type]" value="' . htmlspecialchars($val['type']) . '" />' . "\n"; echo '<input type="hidden" name="_files[' . htmlspecialchars($key) . '][data]" value="' . base64_encode(file_get_contents($val['tmp_name'])) . '" />' . "\n"; } } // rozkódování foreach ($_POST['_files'] as $key => $val) { $data = base64_decode($val['data']); $_FILES[$key] = array( 'name' => $val['name'], 'type' => $val['type'], 'size' => strlen($data), 'tmp_name' => tempnam($_ENV["TEMP"], 'file'), 'error' => UPLOAD_ERR_OK, ); file_put_contents($_FILES[$key]['tmp_name'], $data); } ?>
Vzhledem ke značné režii (soubor se musí přenášet zpět k uživateli, navíc zakódovaný) bych toto řešení spíše nedoporučoval, velikost zakódovaných dat může navíc překročit post_max_size. Alternativně je možné soubor uložit do dočasného souboru na serveru a jeho jméno dát do formuláře a session proměnné – do session proměnné kvůli tomu, aby si uživatelé soubory nemohli vzájemně krást, do formuláře proto, aby byl ošetřen případ, kdy uživatel odešle víc formulářů v různých oknech. V adresáři, do kterého se soubory ukládají, je vhodné čas od času smazat staré soubory kvůli formulářům, které už nikdy nebyly odeslány. Pokud byste se pro jeden z těchto způsobů rozhodli, je potřeba mít na paměti rozličná omezení: jednak do adresáře $_ENV["TEMP"]
nemusí mít skript právo zápisu a hlavně takto vytvořený soubor nepůjde zpracovat funkcí move_uploaded_file.
Lepší je proto možná požádat uživatele o nové nahrání souborů:
<?php if ($_FILES) { echo "<fieldset><legend>Nahrajte prosím znovu tyto soubory:</legend>\n"; foreach ($_FILES as $key => $val) { echo htmlspecialchars($val['name']) . ' (' . round($val['size'] / 1024) . ' KiB): '; echo '<input type="file" name="' . htmlspecialchars($key) . '" />' . "\n"; } echo "</fieldset>\n"; } ?>
Všechna řešení by také bylo vhodné rozšířit o zpracování chybových stavů (u posledního způsobu se např. soubory, které nebyly vůbec nahrané, mohou skrýt ve stylu) a pamatovat na to, že i soubory mohou být nahrávané do pole ve tvaru $_FILES["soubor"]["tmp_name"] = array()
.
Diskuse je zrušena z důvodu spamu.