Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

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

generate_utf_tables.php

Zuletzt modifiziert: 09.10.2024, 12:50 - Dateigröße: 12.40 KiB


 001  <?php
 002  /**
 003  *
 004  * @package phpBB3
 005  * @version $Id$
 006  * @copyright (c) 2005 phpBB Group
 007  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 008  *
 009  */
 010   
 011  if (php_sapi_name() != 'cli')
 012  {
 013      die("This program must be run from the command line.\n");
 014  }
 015   
 016  //
 017  // Security message:
 018  //
 019  // This script is potentially dangerous.
 020  // Remove or comment the next line (die(".... ) to enable this script.
 021  // Do NOT FORGET to either remove this script or disable it after you have used it.
 022  //
 023  die("Please read the first lines of this script for instructions on how to enable it");
 024   
 025  set_time_limit(0);
 026   
 027  define('IN_PHPBB', true);
 028  $phpbb_root_path = '../';
 029  $phpEx = substr(strrchr(__FILE__, '.'), 1);
 030   
 031  echo "Checking for required files\n";
 032  download('http://www.unicode.org/Public/UNIDATA/CompositionExclusions.txt');
 033  download('http://www.unicode.org/Public/UNIDATA/DerivedNormalizationProps.txt');
 034  download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt');
 035  echo "\n";
 036   
 037  require_once($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
 038  $file_contents = array();
 039   
 040  /**
 041  * Generate some Hangul/Jamo stuff
 042  */
 043  echo "\nGenerating Hangul and Jamo tables\n";
 044  for ($i = 0; $i < UNICODE_HANGUL_LCOUNT; ++$i)
 045  {
 046      $utf_char = cp_to_utf(UNICODE_HANGUL_LBASE + $i);
 047      $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i * UNICODE_HANGUL_VCOUNT * UNICODE_HANGUL_TCOUNT + UNICODE_HANGUL_SBASE;
 048      $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_L;
 049  }
 050   
 051  for ($i = 0; $i < UNICODE_HANGUL_VCOUNT; ++$i)
 052  {
 053      $utf_char = cp_to_utf(UNICODE_HANGUL_VBASE + $i);
 054      $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i * UNICODE_HANGUL_TCOUNT;
 055      $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_V;
 056  }
 057   
 058  for ($i = 0; $i < UNICODE_HANGUL_TCOUNT; ++$i)
 059  {
 060      $utf_char = cp_to_utf(UNICODE_HANGUL_TBASE + $i);
 061      $file_contents['utf_normalizer_common']['utf_jamo_index'][$utf_char] = $i;
 062      $file_contents['utf_normalizer_common']['utf_jamo_type'][$utf_char] = UNICODE_JAMO_T;
 063  }
 064   
 065  /**
 066  * Load the CompositionExclusions table
 067  */
 068  echo "Loading CompositionExclusion\n";
 069  $fp = fopen('CompositionExclusions.txt', 'rt');
 070   
 071  $exclude = array();
 072  while (!feof($fp))
 073  {
 074      $line = fgets($fp, 1024);
 075   
 076      if (!strpos(' 0123456789ABCDEFabcdef', $line[0]))
 077      {
 078          continue;
 079      }
 080   
 081      $cp = strtok($line, ' ');
 082   
 083      if ($pos = strpos($cp, '..'))
 084      {
 085          $start = hexdec(substr($cp, 0, $pos));
 086          $end = hexdec(substr($cp, $pos + 2));
 087   
 088          for ($i = $start; $i < $end; ++$i)
 089          {
 090              $exclude[$i] = 1;
 091          }
 092      }
 093      else
 094      {
 095          $exclude[hexdec($cp)] = 1;
 096      }
 097  }
 098  fclose($fp);
 099   
 100  /**
 101  * Load QuickCheck tables
 102  */
 103  echo "Generating QuickCheck tables\n";
 104  $fp = fopen('DerivedNormalizationProps.txt', 'rt');
 105   
 106  while (!feof($fp))
 107  {
 108      $line = fgets($fp, 1024);
 109   
 110      if (!strpos(' 0123456789ABCDEFabcdef', $line[0]))
 111      {
 112          continue;
 113      }
 114   
 115      $p = array_map('trim', explode(';', strtok($line, '#')));
 116   
 117      /**
 118      * Capture only NFC_QC, NFKC_QC
 119      */
 120      if (!preg_match('#^NFK?C_QC$#', $p[1]))
 121      {
 122          continue;
 123      }
 124   
 125      if ($pos = strpos($p[0], '..'))
 126      {
 127          $start = hexdec(substr($p[0], 0, $pos));
 128          $end = hexdec(substr($p[0], $pos + 2));
 129      }
 130      else
 131      {
 132          $start = $end = hexdec($p[0]);
 133      }
 134   
 135      if ($start >= UTF8_HANGUL_FIRST && $end <= UTF8_HANGUL_LAST)
 136      {
 137          /**
 138          * We do not store Hangul syllables in the array
 139          */
 140          continue;
 141      }
 142   
 143      if ($p[2] == 'M')
 144      {
 145          $val = UNICODE_QC_MAYBE;
 146      }
 147      else
 148      {
 149          $val = UNICODE_QC_NO;
 150      }
 151   
 152      if ($p[1] == 'NFKC_QC')
 153      {
 154          $file = 'utf_nfkc_qc';
 155      }
 156      else
 157      {
 158          $file = 'utf_nfc_qc';
 159      }
 160   
 161      for ($i = $start; $i <= $end; ++$i)
 162      {
 163          /**
 164          * The vars have the same name as the file: $utf_nfc_qc is in utf_nfc_qc.php
 165          */
 166          $file_contents[$file][$file][cp_to_utf($i)] = $val;
 167      }
 168  }
 169  fclose($fp);
 170   
 171  /**
 172  * Do mappings
 173  */
 174  echo "Loading Unicode decomposition mappings\n";
 175  $fp = fopen($phpbb_root_path . 'develop/UnicodeData.txt', 'rt');
 176   
 177  $map = array();
 178  while (!feof($fp))
 179  {
 180      $p = explode(';', fgets($fp, 1024));
 181      $cp = hexdec($p[0]);
 182   
 183      if (!empty($p[3]))
 184      {
 185          /**
 186          * Store combining class > 0
 187          */
 188          $file_contents['utf_normalizer_common']['utf_combining_class'][cp_to_utf($cp)] = (int) $p[3];
 189      }
 190   
 191      if (!isset($p[5]) || !preg_match_all('#[0-9A-F]+#', strip_tags($p[5]), $m))
 192      {
 193          continue;
 194      }
 195   
 196      if (strpos($p[5], '>'))
 197      {
 198          $map['NFKD'][$cp] = implode(' ', array_map('hexdec', $m[0]));
 199      }
 200      else
 201      {
 202          $map['NFD'][$cp] = $map['NFKD'][$cp] = implode(' ', array_map('hexdec', $m[0]));
 203      }
 204  }
 205  fclose($fp);
 206   
 207  /**
 208  * Build the canonical composition table
 209  */
 210  echo "Generating the Canonical Composition table\n";
 211  foreach ($map['NFD'] as $cp => $decomp_seq)
 212  {
 213      if (!strpos($decomp_seq, ' ') || isset($exclude[$cp]))
 214      {
 215          /**
 216          * Singletons are excluded from canonical composition
 217          */
 218          continue;
 219      }
 220   
 221      $utf_seq = implode('', array_map('cp_to_utf', explode(' ', $decomp_seq)));
 222   
 223      if (!isset($file_contents['utf_canonical_comp']['utf_canonical_comp'][$utf_seq]))
 224      {
 225          $file_contents['utf_canonical_comp']['utf_canonical_comp'][$utf_seq] = cp_to_utf($cp);
 226      }
 227  }
 228   
 229  /**
 230  * Decompose the NF[K]D mappings recursively and prepare the file contents
 231  */
 232  echo "Generating the Canonical and Compatibility Decomposition tables\n\n";
 233  foreach ($map as $type => $decomp_map)
 234  {
 235      foreach ($decomp_map as $cp => $decomp_seq)
 236      {
 237          $decomp_map[$cp] = decompose($decomp_map, $decomp_seq);
 238      }
 239      unset($decomp_seq);
 240   
 241      if ($type == 'NFKD')
 242      {
 243          $file = 'utf_compatibility_decomp';
 244          $var = 'utf_compatibility_decomp';
 245      }
 246      else
 247      {
 248          $file = 'utf_canonical_decomp';
 249          $var = 'utf_canonical_decomp';
 250      }
 251   
 252      /**
 253      * Generate the corresponding file
 254      */
 255      foreach ($decomp_map as $cp => $decomp_seq)
 256      {
 257          $file_contents[$file][$var][cp_to_utf($cp)] = implode('', array_map('cp_to_utf', explode(' ', $decomp_seq)));
 258      }
 259  }
 260   
 261  /**
 262  * Generate and/or alter the files
 263  */
 264  foreach ($file_contents as $file => $contents)
 265  {
 266      /**
 267      * Generate a new file
 268      */
 269      echo "Writing to $file.$phpEx\n";
 270   
 271      if (!$fp = fopen($phpbb_root_path . 'includes/utf/data/' . $file . '.' . $phpEx, 'wb'))
 272      {
 273          trigger_error('Cannot open ' . $file . ' for write');
 274      }
 275   
 276      fwrite($fp, '<?php');
 277      foreach ($contents as $var => $val)
 278      {
 279          fwrite($fp, "\n\$GLOBALS[" . my_var_export($var) . ']=' . my_var_export($val) . ";");
 280      }
 281      fclose($fp);
 282  }
 283   
 284  echo "\n*** UTF-8 normalization tables done\n\n";
 285   
 286  /**
 287  * Now we'll generate the files needed by the search indexer
 288  */
 289  echo "Generating search indexer tables\n";
 290   
 291  $fp = fopen($phpbb_root_path . 'develop/UnicodeData.txt', 'rt');
 292   
 293  $map = array();
 294  while ($line = fgets($fp, 1024))
 295  {
 296      /**
 297      * The current line is split, $m[0] hold the codepoint in hexadecimal and
 298      * all other fields numbered as in http://www.unicode.org/Public/UNIDATA/UCD.html#UnicodeData.txt
 299      */
 300      $m = explode(';', $line);
 301   
 302      /**
 303      * @var    integer    $cp            Current char codepoint
 304      * @var    string    $utf_char    UTF-8 representation of current char
 305      */
 306      $cp = hexdec($m[0]);
 307      $utf_char = cp_to_utf($cp);
 308   
 309      /**
 310      * $m[2] holds the "General Category" of the character
 311      * @link http://www.unicode.org/Public/UNIDATA/UCD.html#General_Category_Values
 312      */
 313      switch ($m[2][0])
 314      {
 315          case 'L':
 316              /**
 317              * We allow all letters and map them to their lowercased counterpart on the fly
 318              */
 319              $map_to_hex = (isset($m[13][0])) ? $m[13] : $m[0];
 320   
 321              if (preg_match('#^LATIN.*(?:LETTER|LIGATURE) ([A-Z]{2}(?![A-Z]))$#', $m[1], $capture))
 322              {
 323                  /**
 324                  * Special hack for some latin ligatures. Using the name of a character
 325                  * is bad practice, but for now it works well enough.
 326                  *
 327                  * @todo Note that ligatures with combining marks such as U+01E2 are
 328                  * not supported at this time
 329                  */
 330                  $map[$cp] = strtolower($capture[1]);
 331              }
 332              else if (isset($m[13][0]))
 333              {
 334                  /**
 335                  * If the letter has a lowercased form, use it
 336                  */
 337                  $map[$cp] = hex_to_utf($m[13]);
 338              }
 339              else
 340              {
 341                  /**
 342                  * In all other cases, map the letter to itself
 343                  */
 344                  $map[$cp] = $utf_char;
 345              }
 346              break;
 347   
 348          case 'M':
 349              /**
 350              * We allow all marks, they are mapped to themselves
 351              */
 352              $map[$cp] = $utf_char;
 353              break;
 354   
 355          case 'N':
 356              /**
 357              * We allow all numbers, but we map them to their numeric value whenever
 358              * possible. The numeric value (field #8) is in ASCII already
 359              *
 360              * @todo Note that fractions such as U+00BD will be converted to something
 361              * like "1/2", with a slash. However, "1/2" entered in ASCII is converted
 362              * to "1 2". This will have to be fixed.
 363              */
 364              $map[$cp] = (isset($m[8][0])) ? $m[8] : $utf_char;
 365              break;
 366   
 367          default:
 368              /**
 369              * Everything else is ignored, skip to the next line
 370              */
 371              continue 2;
 372      }
 373  }
 374  fclose($fp);
 375   
 376  /**
 377  * Add some cheating
 378  */
 379  $cheats = array(
 380      '00DF'    =>    'ss',        #    German sharp S
 381      '00C5'    =>    'ae',        #    Capital A with diaeresis
 382      '00E4'    =>    'ae',        #    Small A with diaeresis
 383      '00D6'    =>    'oe',        #    Capital O with diaeresis
 384      '00F6'    =>    'oe',        #    Small O with diaeresis
 385      '00DC'    =>    'ue',        #    Capital U with diaeresis
 386      '00FC'    =>    'ue',        #    Small U with diaeresis
 387  );
 388   
 389  /**
 390  * Add our "cheat replacements" to the map
 391  */
 392  foreach ($cheats as $hex => $map_to)
 393  {
 394      $map[hexdec($hex)] = $map_to;
 395  }
 396   
 397  /**
 398  * Split the map into smaller blocks
 399  */
 400  $file_contents = array();
 401  foreach ($map as $cp => $map_to)
 402  {
 403      $file_contents[$cp >> 11][cp_to_utf($cp)] = $map_to;
 404  }
 405  unset($map);
 406   
 407  foreach ($file_contents as $idx => $contents)
 408  {
 409      echo "Writing to search_indexer_$idx.$phpEx\n";
 410      $fp = fopen($phpbb_root_path . 'includes/utf/data/search_indexer_' . $idx . '.' . $phpEx, 'wb');
 411      fwrite($fp, '<?php return ' . my_var_export($contents) . ';');
 412      fclose($fp);
 413  }
 414  echo "\n*** Search indexer tables done\n\n";
 415   
 416   
 417  die("\nAll done!\n");
 418   
 419   
 420  ////////////////////////////////////////////////////////////////////////////////
 421  //                             Internal functions                             //
 422  ////////////////////////////////////////////////////////////////////////////////
 423   
 424  /**
 425  * Decompose a sequence recusively
 426  *
 427  * @param    array    $decomp_map    Decomposition mapping, passed by reference
 428  * @param    string    $decomp_seq    Decomposition sequence as decimal codepoints separated with a space
 429  * @return    string                Decomposition sequence, fully decomposed
 430  */
 431  function decompose(&$decomp_map, $decomp_seq)
 432  {
 433      $ret = array();
 434      foreach (explode(' ', $decomp_seq) as $cp)
 435      {
 436          if (isset($decomp_map[$cp]))
 437          {
 438              $ret[] = decompose($decomp_map, $decomp_map[$cp]);
 439          }
 440          else
 441          {
 442              $ret[] = $cp;
 443          }
 444      }
 445   
 446      return implode(' ', $ret);
 447  }
 448   
 449   
 450  /**
 451  * Return a parsable string representation of a variable
 452  *
 453  * This is function is limited to array/strings/integers
 454  *
 455  * @param    mixed    $var        Variable
 456  * @return    string                PHP code representing the variable
 457  */
 458  function my_var_export($var)
 459  {
 460      if (is_array($var))
 461      {
 462          $lines = array();
 463   
 464          foreach ($var as $k => $v)
 465          {
 466              $lines[] = my_var_export($k) . '=>' . my_var_export($v);
 467          }
 468   
 469          return 'array(' . implode(',', $lines) . ')';
 470      }
 471      else if (is_string($var))
 472      {
 473          return "'" . str_replace(array('\\', "'"), array('\\\\', "\\'"), $var) . "'";
 474      }
 475      else
 476      {
 477          return $var;
 478      }
 479  }
 480   
 481  /**
 482  * Download a file to the develop/ dir
 483  *
 484  * @param    string    $url        URL of the file to download
 485  * @return    void
 486  */
 487  function download($url)
 488  {
 489      global $phpbb_root_path;
 490   
 491      if (file_exists($phpbb_root_path . 'develop/' . basename($url)))
 492      {
 493          return;
 494      }
 495   
 496      echo 'Downloading from ', $url, ' ';
 497   
 498      if (!$fpr = fopen($url, 'rb'))
 499      {
 500          die("Can't download from $url\nPlease download it yourself and put it in the develop/ dir, kthxbai");
 501      }
 502   
 503      if (!$fpw = fopen($phpbb_root_path . 'develop/' . basename($url), 'wb'))
 504      {
 505          die("Can't open develop/" . basename($url) . " for output... please check your permissions or something");
 506      }
 507   
 508      $i = 0;
 509      $chunk = 32768;
 510      $done = '';
 511   
 512      while (!feof($fpr))
 513      {
 514          $i += fwrite($fpw, fread($fpr, $chunk));
 515          echo str_repeat("\x08", strlen($done));
 516   
 517          $done = ($i >> 10) . ' KiB';
 518          echo $done;
 519      }
 520      fclose($fpr);
 521      fclose($fpw);
 522   
 523      echo "\n";
 524  }
 525   
 526  /**
 527  * Convert a codepoint in hexadecimal to a UTF-8 char
 528  *
 529  * @param    string    $hex        Codepoint, in hexadecimal
 530  * @return    string                UTF-8 char
 531  */
 532  function hex_to_utf($hex)
 533  {
 534      return cp_to_utf(hexdec($hex));
 535  }
 536   
 537  /**
 538  * Return a UTF string formed from a sequence of codepoints in hexadecimal
 539  *
 540  * @param    string    $seq        Sequence of codepoints, separated with a space
 541  * @return    string                UTF-8 string
 542  */
 543  function hexseq_to_utf($seq)
 544  {
 545      return implode('', array_map('hex_to_utf', explode(' ', $seq)));
 546  }
 547   
 548  /**
 549  * Convert a codepoint to a UTF-8 char
 550  *
 551  * @param    integer    $cp            Unicode codepoint
 552  * @return    string                UTF-8 string
 553  */
 554  function cp_to_utf($cp)
 555  {
 556      if ($cp > 0xFFFF)
 557      {
 558          return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
 559      }
 560      else if ($cp > 0x7FF)
 561      {
 562          return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
 563      }
 564      else if ($cp > 0x7F)
 565      {
 566          return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F));
 567      }
 568      else
 569      {
 570          return chr($cp);
 571      }
 572  }