Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

utf_tools.php

Zuletzt modifiziert: 02.04.2025, 15:01 - Dateigröße: 40.73 KiB


0001  <?php
0002  /**
0003  *
0004  * This file is part of the phpBB Forum Software package.
0005  *
0006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007  * @license GNU General Public License, version 2 (GPL-2.0)
0008  *
0009  * For full copyright and license information, please see
0010  * the docs/CREDITS.txt file.
0011  *
0012  */
0013   
0014  /**
0015  */
0016  if (!defined('IN_PHPBB'))
0017  {
0018      exit;
0019  }
0020   
0021  // Enforce ASCII only string handling
0022  setlocale(LC_CTYPE, 'C');
0023   
0024  /**
0025   * UTF-8 portability layer is provided by
0026   * symfony/polyfill-mbstring, symfony/polyfill-intl-normalizer, symfony/polyfill-php72
0027   */
0028   
0029  /**
0030  * UTF-8 tools
0031  *
0032  * Whenever possible, these functions will try to use PHP's built-in functions or
0033  * extensions, otherwise they will default to custom routines.
0034  *
0035  */
0036   
0037  /**
0038  * UTF-8 aware alternative to strrpos
0039  * @ignore
0040  */
0041  function utf8_strrpos($str,    $needle, $offset = null)
0042  {
0043      // Emulate behaviour of strrpos rather than raising warning
0044      if (empty($str))
0045      {
0046          return false;
0047      }
0048   
0049      if (is_null($offset))
0050      {
0051          return mb_strrpos($str, $needle);
0052      }
0053      else
0054      {
0055          return mb_strrpos($str, $needle, $offset);
0056      }
0057  }
0058   
0059  /**
0060  * UTF-8 aware alternative to strpos
0061  * @ignore
0062  */
0063  function utf8_strpos($str, $needle, $offset = null)
0064  {
0065      if (is_null($offset))
0066      {
0067          return mb_strpos($str, $needle);
0068      }
0069      else
0070      {
0071          return mb_strpos($str, $needle, $offset);
0072      }
0073  }
0074   
0075  /**
0076  * UTF-8 aware alternative to stripos
0077  * @ignore
0078  */
0079  function utf8_stripos($str, $needle, $offset = null)
0080  {
0081      if (is_null($offset))
0082      {
0083          return mb_stripos($str, $needle);
0084      }
0085      else
0086      {
0087          return mb_stripos($str, $needle, $offset);
0088      }
0089  }
0090   
0091  /**
0092  * UTF-8 aware alternative to strtolower
0093  * @ignore
0094  */
0095  function utf8_strtolower($str)
0096  {
0097      return mb_strtolower($str);
0098  }
0099   
0100  /**
0101  * UTF-8 aware alternative to strtoupper
0102  * @ignore
0103  */
0104  function utf8_strtoupper($str)
0105  {
0106      return mb_strtoupper($str);
0107  }
0108   
0109  /**
0110  * UTF-8 aware alternative to substr
0111  * @ignore
0112  */
0113  function utf8_substr($str, $offset, $length = null)
0114  {
0115      if (is_null($length))
0116      {
0117          return mb_substr($str, $offset);
0118      }
0119      else
0120      {
0121          return mb_substr($str, $offset, $length);
0122      }
0123  }
0124   
0125  /**
0126  * Return the length (in characters) of a UTF-8 string
0127  * @ignore
0128  */
0129  function utf8_strlen($text)
0130  {
0131      return mb_strlen($text, 'utf-8');
0132  }
0133   
0134  /**
0135  * UTF-8 aware alternative to str_split
0136  * Convert a string to an array
0137  *
0138  * @author Harry Fuecks
0139  * @param string $str UTF-8 encoded
0140  * @param int $split_len number to characters to split string by
0141  * @return array characters in string reverses
0142  */
0143  function utf8_str_split($str, $split_len = 1)
0144  {
0145      if (!is_int($split_len) || $split_len < 1)
0146      {
0147          return false;
0148      }
0149   
0150      $len = utf8_strlen($str);
0151      if ($len <= $split_len)
0152      {
0153          return array($str);
0154      }
0155   
0156      preg_match_all('/.{' . $split_len . '}|[^\x00]{1,' . $split_len . '}$/us', $str, $ar);
0157      return $ar[0];
0158  }
0159   
0160  /**
0161  * UTF-8 aware alternative to strspn
0162  * Find length of initial segment matching the mask
0163  *
0164  * @author Harry Fuecks
0165  */
0166  function utf8_strspn($str, $mask, $start = null, $length = null)
0167  {
0168      if ($start !== null || $length !== null)
0169      {
0170          $str = utf8_substr($str, $start, $length);
0171      }
0172   
0173      preg_match('/^[' . $mask . ']+/u', $str, $matches);
0174   
0175      if (isset($matches[0]))
0176      {
0177          return utf8_strlen($matches[0]);
0178      }
0179   
0180      return 0;
0181  }
0182   
0183  /**
0184  * UTF-8 aware alternative to ucfirst
0185  * Make a string's first character uppercase
0186  *
0187  * @author Harry Fuecks
0188  * @param string $str
0189  * @return string with first character as upper case (if applicable)
0190  */
0191  function utf8_ucfirst($str)
0192  {
0193      switch (utf8_strlen($str))
0194      {
0195          case 0:
0196              return '';
0197          break;
0198   
0199          case 1:
0200              return utf8_strtoupper($str);
0201          break;
0202   
0203          default:
0204              preg_match('/^(.{1})(.*)$/us', $str, $matches);
0205              return utf8_strtoupper($matches[1]) . $matches[2];
0206          break;
0207      }
0208  }
0209   
0210  /**
0211  * Recode a string to UTF-8
0212  *
0213  * If the encoding is not supported, the string is returned as-is
0214  *
0215  * @param    string    $string        Original string
0216  * @param    string    $encoding    Original encoding (lowered)
0217  * @return    string                The string, encoded in UTF-8
0218  */
0219  function utf8_recode($string, $encoding)
0220  {
0221      $encoding = strtolower($encoding);
0222   
0223      if ($encoding == 'utf-8' || !is_string($string) || empty($string))
0224      {
0225          return $string;
0226      }
0227   
0228      // we force iso-8859-1 to be cp1252
0229      if ($encoding == 'iso-8859-1')
0230      {
0231          $encoding = 'cp1252';
0232      }
0233      // convert iso-8859-8-i to iso-8859-8
0234      else if ($encoding == 'iso-8859-8-i')
0235      {
0236          $encoding = 'iso-8859-8';
0237          $string = hebrev($string);
0238      }
0239   
0240      // First, try iconv()
0241      if (function_exists('iconv'))
0242      {
0243          $ret = @iconv($encoding, 'utf-8', $string);
0244   
0245          if (!empty($ret))
0246          {
0247              return $ret;
0248          }
0249      }
0250   
0251      // Try the mb_string extension
0252      if (function_exists('mb_convert_encoding'))
0253      {
0254          // mbstring is nasty on PHP4, we must make *sure* that we send a good encoding
0255          switch ($encoding)
0256          {
0257              case 'iso-8859-1':
0258              case 'iso-8859-2':
0259              case 'iso-8859-4':
0260              case 'iso-8859-7':
0261              case 'iso-8859-9':
0262              case 'iso-8859-15':
0263              case 'windows-1251':
0264              case 'windows-1252':
0265              case 'cp1252':
0266              case 'shift_jis':
0267              case 'euc-kr':
0268              case 'big5':
0269              case 'gb2312':
0270                  $ret = @mb_convert_encoding($string, 'utf-8', $encoding);
0271   
0272                  if (!empty($ret))
0273                  {
0274                      return $ret;
0275                  }
0276          }
0277      }
0278   
0279      // Try the recode extension
0280      if (function_exists('recode_string'))
0281      {
0282          $ret = @recode_string($encoding . '..utf-8', $string);
0283   
0284          if (!empty($ret))
0285          {
0286              return $ret;
0287          }
0288      }
0289   
0290      // If nothing works, check if we have a custom transcoder available
0291      if (!preg_match('#^[a-z0-9_ \\-]+$#', $encoding))
0292      {
0293          // Make sure the encoding name is alphanumeric, we don't want it to be abused into loading arbitrary files
0294          trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR);
0295      }
0296   
0297      global $phpbb_root_path, $phpEx;
0298   
0299      // iso-8859-* character encoding
0300      if (preg_match('/iso[_ -]?8859[_ -]?(\\d+)/', $encoding, $array))
0301      {
0302          switch ($array[1])
0303          {
0304              case '1':
0305              case '2':
0306              case '4':
0307              case '7':
0308              case '8':
0309              case '9':
0310              case '15':
0311                  if (!function_exists('iso_8859_' . $array[1]))
0312                  {
0313                      if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx))
0314                      {
0315                          trigger_error('Basic reencoder file is missing', E_USER_ERROR);
0316                      }
0317                      include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx);
0318                  }
0319                  return call_user_func('iso_8859_' . $array[1], $string);
0320              break;
0321   
0322              default:
0323                  trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR);
0324              break;
0325          }
0326      }
0327   
0328      // CP/WIN character encoding
0329      if (preg_match('/(?:cp|windows)[_\- ]?(\\d+)/', $encoding, $array))
0330      {
0331          switch ($array[1])
0332          {
0333              case '932':
0334              break;
0335              case '1250':
0336              case '1251':
0337              case '1252':
0338              case '1254':
0339              case '1255':
0340              case '1256':
0341              case '1257':
0342              case '874':
0343                  if (!function_exists('cp' . $array[1]))
0344                  {
0345                      if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx))
0346                      {
0347                          trigger_error('Basic reencoder file is missing', E_USER_ERROR);
0348                      }
0349                      include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx);
0350                  }
0351                  return call_user_func('cp' . $array[1], $string);
0352              break;
0353   
0354              default:
0355                  trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR);
0356              break;
0357          }
0358      }
0359   
0360      // TIS-620
0361      if (preg_match('/tis[_ -]?620/', $encoding))
0362      {
0363          if (!function_exists('tis_620'))
0364          {
0365              if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx))
0366              {
0367                  trigger_error('Basic reencoder file is missing', E_USER_ERROR);
0368              }
0369              include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx);
0370          }
0371          return tis_620($string);
0372      }
0373   
0374      // SJIS
0375      if (preg_match('/sjis(?:[_ -]?win)?|(?:cp|ibm)[_ -]?932|shift[_ -]?jis/', $encoding))
0376      {
0377          if (!function_exists('sjis'))
0378          {
0379              if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx))
0380              {
0381                  trigger_error('CJK reencoder file is missing', E_USER_ERROR);
0382              }
0383              include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx);
0384          }
0385          return sjis($string);
0386      }
0387   
0388      // EUC_KR
0389      if (preg_match('/euc[_ -]?kr/', $encoding))
0390      {
0391          if (!function_exists('euc_kr'))
0392          {
0393              if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx))
0394              {
0395                  trigger_error('CJK reencoder file is missing', E_USER_ERROR);
0396              }
0397              include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx);
0398          }
0399          return euc_kr($string);
0400      }
0401   
0402      // BIG-5
0403      if (preg_match('/big[_ -]?5/', $encoding))
0404      {
0405          if (!function_exists('big5'))
0406          {
0407              if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx))
0408              {
0409                  trigger_error('CJK reencoder file is missing', E_USER_ERROR);
0410              }
0411              include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx);
0412          }
0413          return big5($string);
0414      }
0415   
0416      // GB2312
0417      if (preg_match('/gb[_ -]?2312/', $encoding))
0418      {
0419          if (!function_exists('gb2312'))
0420          {
0421              if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx))
0422              {
0423                  trigger_error('CJK reencoder file is missing', E_USER_ERROR);
0424              }
0425              include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx);
0426          }
0427          return gb2312($string);
0428      }
0429   
0430      // Trigger an error?! Fow now just give bad data :-(
0431      trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR);
0432  }
0433   
0434  /**
0435   * Replace some special UTF-8 chars that are not in ASCII with their UCR.
0436   * using their Numeric Character Reference's Hexadecimal notation.
0437   *
0438   * Doesn't interfere with Japanese or Cyrillic etc.
0439   * Unicode character visualization will depend on the character support
0440   * of your web browser and the fonts installed on your system.
0441   *
0442   * @see https://en.wikibooks.org/wiki/Unicode/Character_reference/1F000-1FFFF
0443   *
0444   * @param    string    $text        UTF-8 string in NFC
0445   * @return    string                ASCII string using NCR for non-ASCII chars
0446   */
0447  function utf8_encode_ucr($text)
0448  {
0449      return preg_replace_callback('/[\\xF0-\\xF4].../', 'utf8_encode_ncr_callback', $text);
0450  }
0451   
0452  /**
0453   * Replace all UTF-8 chars that are not in ASCII with their NCR
0454   * using their Numeric Character Reference's Hexadecimal notation.
0455   *
0456   * @param    string    $text        UTF-8 string in NFC
0457   * @return    string                ASCII string using NCRs for non-ASCII chars
0458   */
0459  function utf8_encode_ncr($text)
0460  {
0461      return preg_replace_callback('#[\\xC2-\\xF4][\\x80-\\xBF]{1,3}#', 'utf8_encode_ncr_callback', $text);
0462  }
0463   
0464  /**
0465   * Callback used in utf8_encode_ncr() and utf8_encode_ucr()
0466   *
0467   * Takes a UTF-8 char and replaces it with its NCR. Attention, $m is an array
0468   *
0469   * @param    array    $m            0-based numerically indexed array passed by preg_replace_callback()
0470   * @return    string                A HTML NCR if the character is valid, or the original string otherwise
0471   */
0472  function utf8_encode_ncr_callback($m)
0473  {
0474      return '&#' . utf8_ord($m[0]) . ';';
0475  }
0476   
0477  /**
0478  * Converts a UTF-8 char to an NCR
0479  *
0480  * @param string $chr UTF-8 char
0481  * @return integer UNICODE code point
0482  */
0483  function utf8_ord($chr)
0484  {
0485      switch (strlen($chr))
0486      {
0487          case 1:
0488              return ord($chr);
0489          break;
0490   
0491          case 2:
0492              return ((ord($chr[0]) & 0x1F) << 6) | (ord($chr[1]) & 0x3F);
0493          break;
0494   
0495          case 3:
0496              return ((ord($chr[0]) & 0x0F) << 12) | ((ord($chr[1]) & 0x3F) << 6) | (ord($chr[2]) & 0x3F);
0497          break;
0498   
0499          case 4:
0500              return ((ord($chr[0]) & 0x07) << 18) | ((ord($chr[1]) & 0x3F) << 12) | ((ord($chr[2]) & 0x3F) << 6) | (ord($chr[3]) & 0x3F);
0501          break;
0502   
0503          default:
0504              return $chr;
0505      }
0506  }
0507   
0508  /**
0509  * Converts an NCR to a UTF-8 char
0510  *
0511  * @param    int        $cp    UNICODE code point
0512  * @return    string        UTF-8 char
0513  */
0514  function utf8_chr($cp)
0515  {
0516      if ($cp > 0xFFFF)
0517      {
0518          return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
0519      }
0520      else if ($cp > 0x7FF)
0521      {
0522          return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
0523      }
0524      else if ($cp > 0x7F)
0525      {
0526          return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F));
0527      }
0528      else
0529      {
0530          return chr($cp);
0531      }
0532  }
0533   
0534  /**
0535  * Convert Numeric Character References to UTF-8 chars
0536  *
0537  * Notes:
0538  *    - we do not convert NCRs recursively, if you pass &#38;#38; it will return &#38;
0539  *    - we DO NOT check for the existence of the Unicode characters, therefore an entity may be converted to an inexistent codepoint
0540  *
0541  * @param    string    $text        String to convert, encoded in UTF-8 (no normal form required)
0542  * @return    string                UTF-8 string where NCRs have been replaced with the actual chars
0543  */
0544  function utf8_decode_ncr($text)
0545  {
0546      return preg_replace_callback('/&#([0-9]{1,6}|x[0-9A-F]{1,5});/i', 'utf8_decode_ncr_callback', $text);
0547  }
0548   
0549  /**
0550  * Callback used in decode_ncr()
0551  *
0552  * Takes a NCR (in decimal or hexadecimal) and returns a UTF-8 char. Attention, $m is an array.
0553  * It will ignore most of invalid NCRs, but not all!
0554  *
0555  * @param    array    $m            0-based numerically indexed array passed by preg_replace_callback()
0556  * @return    string                UTF-8 char
0557  */
0558  function utf8_decode_ncr_callback($m)
0559  {
0560      $cp = (strncasecmp($m[1], 'x', 1)) ? $m[1] : hexdec(substr($m[1], 1));
0561   
0562      return utf8_chr($cp);
0563  }
0564   
0565  /**
0566  * Case folds a unicode string as per Unicode 5.0, section 3.13
0567  *
0568  * @param    string    $text    text to be case folded
0569  * @param    string    $option    determines how we will fold the cases
0570  * @return    string            case folded text
0571  */
0572  function utf8_case_fold($text, $option = 'full')
0573  {
0574      static $uniarray = array();
0575      global $phpbb_root_path, $phpEx;
0576   
0577      // common is always set
0578      if (!isset($uniarray['c']))
0579      {
0580          $uniarray['c'] = include($phpbb_root_path . 'includes/utf/data/case_fold_c.' . $phpEx);
0581      }
0582   
0583      // only set full if we need to
0584      if ($option === 'full' && !isset($uniarray['f']))
0585      {
0586          $uniarray['f'] = include($phpbb_root_path . 'includes/utf/data/case_fold_f.' . $phpEx);
0587      }
0588   
0589      // only set simple if we need to
0590      if ($option !== 'full' && !isset($uniarray['s']))
0591      {
0592          $uniarray['s'] = include($phpbb_root_path . 'includes/utf/data/case_fold_s.' . $phpEx);
0593      }
0594   
0595      // common is always replaced
0596      $text = strtr($text, $uniarray['c']);
0597   
0598      if ($option === 'full')
0599      {
0600          // full replaces a character with multiple characters
0601          $text = strtr($text, $uniarray['f']);
0602      }
0603      else
0604      {
0605          // simple replaces a character with another character
0606          $text = strtr($text, $uniarray['s']);
0607      }
0608   
0609      return $text;
0610  }
0611   
0612  /**
0613  * Takes the input and does a "special" case fold. It does minor normalization
0614  * and returns NFKC compatable text
0615  *
0616  * @param    string    $text    text to be case folded
0617  * @param    string    $option    determines how we will fold the cases
0618  * @return    string            case folded text
0619  */
0620  function utf8_case_fold_nfkc($text, $option = 'full')
0621  {
0622      static $fc_nfkc_closure = array(
0623          "\xCD\xBA"    => "\x20\xCE\xB9",
0624          "\xCF\x92"    => "\xCF\x85",
0625          "\xCF\x93"    => "\xCF\x8D",
0626          "\xCF\x94"    => "\xCF\x8B",
0627          "\xCF\xB2"    => "\xCF\x83",
0628          "\xCF\xB9"    => "\xCF\x83",
0629          "\xE1\xB4\xAC"    => "\x61",
0630          "\xE1\xB4\xAD"    => "\xC3\xA6",
0631          "\xE1\xB4\xAE"    => "\x62",
0632          "\xE1\xB4\xB0"    => "\x64",
0633          "\xE1\xB4\xB1"    => "\x65",
0634          "\xE1\xB4\xB2"    => "\xC7\x9D",
0635          "\xE1\xB4\xB3"    => "\x67",
0636          "\xE1\xB4\xB4"    => "\x68",
0637          "\xE1\xB4\xB5"    => "\x69",
0638          "\xE1\xB4\xB6"    => "\x6A",
0639          "\xE1\xB4\xB7"    => "\x6B",
0640          "\xE1\xB4\xB8"    => "\x6C",
0641          "\xE1\xB4\xB9"    => "\x6D",
0642          "\xE1\xB4\xBA"    => "\x6E",
0643          "\xE1\xB4\xBC"    => "\x6F",
0644          "\xE1\xB4\xBD"    => "\xC8\xA3",
0645          "\xE1\xB4\xBE"    => "\x70",
0646          "\xE1\xB4\xBF"    => "\x72",
0647          "\xE1\xB5\x80"    => "\x74",
0648          "\xE1\xB5\x81"    => "\x75",
0649          "\xE1\xB5\x82"    => "\x77",
0650          "\xE2\x82\xA8"    => "\x72\x73",
0651          "\xE2\x84\x82"    => "\x63",
0652          "\xE2\x84\x83"    => "\xC2\xB0\x63",
0653          "\xE2\x84\x87"    => "\xC9\x9B",
0654          "\xE2\x84\x89"    => "\xC2\xB0\x66",
0655          "\xE2\x84\x8B"    => "\x68",
0656          "\xE2\x84\x8C"    => "\x68",
0657          "\xE2\x84\x8D"    => "\x68",
0658          "\xE2\x84\x90"    => "\x69",
0659          "\xE2\x84\x91"    => "\x69",
0660          "\xE2\x84\x92"    => "\x6C",
0661          "\xE2\x84\x95"    => "\x6E",
0662          "\xE2\x84\x96"    => "\x6E\x6F",
0663          "\xE2\x84\x99"    => "\x70",
0664          "\xE2\x84\x9A"    => "\x71",
0665          "\xE2\x84\x9B"    => "\x72",
0666          "\xE2\x84\x9C"    => "\x72",
0667          "\xE2\x84\x9D"    => "\x72",
0668          "\xE2\x84\xA0"    => "\x73\x6D",
0669          "\xE2\x84\xA1"    => "\x74\x65\x6C",
0670          "\xE2\x84\xA2"    => "\x74\x6D",
0671          "\xE2\x84\xA4"    => "\x7A",
0672          "\xE2\x84\xA8"    => "\x7A",
0673          "\xE2\x84\xAC"    => "\x62",
0674          "\xE2\x84\xAD"    => "\x63",
0675          "\xE2\x84\xB0"    => "\x65",
0676          "\xE2\x84\xB1"    => "\x66",
0677          "\xE2\x84\xB3"    => "\x6D",
0678          "\xE2\x84\xBB"    => "\x66\x61\x78",
0679          "\xE2\x84\xBE"    => "\xCE\xB3",
0680          "\xE2\x84\xBF"    => "\xCF\x80",
0681          "\xE2\x85\x85"    => "\x64",
0682          "\xE3\x89\x90"    => "\x70\x74\x65",
0683          "\xE3\x8B\x8C"    => "\x68\x67",
0684          "\xE3\x8B\x8E"    => "\x65\x76",
0685          "\xE3\x8B\x8F"    => "\x6C\x74\x64",
0686          "\xE3\x8D\xB1"    => "\x68\x70\x61",
0687          "\xE3\x8D\xB3"    => "\x61\x75",
0688          "\xE3\x8D\xB5"    => "\x6F\x76",
0689          "\xE3\x8D\xBA"    => "\x69\x75",
0690          "\xE3\x8E\x80"    => "\x70\x61",
0691          "\xE3\x8E\x81"    => "\x6E\x61",
0692          "\xE3\x8E\x82"    => "\xCE\xBC\x61",
0693          "\xE3\x8E\x83"    => "\x6D\x61",
0694          "\xE3\x8E\x84"    => "\x6B\x61",
0695          "\xE3\x8E\x85"    => "\x6B\x62",
0696          "\xE3\x8E\x86"    => "\x6D\x62",
0697          "\xE3\x8E\x87"    => "\x67\x62",
0698          "\xE3\x8E\x8A"    => "\x70\x66",
0699          "\xE3\x8E\x8B"    => "\x6E\x66",
0700          "\xE3\x8E\x8C"    => "\xCE\xBC\x66",
0701          "\xE3\x8E\x90"    => "\x68\x7A",
0702          "\xE3\x8E\x91"    => "\x6B\x68\x7A",
0703          "\xE3\x8E\x92"    => "\x6D\x68\x7A",
0704          "\xE3\x8E\x93"    => "\x67\x68\x7A",
0705          "\xE3\x8E\x94"    => "\x74\x68\x7A",
0706          "\xE3\x8E\xA9"    => "\x70\x61",
0707          "\xE3\x8E\xAA"    => "\x6B\x70\x61",
0708          "\xE3\x8E\xAB"    => "\x6D\x70\x61",
0709          "\xE3\x8E\xAC"    => "\x67\x70\x61",
0710          "\xE3\x8E\xB4"    => "\x70\x76",
0711          "\xE3\x8E\xB5"    => "\x6E\x76",
0712          "\xE3\x8E\xB6"    => "\xCE\xBC\x76",
0713          "\xE3\x8E\xB7"    => "\x6D\x76",
0714          "\xE3\x8E\xB8"    => "\x6B\x76",
0715          "\xE3\x8E\xB9"    => "\x6D\x76",
0716          "\xE3\x8E\xBA"    => "\x70\x77",
0717          "\xE3\x8E\xBB"    => "\x6E\x77",
0718          "\xE3\x8E\xBC"    => "\xCE\xBC\x77",
0719          "\xE3\x8E\xBD"    => "\x6D\x77",
0720          "\xE3\x8E\xBE"    => "\x6B\x77",
0721          "\xE3\x8E\xBF"    => "\x6D\x77",
0722          "\xE3\x8F\x80"    => "\x6B\xCF\x89",
0723          "\xE3\x8F\x81"    => "\x6D\xCF\x89",
0724          "\xE3\x8F\x83"    => "\x62\x71",
0725          "\xE3\x8F\x86"    => "\x63\xE2\x88\x95\x6B\x67",
0726          "\xE3\x8F\x87"    => "\x63\x6F\x2E",
0727          "\xE3\x8F\x88"    => "\x64\x62",
0728          "\xE3\x8F\x89"    => "\x67\x79",
0729          "\xE3\x8F\x8B"    => "\x68\x70",
0730          "\xE3\x8F\x8D"    => "\x6B\x6B",
0731          "\xE3\x8F\x8E"    => "\x6B\x6D",
0732          "\xE3\x8F\x97"    => "\x70\x68",
0733          "\xE3\x8F\x99"    => "\x70\x70\x6D",
0734          "\xE3\x8F\x9A"    => "\x70\x72",
0735          "\xE3\x8F\x9C"    => "\x73\x76",
0736          "\xE3\x8F\x9D"    => "\x77\x62",
0737          "\xE3\x8F\x9E"    => "\x76\xE2\x88\x95\x6D",
0738          "\xE3\x8F\x9F"    => "\x61\xE2\x88\x95\x6D",
0739          "\xF0\x9D\x90\x80"    => "\x61",
0740          "\xF0\x9D\x90\x81"    => "\x62",
0741          "\xF0\x9D\x90\x82"    => "\x63",
0742          "\xF0\x9D\x90\x83"    => "\x64",
0743          "\xF0\x9D\x90\x84"    => "\x65",
0744          "\xF0\x9D\x90\x85"    => "\x66",
0745          "\xF0\x9D\x90\x86"    => "\x67",
0746          "\xF0\x9D\x90\x87"    => "\x68",
0747          "\xF0\x9D\x90\x88"    => "\x69",
0748          "\xF0\x9D\x90\x89"    => "\x6A",
0749          "\xF0\x9D\x90\x8A"    => "\x6B",
0750          "\xF0\x9D\x90\x8B"    => "\x6C",
0751          "\xF0\x9D\x90\x8C"    => "\x6D",
0752          "\xF0\x9D\x90\x8D"    => "\x6E",
0753          "\xF0\x9D\x90\x8E"    => "\x6F",
0754          "\xF0\x9D\x90\x8F"    => "\x70",
0755          "\xF0\x9D\x90\x90"    => "\x71",
0756          "\xF0\x9D\x90\x91"    => "\x72",
0757          "\xF0\x9D\x90\x92"    => "\x73",
0758          "\xF0\x9D\x90\x93"    => "\x74",
0759          "\xF0\x9D\x90\x94"    => "\x75",
0760          "\xF0\x9D\x90\x95"    => "\x76",
0761          "\xF0\x9D\x90\x96"    => "\x77",
0762          "\xF0\x9D\x90\x97"    => "\x78",
0763          "\xF0\x9D\x90\x98"    => "\x79",
0764          "\xF0\x9D\x90\x99"    => "\x7A",
0765          "\xF0\x9D\x90\xB4"    => "\x61",
0766          "\xF0\x9D\x90\xB5"    => "\x62",
0767          "\xF0\x9D\x90\xB6"    => "\x63",
0768          "\xF0\x9D\x90\xB7"    => "\x64",
0769          "\xF0\x9D\x90\xB8"    => "\x65",
0770          "\xF0\x9D\x90\xB9"    => "\x66",
0771          "\xF0\x9D\x90\xBA"    => "\x67",
0772          "\xF0\x9D\x90\xBB"    => "\x68",
0773          "\xF0\x9D\x90\xBC"    => "\x69",
0774          "\xF0\x9D\x90\xBD"    => "\x6A",
0775          "\xF0\x9D\x90\xBE"    => "\x6B",
0776          "\xF0\x9D\x90\xBF"    => "\x6C",
0777          "\xF0\x9D\x91\x80"    => "\x6D",
0778          "\xF0\x9D\x91\x81"    => "\x6E",
0779          "\xF0\x9D\x91\x82"    => "\x6F",
0780          "\xF0\x9D\x91\x83"    => "\x70",
0781          "\xF0\x9D\x91\x84"    => "\x71",
0782          "\xF0\x9D\x91\x85"    => "\x72",
0783          "\xF0\x9D\x91\x86"    => "\x73",
0784          "\xF0\x9D\x91\x87"    => "\x74",
0785          "\xF0\x9D\x91\x88"    => "\x75",
0786          "\xF0\x9D\x91\x89"    => "\x76",
0787          "\xF0\x9D\x91\x8A"    => "\x77",
0788          "\xF0\x9D\x91\x8B"    => "\x78",
0789          "\xF0\x9D\x91\x8C"    => "\x79",
0790          "\xF0\x9D\x91\x8D"    => "\x7A",
0791          "\xF0\x9D\x91\xA8"    => "\x61",
0792          "\xF0\x9D\x91\xA9"    => "\x62",
0793          "\xF0\x9D\x91\xAA"    => "\x63",
0794          "\xF0\x9D\x91\xAB"    => "\x64",
0795          "\xF0\x9D\x91\xAC"    => "\x65",
0796          "\xF0\x9D\x91\xAD"    => "\x66",
0797          "\xF0\x9D\x91\xAE"    => "\x67",
0798          "\xF0\x9D\x91\xAF"    => "\x68",
0799          "\xF0\x9D\x91\xB0"    => "\x69",
0800          "\xF0\x9D\x91\xB1"    => "\x6A",
0801          "\xF0\x9D\x91\xB2"    => "\x6B",
0802          "\xF0\x9D\x91\xB3"    => "\x6C",
0803          "\xF0\x9D\x91\xB4"    => "\x6D",
0804          "\xF0\x9D\x91\xB5"    => "\x6E",
0805          "\xF0\x9D\x91\xB6"    => "\x6F",
0806          "\xF0\x9D\x91\xB7"    => "\x70",
0807          "\xF0\x9D\x91\xB8"    => "\x71",
0808          "\xF0\x9D\x91\xB9"    => "\x72",
0809          "\xF0\x9D\x91\xBA"    => "\x73",
0810          "\xF0\x9D\x91\xBB"    => "\x74",
0811          "\xF0\x9D\x91\xBC"    => "\x75",
0812          "\xF0\x9D\x91\xBD"    => "\x76",
0813          "\xF0\x9D\x91\xBE"    => "\x77",
0814          "\xF0\x9D\x91\xBF"    => "\x78",
0815          "\xF0\x9D\x92\x80"    => "\x79",
0816          "\xF0\x9D\x92\x81"    => "\x7A",
0817          "\xF0\x9D\x92\x9C"    => "\x61",
0818          "\xF0\x9D\x92\x9E"    => "\x63",
0819          "\xF0\x9D\x92\x9F"    => "\x64",
0820          "\xF0\x9D\x92\xA2"    => "\x67",
0821          "\xF0\x9D\x92\xA5"    => "\x6A",
0822          "\xF0\x9D\x92\xA6"    => "\x6B",
0823          "\xF0\x9D\x92\xA9"    => "\x6E",
0824          "\xF0\x9D\x92\xAA"    => "\x6F",
0825          "\xF0\x9D\x92\xAB"    => "\x70",
0826          "\xF0\x9D\x92\xAC"    => "\x71",
0827          "\xF0\x9D\x92\xAE"    => "\x73",
0828          "\xF0\x9D\x92\xAF"    => "\x74",
0829          "\xF0\x9D\x92\xB0"    => "\x75",
0830          "\xF0\x9D\x92\xB1"    => "\x76",
0831          "\xF0\x9D\x92\xB2"    => "\x77",
0832          "\xF0\x9D\x92\xB3"    => "\x78",
0833          "\xF0\x9D\x92\xB4"    => "\x79",
0834          "\xF0\x9D\x92\xB5"    => "\x7A",
0835          "\xF0\x9D\x93\x90"    => "\x61",
0836          "\xF0\x9D\x93\x91"    => "\x62",
0837          "\xF0\x9D\x93\x92"    => "\x63",
0838          "\xF0\x9D\x93\x93"    => "\x64",
0839          "\xF0\x9D\x93\x94"    => "\x65",
0840          "\xF0\x9D\x93\x95"    => "\x66",
0841          "\xF0\x9D\x93\x96"    => "\x67",
0842          "\xF0\x9D\x93\x97"    => "\x68",
0843          "\xF0\x9D\x93\x98"    => "\x69",
0844          "\xF0\x9D\x93\x99"    => "\x6A",
0845          "\xF0\x9D\x93\x9A"    => "\x6B",
0846          "\xF0\x9D\x93\x9B"    => "\x6C",
0847          "\xF0\x9D\x93\x9C"    => "\x6D",
0848          "\xF0\x9D\x93\x9D"    => "\x6E",
0849          "\xF0\x9D\x93\x9E"    => "\x6F",
0850          "\xF0\x9D\x93\x9F"    => "\x70",
0851          "\xF0\x9D\x93\xA0"    => "\x71",
0852          "\xF0\x9D\x93\xA1"    => "\x72",
0853          "\xF0\x9D\x93\xA2"    => "\x73",
0854          "\xF0\x9D\x93\xA3"    => "\x74",
0855          "\xF0\x9D\x93\xA4"    => "\x75",
0856          "\xF0\x9D\x93\xA5"    => "\x76",
0857          "\xF0\x9D\x93\xA6"    => "\x77",
0858          "\xF0\x9D\x93\xA7"    => "\x78",
0859          "\xF0\x9D\x93\xA8"    => "\x79",
0860          "\xF0\x9D\x93\xA9"    => "\x7A",
0861          "\xF0\x9D\x94\x84"    => "\x61",
0862          "\xF0\x9D\x94\x85"    => "\x62",
0863          "\xF0\x9D\x94\x87"    => "\x64",
0864          "\xF0\x9D\x94\x88"    => "\x65",
0865          "\xF0\x9D\x94\x89"    => "\x66",
0866          "\xF0\x9D\x94\x8A"    => "\x67",
0867          "\xF0\x9D\x94\x8D"    => "\x6A",
0868          "\xF0\x9D\x94\x8E"    => "\x6B",
0869          "\xF0\x9D\x94\x8F"    => "\x6C",
0870          "\xF0\x9D\x94\x90"    => "\x6D",
0871          "\xF0\x9D\x94\x91"    => "\x6E",
0872          "\xF0\x9D\x94\x92"    => "\x6F",
0873          "\xF0\x9D\x94\x93"    => "\x70",
0874          "\xF0\x9D\x94\x94"    => "\x71",
0875          "\xF0\x9D\x94\x96"    => "\x73",
0876          "\xF0\x9D\x94\x97"    => "\x74",
0877          "\xF0\x9D\x94\x98"    => "\x75",
0878          "\xF0\x9D\x94\x99"    => "\x76",
0879          "\xF0\x9D\x94\x9A"    => "\x77",
0880          "\xF0\x9D\x94\x9B"    => "\x78",
0881          "\xF0\x9D\x94\x9C"    => "\x79",
0882          "\xF0\x9D\x94\xB8"    => "\x61",
0883          "\xF0\x9D\x94\xB9"    => "\x62",
0884          "\xF0\x9D\x94\xBB"    => "\x64",
0885          "\xF0\x9D\x94\xBC"    => "\x65",
0886          "\xF0\x9D\x94\xBD"    => "\x66",
0887          "\xF0\x9D\x94\xBE"    => "\x67",
0888          "\xF0\x9D\x95\x80"    => "\x69",
0889          "\xF0\x9D\x95\x81"    => "\x6A",
0890          "\xF0\x9D\x95\x82"    => "\x6B",
0891          "\xF0\x9D\x95\x83"    => "\x6C",
0892          "\xF0\x9D\x95\x84"    => "\x6D",
0893          "\xF0\x9D\x95\x86"    => "\x6F",
0894          "\xF0\x9D\x95\x8A"    => "\x73",
0895          "\xF0\x9D\x95\x8B"    => "\x74",
0896          "\xF0\x9D\x95\x8C"    => "\x75",
0897          "\xF0\x9D\x95\x8D"    => "\x76",
0898          "\xF0\x9D\x95\x8E"    => "\x77",
0899          "\xF0\x9D\x95\x8F"    => "\x78",
0900          "\xF0\x9D\x95\x90"    => "\x79",
0901          "\xF0\x9D\x95\xAC"    => "\x61",
0902          "\xF0\x9D\x95\xAD"    => "\x62",
0903          "\xF0\x9D\x95\xAE"    => "\x63",
0904          "\xF0\x9D\x95\xAF"    => "\x64",
0905          "\xF0\x9D\x95\xB0"    => "\x65",
0906          "\xF0\x9D\x95\xB1"    => "\x66",
0907          "\xF0\x9D\x95\xB2"    => "\x67",
0908          "\xF0\x9D\x95\xB3"    => "\x68",
0909          "\xF0\x9D\x95\xB4"    => "\x69",
0910          "\xF0\x9D\x95\xB5"    => "\x6A",
0911          "\xF0\x9D\x95\xB6"    => "\x6B",
0912          "\xF0\x9D\x95\xB7"    => "\x6C",
0913          "\xF0\x9D\x95\xB8"    => "\x6D",
0914          "\xF0\x9D\x95\xB9"    => "\x6E",
0915          "\xF0\x9D\x95\xBA"    => "\x6F",
0916          "\xF0\x9D\x95\xBB"    => "\x70",
0917          "\xF0\x9D\x95\xBC"    => "\x71",
0918          "\xF0\x9D\x95\xBD"    => "\x72",
0919          "\xF0\x9D\x95\xBE"    => "\x73",
0920          "\xF0\x9D\x95\xBF"    => "\x74",
0921          "\xF0\x9D\x96\x80"    => "\x75",
0922          "\xF0\x9D\x96\x81"    => "\x76",
0923          "\xF0\x9D\x96\x82"    => "\x77",
0924          "\xF0\x9D\x96\x83"    => "\x78",
0925          "\xF0\x9D\x96\x84"    => "\x79",
0926          "\xF0\x9D\x96\x85"    => "\x7A",
0927          "\xF0\x9D\x96\xA0"    => "\x61",
0928          "\xF0\x9D\x96\xA1"    => "\x62",
0929          "\xF0\x9D\x96\xA2"    => "\x63",
0930          "\xF0\x9D\x96\xA3"    => "\x64",
0931          "\xF0\x9D\x96\xA4"    => "\x65",
0932          "\xF0\x9D\x96\xA5"    => "\x66",
0933          "\xF0\x9D\x96\xA6"    => "\x67",
0934          "\xF0\x9D\x96\xA7"    => "\x68",
0935          "\xF0\x9D\x96\xA8"    => "\x69",
0936          "\xF0\x9D\x96\xA9"    => "\x6A",
0937          "\xF0\x9D\x96\xAA"    => "\x6B",
0938          "\xF0\x9D\x96\xAB"    => "\x6C",
0939          "\xF0\x9D\x96\xAC"    => "\x6D",
0940          "\xF0\x9D\x96\xAD"    => "\x6E",
0941          "\xF0\x9D\x96\xAE"    => "\x6F",
0942          "\xF0\x9D\x96\xAF"    => "\x70",
0943          "\xF0\x9D\x96\xB0"    => "\x71",
0944          "\xF0\x9D\x96\xB1"    => "\x72",
0945          "\xF0\x9D\x96\xB2"    => "\x73",
0946          "\xF0\x9D\x96\xB3"    => "\x74",
0947          "\xF0\x9D\x96\xB4"    => "\x75",
0948          "\xF0\x9D\x96\xB5"    => "\x76",
0949          "\xF0\x9D\x96\xB6"    => "\x77",
0950          "\xF0\x9D\x96\xB7"    => "\x78",
0951          "\xF0\x9D\x96\xB8"    => "\x79",
0952          "\xF0\x9D\x96\xB9"    => "\x7A",
0953          "\xF0\x9D\x97\x94"    => "\x61",
0954          "\xF0\x9D\x97\x95"    => "\x62",
0955          "\xF0\x9D\x97\x96"    => "\x63",
0956          "\xF0\x9D\x97\x97"    => "\x64",
0957          "\xF0\x9D\x97\x98"    => "\x65",
0958          "\xF0\x9D\x97\x99"    => "\x66",
0959          "\xF0\x9D\x97\x9A"    => "\x67",
0960          "\xF0\x9D\x97\x9B"    => "\x68",
0961          "\xF0\x9D\x97\x9C"    => "\x69",
0962          "\xF0\x9D\x97\x9D"    => "\x6A",
0963          "\xF0\x9D\x97\x9E"    => "\x6B",
0964          "\xF0\x9D\x97\x9F"    => "\x6C",
0965          "\xF0\x9D\x97\xA0"    => "\x6D",
0966          "\xF0\x9D\x97\xA1"    => "\x6E",
0967          "\xF0\x9D\x97\xA2"    => "\x6F",
0968          "\xF0\x9D\x97\xA3"    => "\x70",
0969          "\xF0\x9D\x97\xA4"    => "\x71",
0970          "\xF0\x9D\x97\xA5"    => "\x72",
0971          "\xF0\x9D\x97\xA6"    => "\x73",
0972          "\xF0\x9D\x97\xA7"    => "\x74",
0973          "\xF0\x9D\x97\xA8"    => "\x75",
0974          "\xF0\x9D\x97\xA9"    => "\x76",
0975          "\xF0\x9D\x97\xAA"    => "\x77",
0976          "\xF0\x9D\x97\xAB"    => "\x78",
0977          "\xF0\x9D\x97\xAC"    => "\x79",
0978          "\xF0\x9D\x97\xAD"    => "\x7A",
0979          "\xF0\x9D\x98\x88"    => "\x61",
0980          "\xF0\x9D\x98\x89"    => "\x62",
0981          "\xF0\x9D\x98\x8A"    => "\x63",
0982          "\xF0\x9D\x98\x8B"    => "\x64",
0983          "\xF0\x9D\x98\x8C"    => "\x65",
0984          "\xF0\x9D\x98\x8D"    => "\x66",
0985          "\xF0\x9D\x98\x8E"    => "\x67",
0986          "\xF0\x9D\x98\x8F"    => "\x68",
0987          "\xF0\x9D\x98\x90"    => "\x69",
0988          "\xF0\x9D\x98\x91"    => "\x6A",
0989          "\xF0\x9D\x98\x92"    => "\x6B",
0990          "\xF0\x9D\x98\x93"    => "\x6C",
0991          "\xF0\x9D\x98\x94"    => "\x6D",
0992          "\xF0\x9D\x98\x95"    => "\x6E",
0993          "\xF0\x9D\x98\x96"    => "\x6F",
0994          "\xF0\x9D\x98\x97"    => "\x70",
0995          "\xF0\x9D\x98\x98"    => "\x71",
0996          "\xF0\x9D\x98\x99"    => "\x72",
0997          "\xF0\x9D\x98\x9A"    => "\x73",
0998          "\xF0\x9D\x98\x9B"    => "\x74",
0999          "\xF0\x9D\x98\x9C"    => "\x75",
1000          "\xF0\x9D\x98\x9D"    => "\x76",
1001          "\xF0\x9D\x98\x9E"    => "\x77",
1002          "\xF0\x9D\x98\x9F"    => "\x78",
1003          "\xF0\x9D\x98\xA0"    => "\x79",
1004          "\xF0\x9D\x98\xA1"    => "\x7A",
1005          "\xF0\x9D\x98\xBC"    => "\x61",
1006          "\xF0\x9D\x98\xBD"    => "\x62",
1007          "\xF0\x9D\x98\xBE"    => "\x63",
1008          "\xF0\x9D\x98\xBF"    => "\x64",
1009          "\xF0\x9D\x99\x80"    => "\x65",
1010          "\xF0\x9D\x99\x81"    => "\x66",
1011          "\xF0\x9D\x99\x82"    => "\x67",
1012          "\xF0\x9D\x99\x83"    => "\x68",
1013          "\xF0\x9D\x99\x84"    => "\x69",
1014          "\xF0\x9D\x99\x85"    => "\x6A",
1015          "\xF0\x9D\x99\x86"    => "\x6B",
1016          "\xF0\x9D\x99\x87"    => "\x6C",
1017          "\xF0\x9D\x99\x88"    => "\x6D",
1018          "\xF0\x9D\x99\x89"    => "\x6E",
1019          "\xF0\x9D\x99\x8A"    => "\x6F",
1020          "\xF0\x9D\x99\x8B"    => "\x70",
1021          "\xF0\x9D\x99\x8C"    => "\x71",
1022          "\xF0\x9D\x99\x8D"    => "\x72",
1023          "\xF0\x9D\x99\x8E"    => "\x73",
1024          "\xF0\x9D\x99\x8F"    => "\x74",
1025          "\xF0\x9D\x99\x90"    => "\x75",
1026          "\xF0\x9D\x99\x91"    => "\x76",
1027          "\xF0\x9D\x99\x92"    => "\x77",
1028          "\xF0\x9D\x99\x93"    => "\x78",
1029          "\xF0\x9D\x99\x94"    => "\x79",
1030          "\xF0\x9D\x99\x95"    => "\x7A",
1031          "\xF0\x9D\x99\xB0"    => "\x61",
1032          "\xF0\x9D\x99\xB1"    => "\x62",
1033          "\xF0\x9D\x99\xB2"    => "\x63",
1034          "\xF0\x9D\x99\xB3"    => "\x64",
1035          "\xF0\x9D\x99\xB4"    => "\x65",
1036          "\xF0\x9D\x99\xB5"    => "\x66",
1037          "\xF0\x9D\x99\xB6"    => "\x67",
1038          "\xF0\x9D\x99\xB7"    => "\x68",
1039          "\xF0\x9D\x99\xB8"    => "\x69",
1040          "\xF0\x9D\x99\xB9"    => "\x6A",
1041          "\xF0\x9D\x99\xBA"    => "\x6B",
1042          "\xF0\x9D\x99\xBB"    => "\x6C",
1043          "\xF0\x9D\x99\xBC"    => "\x6D",
1044          "\xF0\x9D\x99\xBD"    => "\x6E",
1045          "\xF0\x9D\x99\xBE"    => "\x6F",
1046          "\xF0\x9D\x99\xBF"    => "\x70",
1047          "\xF0\x9D\x9A\x80"    => "\x71",
1048          "\xF0\x9D\x9A\x81"    => "\x72",
1049          "\xF0\x9D\x9A\x82"    => "\x73",
1050          "\xF0\x9D\x9A\x83"    => "\x74",
1051          "\xF0\x9D\x9A\x84"    => "\x75",
1052          "\xF0\x9D\x9A\x85"    => "\x76",
1053          "\xF0\x9D\x9A\x86"    => "\x77",
1054          "\xF0\x9D\x9A\x87"    => "\x78",
1055          "\xF0\x9D\x9A\x88"    => "\x79",
1056          "\xF0\x9D\x9A\x89"    => "\x7A",
1057          "\xF0\x9D\x9A\xA8"    => "\xCE\xB1",
1058          "\xF0\x9D\x9A\xA9"    => "\xCE\xB2",
1059          "\xF0\x9D\x9A\xAA"    => "\xCE\xB3",
1060          "\xF0\x9D\x9A\xAB"    => "\xCE\xB4",
1061          "\xF0\x9D\x9A\xAC"    => "\xCE\xB5",
1062          "\xF0\x9D\x9A\xAD"    => "\xCE\xB6",
1063          "\xF0\x9D\x9A\xAE"    => "\xCE\xB7",
1064          "\xF0\x9D\x9A\xAF"    => "\xCE\xB8",
1065          "\xF0\x9D\x9A\xB0"    => "\xCE\xB9",
1066          "\xF0\x9D\x9A\xB1"    => "\xCE\xBA",
1067          "\xF0\x9D\x9A\xB2"    => "\xCE\xBB",
1068          "\xF0\x9D\x9A\xB3"    => "\xCE\xBC",
1069          "\xF0\x9D\x9A\xB4"    => "\xCE\xBD",
1070          "\xF0\x9D\x9A\xB5"    => "\xCE\xBE",
1071          "\xF0\x9D\x9A\xB6"    => "\xCE\xBF",
1072          "\xF0\x9D\x9A\xB7"    => "\xCF\x80",
1073          "\xF0\x9D\x9A\xB8"    => "\xCF\x81",
1074          "\xF0\x9D\x9A\xB9"    => "\xCE\xB8",
1075          "\xF0\x9D\x9A\xBA"    => "\xCF\x83",
1076          "\xF0\x9D\x9A\xBB"    => "\xCF\x84",
1077          "\xF0\x9D\x9A\xBC"    => "\xCF\x85",
1078          "\xF0\x9D\x9A\xBD"    => "\xCF\x86",
1079          "\xF0\x9D\x9A\xBE"    => "\xCF\x87",
1080          "\xF0\x9D\x9A\xBF"    => "\xCF\x88",
1081          "\xF0\x9D\x9B\x80"    => "\xCF\x89",
1082          "\xF0\x9D\x9B\x93"    => "\xCF\x83",
1083          "\xF0\x9D\x9B\xA2"    => "\xCE\xB1",
1084          "\xF0\x9D\x9B\xA3"    => "\xCE\xB2",
1085          "\xF0\x9D\x9B\xA4"    => "\xCE\xB3",
1086          "\xF0\x9D\x9B\xA5"    => "\xCE\xB4",
1087          "\xF0\x9D\x9B\xA6"    => "\xCE\xB5",
1088          "\xF0\x9D\x9B\xA7"    => "\xCE\xB6",
1089          "\xF0\x9D\x9B\xA8"    => "\xCE\xB7",
1090          "\xF0\x9D\x9B\xA9"    => "\xCE\xB8",
1091          "\xF0\x9D\x9B\xAA"    => "\xCE\xB9",
1092          "\xF0\x9D\x9B\xAB"    => "\xCE\xBA",
1093          "\xF0\x9D\x9B\xAC"    => "\xCE\xBB",
1094          "\xF0\x9D\x9B\xAD"    => "\xCE\xBC",
1095          "\xF0\x9D\x9B\xAE"    => "\xCE\xBD",
1096          "\xF0\x9D\x9B\xAF"    => "\xCE\xBE",
1097          "\xF0\x9D\x9B\xB0"    => "\xCE\xBF",
1098          "\xF0\x9D\x9B\xB1"    => "\xCF\x80",
1099          "\xF0\x9D\x9B\xB2"    => "\xCF\x81",
1100          "\xF0\x9D\x9B\xB3"    => "\xCE\xB8",
1101          "\xF0\x9D\x9B\xB4"    => "\xCF\x83",
1102          "\xF0\x9D\x9B\xB5"    => "\xCF\x84",
1103          "\xF0\x9D\x9B\xB6"    => "\xCF\x85",
1104          "\xF0\x9D\x9B\xB7"    => "\xCF\x86",
1105          "\xF0\x9D\x9B\xB8"    => "\xCF\x87",
1106          "\xF0\x9D\x9B\xB9"    => "\xCF\x88",
1107          "\xF0\x9D\x9B\xBA"    => "\xCF\x89",
1108          "\xF0\x9D\x9C\x8D"    => "\xCF\x83",
1109          "\xF0\x9D\x9C\x9C"    => "\xCE\xB1",
1110          "\xF0\x9D\x9C\x9D"    => "\xCE\xB2",
1111          "\xF0\x9D\x9C\x9E"    => "\xCE\xB3",
1112          "\xF0\x9D\x9C\x9F"    => "\xCE\xB4",
1113          "\xF0\x9D\x9C\xA0"    => "\xCE\xB5",
1114          "\xF0\x9D\x9C\xA1"    => "\xCE\xB6",
1115          "\xF0\x9D\x9C\xA2"    => "\xCE\xB7",
1116          "\xF0\x9D\x9C\xA3"    => "\xCE\xB8",
1117          "\xF0\x9D\x9C\xA4"    => "\xCE\xB9",
1118          "\xF0\x9D\x9C\xA5"    => "\xCE\xBA",
1119          "\xF0\x9D\x9C\xA6"    => "\xCE\xBB",
1120          "\xF0\x9D\x9C\xA7"    => "\xCE\xBC",
1121          "\xF0\x9D\x9C\xA8"    => "\xCE\xBD",
1122          "\xF0\x9D\x9C\xA9"    => "\xCE\xBE",
1123          "\xF0\x9D\x9C\xAA"    => "\xCE\xBF",
1124          "\xF0\x9D\x9C\xAB"    => "\xCF\x80",
1125          "\xF0\x9D\x9C\xAC"    => "\xCF\x81",
1126          "\xF0\x9D\x9C\xAD"    => "\xCE\xB8",
1127          "\xF0\x9D\x9C\xAE"    => "\xCF\x83",
1128          "\xF0\x9D\x9C\xAF"    => "\xCF\x84",
1129          "\xF0\x9D\x9C\xB0"    => "\xCF\x85",
1130          "\xF0\x9D\x9C\xB1"    => "\xCF\x86",
1131          "\xF0\x9D\x9C\xB2"    => "\xCF\x87",
1132          "\xF0\x9D\x9C\xB3"    => "\xCF\x88",
1133          "\xF0\x9D\x9C\xB4"    => "\xCF\x89",
1134          "\xF0\x9D\x9D\x87"    => "\xCF\x83",
1135          "\xF0\x9D\x9D\x96"    => "\xCE\xB1",
1136          "\xF0\x9D\x9D\x97"    => "\xCE\xB2",
1137          "\xF0\x9D\x9D\x98"    => "\xCE\xB3",
1138          "\xF0\x9D\x9D\x99"    => "\xCE\xB4",
1139          "\xF0\x9D\x9D\x9A"    => "\xCE\xB5",
1140          "\xF0\x9D\x9D\x9B"    => "\xCE\xB6",
1141          "\xF0\x9D\x9D\x9C"    => "\xCE\xB7",
1142          "\xF0\x9D\x9D\x9D"    => "\xCE\xB8",
1143          "\xF0\x9D\x9D\x9E"    => "\xCE\xB9",
1144          "\xF0\x9D\x9D\x9F"    => "\xCE\xBA",
1145          "\xF0\x9D\x9D\xA0"    => "\xCE\xBB",
1146          "\xF0\x9D\x9D\xA1"    => "\xCE\xBC",
1147          "\xF0\x9D\x9D\xA2"    => "\xCE\xBD",
1148          "\xF0\x9D\x9D\xA3"    => "\xCE\xBE",
1149          "\xF0\x9D\x9D\xA4"    => "\xCE\xBF",
1150          "\xF0\x9D\x9D\xA5"    => "\xCF\x80",
1151          "\xF0\x9D\x9D\xA6"    => "\xCF\x81",
1152          "\xF0\x9D\x9D\xA7"    => "\xCE\xB8",
1153          "\xF0\x9D\x9D\xA8"    => "\xCF\x83",
1154          "\xF0\x9D\x9D\xA9"    => "\xCF\x84",
1155          "\xF0\x9D\x9D\xAA"    => "\xCF\x85",
1156          "\xF0\x9D\x9D\xAB"    => "\xCF\x86",
1157          "\xF0\x9D\x9D\xAC"    => "\xCF\x87",
1158          "\xF0\x9D\x9D\xAD"    => "\xCF\x88",
1159          "\xF0\x9D\x9D\xAE"    => "\xCF\x89",
1160          "\xF0\x9D\x9E\x81"    => "\xCF\x83",
1161          "\xF0\x9D\x9E\x90"    => "\xCE\xB1",
1162          "\xF0\x9D\x9E\x91"    => "\xCE\xB2",
1163          "\xF0\x9D\x9E\x92"    => "\xCE\xB3",
1164          "\xF0\x9D\x9E\x93"    => "\xCE\xB4",
1165          "\xF0\x9D\x9E\x94"    => "\xCE\xB5",
1166          "\xF0\x9D\x9E\x95"    => "\xCE\xB6",
1167          "\xF0\x9D\x9E\x96"    => "\xCE\xB7",
1168          "\xF0\x9D\x9E\x97"    => "\xCE\xB8",
1169          "\xF0\x9D\x9E\x98"    => "\xCE\xB9",
1170          "\xF0\x9D\x9E\x99"    => "\xCE\xBA",
1171          "\xF0\x9D\x9E\x9A"    => "\xCE\xBB",
1172          "\xF0\x9D\x9E\x9B"    => "\xCE\xBC",
1173          "\xF0\x9D\x9E\x9C"    => "\xCE\xBD",
1174          "\xF0\x9D\x9E\x9D"    => "\xCE\xBE",
1175          "\xF0\x9D\x9E\x9E"    => "\xCE\xBF",
1176          "\xF0\x9D\x9E\x9F"    => "\xCF\x80",
1177          "\xF0\x9D\x9E\xA0"    => "\xCF\x81",
1178          "\xF0\x9D\x9E\xA1"    => "\xCE\xB8",
1179          "\xF0\x9D\x9E\xA2"    => "\xCF\x83",
1180          "\xF0\x9D\x9E\xA3"    => "\xCF\x84",
1181          "\xF0\x9D\x9E\xA4"    => "\xCF\x85",
1182          "\xF0\x9D\x9E\xA5"    => "\xCF\x86",
1183          "\xF0\x9D\x9E\xA6"    => "\xCF\x87",
1184          "\xF0\x9D\x9E\xA7"    => "\xCF\x88",
1185          "\xF0\x9D\x9E\xA8"    => "\xCF\x89",
1186          "\xF0\x9D\x9E\xBB"    => "\xCF\x83",
1187          "\xF0\x9D\x9F\x8A"    => "\xCF\x9D",
1188      );
1189   
1190      // do the case fold
1191      $text = utf8_case_fold($text, $option);
1192   
1193      // convert to NFKC
1194      Normalizer::normalize($text, Normalizer::NFKC);
1195   
1196      // FC_NFKC_Closure, http://www.unicode.org/Public/5.0.0/ucd/DerivedNormalizationProps.txt
1197      $text = strtr($text, $fc_nfkc_closure);
1198   
1199      return $text;
1200  }
1201   
1202  /**
1203  * Assume the input is NFC:
1204  * Takes the input and does a "special" case fold. It does minor normalization as well.
1205  *
1206  * @param    string    $text    text to be case folded
1207  * @param    string    $option    determines how we will fold the cases
1208  * @return    string            case folded text
1209  */
1210  function utf8_case_fold_nfc($text, $option = 'full')
1211  {
1212      static $uniarray = array();
1213      static $ypogegrammeni = array(
1214          "\xCD\xBA"        => "\x20\xCD\x85",
1215          "\xE1\xBE\x80"    => "\xE1\xBC\x80\xCD\x85",
1216          "\xE1\xBE\x81"    => "\xE1\xBC\x81\xCD\x85",
1217          "\xE1\xBE\x82"    => "\xE1\xBC\x82\xCD\x85",
1218          "\xE1\xBE\x83"    => "\xE1\xBC\x83\xCD\x85",
1219          "\xE1\xBE\x84"    => "\xE1\xBC\x84\xCD\x85",
1220          "\xE1\xBE\x85"    => "\xE1\xBC\x85\xCD\x85",
1221          "\xE1\xBE\x86"    => "\xE1\xBC\x86\xCD\x85",
1222          "\xE1\xBE\x87"    => "\xE1\xBC\x87\xCD\x85",
1223          "\xE1\xBE\x88"    => "\xE1\xBC\x88\xCD\x85",
1224          "\xE1\xBE\x89"    => "\xE1\xBC\x89\xCD\x85",
1225          "\xE1\xBE\x8A"    => "\xE1\xBC\x8A\xCD\x85",
1226          "\xE1\xBE\x8B"    => "\xE1\xBC\x8B\xCD\x85",
1227          "\xE1\xBE\x8C"    => "\xE1\xBC\x8C\xCD\x85",
1228          "\xE1\xBE\x8D"    => "\xE1\xBC\x8D\xCD\x85",
1229          "\xE1\xBE\x8E"    => "\xE1\xBC\x8E\xCD\x85",
1230          "\xE1\xBE\x8F"    => "\xE1\xBC\x8F\xCD\x85",
1231          "\xE1\xBE\x90"    => "\xE1\xBC\xA0\xCD\x85",
1232          "\xE1\xBE\x91"    => "\xE1\xBC\xA1\xCD\x85",
1233          "\xE1\xBE\x92"    => "\xE1\xBC\xA2\xCD\x85",
1234          "\xE1\xBE\x93"    => "\xE1\xBC\xA3\xCD\x85",
1235          "\xE1\xBE\x94"    => "\xE1\xBC\xA4\xCD\x85",
1236          "\xE1\xBE\x95"    => "\xE1\xBC\xA5\xCD\x85",
1237          "\xE1\xBE\x96"    => "\xE1\xBC\xA6\xCD\x85",
1238          "\xE1\xBE\x97"    => "\xE1\xBC\xA7\xCD\x85",
1239          "\xE1\xBE\x98"    => "\xE1\xBC\xA8\xCD\x85",
1240          "\xE1\xBE\x99"    => "\xE1\xBC\xA9\xCD\x85",
1241          "\xE1\xBE\x9A"    => "\xE1\xBC\xAA\xCD\x85",
1242          "\xE1\xBE\x9B"    => "\xE1\xBC\xAB\xCD\x85",
1243          "\xE1\xBE\x9C"    => "\xE1\xBC\xAC\xCD\x85",
1244          "\xE1\xBE\x9D"    => "\xE1\xBC\xAD\xCD\x85",
1245          "\xE1\xBE\x9E"    => "\xE1\xBC\xAE\xCD\x85",
1246          "\xE1\xBE\x9F"    => "\xE1\xBC\xAF\xCD\x85",
1247          "\xE1\xBE\xA0"    => "\xE1\xBD\xA0\xCD\x85",
1248          "\xE1\xBE\xA1"    => "\xE1\xBD\xA1\xCD\x85",
1249          "\xE1\xBE\xA2"    => "\xE1\xBD\xA2\xCD\x85",
1250          "\xE1\xBE\xA3"    => "\xE1\xBD\xA3\xCD\x85",
1251          "\xE1\xBE\xA4"    => "\xE1\xBD\xA4\xCD\x85",
1252          "\xE1\xBE\xA5"    => "\xE1\xBD\xA5\xCD\x85",
1253          "\xE1\xBE\xA6"    => "\xE1\xBD\xA6\xCD\x85",
1254          "\xE1\xBE\xA7"    => "\xE1\xBD\xA7\xCD\x85",
1255          "\xE1\xBE\xA8"    => "\xE1\xBD\xA8\xCD\x85",
1256          "\xE1\xBE\xA9"    => "\xE1\xBD\xA9\xCD\x85",
1257          "\xE1\xBE\xAA"    => "\xE1\xBD\xAA\xCD\x85",
1258          "\xE1\xBE\xAB"    => "\xE1\xBD\xAB\xCD\x85",
1259          "\xE1\xBE\xAC"    => "\xE1\xBD\xAC\xCD\x85",
1260          "\xE1\xBE\xAD"    => "\xE1\xBD\xAD\xCD\x85",
1261          "\xE1\xBE\xAE"    => "\xE1\xBD\xAE\xCD\x85",
1262          "\xE1\xBE\xAF"    => "\xE1\xBD\xAF\xCD\x85",
1263          "\xE1\xBE\xB2"    => "\xE1\xBD\xB0\xCD\x85",
1264          "\xE1\xBE\xB3"    => "\xCE\xB1\xCD\x85",
1265          "\xE1\xBE\xB4"    => "\xCE\xAC\xCD\x85",
1266          "\xE1\xBE\xB7"    => "\xE1\xBE\xB6\xCD\x85",
1267          "\xE1\xBE\xBC"    => "\xCE\x91\xCD\x85",
1268          "\xE1\xBF\x82"    => "\xE1\xBD\xB4\xCD\x85",
1269          "\xE1\xBF\x83"    => "\xCE\xB7\xCD\x85",
1270          "\xE1\xBF\x84"    => "\xCE\xAE\xCD\x85",
1271          "\xE1\xBF\x87"    => "\xE1\xBF\x86\xCD\x85",
1272          "\xE1\xBF\x8C"    => "\xCE\x97\xCD\x85",
1273          "\xE1\xBF\xB2"    => "\xE1\xBD\xBC\xCD\x85",
1274          "\xE1\xBF\xB3"    => "\xCF\x89\xCD\x85",
1275          "\xE1\xBF\xB4"    => "\xCF\x8E\xCD\x85",
1276          "\xE1\xBF\xB7"    => "\xE1\xBF\xB6\xCD\x85",
1277          "\xE1\xBF\xBC"    => "\xCE\xA9\xCD\x85",
1278      );
1279   
1280      // perform a small trick, avoid further normalization on composed points that contain U+0345 in their decomposition
1281      $text = strtr($text, $ypogegrammeni);
1282   
1283      // do the case fold
1284      $text = utf8_case_fold($text, $option);
1285   
1286      return $text;
1287  }
1288   
1289  /**
1290  * wrapper around PHP's native normalizer from intl
1291  * previously a PECL extension, included in the core since PHP 5.3.0
1292  * http://php.net/manual/en/normalizer.normalize.php
1293  *
1294  * @param    mixed    $strings    a string or an array of strings to normalize
1295  * @return    mixed                the normalized content, preserving array keys if array given.
1296  */
1297  function utf8_normalize_nfc($strings)
1298  {
1299      if (empty($strings))
1300      {
1301          return $strings;
1302      }
1303   
1304      if (!is_array($strings))
1305      {
1306          if (Normalizer::isNormalized($strings))
1307          {
1308              return $strings;
1309          }
1310          return (string) Normalizer::normalize($strings);
1311      }
1312      else
1313      {
1314          foreach ($strings as $key => $string)
1315          {
1316              if (is_array($string))
1317              {
1318                  foreach ($string as $_key => $_string)
1319                  {
1320                      if (Normalizer::isNormalized($strings[$key][$_key]))
1321                      {
1322                          continue;
1323                      }
1324                      $strings[$key][$_key] = (string) Normalizer::normalize($strings[$key][$_key]);
1325                  }
1326              }
1327              else
1328              {
1329                  if (Normalizer::isNormalized($strings[$key]))
1330                  {
1331                      continue;
1332                  }
1333                  $strings[$key] = (string) Normalizer::normalize($strings[$key]);
1334              }
1335          }
1336      }
1337   
1338      return $strings;
1339  }
1340   
1341  /**
1342  * This function is used to generate a "clean" version of a string.
1343  * Clean means that it is a case insensitive form (case folding) and that it is normalized (NFC).
1344  * Additionally a homographs of one character are transformed into one specific character (preferably ASCII
1345  * if it is an ASCII character).
1346  *
1347  * Please be aware that if you change something within this function or within
1348  * functions used here you need to rebuild/update the username_clean column in the users table. And all other
1349  * columns that store a clean string otherwise you will break this functionality.
1350  *
1351  * @param    string    $text    An unclean string, mabye user input (has to be valid UTF-8!)
1352  * @return    string            Cleaned up version of the input string
1353  */
1354  function utf8_clean_string($text)
1355  {
1356      global $phpbb_root_path, $phpEx;
1357   
1358      static $homographs = array();
1359      if (empty($homographs))
1360      {
1361          $homographs = include($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx);
1362      }
1363   
1364      $text = utf8_case_fold_nfkc($text);
1365      $text = strtr($text, $homographs);
1366      // Other control characters
1367      $text = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $text);
1368   
1369      // we need to reduce multiple spaces to a single one
1370      $text = preg_replace('# {2,}#', ' ', $text);
1371   
1372      // we can use trim here as all the other space characters should have been turned
1373      // into normal ASCII spaces by now
1374      return trim($text);
1375  }
1376   
1377  /**
1378  * A wrapper for htmlspecialchars($value, ENT_COMPAT, 'UTF-8')
1379  */
1380  function utf8_htmlspecialchars($value)
1381  {
1382      return htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
1383  }
1384   
1385  /**
1386  * Trying to convert returned system message to utf8
1387  *
1388  * PHP assumes such messages are ISO-8859-1 so we'll do that too
1389  * and if it breaks messages we'll blame it on them ;-)
1390  */
1391  function utf8_convert_message($message)
1392  {
1393      // First of all check if conversion is neded at all, as there is no point
1394      // in converting ASCII messages from ISO-8859-1 to UTF-8
1395      if (!preg_match('/[\x80-\xFF]/', $message))
1396      {
1397          return utf8_htmlspecialchars($message);
1398      }
1399   
1400      // else we need to convert some part of the message
1401      return utf8_htmlspecialchars(utf8_recode($message, 'ISO-8859-1'));
1402  }
1403   
1404  /**
1405  * UTF8-compatible wordwrap replacement
1406  *
1407  * @param    string    $string    The input string
1408  * @param    int        $width    The column width. Defaults to 75.
1409  * @param    string    $break    The line is broken using the optional break parameter. Defaults to '\n'.
1410  * @param    bool    $cut    If the cut is set to TRUE, the string is always wrapped at the specified width. So if you have a word that is larger than the given width, it is broken apart.
1411  *
1412  * @return    string            the given string wrapped at the specified column.
1413  *
1414  */
1415  function utf8_wordwrap($string, $width = 75, $break = "\n", $cut = false)
1416  {
1417      // We first need to explode on $break, not destroying existing (intended) breaks
1418      $lines = explode($break, $string);
1419      $new_lines = array(0 => '');
1420      $index = 0;
1421   
1422      foreach ($lines as $line)
1423      {
1424          $words = explode(' ', $line);
1425   
1426          for ($i = 0, $size = count($words); $i < $size; $i++)
1427          {
1428              $word = $words[$i];
1429   
1430              // If cut is true we need to cut the word if it is > width chars
1431              if ($cut && utf8_strlen($word) > $width)
1432              {
1433                  $words[$i] = utf8_substr($word, $width);
1434                  $word = utf8_substr($word, 0, $width);
1435                  $i--;
1436              }
1437   
1438              if (utf8_strlen($new_lines[$index] . $word) > $width)
1439              {
1440                  $new_lines[$index] = substr($new_lines[$index], 0, -1);
1441                  $index++;
1442                  $new_lines[$index] = '';
1443              }
1444   
1445              $new_lines[$index] .= $word . ' ';
1446          }
1447   
1448          $new_lines[$index] = substr($new_lines[$index], 0, -1);
1449          $index++;
1450          $new_lines[$index] = '';
1451      }
1452   
1453      unset($new_lines[$index]);
1454      return implode($break, $new_lines);
1455  }
1456   
1457  /**
1458  * UTF8-safe basename() function
1459  *
1460  * basename() has some limitations and is dependent on the locale setting
1461  * according to the PHP manual. Therefore we provide our own locale independent
1462  * basename function.
1463  *
1464  * @param string $filename The filename basename() should be applied to
1465  * @return string The basenamed filename
1466  */
1467  function utf8_basename($filename)
1468  {
1469      // We always check for forward slash AND backward slash
1470      // because they could be mixed or "sneaked" in. ;)
1471      // You know, never trust user input...
1472      if (strpos($filename, '/') !== false)
1473      {
1474          $filename = utf8_substr($filename, utf8_strrpos($filename, '/') + 1);
1475      }
1476   
1477      if (strpos($filename, '\\') !== false)
1478      {
1479          $filename = utf8_substr($filename, utf8_strrpos($filename, '\\') + 1);
1480      }
1481   
1482      return $filename;
1483  }
1484