Net
[ class tree: Net ] [ index: Net ] [ all elements ]

Source for file IDNA2.php

Documentation is available at IDNA2.php

  1. <?php
  2.  
  3. // {{{ license
  4.  
  5. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
  6. //
  7. // +----------------------------------------------------------------------+
  8. // | This library is free software; you can redistribute it and/or modify |
  9. // | it under the terms of the GNU Lesser General Public License as       |
  10. // | published by the Free Software Foundation; either version 2.1 of the |
  11. // | License, or (at your option) any later version.                      |
  12. // |                                                                      |
  13. // | This library is distributed in the hope that it will be useful, but  |
  14. // | WITHOUT ANY WARRANTY; without even the implied warranty of           |
  15. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
  16. // | Lesser General Public License for more details.                      |
  17. // |                                                                      |
  18. // | You should have received a copy of the GNU Lesser General Public     |
  19. // | License along with this library; if not, write to the Free Software  |
  20. // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
  21. // | USA.                                                                 |
  22. // +----------------------------------------------------------------------+
  23. //
  24.  
  25. // }}}
  26. require_once 'Net/IDNA2/Exception.php';
  27. require_once 'Net/IDNA2/Exception/Nameprep.php';
  28.  
  29. /**
  30.  * Encode/decode Internationalized Domain Names.
  31.  *
  32.  * The class allows to convert internationalized domain names
  33.  * (see RFC 3490 for details) as they can be used with various registries worldwide
  34.  * to be translated between their original (localized) form and their encoded form
  35.  * as it will be used in the DNS (Domain Name System).
  36.  *
  37.  * The class provides two public methods, encode() and decode(), which do exactly
  38.  * what you would expect them to do. You are allowed to use complete domain names,
  39.  * simple strings and complete email addresses as well. That means, that you might
  40.  * use any of the following notations:
  41.  *
  42.  * - www.n�rgler.com
  43.  * - xn--nrgler-wxa
  44.  * - xn--brse-5qa.xn--knrz-1ra.info
  45.  *
  46.  * Unicode input might be given as either UTF-8 string, UCS-4 string or UCS-4
  47.  * array. Unicode output is available in the same formats.
  48.  * You can select your preferred format via {@link set_paramter()}.
  49.  *
  50.  * ACE input and output is always expected to be ASCII.
  51.  *
  52.  * @package Net
  53.  * @author  Markus Nix <mnix@docuverse.de>
  54.  * @author  Matthias Sommerfeld <mso@phlylabs.de>
  55.  * @author  Stefan Neufeind <pear.neufeind@speedpartner.de>
  56.  * @version $Id: IDNA2.php 305344 2010-11-14 23:52:42Z neufeind $
  57.  */
  58. class Net_IDNA2
  59. {
  60.     // {{{ npdata
  61.     /**
  62.      * These Unicode codepoints are
  63.      * mapped to nothing, See RFC3454 for details
  64.      *
  65.      * @static
  66.      * @var array 
  67.      * @access private
  68.      */
  69.     private static $_np_map_nothing = array(
  70.         0xAD,
  71.         0x34F,
  72.         0x1806,
  73.         0x180B,
  74.         0x180C,
  75.         0x180D,
  76.         0x200B,
  77.         0x200C,
  78.         0x200D,
  79.         0x2060,
  80.         0xFE00,
  81.         0xFE01,
  82.         0xFE02,
  83.         0xFE03,
  84.         0xFE04,
  85.         0xFE05,
  86.         0xFE06,
  87.         0xFE07,
  88.         0xFE08,
  89.         0xFE09,
  90.         0xFE0A,
  91.         0xFE0B,
  92.         0xFE0C,
  93.         0xFE0D,
  94.         0xFE0E,
  95.         0xFE0F,
  96.         0xFEFF
  97.     );
  98.  
  99.     /**
  100.      * Prohibited codepints
  101.      *
  102.      * @static
  103.      * @var array 
  104.      * @access private
  105.      */
  106.     private static $_general_prohibited = array(
  107.         0,
  108.         1,
  109.         2,
  110.         3,
  111.         4,
  112.         5,
  113.         6,
  114.         7,
  115.         8,
  116.         9,
  117.         0xA,
  118.         0xB,
  119.         0xC,
  120.         0xD,
  121.         0xE,
  122.         0xF,
  123.         0x10,
  124.         0x11,
  125.         0x12,
  126.         0x13,
  127.         0x14,
  128.         0x15,
  129.         0x16,
  130.         0x17,
  131.         0x18,
  132.         0x19,
  133.         0x1A,
  134.         0x1B,
  135.         0x1C,
  136.         0x1D,
  137.         0x1E,
  138.         0x1F,
  139.         0x20,
  140.         0x21,
  141.         0x22,
  142.         0x23,
  143.         0x24,
  144.         0x25,
  145.         0x26,
  146.         0x27,
  147.         0x28,
  148.         0x29,
  149.         0x2A,
  150.         0x2B,
  151.         0x2C,
  152.         0x2F,
  153.         0x3B,
  154.         0x3C,
  155.         0x3D,
  156.         0x3E,
  157.         0x3F,
  158.         0x40,
  159.         0x5B,
  160.         0x5C,
  161.         0x5D,
  162.         0x5E,
  163.         0x5F,
  164.         0x60,
  165.         0x7B,
  166.         0x7C,
  167.         0x7D,
  168.         0x7E,
  169.         0x7F,
  170.         0x3002
  171.     );
  172.  
  173.     /**
  174.      * Codepints prohibited by Nameprep
  175.      * @static
  176.      * @var array 
  177.      * @access private
  178.      */
  179.     private static $_np_prohibit = array(
  180.         0xA0,
  181.         0x1680,
  182.         0x2000,
  183.         0x2001,
  184.         0x2002,
  185.         0x2003,
  186.         0x2004,
  187.         0x2005,
  188.         0x2006,
  189.         0x2007,
  190.         0x2008,
  191.         0x2009,
  192.         0x200A,
  193.         0x200B,
  194.         0x202F,
  195.         0x205F,
  196.         0x3000,
  197.         0x6DD,
  198.         0x70F,
  199.         0x180E,
  200.         0x200C,
  201.         0x200D,
  202.         0x2028,
  203.         0x2029,
  204.         0xFEFF,
  205.         0xFFF9,
  206.         0xFFFA,
  207.         0xFFFB,
  208.         0xFFFC,
  209.         0xFFFE,
  210.         0xFFFF,
  211.         0x1FFFE,
  212.         0x1FFFF,
  213.         0x2FFFE,
  214.         0x2FFFF,
  215.         0x3FFFE,
  216.         0x3FFFF,
  217.         0x4FFFE,
  218.         0x4FFFF,
  219.         0x5FFFE,
  220.         0x5FFFF,
  221.         0x6FFFE,
  222.         0x6FFFF,
  223.         0x7FFFE,
  224.         0x7FFFF,
  225.         0x8FFFE,
  226.         0x8FFFF,
  227.         0x9FFFE,
  228.         0x9FFFF,
  229.         0xAFFFE,
  230.         0xAFFFF,
  231.         0xBFFFE,
  232.         0xBFFFF,
  233.         0xCFFFE,
  234.         0xCFFFF,
  235.         0xDFFFE,
  236.         0xDFFFF,
  237.         0xEFFFE,
  238.         0xEFFFF,
  239.         0xFFFFE,
  240.         0xFFFFF,
  241.         0x10FFFE,
  242.         0x10FFFF,
  243.         0xFFF9,
  244.         0xFFFA,
  245.         0xFFFB,
  246.         0xFFFC,
  247.         0xFFFD,
  248.         0x340,
  249.         0x341,
  250.         0x200E,
  251.         0x200F,
  252.         0x202A,
  253.         0x202B,
  254.         0x202C,
  255.         0x202D,
  256.         0x202E,
  257.         0x206A,
  258.         0x206B,
  259.         0x206C,
  260.         0x206D,
  261.         0x206E,
  262.         0x206F,
  263.         0xE0001
  264.     );
  265.  
  266.     /**
  267.      * Codepoint ranges prohibited by nameprep
  268.      *
  269.      * @static
  270.      * @var array 
  271.      * @access private
  272.      */
  273.     private static $_np_prohibit_ranges = array(
  274.         array(0x80,     0x9F    ),
  275.         array(0x2060,   0x206F  ),
  276.         array(0x1D173,  0x1D17A ),
  277.         array(0xE000,   0xF8FF  ),
  278.         array(0xF0000,  0xFFFFD ),
  279.         array(0x1000000x10FFFD),
  280.         array(0xFDD0,   0xFDEF  ),
  281.         array(0xD800,   0xDFFF  ),
  282.         array(0x2FF0,   0x2FFB  ),
  283.         array(0xE0020,  0xE007F )
  284.     );
  285.  
  286.     /**
  287.      * Replacement mappings (casemapping, replacement sequences, ...)
  288.      *
  289.      * @static
  290.      * @var array 
  291.      * @access private
  292.      */
  293.     private static $_np_replacemaps = array(
  294.         0x41    => array(0x61),
  295.         0x42    => array(0x62),
  296.         0x43    => array(0x63),
  297.         0x44    => array(0x64),
  298.         0x45    => array(0x65),
  299.         0x46    => array(0x66),
  300.         0x47    => array(0x67),
  301.         0x48    => array(0x68),
  302.         0x49    => array(0x69),
  303.         0x4A    => array(0x6A),
  304.         0x4B    => array(0x6B),
  305.         0x4C    => array(0x6C),
  306.         0x4D    => array(0x6D),
  307.         0x4E    => array(0x6E),
  308.         0x4F    => array(0x6F),
  309.         0x50    => array(0x70),
  310.         0x51    => array(0x71),
  311.         0x52    => array(0x72),
  312.         0x53    => array(0x73),
  313.         0x54    => array(0x74),
  314.         0x55    => array(0x75),
  315.         0x56    => array(0x76),
  316.         0x57    => array(0x77),
  317.         0x58    => array(0x78),
  318.         0x59    => array(0x79),
  319.         0x5A    => array(0x7A),
  320.         0xB5    => array(0x3BC),
  321.         0xC0    => array(0xE0),
  322.         0xC1    => array(0xE1),
  323.         0xC2    => array(0xE2),
  324.         0xC3    => array(0xE3),
  325.         0xC4    => array(0xE4),
  326.         0xC5    => array(0xE5),
  327.         0xC6    => array(0xE6),
  328.         0xC7    => array(0xE7),
  329.         0xC8    => array(0xE8),
  330.         0xC9    => array(0xE9),
  331.         0xCA    => array(0xEA),
  332.         0xCB    => array(0xEB),
  333.         0xCC    => array(0xEC),
  334.         0xCD    => array(0xED),
  335.         0xCE    => array(0xEE),
  336.         0xCF    => array(0xEF),
  337.         0xD0    => array(0xF0),
  338.         0xD1    => array(0xF1),
  339.         0xD2    => array(0xF2),
  340.         0xD3    => array(0xF3),
  341.         0xD4    => array(0xF4),
  342.         0xD5    => array(0xF5),
  343.         0xD6    => array(0xF6),
  344.         0xD8    => array(0xF8),
  345.         0xD9    => array(0xF9),
  346.         0xDA    => array(0xFA),
  347.         0xDB    => array(0xFB),
  348.         0xDC    => array(0xFC),
  349.         0xDD    => array(0xFD),
  350.         0xDE    => array(0xFE),
  351.         0xDF    => array(0x730x73),
  352.         0x100   => array(0x101),
  353.         0x102   => array(0x103),
  354.         0x104   => array(0x105),
  355.         0x106   => array(0x107),
  356.         0x108   => array(0x109),
  357.         0x10A   => array(0x10B),
  358.         0x10C   => array(0x10D),
  359.         0x10E   => array(0x10F),
  360.         0x110   => array(0x111),
  361.         0x112   => array(0x113),
  362.         0x114   => array(0x115),
  363.         0x116   => array(0x117),
  364.         0x118   => array(0x119),
  365.         0x11A   => array(0x11B),
  366.         0x11C   => array(0x11D),
  367.         0x11E   => array(0x11F),
  368.         0x120   => array(0x121),
  369.         0x122   => array(0x123),
  370.         0x124   => array(0x125),
  371.         0x126   => array(0x127),
  372.         0x128   => array(0x129),
  373.         0x12A   => array(0x12B),
  374.         0x12C   => array(0x12D),
  375.         0x12E   => array(0x12F),
  376.         0x130   => array(0x690x307),
  377.         0x132   => array(0x133),
  378.         0x134   => array(0x135),
  379.         0x136   => array(0x137),
  380.         0x139   => array(0x13A),
  381.         0x13B   => array(0x13C),
  382.         0x13D   => array(0x13E),
  383.         0x13F   => array(0x140),
  384.         0x141   => array(0x142),
  385.         0x143   => array(0x144),
  386.         0x145   => array(0x146),
  387.         0x147   => array(0x148),
  388.         0x149   => array(0x2BC0x6E),
  389.         0x14A   => array(0x14B),
  390.         0x14C   => array(0x14D),
  391.         0x14E   => array(0x14F),
  392.         0x150   => array(0x151),
  393.         0x152   => array(0x153),
  394.         0x154   => array(0x155),
  395.         0x156   => array(0x157),
  396.         0x158   => array(0x159),
  397.         0x15A   => array(0x15B),
  398.         0x15C   => array(0x15D),
  399.         0x15E   => array(0x15F),
  400.         0x160   => array(0x161),
  401.         0x162   => array(0x163),
  402.         0x164   => array(0x165),
  403.         0x166   => array(0x167),
  404.         0x168   => array(0x169),
  405.         0x16A   => array(0x16B),
  406.         0x16C   => array(0x16D),
  407.         0x16E   => array(0x16F),
  408.         0x170   => array(0x171),
  409.         0x172   => array(0x173),
  410.         0x174   => array(0x175),
  411.         0x176   => array(0x177),
  412.         0x178   => array(0xFF),
  413.         0x179   => array(0x17A),
  414.         0x17B   => array(0x17C),
  415.         0x17D   => array(0x17E),
  416.         0x17F   => array(0x73),
  417.         0x181   => array(0x253),
  418.         0x182   => array(0x183),
  419.         0x184   => array(0x185),
  420.         0x186   => array(0x254),
  421.         0x187   => array(0x188),
  422.         0x189   => array(0x256),
  423.         0x18A   => array(0x257),
  424.         0x18B   => array(0x18C),
  425.         0x18E   => array(0x1DD),
  426.         0x18F   => array(0x259),
  427.         0x190   => array(0x25B),
  428.         0x191   => array(0x192),
  429.         0x193   => array(0x260),
  430.         0x194   => array(0x263),
  431.         0x196   => array(0x269),
  432.         0x197   => array(0x268),
  433.         0x198   => array(0x199),
  434.         0x19C   => array(0x26F),
  435.         0x19D   => array(0x272),
  436.         0x19F   => array(0x275),
  437.         0x1A0   => array(0x1A1),
  438.         0x1A2   => array(0x1A3),
  439.         0x1A4   => array(0x1A5),
  440.         0x1A6   => array(0x280),
  441.         0x1A7   => array(0x1A8),
  442.         0x1A9   => array(0x283),
  443.         0x1AC   => array(0x1AD),
  444.         0x1AE   => array(0x288),
  445.         0x1AF   => array(0x1B0),
  446.         0x1B1   => array(0x28A),
  447.         0x1B2   => array(0x28B),
  448.         0x1B3   => array(0x1B4),
  449.         0x1B5   => array(0x1B6),
  450.         0x1B7   => array(0x292),
  451.         0x1B8   => array(0x1B9),
  452.         0x1BC   => array(0x1BD),
  453.         0x1C4   => array(0x1C6),
  454.         0x1C5   => array(0x1C6),
  455.         0x1C7   => array(0x1C9),
  456.         0x1C8   => array(0x1C9),
  457.         0x1CA   => array(0x1CC),
  458.         0x1CB   => array(0x1CC),
  459.         0x1CD   => array(0x1CE),
  460.         0x1CF   => array(0x1D0),
  461.         0x1D1   => array(0x1D2),
  462.         0x1D3   => array(0x1D4),
  463.         0x1D5   => array(0x1D6),
  464.         0x1D7   => array(0x1D8),
  465.         0x1D9   => array(0x1DA),
  466.         0x1DB   => array(0x1DC),
  467.         0x1DE   => array(0x1DF),
  468.         0x1E0   => array(0x1E1),
  469.         0x1E2   => array(0x1E3),
  470.         0x1E4   => array(0x1E5),
  471.         0x1E6   => array(0x1E7),
  472.         0x1E8   => array(0x1E9),
  473.         0x1EA   => array(0x1EB),
  474.         0x1EC   => array(0x1ED),
  475.         0x1EE   => array(0x1EF),
  476.         0x1F0   => array(0x6A0x30C),
  477.         0x1F1   => array(0x1F3),
  478.         0x1F2   => array(0x1F3),
  479.         0x1F4   => array(0x1F5),
  480.         0x1F6   => array(0x195),
  481.         0x1F7   => array(0x1BF),
  482.         0x1F8   => array(0x1F9),
  483.         0x1FA   => array(0x1FB),
  484.         0x1FC   => array(0x1FD),
  485.         0x1FE   => array(0x1FF),
  486.         0x200   => array(0x201),
  487.         0x202   => array(0x203),
  488.         0x204   => array(0x205),
  489.         0x206   => array(0x207),
  490.         0x208   => array(0x209),
  491.         0x20A   => array(0x20B),
  492.         0x20C   => array(0x20D),
  493.         0x20E   => array(0x20F),
  494.         0x210   => array(0x211),
  495.         0x212   => array(0x213),
  496.         0x214   => array(0x215),
  497.         0x216   => array(0x217),
  498.         0x218   => array(0x219),
  499.         0x21A   => array(0x21B),
  500.         0x21C   => array(0x21D),
  501.         0x21E   => array(0x21F),
  502.         0x220   => array(0x19E),
  503.         0x222   => array(0x223),
  504.         0x224   => array(0x225),
  505.         0x226   => array(0x227),
  506.         0x228   => array(0x229),
  507.         0x22A   => array(0x22B),
  508.         0x22C   => array(0x22D),
  509.         0x22E   => array(0x22F),
  510.         0x230   => array(0x231),
  511.         0x232   => array(0x233),
  512.         0x345   => array(0x3B9),
  513.         0x37A   => array(0x200x3B9),
  514.         0x386   => array(0x3AC),
  515.         0x388   => array(0x3AD),
  516.         0x389   => array(0x3AE),
  517.         0x38A   => array(0x3AF),
  518.         0x38C   => array(0x3CC),
  519.         0x38E   => array(0x3CD),
  520.         0x38F   => array(0x3CE),
  521.         0x390   => array(0x3B90x3080x301),
  522.         0x391   => array(0x3B1),
  523.         0x392   => array(0x3B2),
  524.         0x393   => array(0x3B3),
  525.         0x394   => array(0x3B4),
  526.         0x395   => array(0x3B5),
  527.         0x396   => array(0x3B6),
  528.         0x397   => array(0x3B7),
  529.         0x398   => array(0x3B8),
  530.         0x399   => array(0x3B9),
  531.         0x39A   => array(0x3BA),
  532.         0x39B   => array(0x3BB),
  533.         0x39C   => array(0x3BC),
  534.         0x39D   => array(0x3BD),
  535.         0x39E   => array(0x3BE),
  536.         0x39F   => array(0x3BF),
  537.         0x3A0   => array(0x3C0),
  538.         0x3A1   => array(0x3C1),
  539.         0x3A3   => array(0x3C3),
  540.         0x3A4   => array(0x3C4),
  541.         0x3A5   => array(0x3C5),
  542.         0x3A6   => array(0x3C6),
  543.         0x3A7   => array(0x3C7),
  544.         0x3A8   => array(0x3C8),
  545.         0x3A9   => array(0x3C9),
  546.         0x3AA   => array(0x3CA),
  547.         0x3AB   => array(0x3CB),
  548.         0x3B0   => array(0x3C50x3080x301),
  549.         0x3C2   => array(0x3C3),
  550.         0x3D0   => array(0x3B2),
  551.         0x3D1   => array(0x3B8),
  552.         0x3D2   => array(0x3C5),
  553.         0x3D3   => array(0x3CD),
  554.         0x3D4   => array(0x3CB),
  555.         0x3D5   => array(0x3C6),
  556.         0x3D6   => array(0x3C0),
  557.         0x3D8   => array(0x3D9),
  558.         0x3DA   => array(0x3DB),
  559.         0x3DC   => array(0x3DD),
  560.         0x3DE   => array(0x3DF),
  561.         0x3E0   => array(0x3E1),
  562.         0x3E2   => array(0x3E3),
  563.         0x3E4   => array(0x3E5),
  564.         0x3E6   => array(0x3E7),
  565.         0x3E8   => array(0x3E9),
  566.         0x3EA   => array(0x3EB),
  567.         0x3EC   => array(0x3ED),
  568.         0x3EE   => array(0x3EF),
  569.         0x3F0   => array(0x3BA),
  570.         0x3F1   => array(0x3C1),
  571.         0x3F2   => array(0x3C3),
  572.         0x3F4   => array(0x3B8),
  573.         0x3F5   => array(0x3B5),
  574.         0x400   => array(0x450),
  575.         0x401   => array(0x451),
  576.         0x402   => array(0x452),
  577.         0x403   => array(0x453),
  578.         0x404   => array(0x454),
  579.         0x405   => array(0x455),
  580.         0x406   => array(0x456),
  581.         0x407   => array(0x457),
  582.         0x408   => array(0x458),
  583.         0x409   => array(0x459),
  584.         0x40A   => array(0x45A),
  585.         0x40B   => array(0x45B),
  586.         0x40C   => array(0x45C),
  587.         0x40D   => array(0x45D),
  588.         0x40E   => array(0x45E),
  589.         0x40F   => array(0x45F),
  590.         0x410   => array(0x430),
  591.         0x411   => array(0x431),
  592.         0x412   => array(0x432),
  593.         0x413   => array(0x433),
  594.         0x414   => array(0x434),
  595.         0x415   => array(0x435),
  596.         0x416   => array(0x436),
  597.         0x417   => array(0x437),
  598.         0x418   => array(0x438),
  599.         0x419   => array(0x439),
  600.         0x41A   => array(0x43A),
  601.         0x41B   => array(0x43B),
  602.         0x41C   => array(0x43C),
  603.         0x41D   => array(0x43D),
  604.         0x41E   => array(0x43E),
  605.         0x41F   => array(0x43F),
  606.         0x420   => array(0x440),
  607.         0x421   => array(0x441),
  608.         0x422   => array(0x442),
  609.         0x423   => array(0x443),
  610.         0x424   => array(0x444),
  611.         0x425   => array(0x445),
  612.         0x426   => array(0x446),
  613.         0x427   => array(0x447),
  614.         0x428   => array(0x448),
  615.         0x429   => array(0x449),
  616.         0x42A   => array(0x44A),
  617.         0x42B   => array(0x44B),
  618.         0x42C   => array(0x44C),
  619.         0x42D   => array(0x44D),
  620.         0x42E   => array(0x44E),
  621.         0x42F   => array(0x44F),
  622.         0x460   => array(0x461),
  623.         0x462   => array(0x463),
  624.         0x464   => array(0x465),
  625.         0x466   => array(0x467),
  626.         0x468   => array(0x469),
  627.         0x46A   => array(0x46B),
  628.         0x46C   => array(0x46D),
  629.         0x46E   => array(0x46F),
  630.         0x470   => array(0x471),
  631.         0x472   => array(0x473),
  632.         0x474   => array(0x475),
  633.         0x476   => array(0x477),
  634.         0x478   => array(0x479),
  635.         0x47A   => array(0x47B),
  636.         0x47C   => array(0x47D),
  637.         0x47E   => array(0x47F),
  638.         0x480   => array(0x481),
  639.         0x48A   => array(0x48B),
  640.         0x48C   => array(0x48D),
  641.         0x48E   => array(0x48F),
  642.         0x490   => array(0x491),
  643.         0x492   => array(0x493),
  644.         0x494   => array(0x495),
  645.         0x496   => array(0x497),
  646.         0x498   => array(0x499),
  647.         0x49A   => array(0x49B),
  648.         0x49C   => array(0x49D),
  649.         0x49E   => array(0x49F),
  650.         0x4A0   => array(0x4A1),
  651.         0x4A2   => array(0x4A3),
  652.         0x4A4   => array(0x4A5),
  653.         0x4A6   => array(0x4A7),
  654.         0x4A8   => array(0x4A9),
  655.         0x4AA   => array(0x4AB),
  656.         0x4AC   => array(0x4AD),
  657.         0x4AE   => array(0x4AF),
  658.         0x4B0   => array(0x4B1),
  659.         0x4B2   => array(0x4B3),
  660.         0x4B4   => array(0x4B5),
  661.         0x4B6   => array(0x4B7),
  662.         0x4B8   => array(0x4B9),
  663.         0x4BA   => array(0x4BB),
  664.         0x4BC   => array(0x4BD),
  665.         0x4BE   => array(0x4BF),
  666.         0x4C1   => array(0x4C2),
  667.         0x4C3   => array(0x4C4),
  668.         0x4C5   => array(0x4C6),
  669.         0x4C7   => array(0x4C8),
  670.         0x4C9   => array(0x4CA),
  671.         0x4CB   => array(0x4CC),
  672.         0x4CD   => array(0x4CE),
  673.         0x4D0   => array(0x4D1),
  674.         0x4D2   => array(0x4D3),
  675.         0x4D4   => array(0x4D5),
  676.         0x4D6   => array(0x4D7),
  677.         0x4D8   => array(0x4D9),
  678.         0x4DA   => array(0x4DB),
  679.         0x4DC   => array(0x4DD),
  680.         0x4DE   => array(0x4DF),
  681.         0x4E0   => array(0x4E1),
  682.         0x4E2   => array(0x4E3),
  683.         0x4E4   => array(0x4E5),
  684.         0x4E6   => array(0x4E7),
  685.         0x4E8   => array(0x4E9),
  686.         0x4EA   => array(0x4EB),
  687.         0x4EC   => array(0x4ED),
  688.         0x4EE   => array(0x4EF),
  689.         0x4F0   => array(0x4F1),
  690.         0x4F2   => array(0x4F3),
  691.         0x4F4   => array(0x4F5),
  692.         0x4F8   => array(0x4F9),
  693.         0x500   => array(0x501),
  694.         0x502   => array(0x503),
  695.         0x504   => array(0x505),
  696.         0x506   => array(0x507),
  697.         0x508   => array(0x509),
  698.         0x50A   => array(0x50B),
  699.         0x50C   => array(0x50D),
  700.         0x50E   => array(0x50F),
  701.         0x531   => array(0x561),
  702.         0x532   => array(0x562),
  703.         0x533   => array(0x563),
  704.         0x534   => array(0x564),
  705.         0x535   => array(0x565),
  706.         0x536   => array(0x566),
  707.         0x537   => array(0x567),
  708.         0x538   => array(0x568),
  709.         0x539   => array(0x569),
  710.         0x53A   => array(0x56A),
  711.         0x53B   => array(0x56B),
  712.         0x53C   => array(0x56C),
  713.         0x53D   => array(0x56D),
  714.         0x53E   => array(0x56E),
  715.         0x53F   => array(0x56F),
  716.         0x540   => array(0x570),
  717.         0x541   => array(0x571),
  718.         0x542   => array(0x572),
  719.         0x543   => array(0x573),
  720.         0x544   => array(0x574),
  721.         0x545   => array(0x575),
  722.         0x546   => array(0x576),
  723.         0x547   => array(0x577),
  724.         0x548   => array(0x578),
  725.         0x549   => array(0x579),
  726.         0x54A   => array(0x57A),
  727.         0x54B   => array(0x57B),
  728.         0x54C   => array(0x57C),
  729.         0x54D   => array(0x57D),
  730.         0x54E   => array(0x57E),
  731.         0x54F   => array(0x57F),
  732.         0x550   => array(0x580),
  733.         0x551   => array(0x581),
  734.         0x552   => array(0x582),
  735.         0x553   => array(0x583),
  736.         0x554   => array(0x584),
  737.         0x555   => array(0x585),
  738.         0x556   => array(0x586),
  739.         0x587   => array(0x5650x582),
  740.         0x1E00  => array(0x1E01),
  741.         0x1E02  => array(0x1E03),
  742.         0x1E04  => array(0x1E05),
  743.         0x1E06  => array(0x1E07),
  744.         0x1E08  => array(0x1E09),
  745.         0x1E0A  => array(0x1E0B),
  746.         0x1E0C  => array(0x1E0D),
  747.         0x1E0E  => array(0x1E0F),
  748.         0x1E10  => array(0x1E11),
  749.         0x1E12  => array(0x1E13),
  750.         0x1E14  => array(0x1E15),
  751.         0x1E16  => array(0x1E17),
  752.         0x1E18  => array(0x1E19),
  753.         0x1E1A  => array(0x1E1B),
  754.         0x1E1C  => array(0x1E1D),
  755.         0x1E1E  => array(0x1E1F),
  756.         0x1E20  => array(0x1E21),
  757.         0x1E22  => array(0x1E23),
  758.         0x1E24  => array(0x1E25),
  759.         0x1E26  => array(0x1E27),
  760.         0x1E28  => array(0x1E29),
  761.         0x1E2A  => array(0x1E2B),
  762.         0x1E2C  => array(0x1E2D),
  763.         0x1E2E  => array(0x1E2F),
  764.         0x1E30  => array(0x1E31),
  765.         0x1E32  => array(0x1E33),
  766.         0x1E34  => array(0x1E35),
  767.         0x1E36  => array(0x1E37),
  768.         0x1E38  => array(0x1E39),
  769.         0x1E3A  => array(0x1E3B),
  770.         0x1E3C  => array(0x1E3D),
  771.         0x1E3E  => array(0x1E3F),
  772.         0x1E40  => array(0x1E41),
  773.         0x1E42  => array(0x1E43),
  774.         0x1E44  => array(0x1E45),
  775.         0x1E46  => array(0x1E47),
  776.         0x1E48  => array(0x1E49),
  777.         0x1E4A  => array(0x1E4B),
  778.         0x1E4C  => array(0x1E4D),
  779.         0x1E4E  => array(0x1E4F),
  780.         0x1E50  => array(0x1E51),
  781.         0x1E52  => array(0x1E53),
  782.         0x1E54  => array(0x1E55),
  783.         0x1E56  => array(0x1E57),
  784.         0x1E58  => array(0x1E59),
  785.         0x1E5A  => array(0x1E5B),
  786.         0x1E5C  => array(0x1E5D),
  787.         0x1E5E  => array(0x1E5F),
  788.         0x1E60  => array(0x1E61),
  789.         0x1E62  => array(0x1E63),
  790.         0x1E64  => array(0x1E65),
  791.         0x1E66  => array(0x1E67),
  792.         0x1E68  => array(0x1E69),
  793.         0x1E6A  => array(0x1E6B),
  794.         0x1E6C  => array(0x1E6D),
  795.         0x1E6E  => array(0x1E6F),
  796.         0x1E70  => array(0x1E71),
  797.         0x1E72  => array(0x1E73),
  798.         0x1E74  => array(0x1E75),
  799.         0x1E76  => array(0x1E77),
  800.         0x1E78  => array(0x1E79),
  801.         0x1E7A  => array(0x1E7B),
  802.         0x1E7C  => array(0x1E7D),
  803.         0x1E7E  => array(0x1E7F),
  804.         0x1E80  => array(0x1E81),
  805.         0x1E82  => array(0x1E83),
  806.         0x1E84  => array(0x1E85),
  807.         0x1E86  => array(0x1E87),
  808.         0x1E88  => array(0x1E89),
  809.         0x1E8A  => array(0x1E8B),
  810.         0x1E8C  => array(0x1E8D),
  811.         0x1E8E  => array(0x1E8F),
  812.         0x1E90  => array(0x1E91),
  813.         0x1E92  => array(0x1E93),
  814.         0x1E94  => array(0x1E95),
  815.         0x1E96  => array(0x680x331),
  816.         0x1E97  => array(0x740x308),
  817.         0x1E98  => array(0x770x30A),
  818.         0x1E99  => array(0x790x30A),
  819.         0x1E9A  => array(0x610x2BE),
  820.         0x1E9B  => array(0x1E61),
  821.         0x1EA0  => array(0x1EA1),
  822.         0x1EA2  => array(0x1EA3),
  823.         0x1EA4  => array(0x1EA5),
  824.         0x1EA6  => array(0x1EA7),
  825.         0x1EA8  => array(0x1EA9),
  826.         0x1EAA  => array(0x1EAB),
  827.         0x1EAC  => array(0x1EAD),
  828.         0x1EAE  => array(0x1EAF),
  829.         0x1EB0  => array(0x1EB1),
  830.         0x1EB2  => array(0x1EB3),
  831.         0x1EB4  => array(0x1EB5),
  832.         0x1EB6  => array(0x1EB7),
  833.         0x1EB8  => array(0x1EB9),
  834.         0x1EBA  => array(0x1EBB),
  835.         0x1EBC  => array(0x1EBD),
  836.         0x1EBE  => array(0x1EBF),
  837.         0x1EC0  => array(0x1EC1),
  838.         0x1EC2  => array(0x1EC3),
  839.         0x1EC4  => array(0x1EC5),
  840.         0x1EC6  => array(0x1EC7),
  841.         0x1EC8  => array(0x1EC9),
  842.         0x1ECA  => array(0x1ECB),
  843.         0x1ECC  => array(0x1ECD),
  844.         0x1ECE  => array(0x1ECF),
  845.         0x1ED0  => array(0x1ED1),
  846.         0x1ED2  => array(0x1ED3),
  847.         0x1ED4  => array(0x1ED5),
  848.         0x1ED6  => array(0x1ED7),
  849.         0x1ED8  => array(0x1ED9),
  850.         0x1EDA  => array(0x1EDB),
  851.         0x1EDC  => array(0x1EDD),
  852.         0x1EDE  => array(0x1EDF),
  853.         0x1EE0  => array(0x1EE1),
  854.         0x1EE2  => array(0x1EE3),
  855.         0x1EE4  => array(0x1EE5),
  856.         0x1EE6  => array(0x1EE7),
  857.         0x1EE8  => array(0x1EE9),
  858.         0x1EEA  => array(0x1EEB),
  859.         0x1EEC  => array(0x1EED),
  860.         0x1EEE  => array(0x1EEF),
  861.         0x1EF0  => array(0x1EF1),
  862.         0x1EF2  => array(0x1EF3),
  863.         0x1EF4  => array(0x1EF5),
  864.         0x1EF6  => array(0x1EF7),
  865.         0x1EF8  => array(0x1EF9),
  866.         0x1F08  => array(0x1F00),
  867.         0x1F09  => array(0x1F01),
  868.         0x1F0A  => array(0x1F02),
  869.         0x1F0B  => array(0x1F03),
  870.         0x1F0C  => array(0x1F04),
  871.         0x1F0D  => array(0x1F05),
  872.         0x1F0E  => array(0x1F06),
  873.         0x1F0F  => array(0x1F07),
  874.         0x1F18  => array(0x1F10),
  875.         0x1F19  => array(0x1F11),
  876.         0x1F1A  => array(0x1F12),
  877.         0x1F1B  => array(0x1F13),
  878.         0x1F1C  => array(0x1F14),
  879.         0x1F1D  => array(0x1F15),
  880.         0x1F28  => array(0x1F20),
  881.         0x1F29  => array(0x1F21),
  882.         0x1F2A  => array(0x1F22),
  883.         0x1F2B  => array(0x1F23),
  884.         0x1F2C  => array(0x1F24),
  885.         0x1F2D  => array(0x1F25),
  886.         0x1F2E  => array(0x1F26),
  887.         0x1F2F  => array(0x1F27),
  888.         0x1F38  => array(0x1F30),
  889.         0x1F39  => array(0x1F31),
  890.         0x1F3A  => array(0x1F32),
  891.         0x1F3B  => array(0x1F33),
  892.         0x1F3C  => array(0x1F34),
  893.         0x1F3D  => array(0x1F35),
  894.         0x1F3E  => array(0x1F36),
  895.         0x1F3F  => array(0x1F37),
  896.         0x1F48  => array(0x1F40),
  897.         0x1F49  => array(0x1F41),
  898.         0x1F4A  => array(0x1F42),
  899.         0x1F4B  => array(0x1F43),
  900.         0x1F4C  => array(0x1F44),
  901.         0x1F4D  => array(0x1F45),
  902.         0x1F50  => array(0x3C50x313),
  903.         0x1F52  => array(0x3C50x3130x300),
  904.         0x1F54  => array(0x3C50x3130x301),
  905.         0x1F56  => array(0x3C50x3130x342),
  906.         0x1F59  => array(0x1F51),
  907.         0x1F5B  => array(0x1F53),
  908.         0x1F5D  => array(0x1F55),
  909.         0x1F5F  => array(0x1F57),
  910.         0x1F68  => array(0x1F60),
  911.         0x1F69  => array(0x1F61),
  912.         0x1F6A  => array(0x1F62),
  913.         0x1F6B  => array(0x1F63),
  914.         0x1F6C  => array(0x1F64),
  915.         0x1F6D  => array(0x1F65),
  916.         0x1F6E  => array(0x1F66),
  917.         0x1F6F  => array(0x1F67),
  918.         0x1F80  => array(0x1F000x3B9),
  919.         0x1F81  => array(0x1F010x3B9),
  920.         0x1F82  => array(0x1F020x3B9),
  921.         0x1F83  => array(0x1F030x3B9),
  922.         0x1F84  => array(0x1F040x3B9),
  923.         0x1F85  => array(0x1F050x3B9),
  924.         0x1F86  => array(0x1F060x3B9),
  925.         0x1F87  => array(0x1F070x3B9),
  926.         0x1F88  => array(0x1F000x3B9),
  927.         0x1F89  => array(0x1F010x3B9),
  928.         0x1F8A  => array(0x1F020x3B9),
  929.         0x1F8B  => array(0x1F030x3B9),
  930.         0x1F8C  => array(0x1F040x3B9),
  931.         0x1F8D  => array(0x1F050x3B9),
  932.         0x1F8E  => array(0x1F060x3B9),
  933.         0x1F8F  => array(0x1F070x3B9),
  934.         0x1F90  => array(0x1F200x3B9),
  935.         0x1F91  => array(0x1F210x3B9),
  936.         0x1F92  => array(0x1F220x3B9),
  937.         0x1F93  => array(0x1F230x3B9),
  938.         0x1F94  => array(0x1F240x3B9),
  939.         0x1F95  => array(0x1F250x3B9),
  940.         0x1F96  => array(0x1F260x3B9),
  941.         0x1F97  => array(0x1F270x3B9),
  942.         0x1F98  => array(0x1F200x3B9),
  943.         0x1F99  => array(0x1F210x3B9),
  944.         0x1F9A  => array(0x1F220x3B9),
  945.         0x1F9B  => array(0x1F230x3B9),
  946.         0x1F9C  => array(0x1F240x3B9),
  947.         0x1F9D  => array(0x1F250x3B9),
  948.         0x1F9E  => array(0x1F260x3B9),
  949.         0x1F9F  => array(0x1F270x3B9),
  950.         0x1FA0  => array(0x1F600x3B9),
  951.         0x1FA1  => array(0x1F610x3B9),
  952.         0x1FA2  => array(0x1F620x3B9),
  953.         0x1FA3  => array(0x1F630x3B9),
  954.         0x1FA4  => array(0x1F640x3B9),
  955.         0x1FA5  => array(0x1F650x3B9),
  956.         0x1FA6  => array(0x1F660x3B9),
  957.         0x1FA7  => array(0x1F670x3B9),
  958.         0x1FA8  => array(0x1F600x3B9),
  959.         0x1FA9  => array(0x1F610x3B9),
  960.         0x1FAA  => array(0x1F620x3B9),
  961.         0x1FAB  => array(0x1F630x3B9),
  962.         0x1FAC  => array(0x1F640x3B9),
  963.         0x1FAD  => array(0x1F650x3B9),
  964.         0x1FAE  => array(0x1F660x3B9),
  965.         0x1FAF  => array(0x1F670x3B9),
  966.         0x1FB2  => array(0x1F700x3B9),
  967.         0x1FB3  => array(0x3B10x3B9),
  968.         0x1FB4  => array(0x3AC0x3B9),
  969.         0x1FB6  => array(0x3B10x342),
  970.         0x1FB7  => array(0x3B10x3420x3B9),
  971.         0x1FB8  => array(0x1FB0),
  972.         0x1FB9  => array(0x1FB1),
  973.         0x1FBA  => array(0x1F70),
  974.         0x1FBB  => array(0x1F71),
  975.         0x1FBC  => array(0x3B10x3B9),
  976.         0x1FBE  => array(0x3B9),
  977.         0x1FC2  => array(0x1F740x3B9),
  978.         0x1FC3  => array(0x3B70x3B9),
  979.         0x1FC4  => array(0x3AE0x3B9),
  980.         0x1FC6  => array(0x3B70x342),
  981.         0x1FC7  => array(0x3B70x3420x3B9),
  982.         0x1FC8  => array(0x1F72),
  983.         0x1FC9  => array(0x1F73),
  984.         0x1FCA  => array(0x1F74),
  985.         0x1FCB  => array(0x1F75),
  986.         0x1FCC  => array(0x3B70x3B9),
  987.         0x1FD2  => array(0x3B90x3080x300),
  988.         0x1FD3  => array(0x3B90x3080x301),
  989.         0x1FD6  => array(0x3B90x342),
  990.         0x1FD7  => array(0x3B90x3080x342),
  991.         0x1FD8  => array(0x1FD0),
  992.         0x1FD9  => array(0x1FD1),
  993.         0x1FDA  => array(0x1F76),
  994.         0x1FDB  => array(0x1F77),
  995.         0x1FE2  => array(0x3C50x3080x300),
  996.         0x1FE3  => array(0x3C50x3080x301),
  997.         0x1FE4  => array(0x3C10x313),
  998.         0x1FE6  => array(0x3C50x342),
  999.         0x1FE7  => array(0x3C50x3080x342),
  1000.         0x1FE8  => array(0x1FE0),
  1001.         0x1FE9  => array(0x1FE1),
  1002.         0x1FEA  => array(0x1F7A),
  1003.         0x1FEB  => array(0x1F7B),
  1004.         0x1FEC  => array(0x1FE5),
  1005.         0x1FF2  => array(0x1F7C0x3B9),
  1006.         0x1FF3  => array(0x3C90x3B9),
  1007.         0x1FF4  => array(0x3CE0x3B9),
  1008.         0x1FF6  => array(0x3C90x342),
  1009.         0x1FF7  => array(0x3C90x3420x3B9),
  1010.         0x1FF8  => array(0x1F78),
  1011.         0x1FF9  => array(0x1F79),
  1012.         0x1FFA  => array(0x1F7C),
  1013.         0x1FFB  => array(0x1F7D),
  1014.         0x1FFC  => array(0x3C90x3B9),
  1015.         0x20A8  => array(0x720x73),
  1016.         0x2102  => array(0x63),
  1017.         0x2103  => array(0xB00x63),
  1018.         0x2107  => array(0x25B),
  1019.         0x2109  => array(0xB00x66),
  1020.         0x210B  => array(0x68),
  1021.         0x210C  => array(0x68),
  1022.         0x210D  => array(0x68),
  1023.         0x2110  => array(0x69),
  1024.         0x2111  => array(0x69),
  1025.         0x2112  => array(0x6C),
  1026.         0x2115  => array(0x6E),
  1027.         0x2116  => array(0x6E0x6F),
  1028.         0x2119  => array(0x70),
  1029.         0x211A  => array(0x71),
  1030.         0x211B  => array(0x72),
  1031.         0x211C  => array(0x72),
  1032.         0x211D  => array(0x72),
  1033.         0x2120  => array(0x730x6D),
  1034.         0x2121  => array(0x740x650x6C),
  1035.         0x2122  => array(0x740x6D),
  1036.         0x2124  => array(0x7A),
  1037.         0x2126  => array(0x3C9),
  1038.         0x2128  => array(0x7A),
  1039.         0x212A  => array(0x6B),
  1040.         0x212B  => array(0xE5),
  1041.         0x212C  => array(0x62),
  1042.         0x212D  => array(0x63),
  1043.         0x2130  => array(0x65),
  1044.         0x2131  => array(0x66),
  1045.         0x2133  => array(0x6D),
  1046.         0x213E  => array(0x3B3),
  1047.         0x213F  => array(0x3C0),
  1048.         0x2145  => array(0x64),
  1049.         0x2160  => array(0x2170),
  1050.         0x2161  => array(0x2171),
  1051.         0x2162  => array(0x2172),
  1052.         0x2163  => array(0x2173),
  1053.         0x2164  => array(0x2174),
  1054.         0x2165  => array(0x2175),
  1055.         0x2166  => array(0x2176),
  1056.         0x2167  => array(0x2177),
  1057.         0x2168  => array(0x2178),
  1058.         0x2169  => array(0x2179),
  1059.         0x216A  => array(0x217A),
  1060.         0x216B  => array(0x217B),
  1061.         0x216C  => array(0x217C),
  1062.         0x216D  => array(0x217D),
  1063.         0x216E  => array(0x217E),
  1064.         0x216F  => array(0x217F),
  1065.         0x24B6  => array(0x24D0),
  1066.         0x24B7  => array(0x24D1),
  1067.         0x24B8  => array(0x24D2),
  1068.         0x24B9  => array(0x24D3),
  1069.         0x24BA  => array(0x24D4),
  1070.         0x24BB  => array(0x24D5),
  1071.         0x24BC  => array(0x24D6),
  1072.         0x24BD  => array(0x24D7),
  1073.         0x24BE  => array(0x24D8),
  1074.         0x24BF  => array(0x24D9),
  1075.         0x24C0  => array(0x24DA),
  1076.         0x24C1  => array(0x24DB),
  1077.         0x24C2  => array(0x24DC),
  1078.         0x24C3  => array(0x24DD),
  1079.         0x24C4  => array(0x24DE),
  1080.         0x24C5  => array(0x24DF),
  1081.         0x24C6  => array(0x24E0),
  1082.         0x24C7  => array(0x24E1),
  1083.         0x24C8  => array(0x24E2),
  1084.         0x24C9  => array(0x24E3),
  1085.         0x24CA  => array(0x24E4),
  1086.         0x24CB  => array(0x24E5),
  1087.         0x24CC  => array(0x24E6),
  1088.         0x24CD  => array(0x24E7),
  1089.         0x24CE  => array(0x24E8),
  1090.         0x24CF  => array(0x24E9),
  1091.         0x3371  => array(0x680x700x61),
  1092.         0x3373  => array(0x610x75),
  1093.         0x3375  => array(0x6F0x76),
  1094.         0x3380  => array(0x700x61),
  1095.         0x3381  => array(0x6E0x61),
  1096.         0x3382  => array(0x3BC0x61),
  1097.         0x3383  => array(0x6D0x61),
  1098.         0x3384  => array(0x6B0x61),
  1099.         0x3385  => array(0x6B0x62),
  1100.         0x3386  => array(0x6D0x62),
  1101.         0x3387  => array(0x670x62),
  1102.         0x338A  => array(0x700x66),
  1103.         0x338B  => array(0x6E0x66),
  1104.         0x338C  => array(0x3BC0x66),
  1105.         0x3390  => array(0x680x7A),
  1106.         0x3391  => array(0x6B0x680x7A),
  1107.         0x3392  => array(0x6D0x680x7A),
  1108.         0x3393  => array(0x670x680x7A),
  1109.         0x3394  => array(0x740x680x7A),
  1110.         0x33A9  => array(0x700x61),
  1111.         0x33AA  => array(0x6B0x700x61),
  1112.         0x33AB  => array(0x6D0x700x61),
  1113.         0x33AC  => array(0x670x700x61),
  1114.         0x33B4  => array(0x700x76),
  1115.         0x33B5  => array(0x6E0x76),
  1116.         0x33B6  => array(0x3BC0x76),
  1117.         0x33B7  => array(0x6D0x76),
  1118.         0x33B8  => array(0x6B0x76),
  1119.         0x33B9  => array(0x6D0x76),
  1120.         0x33BA  => array(0x700x77),
  1121.         0x33BB  => array(0x6E0x77),
  1122.         0x33BC  => array(0x3BC0x77),
  1123.         0x33BD  => array(0x6D0x77),
  1124.         0x33BE  => array(0x6B0x77),
  1125.         0x33BF  => array(0x6D0x77),
  1126.         0x33C0  => array(0x6B0x3C9),
  1127.         0x33C1  => array(0x6D0x3C9),
  1128.         /* 0x33C2  => array(0x61, 0x2E, 0x6D, 0x2E), */
  1129.         0x33C3  => array(0x620x71),
  1130.         0x33C6  => array(0x630x22150x6B0x67),
  1131.         0x33C7  => array(0x630x6F0x2E),
  1132.         0x33C8  => array(0x640x62),
  1133.         0x33C9  => array(0x670x79),
  1134.         0x33CB  => array(0x680x70),
  1135.         0x33CD  => array(0x6B0x6B),
  1136.         0x33CE  => array(0x6B0x6D),
  1137.         0x33D7  => array(0x700x68),
  1138.         0x33D9  => array(0x700x700x6D),
  1139.         0x33DA  => array(0x700x72),
  1140.         0x33DC  => array(0x730x76),
  1141.         0x33DD  => array(0x770x62),
  1142.         0xFB00  => array(0x660x66),
  1143.         0xFB01  => array(0x660x69),
  1144.         0xFB02  => array(0x660x6C),
  1145.         0xFB03  => array(0x660x660x69),
  1146.         0xFB04  => array(0x660x660x6C),
  1147.         0xFB05  => array(0x730x74),
  1148.         0xFB06  => array(0x730x74),
  1149.         0xFB13  => array(0x5740x576),
  1150.         0xFB14  => array(0x5740x565),
  1151.         0xFB15  => array(0x5740x56B),
  1152.         0xFB16  => array(0x57E0x576),
  1153.         0xFB17  => array(0x5740x56D),
  1154.         0xFF21  => array(0xFF41),
  1155.         0xFF22  => array(0xFF42),
  1156.         0xFF23  => array(0xFF43),
  1157.         0xFF24  => array(0xFF44),
  1158.         0xFF25  => array(0xFF45),
  1159.         0xFF26  => array(0xFF46),
  1160.         0xFF27  => array(0xFF47),
  1161.         0xFF28  => array(0xFF48),
  1162.         0xFF29  => array(0xFF49),
  1163.         0xFF2A  => array(0xFF4A),
  1164.         0xFF2B  => array(0xFF4B),
  1165.         0xFF2C  => array(0xFF4C),
  1166.         0xFF2D  => array(0xFF4D),
  1167.         0xFF2E  => array(0xFF4E),
  1168.         0xFF2F  => array(0xFF4F),
  1169.         0xFF30  => array(0xFF50),
  1170.         0xFF31  => array(0xFF51),
  1171.         0xFF32  => array(0xFF52),
  1172.         0xFF33  => array(0xFF53),
  1173.         0xFF34  => array(0xFF54),
  1174.         0xFF35  => array(0xFF55),
  1175.         0xFF36  => array(0xFF56),
  1176.         0xFF37  => array(0xFF57),
  1177.         0xFF38  => array(0xFF58),
  1178.         0xFF39  => array(0xFF59),
  1179.         0xFF3A  => array(0xFF5A),
  1180.         0x10400 => array(0x10428),
  1181.         0x10401 => array(0x10429),
  1182.         0x10402 => array(0x1042A),
  1183.         0x10403 => array(0x1042B),
  1184.         0x10404 => array(0x1042C),
  1185.         0x10405 => array(0x1042D),
  1186.         0x10406 => array(0x1042E),
  1187.         0x10407 => array(0x1042F),
  1188.         0x10408 => array(0x10430),
  1189.         0x10409 => array(0x10431),
  1190.         0x1040A => array(0x10432),
  1191.         0x1040B => array(0x10433),
  1192.         0x1040C => array(0x10434),
  1193.         0x1040D => array(0x10435),
  1194.         0x1040E => array(0x10436),
  1195.         0x1040F => array(0x10437),
  1196.         0x10410 => array(0x10438),
  1197.         0x10411 => array(0x10439),
  1198.         0x10412 => array(0x1043A),
  1199.         0x10413 => array(0x1043B),
  1200.         0x10414 => array(0x1043C),
  1201.         0x10415 => array(0x1043D),
  1202.         0x10416 => array(0x1043E),
  1203.         0x10417 => array(0x1043F),
  1204.         0x10418 => array(0x10440),
  1205.         0x10419 => array(0x10441),
  1206.         0x1041A => array(0x10442),
  1207.         0x1041B => array(0x10443),
  1208.         0x1041C => array(0x10444),
  1209.         0x1041D => array(0x10445),
  1210.         0x1041E => array(0x10446),
  1211.         0x1041F => array(0x10447),
  1212.         0x10420 => array(0x10448),
  1213.         0x10421 => array(0x10449),
  1214.         0x10422 => array(0x1044A),
  1215.         0x10423 => array(0x1044B),
  1216.         0x10424 => array(0x1044C),
  1217.         0x10425 => array(0x1044D),
  1218.         0x1D400 => array(0x61),
  1219.         0x1D401 => array(0x62),
  1220.         0x1D402 => array(0x63),
  1221.         0x1D403 => array(0x64),
  1222.         0x1D404 => array(0x65),
  1223.         0x1D405 => array(0x66),
  1224.         0x1D406 => array(0x67),
  1225.         0x1D407 => array(0x68),
  1226.         0x1D408 => array(0x69),
  1227.         0x1D409 => array(0x6A),
  1228.         0x1D40A => array(0x6B),
  1229.         0x1D40B => array(0x6C),
  1230.         0x1D40C => array(0x6D),
  1231.         0x1D40D => array(0x6E),
  1232.         0x1D40E => array(0x6F),
  1233.         0x1D40F => array(0x70),
  1234.         0x1D410 => array(0x71),
  1235.         0x1D411 => array(0x72),
  1236.         0x1D412 => array(0x73),
  1237.         0x1D413 => array(0x74),
  1238.         0x1D414 => array(0x75),
  1239.         0x1D415 => array(0x76),
  1240.         0x1D416 => array(0x77),
  1241.         0x1D417 => array(0x78),
  1242.         0x1D418 => array(0x79),
  1243.         0x1D419 => array(0x7A),
  1244.         0x1D434 => array(0x61),
  1245.         0x1D435 => array(0x62),
  1246.         0x1D436 => array(0x63),
  1247.         0x1D437 => array(0x64),
  1248.         0x1D438 => array(0x65),
  1249.         0x1D439 => array(0x66),
  1250.         0x1D43A => array(0x67),
  1251.         0x1D43B => array(0x68),
  1252.         0x1D43C => array(0x69),
  1253.         0x1D43D => array(0x6A),
  1254.         0x1D43E => array(0x6B),
  1255.         0x1D43F => array(0x6C),
  1256.         0x1D440 => array(0x6D),
  1257.         0x1D441 => array(0x6E),
  1258.         0x1D442 => array(0x6F),
  1259.         0x1D443 => array(0x70),
  1260.         0x1D444 => array(0x71),
  1261.         0x1D445 => array(0x72),
  1262.         0x1D446 => array(0x73),
  1263.         0x1D447 => array(0x74),
  1264.         0x1D448 => array(0x75),
  1265.         0x1D449 => array(0x76),
  1266.         0x1D44A => array(0x77),
  1267.         0x1D44B => array(0x78),
  1268.         0x1D44C => array(0x79),
  1269.         0x1D44D => array(0x7A),
  1270.         0x1D468 => array(0x61),
  1271.         0x1D469 => array(0x62),
  1272.         0x1D46A => array(0x63),
  1273.         0x1D46B => array(0x64),
  1274.         0x1D46C => array(0x65),
  1275.         0x1D46D => array(0x66),
  1276.         0x1D46E => array(0x67),
  1277.         0x1D46F => array(0x68),
  1278.         0x1D470 => array(0x69),
  1279.         0x1D471 => array(0x6A),
  1280.         0x1D472 => array(0x6B),
  1281.         0x1D473 => array(0x6C),
  1282.         0x1D474 => array(0x6D),
  1283.         0x1D475 => array(0x6E),
  1284.         0x1D476 => array(0x6F),
  1285.         0x1D477 => array(0x70),
  1286.         0x1D478 => array(0x71),
  1287.         0x1D479 => array(0x72),
  1288.         0x1D47A => array(0x73),
  1289.         0x1D47B => array(0x74),
  1290.         0x1D47C => array(0x75),
  1291.         0x1D47D => array(0x76),
  1292.         0x1D47E => array(0x77),
  1293.         0x1D47F => array(0x78),
  1294.         0x1D480 => array(0x79),
  1295.         0x1D481 => array(0x7A),
  1296.         0x1D49C => array(0x61),
  1297.         0x1D49E => array(0x63),
  1298.         0x1D49F => array(0x64),
  1299.         0x1D4A2 => array(0x67),
  1300.         0x1D4A5 => array(0x6A),
  1301.         0x1D4A6 => array(0x6B),
  1302.         0x1D4A9 => array(0x6E),
  1303.         0x1D4AA => array(0x6F),
  1304.         0x1D4AB => array(0x70),
  1305.         0x1D4AC => array(0x71),
  1306.         0x1D4AE => array(0x73),
  1307.         0x1D4AF => array(0x74),
  1308.         0x1D4B0 => array(0x75),
  1309.         0x1D4B1 => array(0x76),
  1310.         0x1D4B2 => array(0x77),
  1311.         0x1D4B3 => array(0x78),
  1312.         0x1D4B4 => array(0x79),
  1313.         0x1D4B5 => array(0x7A),
  1314.         0x1D4D0 => array(0x61),
  1315.         0x1D4D1 => array(0x62),
  1316.         0x1D4D2 => array(0x63),
  1317.         0x1D4D3 => array(0x64),
  1318.         0x1D4D4 => array(0x65),
  1319.         0x1D4D5 => array(0x66),
  1320.         0x1D4D6 => array(0x67),
  1321.         0x1D4D7 => array(0x68),
  1322.         0x1D4D8 => array(0x69),
  1323.         0x1D4D9 => array(0x6A),
  1324.         0x1D4DA => array(0x6B),
  1325.         0x1D4DB => array(0x6C),
  1326.         0x1D4DC => array(0x6D),
  1327.         0x1D4DD => array(0x6E),
  1328.         0x1D4DE => array(0x6F),
  1329.         0x1D4DF => array(0x70),
  1330.         0x1D4E0 => array(0x71),
  1331.         0x1D4E1 => array(0x72),
  1332.         0x1D4E2 => array(0x73),
  1333.         0x1D4E3 => array(0x74),
  1334.         0x1D4E4 => array(0x75),
  1335.         0x1D4E5 => array(0x76),
  1336.         0x1D4E6 => array(0x77),
  1337.         0x1D4E7 => array(0x78),
  1338.         0x1D4E8 => array(0x79),
  1339.         0x1D4E9 => array(0x7A),
  1340.         0x1D504 => array(0x61),
  1341.         0x1D505 => array(0x62),
  1342.         0x1D507 => array(0x64),
  1343.         0x1D508 => array(0x65),
  1344.         0x1D509 => array(0x66),
  1345.         0x1D50A => array(0x67),
  1346.         0x1D50D => array(0x6A),
  1347.         0x1D50E => array(0x6B),
  1348.         0x1D50F => array(0x6C),
  1349.         0x1D510 => array(0x6D),
  1350.         0x1D511 => array(0x6E),
  1351.         0x1D512 => array(0x6F),
  1352.         0x1D513 => array(0x70),
  1353.         0x1D514 => array(0x71),
  1354.         0x1D516 => array(0x73),
  1355.         0x1D517 => array(0x74),
  1356.         0x1D518 => array(0x75),
  1357.         0x1D519 => array(0x76),
  1358.         0x1D51A => array(0x77),
  1359.         0x1D51B => array(0x78),
  1360.         0x1D51C => array(0x79),
  1361.         0x1D538 => array(0x61),
  1362.         0x1D539 => array(0x62),
  1363.         0x1D53B => array(0x64),
  1364.         0x1D53C => array(0x65),
  1365.         0x1D53D => array(0x66),
  1366.         0x1D53E => array(0x67),
  1367.         0x1D540 => array(0x69),
  1368.         0x1D541 => array(0x6A),
  1369.         0x1D542 => array(0x6B),
  1370.         0x1D543 => array(0x6C),
  1371.         0x1D544 => array(0x6D),
  1372.         0x1D546 => array(0x6F),
  1373.         0x1D54A => array(0x73),
  1374.         0x1D54B => array(0x74),
  1375.         0x1D54C => array(0x75),
  1376.         0x1D54D => array(0x76),
  1377.         0x1D54E => array(0x77),
  1378.         0x1D54F => array(0x78),
  1379.         0x1D550 => array(0x79),
  1380.         0x1D56C => array(0x61),
  1381.         0x1D56D => array(0x62),
  1382.         0x1D56E => array(0x63),
  1383.         0x1D56F => array(0x64),
  1384.         0x1D570 => array(0x65),
  1385.         0x1D571 => array(0x66),
  1386.         0x1D572 => array(0x67),
  1387.         0x1D573 => array(0x68),
  1388.         0x1D574 => array(0x69),
  1389.         0x1D575 => array(0x6A),
  1390.         0x1D576 => array(0x6B),
  1391.         0x1D577 => array(0x6C),
  1392.         0x1D578 => array(0x6D),
  1393.         0x1D579 => array(0x6E),
  1394.         0x1D57A => array(0x6F),
  1395.         0x1D57B => array(0x70),
  1396.         0x1D57C => array(0x71),
  1397.         0x1D57D => array(0x72),
  1398.         0x1D57E => array(0x73),
  1399.         0x1D57F => array(0x74),
  1400.         0x1D580 => array(0x75),
  1401.         0x1D581 => array(0x76),
  1402.         0x1D582 => array(0x77),
  1403.         0x1D583 => array(0x78),
  1404.         0x1D584 => array(0x79),
  1405.         0x1D585 => array(0x7A),
  1406.         0x1D5A0 => array(0x61),
  1407.         0x1D5A1 => array(0x62),
  1408.         0x1D5A2 => array(0x63),
  1409.         0x1D5A3 => array(0x64),
  1410.         0x1D5A4 => array(0x65),
  1411.         0x1D5A5 => array(0x66),
  1412.         0x1D5A6 => array(0x67),
  1413.         0x1D5A7 => array(0x68),
  1414.         0x1D5A8 => array(0x69),
  1415.         0x1D5A9 => array(0x6A),
  1416.         0x1D5AA => array(0x6B),
  1417.         0x1D5AB => array(0x6C),
  1418.         0x1D5AC => array(0x6D),
  1419.         0x1D5AD => array(0x6E),
  1420.         0x1D5AE => array(0x6F),
  1421.         0x1D5AF => array(0x70),
  1422.         0x1D5B0 => array(0x71),
  1423.         0x1D5B1 => array(0x72),
  1424.         0x1D5B2 => array(0x73),
  1425.         0x1D5B3 => array(0x74),
  1426.         0x1D5B4 => array(0x75),
  1427.         0x1D5B5 => array(0x76),
  1428.         0x1D5B6 => array(0x77),
  1429.         0x1D5B7 => array(0x78),
  1430.         0x1D5B8 => array(0x79),
  1431.         0x1D5B9 => array(0x7A),
  1432.         0x1D5D4 => array(0x61),
  1433.         0x1D5D5 => array(0x62),
  1434.         0x1D5D6 => array(0x63),
  1435.         0x1D5D7 => array(0x64),
  1436.         0x1D5D8 => array(0x65),
  1437.         0x1D5D9 => array(0x66),
  1438.         0x1D5DA => array(0x67),
  1439.         0x1D5DB => array(0x68),
  1440.         0x1D5DC => array(0x69),
  1441.         0x1D5DD => array(0x6A),
  1442.         0x1D5DE => array(0x6B),
  1443.         0x1D5DF => array(0x6C),
  1444.         0x1D5E0 => array(0x6D),
  1445.         0x1D5E1 => array(0x6E),
  1446.         0x1D5E2 => array(0x6F),
  1447.         0x1D5E3 => array(0x70),
  1448.         0x1D5E4 => array(0x71),
  1449.         0x1D5E5 => array(0x72),
  1450.         0x1D5E6 => array(0x73),
  1451.         0x1D5E7 => array(0x74),
  1452.         0x1D5E8 => array(0x75),
  1453.         0x1D5E9 => array(0x76),
  1454.         0x1D5EA => array(0x77),
  1455.         0x1D5EB => array(0x78),
  1456.         0x1D5EC => array(0x79),
  1457.         0x1D5ED => array(0x7A),
  1458.         0x1D608 => array(0x61),
  1459.         0x1D609 => array(0x62),
  1460.         0x1D60A => array(0x63),
  1461.         0x1D60B => array(0x64),
  1462.         0x1D60C => array(0x65),
  1463.         0x1D60D => array(0x66),
  1464.         0x1D60E => array(0x67),
  1465.         0x1D60F => array(0x68),
  1466.         0x1D610 => array(0x69),
  1467.         0x1D611 => array(0x6A),
  1468.         0x1D612 => array(0x6B),
  1469.         0x1D613 => array(0x6C),
  1470.         0x1D614 => array(0x6D),
  1471.         0x1D615 => array(0x6E),
  1472.         0x1D616 => array(0x6F),
  1473.         0x1D617 => array(0x70),
  1474.         0x1D618 => array(0x71),
  1475.         0x1D619 => array(0x72),
  1476.         0x1D61A => array(0x73),
  1477.         0x1D61B => array(0x74),
  1478.         0x1D61C => array(0x75),
  1479.         0x1D61D => array(0x76),
  1480.         0x1D61E => array(0x77),
  1481.         0x1D61F => array(0x78),
  1482.         0x1D620 => array(0x79),
  1483.         0x1D621 => array(0x7A),
  1484.         0x1D63C => array(0x61),
  1485.         0x1D63D => array(0x62),
  1486.         0x1D63E => array(0x63),
  1487.         0x1D63F => array(0x64),
  1488.         0x1D640 => array(0x65),
  1489.         0x1D641 => array(0x66),
  1490.         0x1D642 => array(0x67),
  1491.         0x1D643 => array(0x68),
  1492.         0x1D644 => array(0x69),
  1493.         0x1D645 => array(0x6A),
  1494.         0x1D646 => array(0x6B),
  1495.         0x1D647 => array(0x6C),
  1496.         0x1D648 => array(0x6D),
  1497.         0x1D649 => array(0x6E),
  1498.         0x1D64A => array(0x6F),
  1499.         0x1D64B => array(0x70),
  1500.         0x1D64C => array(0x71),
  1501.         0x1D64D => array(0x72),
  1502.         0x1D64E => array(0x73),
  1503.         0x1D64F => array(0x74),
  1504.         0x1D650 => array(0x75),
  1505.         0x1D651 => array(0x76),
  1506.         0x1D652 => array(0x77),
  1507.         0x1D653 => array(0x78),
  1508.         0x1D654 => array(0x79),
  1509.         0x1D655 => array(0x7A),
  1510.         0x1D670 => array(0x61),
  1511.         0x1D671 => array(0x62),
  1512.         0x1D672 => array(0x63),
  1513.         0x1D673 => array(0x64),
  1514.         0x1D674 => array(0x65),
  1515.         0x1D675 => array(0x66),
  1516.         0x1D676 => array(0x67),
  1517.         0x1D677 => array(0x68),
  1518.         0x1D678 => array(0x69),
  1519.         0x1D679 => array(0x6A),
  1520.         0x1D67A => array(0x6B),
  1521.         0x1D67B => array(0x6C),
  1522.         0x1D67C => array(0x6D),
  1523.         0x1D67D => array(0x6E),
  1524.         0x1D67E => array(0x6F),
  1525.         0x1D67F => array(0x70),
  1526.         0x1D680 => array(0x71),
  1527.         0x1D681 => array(0x72),
  1528.         0x1D682 => array(0x73),
  1529.         0x1D683 => array(0x74),
  1530.         0x1D684 => array(0x75),
  1531.         0x1D685 => array(0x76),
  1532.         0x1D686 => array(0x77),
  1533.         0x1D687 => array(0x78),
  1534.         0x1D688 => array(0x79),
  1535.         0x1D689 => array(0x7A),
  1536.         0x1D6A8 => array(0x3B1),
  1537.         0x1D6A9 => array(0x3B2),
  1538.         0x1D6AA => array(0x3B3),
  1539.         0x1D6AB => array(0x3B4),
  1540.         0x1D6AC => array(0x3B5),
  1541.         0x1D6AD => array(0x3B6),
  1542.         0x1D6AE => array(0x3B7),
  1543.         0x1D6AF => array(0x3B8),
  1544.         0x1D6B0 => array(0x3B9),
  1545.         0x1D6B1 => array(0x3BA),
  1546.         0x1D6B2 => array(0x3BB),
  1547.         0x1D6B3 => array(0x3BC),
  1548.         0x1D6B4 => array(0x3BD),
  1549.         0x1D6B5 => array(0x3BE),
  1550.         0x1D6B6 => array(0x3BF),
  1551.         0x1D6B7 => array(0x3C0),
  1552.         0x1D6B8 => array(0x3C1),
  1553.         0x1D6B9 => array(0x3B8),
  1554.         0x1D6BA => array(0x3C3),
  1555.         0x1D6BB => array(0x3C4),
  1556.         0x1D6BC => array(0x3C5),
  1557.         0x1D6BD => array(0x3C6),
  1558.         0x1D6BE => array(0x3C7),
  1559.         0x1D6BF => array(0x3C8),
  1560.         0x1D6C0 => array(0x3C9),
  1561.         0x1D6D3 => array(0x3C3),
  1562.         0x1D6E2 => array(0x3B1),
  1563.         0x1D6E3 => array(0x3B2),
  1564.         0x1D6E4 => array(0x3B3),
  1565.         0x1D6E5 => array(0x3B4),
  1566.         0x1D6E6 => array(0x3B5),
  1567.         0x1D6E7 => array(0x3B6),
  1568.         0x1D6E8 => array(0x3B7),
  1569.         0x1D6E9 => array(0x3B8),
  1570.         0x1D6EA => array(0x3B9),
  1571.         0x1D6EB => array(0x3BA),
  1572.         0x1D6EC => array(0x3BB),
  1573.         0x1D6ED => array(0x3BC),
  1574.         0x1D6EE => array(0x3BD),
  1575.         0x1D6EF => array(0x3BE),
  1576.         0x1D6F0 => array(0x3BF),
  1577.         0x1D6F1 => array(0x3C0),
  1578.         0x1D6F2 => array(0x3C1),
  1579.         0x1D6F3 => array(0x3B8),
  1580.         0x1D6F4 => array(0x3C3),
  1581.         0x1D6F5 => array(0x3C4),
  1582.         0x1D6F6 => array(0x3C5),
  1583.         0x1D6F7 => array(0x3C6),
  1584.         0x1D6F8 => array(0x3C7),
  1585.         0x1D6F9 => array(0x3C8),
  1586.         0x1D6FA => array(0x3C9),
  1587.         0x1D70D => array(0x3C3),
  1588.         0x1D71C => array(0x3B1),
  1589.         0x1D71D => array(0x3B2),
  1590.         0x1D71E => array(0x3B3),
  1591.         0x1D71F => array(0x3B4),
  1592.         0x1D720 => array(0x3B5),
  1593.         0x1D721 => array(0x3B6),
  1594.         0x1D722 => array(0x3B7),
  1595.         0x1D723 => array(0x3B8),
  1596.         0x1D724 => array(0x3B9),
  1597.         0x1D725 => array(0x3BA),
  1598.         0x1D726 => array(0x3BB),
  1599.         0x1D727 => array(0x3BC),
  1600.         0x1D728 => array(0x3BD),
  1601.         0x1D729 => array(0x3BE),
  1602.         0x1D72A => array(0x3BF),
  1603.         0x1D72B => array(0x3C0),
  1604.         0x1D72C => array(0x3C1),
  1605.         0x1D72D => array(0x3B8),
  1606.         0x1D72E => array(0x3C3),
  1607.         0x1D72F => array(0x3C4),
  1608.         0x1D730 => array(0x3C5),
  1609.         0x1D731 => array(0x3C6),
  1610.         0x1D732 => array(0x3C7),
  1611.         0x1D733 => array(0x3C8),
  1612.         0x1D734 => array(0x3C9),
  1613.         0x1D747 => array(0x3C3),
  1614.         0x1D756 => array(0x3B1),
  1615.         0x1D757 => array(0x3B2),
  1616.         0x1D758 => array(0x3B3),
  1617.         0x1D759 => array(0x3B4),
  1618.         0x1D75A => array(0x3B5),
  1619.         0x1D75B => array(0x3B6),
  1620.         0x1D75C => array(0x3B7),
  1621.         0x1D75D => array(0x3B8),
  1622.         0x1D75E => array(0x3B9),
  1623.         0x1D75F => array(0x3BA),
  1624.         0x1D760 => array(0x3BB),
  1625.         0x1D761 => array(0x3BC),
  1626.         0x1D762 => array(0x3BD),
  1627.         0x1D763 => array(0x3BE),
  1628.         0x1D764 => array(0x3BF),
  1629.         0x1D765 => array(0x3C0),
  1630.         0x1D766 => array(0x3C1),
  1631.         0x1D767 => array(0x3B8),
  1632.         0x1D768 => array(0x3C3),
  1633.         0x1D769 => array(0x3C4),
  1634.         0x1D76A => array(0x3C5),
  1635.         0x1D76B => array(0x3C6),
  1636.         0x1D76C => array(0x3C7),
  1637.         0x1D76D => array(0x3C8),
  1638.         0x1D76E => array(0x3C9),
  1639.         0x1D781 => array(0x3C3),
  1640.         0x1D790 => array(0x3B1),
  1641.         0x1D791 => array(0x3B2),
  1642.         0x1D792 => array(0x3B3),
  1643.         0x1D793 => array(0x3B4),
  1644.         0x1D794 => array(0x3B5),
  1645.         0x1D795 => array(0x3B6),
  1646.         0x1D796 => array(0x3B7),
  1647.         0x1D797 => array(0x3B8),
  1648.         0x1D798 => array(0x3B9),
  1649.         0x1D799 => array(0x3BA),
  1650.         0x1D79A => array(0x3BB),
  1651.         0x1D79B => array(0x3BC),
  1652.         0x1D79C => array(0x3BD),
  1653.         0x1D79D => array(0x3BE),
  1654.         0x1D79E => array(0x3BF),
  1655.         0x1D79F => array(0x3C0),
  1656.         0x1D7A0 => array(0x3C1),
  1657.         0x1D7A1 => array(0x3B8),
  1658.         0x1D7A2 => array(0x3C3),
  1659.         0x1D7A3 => array(0x3C4),
  1660.         0x1D7A4 => array(0x3C5),
  1661.         0x1D7A5 => array(0x3C6),
  1662.         0x1D7A6 => array(0x3C7),
  1663.         0x1D7A7 => array(0x3C8),
  1664.         0x1D7A8 => array(0x3C9),
  1665.         0x1D7BB => array(0x3C3),
  1666.         0x3F9   => array(0x3C3),
  1667.         0x1D2C  => array(0x61),
  1668.         0x1D2D  => array(0xE6),
  1669.         0x1D2E  => array(0x62),
  1670.         0x1D30  => array(0x64),
  1671.         0x1D31  => array(0x65),
  1672.         0x1D32  => array(0x1DD),
  1673.         0x1D33  => array(0x67),
  1674.         0x1D34  => array(0x68),
  1675.         0x1D35  => array(0x69),
  1676.         0x1D36  => array(0x6A),
  1677.         0x1D37  => array(0x6B),
  1678.         0x1D38  => array(0x6C),
  1679.         0x1D39  => array(0x6D),
  1680.         0x1D3A  => array(0x6E),
  1681.         0x1D3C  => array(0x6F),
  1682.         0x1D3D  => array(0x223),
  1683.         0x1D3E  => array(0x70),
  1684.         0x1D3F  => array(0x72),
  1685.         0x1D40  => array(0x74),
  1686.         0x1D41  => array(0x75),
  1687.         0x1D42  => array(0x77),
  1688.         0x213B  => array(0x660x610x78),
  1689.         0x3250  => array(0x700x740x65),
  1690.         0x32CC  => array(0x680x67),
  1691.         0x32CE  => array(0x650x76),
  1692.         0x32CF  => array(0x6C0x740x64),
  1693.         0x337A  => array(0x690x75),
  1694.         0x33DE  => array(0x760x22150x6D),
  1695.         0x33DF  => array(0x610x22150x6D)
  1696.     );
  1697.  
  1698.     /**
  1699.      * Normalization Combining Classes; Code Points not listed
  1700.      * got Combining Class 0.
  1701.      *
  1702.      * @static
  1703.      * @var array 
  1704.      * @access private
  1705.      */
  1706.     private static $_np_norm_combcls = array(
  1707.         0x334   => 1,
  1708.         0x335   => 1,
  1709.         0x336   => 1,
  1710.         0x337   => 1,
  1711.         0x338   => 1,
  1712.         0x93C   => 7,
  1713.         0x9BC   => 7,
  1714.         0xA3C   => 7,
  1715.         0xABC   => 7,
  1716.         0xB3C   => 7,
  1717.         0xCBC   => 7,
  1718.         0x1037  => 7,
  1719.         0x3099  => 8,
  1720.         0x309A  => 8,
  1721.         0x94D   => 9,
  1722.         0x9CD   => 9,
  1723.         0xA4D   => 9,
  1724.         0xACD   => 9,
  1725.         0xB4D   => 9,
  1726.         0xBCD   => 9,
  1727.         0xC4D   => 9,
  1728.         0xCCD   => 9,
  1729.         0xD4D   => 9,
  1730.         0xDCA   => 9,
  1731.         0xE3A   => 9,
  1732.         0xF84   => 9,
  1733.         0x1039  => 9,
  1734.         0x1714  => 9,
  1735.         0x1734  => 9,
  1736.         0x17D2  => 9,
  1737.         0x5B0   => 10,
  1738.         0x5B1   => 11,
  1739.         0x5B2   => 12,
  1740.         0x5B3   => 13,
  1741.         0x5B4   => 14,
  1742.         0x5B5   => 15,
  1743.         0x5B6   => 16,
  1744.         0x5B7   => 17,
  1745.         0x5B8   => 18,
  1746.         0x5B9   => 19,
  1747.         0x5BB   => 20,
  1748.         0x5Bc   => 21,
  1749.         0x5BD   => 22,
  1750.         0x5BF   => 23,
  1751.         0x5C1   => 24,
  1752.         0x5C2   => 25,
  1753.         0xFB1E  => 26,
  1754.         0x64B   => 27,
  1755.         0x64C   => 28,
  1756.         0x64D   => 29,
  1757.         0x64E   => 30,
  1758.         0x64F   => 31,
  1759.         0x650   => 32,
  1760.         0x651   => 33,
  1761.         0x652   => 34,
  1762.         0x670   => 35,
  1763.         0x711   => 36,
  1764.         0xC55   => 84,
  1765.         0xC56   => 91,
  1766.         0xE38   => 103,
  1767.         0xE39   => 103,
  1768.         0xE48   => 107,
  1769.         0xE49   => 107,
  1770.         0xE4A   => 107,
  1771.         0xE4B   => 107,
  1772.         0xEB8   => 118,
  1773.         0xEB9   => 118,
  1774.         0xEC8   => 122,
  1775.         0xEC9   => 122,
  1776.         0xECA   => 122,
  1777.         0xECB   => 122,
  1778.         0xF71   => 129,
  1779.         0xF72   => 130,
  1780.         0xF7A   => 130,
  1781.         0xF7B   => 130,
  1782.         0xF7C   => 130,
  1783.         0xF7D   => 130,
  1784.         0xF80   => 130,
  1785.         0xF74   => 132,
  1786.         0x321   => 202,
  1787.         0x322   => 202,
  1788.         0x327   => 202,
  1789.         0x328   => 202,
  1790.         0x31B   => 216,
  1791.         0xF39   => 216,
  1792.         0x1D165 => 216,
  1793.         0x1D166 => 216,
  1794.         0x1D16E => 216,
  1795.         0x1D16F => 216,
  1796.         0x1D170 => 216,
  1797.         0x1D171 => 216,
  1798.         0x1D172 => 216,
  1799.         0x302A  => 218,
  1800.         0x316   => 220,
  1801.         0x317   => 220,
  1802.         0x318   => 220,
  1803.         0x319   => 220,
  1804.         0x31C   => 220,
  1805.         0x31D   => 220,
  1806.         0x31E   => 220,
  1807.         0x31F   => 220,
  1808.         0x320   => 220,
  1809.         0x323   => 220,
  1810.         0x324   => 220,
  1811.         0x325   => 220,
  1812.         0x326   => 220,
  1813.         0x329   => 220,
  1814.         0x32A   => 220,
  1815.         0x32B   => 220,
  1816.         0x32C   => 220,
  1817.         0x32D   => 220,
  1818.         0x32E   => 220,
  1819.         0x32F   => 220,
  1820.         0x330   => 220,
  1821.         0x331   => 220,
  1822.         0x332   => 220,
  1823.         0x333   => 220,
  1824.         0x339   => 220,
  1825.         0x33A   => 220,
  1826.         0x33B   => 220,
  1827.         0x33C   => 220,
  1828.         0x347   => 220,
  1829.         0x348   => 220,
  1830.         0x349   => 220,
  1831.         0x34D   => 220,
  1832.         0x34E   => 220,
  1833.         0x353   => 220,
  1834.         0x354   => 220,
  1835.         0x355   => 220,
  1836.         0x356   => 220,
  1837.         0x591   => 220,
  1838.         0x596   => 220,
  1839.         0x59B   => 220,
  1840.         0x5A3   => 220,
  1841.         0x5A4   => 220,
  1842.         0x5A5   => 220,
  1843.         0x5A6   => 220,
  1844.         0x5A7   => 220,
  1845.         0x5AA   => 220,
  1846.         0x655   => 220,
  1847.         0x656   => 220,
  1848.         0x6E3   => 220,
  1849.         0x6EA   => 220,
  1850.         0x6ED   => 220,
  1851.         0x731   => 220,
  1852.         0x734   => 220,
  1853.         0x737   => 220,
  1854.         0x738   => 220,
  1855.         0x739   => 220,
  1856.         0x73B   => 220,
  1857.         0x73C   => 220,
  1858.         0x73E   => 220,
  1859.         0x742   => 220,
  1860.         0x744   => 220,
  1861.         0x746   => 220,
  1862.         0x748   => 220,
  1863.         0x952   => 220,
  1864.         0xF18   => 220,
  1865.         0xF19   => 220,
  1866.         0xF35   => 220,
  1867.         0xF37   => 220,
  1868.         0xFC6   => 220,
  1869.         0x193B  => 220,
  1870.         0x20E8  => 220,
  1871.         0x1D17B => 220,
  1872.         0x1D17C => 220,
  1873.         0x1D17D => 220,
  1874.         0x1D17E => 220,
  1875.         0x1D17F => 220,
  1876.         0x1D180 => 220,
  1877.         0x1D181 => 220,
  1878.         0x1D182 => 220,
  1879.         0x1D18A => 220,
  1880.         0x1D18B => 220,
  1881.         0x59A   => 222,
  1882.         0x5AD   => 222,
  1883.         0x1929  => 222,
  1884.         0x302D  => 222,
  1885.         0x302E  => 224,
  1886.         0x302F  => 224,
  1887.         0x1D16D => 226,
  1888.         0x5AE   => 228,
  1889.         0x18A9  => 228,
  1890.         0x302B  => 228,
  1891.         0x300   => 230,
  1892.         0x301   => 230,
  1893.         0x302   => 230,
  1894.         0x303   => 230,
  1895.         0x304   => 230,
  1896.         0x305   => 230,
  1897.         0x306   => 230,
  1898.         0x307   => 230,
  1899.         0x308   => 230,
  1900.         0x309   => 230,
  1901.         0x30A   => 230,
  1902.         0x30B   => 230,
  1903.         0x30C   => 230,
  1904.         0x30D   => 230,
  1905.         0x30E   => 230,
  1906.         0x30F   => 230,
  1907.         0x310   => 230,
  1908.         0x311   => 230,
  1909.         0x312   => 230,
  1910.         0x313   => 230,
  1911.         0x314   => 230,
  1912.         0x33D   => 230,
  1913.         0x33E   => 230,
  1914.         0x33F   => 230,
  1915.         0x340   => 230,
  1916.         0x341   => 230,
  1917.         0x342   => 230,
  1918.         0x343   => 230,
  1919.         0x344   => 230,
  1920.         0x346   => 230,
  1921.         0x34A   => 230,
  1922.         0x34B   => 230,
  1923.         0x34C   => 230,
  1924.         0x350   => 230,
  1925.         0x351   => 230,
  1926.         0x352   => 230,
  1927.         0x357   => 230,
  1928.         0x363   => 230,
  1929.         0x364   => 230,
  1930.         0x365   => 230,
  1931.         0x366   => 230,
  1932.         0x367   => 230,
  1933.         0x368   => 230,
  1934.         0x369   => 230,
  1935.         0x36A   => 230,
  1936.         0x36B   => 230,
  1937.         0x36C   => 230,
  1938.         0x36D   => 230,
  1939.         0x36E   => 230,
  1940.         0x36F   => 230,
  1941.         0x483   => 230,
  1942.         0x484   => 230,
  1943.         0x485   => 230,
  1944.         0x486   => 230,
  1945.         0x592   => 230,
  1946.         0x593   => 230,
  1947.         0x594   => 230,
  1948.         0x595   => 230,
  1949.         0x597   => 230,
  1950.         0x598   => 230,
  1951.         0x599   => 230,
  1952.         0x59C   => 230,
  1953.         0x59D   => 230,
  1954.         0x59E   => 230,
  1955.         0x59F   => 230,
  1956.         0x5A0   => 230,
  1957.         0x5A1   => 230,
  1958.         0x5A8   => 230,
  1959.         0x5A9   => 230,
  1960.         0x5AB   => 230,
  1961.         0x5AC   => 230,
  1962.         0x5AF   => 230,
  1963.         0x5C4   => 230,
  1964.         0x610   => 230,
  1965.         0x611   => 230,
  1966.         0x612   => 230,
  1967.         0x613   => 230,
  1968.         0x614   => 230,
  1969.         0x615   => 230,
  1970.         0x653   => 230,
  1971.         0x654   => 230,
  1972.         0x657   => 230,
  1973.         0x658   => 230,
  1974.         0x6D6   => 230,
  1975.         0x6D7   => 230,
  1976.         0x6D8   => 230,
  1977.         0x6D9   => 230,
  1978.         0x6DA   => 230,
  1979.         0x6DB   => 230,
  1980.         0x6DC   => 230,
  1981.         0x6DF   => 230,
  1982.         0x6E0   => 230,
  1983.         0x6E1   => 230,
  1984.         0x6E2   => 230,
  1985.         0x6E4   => 230,
  1986.         0x6E7   => 230,
  1987.         0x6E8   => 230,
  1988.         0x6EB   => 230,
  1989.         0x6EC   => 230,
  1990.         0x730   => 230,
  1991.         0x732   => 230,
  1992.         0x733   => 230,
  1993.         0x735   => 230,
  1994.         0x736   => 230,
  1995.         0x73A   => 230,
  1996.         0x73D   => 230,
  1997.         0x73F   => 230,
  1998.         0x740   => 230,
  1999.         0x741   => 230,
  2000.         0x743   => 230,
  2001.         0x745   => 230,
  2002.         0x747   => 230,
  2003.         0x749   => 230,
  2004.         0x74A   => 230,
  2005.         0x951   => 230,
  2006.         0x953   => 230,
  2007.         0x954   => 230,
  2008.         0xF82   => 230,
  2009.         0xF83   => 230,
  2010.         0xF86   => 230,
  2011.         0xF87   => 230,
  2012.         0x170D  => 230,
  2013.         0x193A  => 230,
  2014.         0x20D0  => 230,
  2015.         0x20D1  => 230,
  2016.         0x20D4  => 230,
  2017.         0x20D5  => 230,
  2018.         0x20D6  => 230,
  2019.         0x20D7  => 230,
  2020.         0x20DB  => 230,
  2021.         0x20DC  => 230,
  2022.         0x20E1  => 230,
  2023.         0x20E7  => 230,
  2024.         0x20E9  => 230,
  2025.         0xFE20  => 230,
  2026.         0xFE21  => 230,
  2027.         0xFE22  => 230,
  2028.         0xFE23  => 230,
  2029.         0x1D185 => 230,
  2030.         0x1D186 => 230,
  2031.         0x1D187 => 230,
  2032.         0x1D189 => 230,
  2033.         0x1D188 => 230,
  2034.         0x1D1AA => 230,
  2035.         0x1D1AB => 230,
  2036.         0x1D1AC => 230,
  2037.         0x1D1AD => 230,
  2038.         0x315   => 232,
  2039.         0x31A   => 232,
  2040.         0x302C  => 232,
  2041.         0x35F   => 233,
  2042.         0x362   => 233,
  2043.         0x35D   => 234,
  2044.         0x35E   => 234,
  2045.         0x360   => 234,
  2046.         0x361   => 234,
  2047.         0x345   => 240
  2048.     );
  2049.     // }}}
  2050.  
  2051.     // {{{ properties
  2052.     /**
  2053.      * @var string 
  2054.      * @access private
  2055.      */
  2056.     private $_punycode_prefix 'xn--';
  2057.  
  2058.     /**
  2059.      * @access private
  2060.      */
  2061.     private $_invalid_ucs = 0x80000000;
  2062.  
  2063.     /**
  2064.      * @access private
  2065.      */
  2066.     private $_max_ucs = 0x10FFFF;
  2067.  
  2068.     /**
  2069.      * @var int 
  2070.      * @access private
  2071.      */
  2072.     private $_base = 36;
  2073.  
  2074.     /**
  2075.      * @var int 
  2076.      * @access private
  2077.      */
  2078.     private $_tmin = 1;
  2079.  
  2080.     /**
  2081.      * @var int 
  2082.      * @access private
  2083.      */
  2084.     private $_tmax = 26;
  2085.  
  2086.     /**
  2087.      * @var int 
  2088.      * @access private
  2089.      */
  2090.     private $_skew = 38;
  2091.  
  2092.     /**
  2093.      * @var int 
  2094.      * @access private
  2095.      */
  2096.     private $_damp = 700;
  2097.  
  2098.     /**
  2099.      * @var int 
  2100.      * @access private
  2101.      */
  2102.     private $_initial_bias = 72;
  2103.  
  2104.     /**
  2105.      * @var int 
  2106.      * @access private
  2107.      */
  2108.     private $_initial_n = 0x80;
  2109.  
  2110.     /**
  2111.      * @var int 
  2112.      * @access private
  2113.      */
  2114.     private $_slast;
  2115.  
  2116.     /**
  2117.      * @access private
  2118.      */
  2119.     private $_sbase = 0xAC00;
  2120.  
  2121.     /**
  2122.      * @access private
  2123.      */
  2124.     private $_lbase = 0x1100;
  2125.  
  2126.     /**
  2127.      * @access private
  2128.      */
  2129.     private $_vbase = 0x1161;
  2130.  
  2131.     /**
  2132.      * @access private
  2133.      */
  2134.     private $_tbase = 0x11a7;
  2135.  
  2136.     /**
  2137.      * @var int 
  2138.      * @access private
  2139.      */
  2140.     private $_lcount = 19;
  2141.  
  2142.     /**
  2143.      * @var int 
  2144.      * @access private
  2145.      */
  2146.     private $_vcount = 21;
  2147.  
  2148.     /**
  2149.      * @var int 
  2150.      * @access private
  2151.      */
  2152.     private $_tcount = 28;
  2153.  
  2154.     /**
  2155.      * vcount * tcount
  2156.      *
  2157.      * @var int 
  2158.      * @access private
  2159.      */
  2160.     private $_ncount = 588;
  2161.  
  2162.     /**
  2163.      * lcount * tcount * vcount
  2164.      *
  2165.      * @var int 
  2166.      * @access private
  2167.      */
  2168.     private $_scount = 11172;
  2169.  
  2170.     /**
  2171.      * Default encoding for encode()'s input and decode()'s output is UTF-8;
  2172.      * Other possible encodings are ucs4_string and ucs4_array
  2173.      * See {@link setParams()} for how to select these
  2174.      *
  2175.      * @var bool 
  2176.      * @access private
  2177.      */
  2178.     private $_api_encoding 'utf8';
  2179.  
  2180.     /**
  2181.      * Overlong UTF-8 encodings are forbidden
  2182.      *
  2183.      * @var bool 
  2184.      * @access private
  2185.      */
  2186.     private $_allow_overlong = false;
  2187.  
  2188.     /**
  2189.      * Behave strict or not
  2190.      *
  2191.      * @var bool 
  2192.      * @access private
  2193.      */
  2194.     private $_strict_mode = false;
  2195.  
  2196.     /**
  2197.      * IDNA-version to use
  2198.      *
  2199.      * Values are "2003" and "2008".
  2200.      * Defaults to "2003", since that was the original version and for
  2201.      * compatibility with previous versions of this library.
  2202.      * If you need to encode "new" characters like the German "Eszett",
  2203.      * please switch to 2008 first before encoding.
  2204.      *
  2205.      * @var bool 
  2206.      * @access private
  2207.      */
  2208.     private $_version '2003';
  2209.  
  2210.     /**
  2211.      * Cached value indicating whether or not mbstring function overloading is
  2212.      * on for strlen
  2213.      *
  2214.      * This is cached for optimal performance.
  2215.      *
  2216.      * @var boolean 
  2217.      * @see Net_IDNA2::_byteLength()
  2218.      */
  2219.     private static $_mb_string_overload = null;
  2220.     // }}}
  2221.  
  2222.  
  2223.     // {{{ constructor
  2224.     /**
  2225.      * Constructor
  2226.      *
  2227.      * @param array $options Options to initialise the object with
  2228.      *
  2229.      * @access public
  2230.      * @see    setParams()
  2231.      */
  2232.     public function __construct($options = null)
  2233.     {
  2234.         $this->_slast $this->_sbase $this->_lcount $this->_vcount $this->_tcount;
  2235.  
  2236.         if (is_array($options)) {
  2237.             $this->setParams($options);
  2238.         }
  2239.  
  2240.         // populate mbstring overloading cache if not set
  2241.         if (self::$_mb_string_overload === null{
  2242.             self::$_mb_string_overload (extension_loaded('mbstring')
  2243.                 && (ini_get('mbstring.func_overload'0x02=== 0x02);
  2244.         }
  2245.     }
  2246.     // }}}
  2247.  
  2248.  
  2249.     /**
  2250.      * Sets a new option value. Available options and values:
  2251.      *
  2252.      * [utf8 -     Use either UTF-8 or ISO-8859-1 as input (true for UTF-8, false
  2253.      *             otherwise); The output is always UTF-8]
  2254.      * [overlong - Unicode does not allow unnecessarily long encodings of chars,
  2255.      *             to allow this, set this parameter to true, else to false;
  2256.      *             default is false.]
  2257.      * [strict -   true: strict mode, good for registration purposes - Causes errors
  2258.      *             on failures; false: loose mode, ideal for "wildlife" applications
  2259.      *             by silently ignoring errors and returning the original input instead]
  2260.      *
  2261.      * @param mixed  $option Parameter to set (string: single parameter; array of Parameter => Value pairs)
  2262.      * @param string $value  Value to use (if parameter 1 is a string)
  2263.      *
  2264.      * @return boolean       true on success, false otherwise
  2265.      * @access public
  2266.      */
  2267.     public function setParams($option$value = false)
  2268.     {
  2269.         if (!is_array($option)) {
  2270.             $option = array($option => $value);
  2271.         }
  2272.  
  2273.         foreach ($option as $k => $v{
  2274.             switch ($k{
  2275.             case 'encoding':
  2276.                 switch ($v{
  2277.                 case 'utf8':
  2278.                 case 'ucs4_string':
  2279.                 case 'ucs4_array':
  2280.                     $this->_api_encoding $v;
  2281.                     break;
  2282.  
  2283.                 default:
  2284.                     throw new InvalidArgumentException('Set Parameter: Unknown parameter '.$v.' for option '.$k);
  2285.                 }
  2286.  
  2287.                 break;
  2288.  
  2289.             case 'overlong':
  2290.                 $this->_allow_overlong ($v? true : false;
  2291.                 break;
  2292.  
  2293.             case 'strict':
  2294.                 $this->_strict_mode ($v? true : false;
  2295.                 break;
  2296.  
  2297.             case 'version':
  2298.                 if (in_array($varray('2003''2008'))) {
  2299.                     $this->_version $v;
  2300.                 else {
  2301.                     throw new InvalidArgumentException('Set Parameter: Invalid parameter '.$v.' for option '.$k);
  2302.                 }
  2303.                 break;
  2304.  
  2305.             default:
  2306.                 return false;
  2307.             }
  2308.         }
  2309.  
  2310.         return true;
  2311.     }
  2312.  
  2313.     /**
  2314.      * Encode a given UTF-8 domain name.
  2315.      *
  2316.      * @param string $decoded           Domain name (UTF-8 or UCS-4)
  2317.      * @param string $one_time_encoding Desired input encoding, see {@link set_parameter}
  2318.      *                                   If not given will use default-encoding
  2319.      *
  2320.      * @return string Encoded Domain name (ACE string)
  2321.      * @return mixed  processed string
  2322.      * @throws Exception
  2323.      * @access public
  2324.      */
  2325.     public function encode($decoded$one_time_encoding = false)
  2326.     {
  2327.         // Forcing conversion of input to UCS4 array
  2328.         // If one time encoding is given, use this, else the objects property
  2329.         switch (($one_time_encoding$one_time_encoding $this->_api_encoding{
  2330.         case 'utf8':
  2331.             $decoded $this->_utf8_to_ucs4($decoded);
  2332.             break;
  2333.         case 'ucs4_string':
  2334.             $decoded $this->_ucs4_string_to_ucs4($decoded);
  2335.         case 'ucs4_array'// No break; before this line. Catch case, but do nothing
  2336.             break;
  2337.         default:
  2338.             throw new InvalidArgumentException('Unsupported input format');
  2339.         }
  2340.  
  2341.         // No input, no output, what else did you expect?
  2342.         if (empty($decoded)) return '';
  2343.  
  2344.         // Anchors for iteration
  2345.         $last_begin = 0;
  2346.         // Output string
  2347.         $output '';
  2348.  
  2349.         foreach ($decoded as $k => $v{
  2350.             // Make sure to use just the plain dot
  2351.             switch($v{
  2352.             case 0x3002:
  2353.             case 0xFF0E:
  2354.             case 0xFF61:
  2355.                 $decoded[$k= 0x2E;
  2356.                 // It's right, no break here
  2357.                 // The codepoints above have to be converted to dots anyway
  2358.  
  2359.             // Stumbling across an anchoring character
  2360.             case 0x2E:
  2361.             case 0x2F:
  2362.             case 0x3A:
  2363.             case 0x3F:
  2364.             case 0x40:
  2365.                 // Neither email addresses nor URLs allowed in strict mode
  2366.                 if ($this->_strict_mode{
  2367.                     throw new InvalidArgumentException('Neither email addresses nor URLs are allowed in strict mode.');
  2368.                 }
  2369.                 // Skip first char
  2370.                 if ($k{
  2371.                     $encoded '';
  2372.                     $encoded $this->_encode(array_slice($decoded$last_begin(($k)-$last_begin)));
  2373.                     if ($encoded{
  2374.                         $output .= $encoded;
  2375.                     else {
  2376.                         $output .= $this->_ucs4_to_utf8(array_slice($decoded$last_begin(($k)-$last_begin)));
  2377.                     }
  2378.                     $output .= chr($decoded[$k]);
  2379.                 }
  2380.                 $last_begin $k + 1;
  2381.             }
  2382.         }
  2383.         // Catch the rest of the string
  2384.         if ($last_begin{
  2385.             $inp_len sizeof($decoded);
  2386.             $encoded '';
  2387.             $encoded $this->_encode(array_slice($decoded$last_begin(($inp_len)-$last_begin)));
  2388.             if ($encoded{
  2389.                 $output .= $encoded;
  2390.             else {
  2391.                 $output .= $this->_ucs4_to_utf8(array_slice($decoded$last_begin(($inp_len)-$last_begin)));
  2392.             }
  2393.             return $output;
  2394.         }
  2395.  
  2396.         if ($output $this->_encode($decoded)) {
  2397.             return $output;
  2398.         }
  2399.  
  2400.         return $this->_ucs4_to_utf8($decoded);
  2401.     }
  2402.  
  2403.     /**
  2404.      * Decode a given ACE domain name.
  2405.      *
  2406.      * @param string $input             Domain name (ACE string)
  2407.      * @param string $one_time_encoding Desired output encoding, see {@link set_parameter}
  2408.      *
  2409.      * @return string                   Decoded Domain name (UTF-8 or UCS-4)
  2410.      * @throws Exception
  2411.      * @access public
  2412.      */
  2413.     public function decode($input$one_time_encoding = false)
  2414.     {
  2415.         // Optionally set
  2416.         if ($one_time_encoding{
  2417.             switch ($one_time_encoding{
  2418.             case 'utf8':
  2419.             case 'ucs4_string':
  2420.             case 'ucs4_array':
  2421.                 break;
  2422.             default:
  2423.                 throw new InvalidArgumentException('Unknown encoding '.$one_time_encoding);
  2424.             }
  2425.         }
  2426.         // Make sure to drop any newline characters around
  2427.         $input trim($input);
  2428.  
  2429.         // Negotiate input and try to determine, wether it is a plain string,
  2430.         // an email address or something like a complete URL
  2431.         if (strpos($input'@')) // Maybe it is an email address
  2432.             // No no in strict mode
  2433.             if ($this->_strict_mode{
  2434.                 throw new InvalidArgumentException('Only simple domain name parts can be handled in strict mode');
  2435.             }
  2436.             list($email_pref$inputexplode('@'$input2);
  2437.             $arr explode('.'$input);
  2438.             foreach ($arr as $k => $v{
  2439.                 $conv $this->_decode($v);
  2440.                 if ($conv$arr[$k$conv;
  2441.             }
  2442.             $return $email_pref '@' join('.'$arr);
  2443.         elseif (preg_match('![:\./]!'$input)) // Or a complete domain name (with or without paths / parameters)
  2444.             // No no in strict mode
  2445.             if ($this->_strict_mode{
  2446.                 throw new InvalidArgumentException('Only simple domain name parts can be handled in strict mode');
  2447.             }
  2448.  
  2449.             $parsed parse_url($input);
  2450.             if (isset($parsed['host'])) {
  2451.                 $arr explode('.'$parsed['host']);
  2452.                 foreach ($arr as $k => $v{
  2453.                     $conv $this->_decode($v);
  2454.                     if ($conv$arr[$k$conv;
  2455.                 }
  2456.                 $parsed['host'join('.'$arr);
  2457.                 if (isset($parsed['scheme'])) {
  2458.                     $parsed['scheme'.= (strtolower($parsed['scheme']== 'mailto'':' '://';
  2459.                 }
  2460.                 $return $this->_unparse_url($parsed);
  2461.             else // parse_url seems to have failed, try without it
  2462.                 $arr explode('.'$input);
  2463.                 foreach ($arr as $k => $v{
  2464.                     $conv $this->_decode($v);
  2465.                     if ($conv$arr[$k$conv;
  2466.                 }
  2467.                 $return join('.'$arr);
  2468.             }
  2469.         else // Otherwise we consider it being a pure domain name string
  2470.             $return $this->_decode($input);
  2471.         }
  2472.         // The output is UTF-8 by default, other output formats need conversion here
  2473.         // If one time encoding is given, use this, else the objects property
  2474.         switch (($one_time_encoding$one_time_encoding $this->_api_encoding{
  2475.         case 'utf8':
  2476.             return $return;
  2477.             break;
  2478.         case 'ucs4_string':
  2479.             return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return));
  2480.             break;
  2481.         case 'ucs4_array':
  2482.             return $this->_utf8_to_ucs4($return);
  2483.             break;
  2484.         default:
  2485.             throw new InvalidArgumentException('Unsupported output format');
  2486.         }
  2487.     }
  2488.  
  2489.  
  2490.     // {{{ private
  2491.     /**
  2492.      * Opposite function to parse_url()
  2493.      *
  2494.      * Inspired by code from comments of php.net-documentation for parse_url()
  2495.      *
  2496.      * @param array $parts_arr parts (strings) as returned by parse_url()
  2497.      *
  2498.      * @return string 
  2499.      * @access private
  2500.      */
  2501.     private function _unparse_url($parts_arr)
  2502.     {
  2503.         if (!empty($parts_arr['scheme'])) {
  2504.             $ret_url $parts_arr['scheme'];
  2505.         }
  2506.         if (!empty($parts_arr['user'])) {
  2507.             $ret_url .= $parts_arr['user'];
  2508.             if (!empty($parts_arr['pass'])) {
  2509.                 $ret_url .= ':' $parts_arr['pass'];
  2510.             }
  2511.             $ret_url .= '@';
  2512.         }
  2513.         $ret_url .= $parts_arr['host'];
  2514.         if (!empty($parts_arr['port'])) {
  2515.             $ret_url .= ':' $parts_arr['port'];
  2516.         }
  2517.         $ret_url .= $parts_arr['path'];
  2518.         if (!empty($parts_arr['query'])) {
  2519.             $ret_url .= '?' $parts_arr['query'];
  2520.         }
  2521.         if (!empty($parts_arr['fragment'])) {
  2522.             $ret_url .= '#' $parts_arr['fragment'];
  2523.         }
  2524.         return $ret_url;
  2525.     }
  2526.  
  2527.     /**
  2528.      * The actual encoding algorithm.
  2529.      *
  2530.      * @param string $decoded Decoded string which should be encoded
  2531.      *
  2532.      * @return string         Encoded string
  2533.      * @throws Exception
  2534.      * @access private
  2535.      */
  2536.     private function _encode($decoded)
  2537.     {
  2538.         // We cannot encode a domain name containing the Punycode prefix
  2539.         $extract = self::_byteLength($this->_punycode_prefix);
  2540.         $check_pref $this->_utf8_to_ucs4($this->_punycode_prefix);
  2541.         $check_deco array_slice($decoded0$extract);
  2542.  
  2543.         if ($check_pref == $check_deco{
  2544.             throw new InvalidArgumentException('This is already a punycode string');
  2545.         }
  2546.  
  2547.         // We will not try to encode strings consisting of basic code points only
  2548.         $encodable = false;
  2549.         foreach ($decoded as $k => $v{
  2550.             if ($v > 0x7a{
  2551.                 $encodable = true;
  2552.                 break;
  2553.             }
  2554.         }
  2555.         if (!$encodable{
  2556.             if ($this->_strict_mode{
  2557.                 throw new InvalidArgumentException('The given string does not contain encodable chars');
  2558.             }
  2559.  
  2560.             return false;
  2561.         }
  2562.  
  2563.         // Do NAMEPREP
  2564.         $decoded $this->_nameprep($decoded);
  2565.  
  2566.         $deco_len count($decoded);
  2567.  
  2568.         // Empty array
  2569.         if (!$deco_len{
  2570.             return false;
  2571.         }
  2572.  
  2573.         // How many chars have been consumed
  2574.         $codecount = 0;
  2575.  
  2576.         // Start with the prefix; copy it to output
  2577.         $encoded $this->_punycode_prefix;
  2578.  
  2579.         $encoded '';
  2580.         // Copy all basic code points to output
  2581.         for ($i = 0; $i $deco_len; ++$i{
  2582.             $test $decoded[$i];
  2583.             // Will match [0-9a-zA-Z-]
  2584.             if ((0x2F < $test && $test < 0x40)
  2585.                 || (0x40 < $test && $test < 0x5B)
  2586.                 || (0x60 < $test && $test <= 0x7B)
  2587.                 || (0x2D == $test)
  2588.             {
  2589.                 $encoded .= chr($decoded[$i]);
  2590.                 $codecount++;
  2591.             }
  2592.         }
  2593.  
  2594.         // All codepoints were basic ones
  2595.         if ($codecount == $deco_len{
  2596.             return $encoded;
  2597.         }
  2598.  
  2599.         // Start with the prefix; copy it to output
  2600.         $encoded $this->_punycode_prefix $encoded;
  2601.  
  2602.         // If we have basic code points in output, add an hyphen to the end
  2603.         if ($codecount{
  2604.             $encoded .= '-';
  2605.         }
  2606.  
  2607.         // Now find and encode all non-basic code points
  2608.         $is_first  = true;
  2609.         $cur_code  $this->_initial_n;
  2610.         $bias      $this->_initial_bias;
  2611.         $delta     = 0;
  2612.  
  2613.         while ($codecount $deco_len{
  2614.             // Find the smallest code point >= the current code point and
  2615.             // remember the last ouccrence of it in the input
  2616.             for ($i = 0$next_code $this->_max_ucs$i $deco_len$i++{
  2617.                 if ($decoded[$i>= $cur_code && $decoded[$i<= $next_code{
  2618.                     $next_code $decoded[$i];
  2619.                 }
  2620.             }
  2621.  
  2622.             $delta += ($next_code $cur_code($codecount + 1);
  2623.             $cur_code $next_code;
  2624.  
  2625.             // Scan input again and encode all characters whose code point is $cur_code
  2626.             for ($i = 0; $i $deco_len$i++{
  2627.                 if ($decoded[$i$cur_code{
  2628.                     $delta++;
  2629.                 else if ($decoded[$i== $cur_code{
  2630.                     for ($q $delta$k $this->_base; 1; $k += $this->_base{
  2631.                         $t ($k <= $bias)?
  2632.                             $this->_tmin :
  2633.                             (($k >= $bias $this->_tmax)$this->_tmax $k $bias);
  2634.  
  2635.                         if ($q $t{
  2636.                             break;
  2637.                         }
  2638.  
  2639.                         $encoded .= $this->_encodeDigit(ceil($t (($q $t($this->_base $t))));
  2640.                         $q ($q $t($this->_base $t);
  2641.                     }
  2642.  
  2643.                     $encoded .= $this->_encodeDigit($q);
  2644.                     $bias $this->_adapt($delta$codecount + 1$is_first);
  2645.                     $codecount++;
  2646.                     $delta = 0;
  2647.                     $is_first = false;
  2648.                 }
  2649.             }
  2650.  
  2651.             $delta++;
  2652.             $cur_code++;
  2653.         }
  2654.  
  2655.         return $encoded;
  2656.     }
  2657.  
  2658.     /**
  2659.      * The actual decoding algorithm.
  2660.      *
  2661.      * @param string $encoded Encoded string which should be decoded
  2662.      *
  2663.      * @return string         Decoded string
  2664.      * @throws Exception
  2665.      * @access private
  2666.      */
  2667.     private function _decode($encoded)
  2668.     {
  2669.         // We do need to find the Punycode prefix
  2670.         if (!preg_match('!^' preg_quote($this->_punycode_prefix'!''!'$encoded)) {
  2671.             return false;
  2672.         }
  2673.  
  2674.         $encode_test preg_replace('!^' preg_quote($this->_punycode_prefix'!''!'''$encoded);
  2675.  
  2676.         // If nothing left after removing the prefix, it is hopeless
  2677.         if (!$encode_test{
  2678.             return false;
  2679.         }
  2680.  
  2681.         // Find last occurence of the delimiter
  2682.         $delim_pos strrpos($encoded'-');
  2683.  
  2684.         if ($delim_pos > self::_byteLength($this->_punycode_prefix)) {
  2685.             for ($k = self::_byteLength($this->_punycode_prefix)$k $delim_pos; ++$k{
  2686.                 $decoded[ord($encoded{$k});
  2687.             }
  2688.         else {
  2689.             $decoded = array();
  2690.         }
  2691.  
  2692.         $deco_len count($decoded);
  2693.         $enco_len = self::_byteLength($encoded);
  2694.  
  2695.         // Wandering through the strings; init
  2696.         $is_first = true;
  2697.         $bias     $this->_initial_bias;
  2698.         $idx      = 0;
  2699.         $char     $this->_initial_n;
  2700.  
  2701.         for ($enco_idx ($delim_pos)($delim_pos + 1: 0; $enco_idx $enco_len; ++$deco_len{
  2702.             for ($old_idx $idx$w = 1$k $this->_base; 1 ; $k += $this->_base{
  2703.                 $digit $this->_decodeDigit($encoded{$enco_idx++});
  2704.                 $idx += $digit $w;
  2705.  
  2706.                 $t ($k <= $bias?
  2707.                     $this->_tmin :
  2708.                     (($k >= $bias $this->_tmax)$this->_tmax ($k $bias));
  2709.  
  2710.                 if ($digit $t{
  2711.                     break;
  2712.                 }
  2713.  
  2714.                 $w = (int)($w ($this->_base $t));
  2715.             }
  2716.  
  2717.             $bias      $this->_adapt($idx $old_idx$deco_len + 1$is_first);
  2718.             $is_first  = false;
  2719.             $char     += (int) ($idx ($deco_len + 1));
  2720.             $idx      %= ($deco_len + 1);
  2721.  
  2722.             if ($deco_len > 0{
  2723.                 // Make room for the decoded char
  2724.                 for ($i $deco_len$i $idx$i--{
  2725.                     $decoded[$i$decoded[($i - 1)];
  2726.                 }
  2727.             }
  2728.  
  2729.             $decoded[$idx++$char;
  2730.         }
  2731.  
  2732.         return $this->_ucs4_to_utf8($decoded);
  2733.     }
  2734.  
  2735.     /**
  2736.      * Adapt the bias according to the current code point and position.
  2737.      *
  2738.      * @param int     $delta    ...
  2739.      * @param int     $npoints  ...
  2740.      * @param boolean $is_first ...
  2741.      *
  2742.      * @return int 
  2743.      * @access private
  2744.      */
  2745.     private function _adapt($delta$npoints$is_first)
  2746.     {
  2747.         $delta = (int) ($is_first ($delta $this->_damp($delta / 2));
  2748.         $delta += (int) ($delta $npoints);
  2749.  
  2750.         for ($k = 0; $delta (($this->_base $this->_tmin$this->_tmax/ 2; $k += $this->_base{
  2751.             $delta = (int) ($delta ($this->_base $this->_tmin));
  2752.         }
  2753.  
  2754.         return (int) ($k ($this->_base $this->_tmin + 1$delta ($delta $this->_skew));
  2755.     }
  2756.  
  2757.     /**
  2758.      * Encoding a certain digit.
  2759.      *
  2760.      * @param int $d One digit to encode
  2761.      *
  2762.      * @return char  Encoded digit
  2763.      * @access private
  2764.      */
  2765.     private function _encodeDigit($d)
  2766.     {
  2767.         return chr($d + 22 + 75 * ($d < 26));
  2768.     }
  2769.  
  2770.     /**
  2771.      * Decode a certain digit.
  2772.      *
  2773.      * @param char $cp One digit (character) to decode
  2774.      *
  2775.      * @return int     Decoded digit
  2776.      * @access private
  2777.      */
  2778.     private function _decodeDigit($cp)
  2779.     {
  2780.         $cp ord($cp);
  2781.         return ($cp - 48 < 10)$cp - 22 : (($cp - 65 < 26)$cp - 65 : (($cp - 97 < 26)$cp - 97 : $this->_base));
  2782.     }
  2783.  
  2784.     /**
  2785.      * Do Nameprep according to RFC3491 and RFC3454.
  2786.      *
  2787.      * @param array $input Unicode Characters
  2788.      *
  2789.      * @return string      Unicode Characters, Nameprep'd
  2790.      * @throws Exception
  2791.      * @access private
  2792.      */
  2793.     private function _nameprep($input)
  2794.     {
  2795.         $output = array();
  2796.  
  2797.         // Walking through the input array, performing the required steps on each of
  2798.         // the input chars and putting the result into the output array
  2799.         // While mapping required chars we apply the cannonical ordering
  2800.  
  2801.         foreach ($input as $v{
  2802.             // Map to nothing == skip that code point
  2803.             if (in_array($vself::$_np_map_nothing)) {
  2804.                 continue;
  2805.             }
  2806.  
  2807.             // Try to find prohibited input
  2808.             if (in_array($vself::$_np_prohibit|| in_array($vself::$_general_prohibited)) {
  2809.                 throw new Net_IDNA2_Exception_Nameprep('Prohibited input U+' sprintf('%08X'$v));
  2810.             }
  2811.  
  2812.             foreach (self::$_np_prohibit_ranges as $range{
  2813.                 if ($range[0<= $v && $v <= $range[1]{
  2814.                     throw new Net_IDNA2_Exception_Nameprep('Prohibited input U+' sprintf('%08X'$v));
  2815.                 }
  2816.             }
  2817.  
  2818.             // Hangul syllable decomposition
  2819.             if (0xAC00 <= $v && $v <= 0xD7AF{
  2820.                 foreach ($this->_hangulDecompose($vas $out{
  2821.                     $output[$out;
  2822.                 }
  2823.             else if (($this->_version == '2003'&& isset(self::$_np_replacemaps[$v])) {
  2824.                 // There's a decomposition mapping for that code point
  2825.                 // Decompositions only in version 2003 (original) of IDNA
  2826.                 foreach ($this->_applyCannonicalOrdering(self::$_np_replacemaps[$v]as $out{
  2827.                     $output[$out;
  2828.                 }
  2829.             else {
  2830.                 $output[$v;
  2831.             }
  2832.         }
  2833.  
  2834.         // Combine code points
  2835.  
  2836.         $last_class   = 0;
  2837.         $last_starter = 0;
  2838.         $out_len      = count($output);
  2839.  
  2840.         for ($i = 0; $i $out_len; ++$i{
  2841.             $class $this->_getCombiningClass($output[$i]);
  2842.  
  2843.             if ((!$last_class || $last_class != $class&& $class{
  2844.                 // Try to match
  2845.                 $seq_len $i $last_starter;
  2846.                 $out $this->_combine(array_slice($output$last_starter$seq_len));
  2847.  
  2848.                 // On match: Replace the last starter with the composed character and remove
  2849.                 // the now redundant non-starter(s)
  2850.                 if ($out{
  2851.                     $output[$last_starter$out;
  2852.  
  2853.                     if (count($out!= $seq_len{
  2854.                         for ($j $i + 1; $j $out_len; ++$j{
  2855.                             $output[$j - 1$output[$j];
  2856.                         }
  2857.  
  2858.                         unset($output[$out_len]);
  2859.                     }
  2860.  
  2861.                     // Rewind the for loop by one, since there can be more possible compositions
  2862.                     $i--;
  2863.                     $out_len--;
  2864.                     $last_class ($i == $last_starter)? 0 : $this->_getCombiningClass($output[$i - 1]);
  2865.  
  2866.                     continue;
  2867.                 }
  2868.             }
  2869.  
  2870.             // The current class is 0
  2871.             if (!$class{
  2872.                 $last_starter $i;
  2873.             }
  2874.  
  2875.             $last_class $class;
  2876.         }
  2877.  
  2878.         return $output;
  2879.     }
  2880.  
  2881.     /**
  2882.      * Decomposes a Hangul syllable
  2883.      * (see http://www.unicode.org/unicode/reports/tr15/#Hangul).
  2884.      *
  2885.      * @param integer $char 32bit UCS4 code point
  2886.      *
  2887.      * @return array        Either Hangul Syllable decomposed or original 32bit
  2888.      *                       value as one value array
  2889.      * @access private
  2890.      */
  2891.     private function _hangulDecompose($char)
  2892.     {
  2893.         $sindex $char $this->_sbase;
  2894.  
  2895.         if ($sindex < 0 || $sindex >= $this->_scount{
  2896.             return array($char);
  2897.         }
  2898.  
  2899.         $result   = array();
  2900.         $T        $this->_tbase $sindex $this->_tcount;
  2901.         $result[= (int)($this->_lbase +  $sindex $this->_ncount);
  2902.         $result[= (int)($this->_vbase ($sindex $this->_ncount$this->_tcount);
  2903.  
  2904.         if ($T != $this->_tbase{
  2905.             $result[$T;
  2906.         }
  2907.  
  2908.         return $result;
  2909.     }
  2910.  
  2911.     /**
  2912.      * Ccomposes a Hangul syllable
  2913.      * (see http://www.unicode.org/unicode/reports/tr15/#Hangul).
  2914.      *
  2915.      * @param array $input Decomposed UCS4 sequence
  2916.      *
  2917.      * @return array       UCS4 sequence with syllables composed
  2918.      * @access private
  2919.      */
  2920.     private function _hangulCompose($input)
  2921.     {
  2922.         $inp_len count($input);
  2923.  
  2924.         if (!$inp_len{
  2925.             return array();
  2926.         }
  2927.  
  2928.         $result   = array();
  2929.         $last     $input[0];
  2930.         $result[$last// copy first char from input to output
  2931.  
  2932.         for ($i = 1; $i $inp_len; ++$i{
  2933.             $char $input[$i];
  2934.  
  2935.             // Find out, wether two current characters from L and V
  2936.             $lindex $last $this->_lbase;
  2937.  
  2938.             if (0 <= $lindex && $lindex $this->_lcount{
  2939.                 $vindex $char $this->_vbase;
  2940.  
  2941.                 if (0 <= $vindex && $vindex $this->_vcount{
  2942.                     // create syllable of form LV
  2943.                     $last    ($this->_sbase ($lindex $this->_vcount $vindex$this->_tcount);
  2944.                     $out_off count($result- 1;
  2945.                     $result[$out_off$last// reset last
  2946.  
  2947.                     // discard char
  2948.                     continue;
  2949.                 }
  2950.             }
  2951.  
  2952.             // Find out, wether two current characters are LV and T
  2953.             $sindex $last $this->_sbase;
  2954.  
  2955.             if (0 <= $sindex && $sindex $this->_scount && ($sindex $this->_tcount== 0{
  2956.                 $tindex $char $this->_tbase;
  2957.  
  2958.                 if (0 <= $tindex && $tindex <= $this->_tcount{
  2959.                     // create syllable of form LVT
  2960.                     $last += $tindex;
  2961.                     $out_off count($result- 1;
  2962.                     $result[$out_off$last// reset last
  2963.  
  2964.                     // discard char
  2965.                     continue;
  2966.                 }
  2967.             }
  2968.  
  2969.             // if neither case was true, just add the character
  2970.             $last $char;
  2971.             $result[$char;
  2972.         }
  2973.  
  2974.         return $result;
  2975.     }
  2976.  
  2977.     /**
  2978.      * Returns the combining class of a certain wide char.
  2979.      *
  2980.      * @param integer $char Wide char to check (32bit integer)
  2981.      *
  2982.      * @return integer      Combining class if found, else 0
  2983.      * @access private
  2984.      */
  2985.     private function _getCombiningClass($char)
  2986.     {
  2987.         return isset(self::$_np_norm_combcls[$char])? self::$_np_norm_combcls[$char: 0;
  2988.     }
  2989.  
  2990.     /**
  2991.      * Apllies the cannonical ordering of a decomposed UCS4 sequence.
  2992.      *
  2993.      * @param array $input Decomposed UCS4 sequence
  2994.      *
  2995.      * @return array       Ordered USC4 sequence
  2996.      * @access private
  2997.      */
  2998.     private function _applyCannonicalOrdering($input)
  2999.     {
  3000.         $swap = true;
  3001.         $size count($input);
  3002.  
  3003.         while ($swap{
  3004.             $swap = false;
  3005.             $last $this->_getCombiningClass($input[0]);
  3006.  
  3007.             for ($i = 0; $i $size - 1; ++$i{
  3008.                 $next $this->_getCombiningClass($input[$i + 1]);
  3009.  
  3010.                 if ($next != 0 && $last $next{
  3011.                     // Move item leftward until it fits
  3012.                     for ($j $i + 1; $j > 0; --$j{
  3013.                         if ($this->_getCombiningClass($input[$j - 1]<= $next{
  3014.                             break;
  3015.                         }
  3016.  
  3017.                         $t $input[$j];
  3018.                         $input[$j$input[$j - 1];
  3019.                         $input[$j - 1$t;
  3020.                         $swap = 1;
  3021.                     }
  3022.  
  3023.                     // Reentering the loop looking at the old character again
  3024.                     $next $last;
  3025.                 }
  3026.  
  3027.                 $last $next;
  3028.             }
  3029.         }
  3030.  
  3031.         return $input;
  3032.     }
  3033.  
  3034.     /**
  3035.      * Do composition of a sequence of starter and non-starter.
  3036.      *
  3037.      * @param array $input UCS4 Decomposed sequence
  3038.      *
  3039.      * @return array       Ordered USC4 sequence
  3040.      * @access private
  3041.      */
  3042.     private function _combine($input)
  3043.     {
  3044.         $inp_len count($input);
  3045.  
  3046.         // Is it a Hangul syllable?
  3047.         if (1 != $inp_len{
  3048.             $hangul $this->_hangulCompose($input);
  3049.  
  3050.             // This place is probably wrong
  3051.             if (count($hangul!= $inp_len{
  3052.                 return $hangul;
  3053.             }
  3054.         }
  3055.  
  3056.         foreach (self::$_np_replacemaps as $np_src => $np_target{
  3057.             if ($np_target[0!= $input[0]{
  3058.                 continue;
  3059.             }
  3060.  
  3061.             if (count($np_target!= $inp_len{
  3062.                 continue;
  3063.             }
  3064.  
  3065.             $hit = false;
  3066.  
  3067.             foreach ($input as $k2 => $v2{
  3068.                 if ($v2 == $np_target[$k2]{
  3069.                     $hit = true;
  3070.                 else {
  3071.                     $hit = false;
  3072.                     break;
  3073.                 }
  3074.             }
  3075.  
  3076.             if ($hit{
  3077.                 return $np_src;
  3078.             }
  3079.         }
  3080.  
  3081.         return false;
  3082.     }
  3083.  
  3084.     /**
  3085.      * This converts an UTF-8 encoded string to its UCS-4 (array) representation
  3086.      * By talking about UCS-4 we mean arrays of 32bit integers representing
  3087.      * each of the "chars". This is due to PHP not being able to handle strings with
  3088.      * bit depth different from 8. This applies to the reverse method _ucs4_to_utf8(), too.
  3089.      * The following UTF-8 encodings are supported:
  3090.      *
  3091.      * bytes bits  representation
  3092.      * 1        7  0xxxxxxx
  3093.      * 2       11  110xxxxx 10xxxxxx
  3094.      * 3       16  1110xxxx 10xxxxxx 10xxxxxx
  3095.      * 4       21  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  3096.      * 5       26  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  3097.      * 6       31  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  3098.      *
  3099.      * Each x represents a bit that can be used to store character data.
  3100.      *
  3101.      * @param string $input utf8-encoded string
  3102.      *
  3103.      * @return array        ucs4-encoded array
  3104.      * @throws Exception
  3105.      * @access private
  3106.      */
  3107.     private function _utf8_to_ucs4($input)
  3108.     {
  3109.         $output = array();
  3110.         $out_len = 0;
  3111.         $inp_len = self::_byteLength($input'8bit');
  3112.         $mode 'next';
  3113.         $test 'none';
  3114.         for ($k = 0; $k $inp_len; ++$k{
  3115.             $v ord($input{$k})// Extract byte from input string
  3116.  
  3117.             if ($v < 128// We found an ASCII char - put into stirng as is
  3118.                 $output[$out_len$v;
  3119.                 ++$out_len;
  3120.                 if ('add' == $mode{
  3121.                     throw new UnexpectedValueException('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
  3122.                 }
  3123.                 continue;
  3124.             }
  3125.             if ('next' == $mode// Try to find the next start byte; determine the width of the Unicode char
  3126.                 $start_byte $v;
  3127.                 $mode 'add';
  3128.                 $test 'range';
  3129.                 if ($v >> 5 == 6// &110xxxxx 10xxxxx
  3130.                     $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
  3131.                     $v ($v - 192<< 6;
  3132.                 elseif ($v >> 4 == 14// &1110xxxx 10xxxxxx 10xxxxxx
  3133.                     $next_byte = 1;
  3134.                     $v ($v - 224<< 12;
  3135.                 elseif ($v >> 3 == 30// &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  3136.                     $next_byte = 2;
  3137.                     $v ($v - 240<< 18;
  3138.                 elseif ($v >> 2 == 62// &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  3139.                     $next_byte = 3;
  3140.                     $v ($v - 248<< 24;
  3141.                 elseif ($v >> 1 == 126// &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  3142.                     $next_byte = 4;
  3143.                     $v ($v - 252<< 30;
  3144.                 else {
  3145.                     throw new UnexpectedValueException('This might be UTF-8, but I don\'t understand it at byte '.$k);
  3146.                 }
  3147.                 if ('add' == $mode{
  3148.                     $output[$out_len= (int) $v;
  3149.                     ++$out_len;
  3150.                     continue;
  3151.                 }
  3152.             }
  3153.             if ('add' == $mode{
  3154.                 if (!$this->_allow_overlong && $test == 'range'{
  3155.                     $test 'none';
  3156.                     if (($v < 0xA0 && $start_byte == 0xE0|| ($v < 0x90 && $start_byte == 0xF0|| ($v > 0x8F && $start_byte == 0xF4)) {
  3157.                         throw new OutOfRangeException('Bogus UTF-8 character detected (out of legal range) at byte '.$k);
  3158.                     }
  3159.                 }
  3160.                 if ($v >> 6 == 2// Bit mask must be 10xxxxxx
  3161.                     $v ($v - 128<< ($next_byte * 6);
  3162.                     $output[($out_len - 1)+= $v;
  3163.                     --$next_byte;
  3164.                 else {
  3165.                     throw new UnexpectedValueException('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
  3166.                 }
  3167.                 if ($next_byte < 0{
  3168.                     $mode 'next';
  3169.                 }
  3170.             }
  3171.         // for
  3172.         return $output;
  3173.     }
  3174.  
  3175.     /**
  3176.      * Convert UCS-4 array into UTF-8 string
  3177.      *
  3178.      * @param array $input ucs4-encoded array
  3179.      *
  3180.      * @return string      utf8-encoded string
  3181.      * @throws Exception
  3182.      * @access private
  3183.      */
  3184.     private function _ucs4_to_utf8($input)
  3185.     {
  3186.         $output '';
  3187.  
  3188.         foreach ($input as $v{
  3189.             // $v = ord($v);
  3190.  
  3191.             if ($v < 128{
  3192.                 // 7bit are transferred literally
  3193.                 $output .= chr($v);
  3194.             else if ($v < 1 << 11{
  3195.                 // 2 bytes
  3196.                 $output .= chr(192 + ($v >> 6))
  3197.                     . chr(128 + ($v 63));
  3198.             else if ($v < 1 << 16{
  3199.                 // 3 bytes
  3200.                 $output .= chr(224 + ($v >> 12))
  3201.                     . chr(128 + (($v >> 663))
  3202.                     . chr(128 + ($v 63));
  3203.             else if ($v < 1 << 21{
  3204.                 // 4 bytes
  3205.                 $output .= chr(240 + ($v >> 18))
  3206.                     . chr(128 + (($v >> 1263))
  3207.                     . chr(128 + (($v >>  663))
  3208.                     . chr(128 + ($v 63));
  3209.             else if ($v < 1 << 26{
  3210.                 // 5 bytes
  3211.                 $output .= chr(248 + ($v >> 24))
  3212.                     . chr(128 + (($v >> 1863))
  3213.                     . chr(128 + (($v >> 1263))
  3214.                     . chr(128 + (($v >>  663))
  3215.                     . chr(128 + ($v 63));
  3216.             else if ($v < 1 << 31{
  3217.                 // 6 bytes
  3218.                 $output .= chr(252 + ($v >> 30))
  3219.                     . chr(128 + (($v >> 2463))
  3220.                     . chr(128 + (($v >> 1863))
  3221.                     . chr(128 + (($v >> 1263))
  3222.                     . chr(128 + (($v >>  663))
  3223.                     . chr(128 + ($v 63));
  3224.             else {
  3225.                 throw new UnexpectedValueException('Conversion from UCS-4 to UTF-8 failed: malformed input');
  3226.             }
  3227.         }
  3228.  
  3229.         return $output;
  3230.     }
  3231.  
  3232.     /**
  3233.      * Convert UCS-4 array into UCS-4 string
  3234.      *
  3235.      * @param array $input ucs4-encoded array
  3236.      *
  3237.      * @return string      ucs4-encoded string
  3238.      * @throws Exception
  3239.      * @access private
  3240.      */
  3241.     private function _ucs4_to_ucs4_string($input)
  3242.     {
  3243.         $output '';
  3244.         // Take array values and split output to 4 bytes per value
  3245.         // The bit mask is 255, which reads &11111111
  3246.         foreach ($input as $v{
  3247.             $output .= ($v (255 << 24>> 24($v (255 << 16>> 16($v (255 << 8>> 8($v 255);
  3248.         }
  3249.         return $output;
  3250.     }
  3251.  
  3252.     /**
  3253.      * Convert UCS-4 string into UCS-4 array
  3254.      *
  3255.      * @param string $input ucs4-encoded string
  3256.      *
  3257.      * @return array        ucs4-encoded array
  3258.      * @throws InvalidArgumentException
  3259.      * @access private
  3260.      */
  3261.     private function _ucs4_string_to_ucs4($input)
  3262.     {
  3263.         $output = array();
  3264.  
  3265.         $inp_len = self::_byteLength($input);
  3266.         // Input length must be dividable by 4
  3267.         if ($inp_len % 4{
  3268.             throw new InvalidArgumentException('Input UCS4 string is broken');
  3269.         }
  3270.  
  3271.         // Empty input - return empty output
  3272.         if (!$inp_len{
  3273.             return $output;
  3274.         }
  3275.  
  3276.         for ($i = 0$out_len = -1; $i $inp_len; ++$i{
  3277.             // Increment output position every 4 input bytes
  3278.             if (!$i % 4{
  3279.                 $out_len++;
  3280.                 $output[$out_len= 0;
  3281.             }
  3282.             $output[$out_len+= ord($input{$i}<< (8 * (3 - ($i % 4) ) );
  3283.         }
  3284.         return $output;
  3285.     }
  3286.  
  3287.     /**
  3288.      * Echo hex representation of UCS4 sequence.
  3289.      *
  3290.      * @param array   $input       UCS4 sequence
  3291.      * @param boolean $include_bit Include bitmask in output
  3292.      *
  3293.      * @return void 
  3294.      * @static
  3295.      * @access private
  3296.      */
  3297.     private static function _showHex($input$include_bit = false)
  3298.     {
  3299.         foreach ($input as $k => $v{
  3300.             echo '['$k'] => 'sprintf('%X'$v);
  3301.  
  3302.             if ($include_bit{
  3303.                 echo ' ('Net_IDNA2::_showBitmask($v)')';
  3304.             }
  3305.  
  3306.             echo "\n";
  3307.         }
  3308.     }
  3309.  
  3310.     /**
  3311.      * Gives you a bit representation of given Byte (8 bits), Word (16 bits) or DWord (32 bits)
  3312.      * Output width is automagically determined
  3313.      *
  3314.      * @param int $octet ...
  3315.      *
  3316.      * @return string    Bitmask-representation
  3317.      * @static
  3318.      * @access private
  3319.      */
  3320.     private static function _showBitmask($octet)
  3321.     {
  3322.         if ($octet >= (1 << 16)) {
  3323.             $w = 31;
  3324.         else if ($octet >= (1 << 8)) {
  3325.             $w = 15;
  3326.         else {
  3327.             $w = 7;
  3328.         }
  3329.  
  3330.         $return '';
  3331.  
  3332.         for ($i $w$i > -1; $i--{
  3333.             $return .= ($octet (1 << $i))'1' '0';
  3334.         }
  3335.  
  3336.         return $return;
  3337.     }
  3338.  
  3339.     /**
  3340.      * Gets the length of a string in bytes even if mbstring function
  3341.      * overloading is turned on
  3342.      *
  3343.      * @param string $string the string for which to get the length.
  3344.      *
  3345.      * @return integer the length of the string in bytes.
  3346.      *
  3347.      * @see Net_IDNA2::$_mb_string_overload
  3348.      */
  3349.     private static function _byteLength($string)
  3350.     {
  3351.         if (self::$_mb_string_overload{
  3352.             return mb_strlen($string'8bit');
  3353.         }
  3354.         return strlen((binary)$string);
  3355.     }
  3356.  
  3357.     // }}}}
  3358.  
  3359.     // {{{ factory
  3360.     /**
  3361.      * Attempts to return a concrete IDNA instance for either php4 or php5.
  3362.      *
  3363.      * @param array $params Set of paramaters
  3364.      *
  3365.      * @return Net_IDNA2 
  3366.      * @access public
  3367.      */
  3368.     function getInstance($params = array())
  3369.     {
  3370.         return new Net_IDNA2($params);
  3371.     }
  3372.     // }}}
  3373.  
  3374.     // {{{ singleton
  3375.     /**
  3376.      * Attempts to return a concrete IDNA instance for either php4 or php5,
  3377.      * only creating a new instance if no IDNA instance with the same
  3378.      * parameters currently exists.
  3379.      *
  3380.      * @param array $params Set of paramaters
  3381.      *
  3382.      * @return object Net_IDNA2 
  3383.      * @access public
  3384.      */
  3385.     function singleton($params = array())
  3386.     {
  3387.         static $instances;
  3388.         if (!isset($instances)) {
  3389.             $instances = array();
  3390.         }
  3391.  
  3392.         $signature serialize($params);
  3393.         if (!isset($instances[$signature])) {
  3394.             $instances[$signatureNet_IDNA2::getInstance($params);
  3395.         }
  3396.  
  3397.         return $instances[$signature];
  3398.     }
  3399.     // }}}
  3400. }
  3401.  
  3402. ?>

Documentation generated on Mon, 11 Mar 2019 15:41:59 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.