From 93262d83c940f87c961ce381645df04aa4ab992e Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Sun, 19 Apr 2026 17:35:05 -0400 Subject: [PATCH 1/2] fix: Restore original behavior of getInfo() for 'file" variable type --- lib/Horde/Form/Type.php | 26 ++++++++++++++------------ src/V3/FileVariable.php | 25 +++++++++++++------------ 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/lib/Horde/Form/Type.php b/lib/Horde/Form/Type.php index 8d6bc76..66a3e9a 100644 --- a/lib/Horde/Form/Type.php +++ b/lib/Horde/Form/Type.php @@ -1180,23 +1180,25 @@ public function isValid($var, $vars, $value, $message) public function getInfo($vars, $var, $info) { - $info = []; $name = $var->getVarName(); try { $GLOBALS['browser']->wasFileUploaded($name); - /** - * WARNING: Horde_Util::dispelMagicQuotes() removed in PSR-4 version - * Magic quotes are obsolete in PHP 8+. Remove this call. - */ -$info['name'] = Horde_Util::dispelMagicQuotes($_FILES[$name]['name']); - $info['type'] = $_FILES[$name]['type']; - $info['tmp_name'] = $_FILES[$name]['tmp_name']; - $info['file'] = $_FILES[$name]['tmp_name']; - $info['error'] = $_FILES[$name]['error']; - $info['size'] = $_FILES[$name]['size']; + return [ + /** + * WARNING: Horde_Util::dispelMagicQuotes() removed in PSR-4 version + * Magic quotes are obsolete in PHP 8+. Remove this call. + */ + 'name' => Horde_Util::dispelMagicQuotes($_FILES[$name]['name']), + 'type' => $_FILES[$name]['type'], + 'tmp_name' => $_FILES[$name]['tmp_name'], + 'file' => $_FILES[$name]['tmp_name'], + 'error' => $_FILES[$name]['error'], + 'size' => $_FILES[$name]['size'], + ]; } catch (Horde_Browser_Exception $e) { } - return $info; + + return null; } /** diff --git a/src/V3/FileVariable.php b/src/V3/FileVariable.php index 2ce1666..ed326ba 100644 --- a/src/V3/FileVariable.php +++ b/src/V3/FileVariable.php @@ -48,24 +48,25 @@ public function isValid(Horde_Variables $vars, $value): bool //TODO: Rename back to getInfo() after the V3 transition protected function getInfoV3($vars) { - $info = []; $name = $this->getVarName(); try { $GLOBALS['browser']->wasFileUploaded($name); - /** - * WARNING: Horde_Util::dispelMagicQuotes() removed in PSR-4 version - * Magic quotes are obsolete in PHP 8+. Remove this call. - */ -$info['name'] = Horde_Util::dispelMagicQuotes($_FILES[$name]['name']); - $info['type'] = $_FILES[$name]['type']; - $info['tmp_name'] = $_FILES[$name]['tmp_name']; - $info['file'] = $_FILES[$name]['tmp_name']; - $info['error'] = $_FILES[$name]['error']; - $info['size'] = $_FILES[$name]['size']; + return [ + /** + * WARNING: Horde_Util::dispelMagicQuotes() removed in PSR-4 version + * Magic quotes are obsolete in PHP 8+. Remove this call. + */ + 'name' => Horde_Util::dispelMagicQuotes($_FILES[$name]['name']), + 'type' => $_FILES[$name]['type'], + 'tmp_name' => $_FILES[$name]['tmp_name'], + 'file' => $_FILES[$name]['tmp_name'], + 'error' => $_FILES[$name]['error'], + 'size' => $_FILES[$name]['size'], + ]; } catch (Horde_Browser_Exception $e) { } - return $info; + return null; } /** From 3664ff0e013c1ffcdaf9e49e6668b4ecbfda5005 Mon Sep 17 00:00:00 2001 From: Ralf Lang Date: Mon, 20 Apr 2026 11:05:50 +0200 Subject: [PATCH 2/2] test: Add regression test against the File behaviour change Previously we handled empty upload and no upload the same way. This handles 93262d8 aka 3828e85 from Dmitry's PR horde/form#24 which we cherry-picked --- test/stubs/HordeStubs.php | 16 ++++ test/unit/Type/FileTypeTest.php | 140 ++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 test/unit/Type/FileTypeTest.php diff --git a/test/stubs/HordeStubs.php b/test/stubs/HordeStubs.php index 7189da1..1bd8ce9 100644 --- a/test/stubs/HordeStubs.php +++ b/test/stubs/HordeStubs.php @@ -144,6 +144,22 @@ class Horde_Form_Translation extends Horde_Translation_Autodetect class Horde_Exception extends Exception {} } +// Horde_Browser_Exception stub +if (!class_exists('Horde_Browser_Exception')) { + class Horde_Browser_Exception extends Exception {} +} + +// Horde_Util stub +if (!class_exists('Horde_Util')) { + class Horde_Util + { + public static function dispelMagicQuotes($input) + { + return $input; + } + } +} + // PEAR stub for legacy error handling if (!class_exists('PEAR')) { class PEAR diff --git a/test/unit/Type/FileTypeTest.php b/test/unit/Type/FileTypeTest.php new file mode 100644 index 0000000..de765d3 --- /dev/null +++ b/test/unit/Type/FileTypeTest.php @@ -0,0 +1,140 @@ +hasFile) { + throw new Horde_Browser_Exception('No file uploaded'); + } + } + }; + } + + protected function tearDown(): void + { + unset($GLOBALS['browser']); + } + + // ======================================================================== + // Legacy Horde_Form_Type_file tests + // ======================================================================== + + public function testLegacyGetInfoReturnsNullWhenNoFileUploaded(): void + { + $GLOBALS['browser'] = $this->makeBrowserStub(false); + + $type = new Horde_Form_Type_file(); + $var = new Horde_Form_Variable('Upload', 'upload_field', $type, false); + $vars = new Horde_Variables([]); + + $result = $type->getInfo($vars, $var, null); + + $this->assertNull($result); + } + + public function testLegacyGetInfoReturnsFileArrayOnUpload(): void + { + $GLOBALS['browser'] = $this->makeBrowserStub(true); + $_FILES['upload_field'] = [ + 'name' => 'test.pdf', + 'type' => 'application/pdf', + 'tmp_name' => '/tmp/php1234', + 'error' => 0, + 'size' => 12345, + ]; + + $type = new Horde_Form_Type_file(); + $var = new Horde_Form_Variable('Upload', 'upload_field', $type, false); + $vars = new Horde_Variables([]); + + $result = $type->getInfo($vars, $var, null); + + $this->assertIsArray($result); + $this->assertSame('test.pdf', $result['name']); + $this->assertSame('application/pdf', $result['type']); + $this->assertSame('/tmp/php1234', $result['tmp_name']); + $this->assertSame('/tmp/php1234', $result['file']); + $this->assertSame(0, $result['error']); + $this->assertSame(12345, $result['size']); + + unset($_FILES['upload_field']); + } + + // ======================================================================== + // V3 FileVariable tests + // ======================================================================== + + public function testV3GetInfoReturnsNullWhenNoFileUploaded(): void + { + $GLOBALS['browser'] = $this->makeBrowserStub(false); + + $var = new FileVariable('Upload', 'upload_field', false); + $vars = new Horde_Variables([]); + + $result = $var->getInfo($vars); + + $this->assertNull($result); + } + + public function testV3GetInfoReturnsFileArrayOnUpload(): void + { + $GLOBALS['browser'] = $this->makeBrowserStub(true); + $_FILES['upload_field'] = [ + 'name' => 'report.xlsx', + 'type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'tmp_name' => '/tmp/php5678', + 'error' => 0, + 'size' => 98765, + ]; + + $var = new FileVariable('Upload', 'upload_field', false); + $vars = new Horde_Variables([]); + + $result = $var->getInfo($vars); + + $this->assertIsArray($result); + $this->assertSame('report.xlsx', $result['name']); + $this->assertSame('/tmp/php5678', $result['tmp_name']); + $this->assertSame('/tmp/php5678', $result['file']); + $this->assertSame(0, $result['error']); + $this->assertSame(98765, $result['size']); + + unset($_FILES['upload_field']); + } +}