testIconvTruncateBug() public static méthode

glibc iconv has a known bug where it doesn't handle the magic IGNORE stanza correctly. In particular, rather than ignore characters, it will return an EILSEQ after consuming some number of characters, and expect you to restart iconv as if it were an E2BIG. Old versions of PHP did not respect the errno, and returned the fragment, so as a result you would see iconv mysteriously truncating output. We can work around this by manually chopping our input into segments of about 8000 characters, as long as PHP ignores the error code. If PHP starts paying attention to the error code, iconv becomes unusable.
public static testIconvTruncateBug ( ) : integer
Résultat integer Error code indicating severity of bug.
 /**
  * Convert a string to UTF-8 based on configuration.
  * @param string $str The string to convert
  * @param HTMLPurifier_Config $config
  * @param HTMLPurifier_Context $context
  * @return string
  */
 public static function convertToUTF8($str, $config, $context)
 {
     $encoding = $config->get('Core.Encoding');
     if ($encoding === 'utf-8') {
         return $str;
     }
     static $iconv = null;
     if ($iconv === null) {
         $iconv = self::iconvAvailable();
     }
     if ($iconv && !$config->get('Test.ForceNoIconv')) {
         // unaffected by bugs, since UTF-8 support all characters
         $str = self::unsafeIconv($encoding, 'utf-8//IGNORE', $str);
         if ($str === false) {
             // $encoding is not a valid encoding
             trigger_error('Invalid encoding ' . $encoding, E_USER_ERROR);
             return '';
         }
         // If the string is bjorked by Shift_JIS or a similar encoding
         // that doesn't support all of ASCII, convert the naughty
         // characters to their true byte-wise ASCII/UTF-8 equivalents.
         $str = strtr($str, self::testEncodingSupportsASCII($encoding));
         return $str;
     } elseif ($encoding === 'iso-8859-1') {
         $str = utf8_encode($str);
         return $str;
     }
     $bug = HTMLPurifier_Encoder::testIconvTruncateBug();
     if ($bug == self::ICONV_OK) {
         trigger_error('Encoding not supported, please install iconv', E_USER_ERROR);
     } else {
         trigger_error('You have a buggy version of iconv, see https://bugs.php.net/bug.php?id=48147 ' . 'and http://sourceware.org/bugzilla/show_bug.cgi?id=13541', E_USER_ERROR);
     }
 }
 /**
  * Calculates the result of this requirement.
  *
  * @return string
  */
 protected function calculateResult()
 {
     if (function_exists('iconv')) {
         // See if it's the buggy version
         if (\HTMLPurifier_Encoder::testIconvTruncateBug() != \HTMLPurifier_Encoder::ICONV_OK) {
             return RequirementResult::Warning;
         } else {
             return RequirementResult::Success;
         }
     } else {
         return RequirementResult::Failed;
     }
 }
Exemple #3
0
 /**
  * Returns whether iconv is installed and not buggy.
  *
  * @return bool
  */
 public static function checkForIconv()
 {
     if (!isset(static::$_iconv)) {
         // Check if iconv is installed. Note we can't just use HTMLPurifier_Encoder::iconvAvailable() because they
         // don't consider iconv "installed" if it's there but "unusable".
         if (function_exists('iconv') && \HTMLPurifier_Encoder::testIconvTruncateBug() === \HTMLPurifier_Encoder::ICONV_OK) {
             static::$_iconv = true;
         } else {
             static::$_iconv = false;
         }
     }
     return static::$_iconv;
 }
Exemple #4
0
 public function testIconvChunking()
 {
     if (!HTMLPurifier_Encoder::iconvAvailable()) {
         return;
     }
     if (HTMLPurifier_Encoder::testIconvTruncateBug() !== HTMLPurifier_Encoder::ICONV_TRUNCATES) {
         return;
     }
     $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aó € b", 4), 'ab');
     $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aa中b", 4), 'aab');
     $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaaαb", 4), 'aaab');
     $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaaaó € b", 4), 'aaaab');
     $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaaa中b", 4), 'aaaab');
     $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aaaaαb", 4), 'aaaab');
 }
Exemple #5
0
 /**
  * Returns whether iconv is installed and not buggy.
  *
  * @return bool
  */
 public static function checkForIconv()
 {
     if (!isset(static::$_iconv)) {
         static::$_iconv = false;
         // Check if iconv is installed. Note we can't just use HTMLPurifier_Encoder::iconvAvailable() because they
         // don't consider iconv "installed" if it's there but "unusable".
         if (!function_exists('iconv')) {
             Craft::log('iconv is not installed.  Will fallback to mbstring.', LogLevel::Warning);
         } else {
             if (\HTMLPurifier_Encoder::testIconvTruncateBug() != \HTMLPurifier_Encoder::ICONV_OK) {
                 Craft::log('Buggy iconv installed.  Will fallback to mbstring.', LogLevel::Warning);
             } else {
                 static::$_iconv = true;
             }
         }
     }
     return static::$_iconv;
 }
 public static function convertToUTF8($str, $config, $context)
 {
     $encoding = $config->get('Core.Encoding');
     if ($encoding === 'utf-8') {
         return $str;
     }
     static $iconv = null;
     if ($iconv === null) {
         $iconv = self::iconvAvailable();
     }
     if ($iconv && !$config->get('Test.ForceNoIconv')) {
         $str = self::unsafeIconv($encoding, 'utf-8//IGNORE', $str);
         if ($str === false) {
             trigger_error('Invalid encoding ' . $encoding, E_USER_ERROR);
             return '';
         }
         $str = strtr($str, self::testEncodingSupportsASCII($encoding));
         return $str;
     } elseif ($encoding === 'iso-8859-1') {
         $str = utf8_encode($str);
         return $str;
     }
     $bug = HTMLPurifier_Encoder::testIconvTruncateBug();
     if ($bug == self::ICONV_OK) {
         trigger_error('Encoding not supported, please install iconv', E_USER_ERROR);
     } else {
         trigger_error('You have a buggy version of iconv, see https://bugs.php.net/bug.php?id=48147 ' . 'and http://sourceware.org/bugzilla/show_bug.cgi?id=13541', E_USER_ERROR);
     }
 }