Skip to content

Commit

Permalink
Fix deprecated $php_errormsg in PHP 7.2
Browse files Browse the repository at this point in the history
From the PHP 8.0 migration guide (https://www.php.net/manual/de/migration80.incompatible.php):
    The track_errors ini directive has been removed.
    This means that php_errormsg is no longer available.
    The error_get_last() function may be used instead.

Also the documentation on $php_errormsg (https://www.php.net/manual/en/reserved.variables.phperrormsg.php) says:
    This feature has been DEPRECATED as of PHP 7.2.0.
    Relying on this feature is highly discouraged.
    Use error_get_last() instead.

The functions Horde_String::convertCharset and Horde_String::_pos are broken up
to assist in better testability and additional tests for the newly introduced
functions are added.

This commit breaks compatibility with PHP 5.6

Signed-off-by: Daniel Ziegenberg <[email protected]>
  • Loading branch information
ziegenberg committed Jan 16, 2022
1 parent c8ee322 commit 39c627e
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 27 deletions.
112 changes: 85 additions & 27 deletions lib/Horde/String.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ public static function convertCharset($input, $from, $to, $force = false)
return $input;
}

if(strlen($input) === 0) {
return $input;
}

return self::_convertCharset($input, $from, $to);
}

Expand Down Expand Up @@ -145,12 +149,7 @@ protected static function _convertCharset($input, $from, $to)

/* Try iconv with transliteration. */
if (Horde_Util::extensionExists('iconv')) {
unset($php_errormsg);
ini_set('track_errors', 1);
$out = @iconv($from, $to . '//TRANSLIT', $input);
$errmsg = isset($php_errormsg);
ini_restore('track_errors');
if (!$errmsg && $out !== false) {
if (($out = self::_convertCharsetIconv($input, $from, $to)) !== false) {
return $out;
}
}
Expand All @@ -170,6 +169,25 @@ protected static function _convertCharset($input, $from, $to)
return $input;
}

/**
* Internal function used to do charset transliteration with iconv.
*
* @param string $input See self::convertCharset().
* @param string $from See self::convertCharset().
* @param string $to See self::convertCharset().
*
* @return mixed The converted string, or false on error.
*/
protected static function _convertCharsetIconv(string $input, string $from, string $to): string
{
error_clear_last();
$out = @iconv($from, $to . '//TRANSLIT', $input);
if (is_null(error_get_last()) && $out !== false) {
return $out;
}
return false;
}

/**
* Makes a string lowercase.
*
Expand Down Expand Up @@ -488,37 +506,77 @@ protected static function _pos(
)
{
if (Horde_Util::extensionExists('mbstring')) {
unset($php_errormsg);
$track_errors = ini_set('track_errors', 1);
$ret = @call_user_func('mb_' . $func, $haystack, $needle, $offset, self::_mbstringCharset($charset));
ini_set('track_errors', $track_errors);
if (!isset($php_errormsg)) {
return $ret;
if (($out = @self::_posMbstring($haystack, $needle, $offset, $charset, $func)) !== false) {
return $out;
}
}

if (Horde_Util::extensionExists('intl')) {
unset($php_errormsg);
$track_errors = ini_set('track_errors', 1);
$ret = self::convertCharset(
@call_user_func(
'grapheme_' . $func,
self::convertCharset($haystack, $charset, 'UTF-8'),
self::convertCharset($needle, $charset, 'UTF-8'),
$offset
),
'UTF-8',
$charset
);
ini_set('track_errors', $track_errors);
if (!isset($php_errormsg)) {
return $ret;
if(($out = @self::_posIntl($haystack, $needle, $offset, $charset, $func)) !== false) {
return $out;
}
}

return $func($haystack, $needle, $offset);
}

/**
* Internal function to perform string position searches using mbstring.
*
* @param string $haystack See self::_pos
* @param string $needle See self::_pos
* @param integer $offset See self::_pos
* @param string $charset See self::_pos
* @param string $func See self::_pos
*
* @return mixed The position of occurrence, or false on error.
*/
protected static function _posMbstring(
$haystack, $needle, $offset, $charset, $func
)
{
error_clear_last();
$ret = @call_user_func('mb_' . $func, $haystack, $needle, $offset, self::_mbstringCharset($charset));
if (is_null(error_get_last())) {
return $ret;
}

return false;
}

/**
* Internal function to perform string position searches using intl.
*
* @param string $haystack See self::_pos
* @param string $needle See self::_pos
* @param integer $offset See self::_pos
* @param string $charset See self::_pos
* @param string $func See self::_pos
*
* @return mixed The position of occurrence, or false on error.
*/
protected static function _posIntl(
$haystack, $needle, $offset, $charset, $func
)
{
error_clear_last();
$ret = self::convertCharset(
@call_user_func(
'grapheme_' . $func,
self::convertCharset($haystack, $charset, 'UTF-8'),
self::convertCharset($needle, $charset, 'UTF-8'),
$offset
),
'UTF-8',
$charset
);
if (is_null(error_get_last())) {
return $ret;
}

return false;
}

/**
* Returns a string padded to a certain length with another string.
* This method behaves exactly like str_pad() but is multibyte safe.
Expand Down
26 changes: 26 additions & 0 deletions test/Horde/Util/Mock/String.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
/**
* Wrapper to test internal Horde_String methods.
*
* @author Daniel Ziegenberg <[email protected]>
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Util
*/
class Horde_Util_Mock_String extends Horde_String
{
public static function testConvertCharsetIconv(string $input, string $from, string $to)
{
return self::_convertCharsetIconv($input, $from, $to);
}

public static function testPosMbstring(string $haystack, string $needle, int $offset, string $charset, string $func)
{
return self::_posMbstring($haystack, $needle, $offset, $charset, $func);
}

public static function testPosIntl(string $haystack, string $needle, int $offset, string $charset, string $func)
{
return self::_posIntl($haystack, $needle, $offset, $charset, $func);
}
}
57 changes: 57 additions & 0 deletions test/Horde/Util/StringTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -731,4 +731,61 @@ public function invalidUtf8Provider()
);
}

/**
* @dataProvider ConvertCharsetIconvProvider
*/
public function testConvertCharsetIconv(string $input, string $from, string $to, $expected): void
{
$this->assertEquals(
$expected,
Horde_Util_Mock_String::testConvertCharsetIconv($input, $from, $to)
);
}

public function ConvertCharsetIconvProvider()
{
return [
'valid character sequence' => ['This will work.', 'UTF-8', 'ISO-8859-1', 'This will work.'],
'illegal character in input string' => ["This is the Euro symbol '€'.", 'UTF-8', 'ISO-8859-1', false]
];
}

/**
* @dataProvider posMbstringProvider
*/
public function testPosMbstring(string $haystack, string $needle, int $offset, string $charset, string $func, $expected): void
{
$this->assertEquals(
$expected,
Horde_Util_Mock_String::testPosMbstring($haystack, $needle, $offset, $charset, $func)
);
}

public function posMbstringProvider()
{
return [
'valid character sequence' => ['Some random string.', 'Some', 0, 'UTF-8', 'strpos', 0],
'invalid search offset' => ['Some random string', 'Some', 50, 'UTF-8', 'strpos', false]
];
}

/**
* @dataProvider posIntlProvider
*/
public function testPosIntl(string $haystack, string $needle, int $offset, string $charset, string $func, $expected): void
{
$this->assertEquals(
$expected,
Horde_Util_Mock_String::testPosIntl($haystack, $needle, $offset, $charset, $func)
);
}

public function posIntlProvider()
{
return [
'valid character sequence' => ['Some random string.', 'Some', 0, 'UTF-8', 'strpos', 0],
'invalid search offset' => ['Some random string', 'Some', 50, 'UTF-8', 'strpos', false]
];
}

}

0 comments on commit 39c627e

Please sign in to comment.