"Fossies" - the Fresh Open Source Software Archive

Member "yii-1.1.22.bf1d26/framework/vendors/Net_IDNA2/Net/IDNA2.php" (16 Jan 2020, 104156 Bytes) of package /linux/www/yii-1.1.22.bf1d26.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "IDNA2.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.1.21.733ac5_vs_1.1.22.bf1d26.

    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 dirname(__FILE__).'/IDNA2/Exception.php';
   27 require_once dirname(__FILE__).'/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(0x100000, 0x10FFFD),
  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(0x73, 0x73),
  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(0x69, 0x307),
  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(0x2BC, 0x6E),
  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(0x6A, 0x30C),
  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(0x20, 0x3B9),
  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(0x3B9, 0x308, 0x301),
  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(0x3C5, 0x308, 0x301),
  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(0x565, 0x582),
  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(0x68, 0x331),
  816         0x1E97  => array(0x74, 0x308),
  817         0x1E98  => array(0x77, 0x30A),
  818         0x1E99  => array(0x79, 0x30A),
  819         0x1E9A  => array(0x61, 0x2BE),
  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(0x3C5, 0x313),
  903         0x1F52  => array(0x3C5, 0x313, 0x300),
  904         0x1F54  => array(0x3C5, 0x313, 0x301),
  905         0x1F56  => array(0x3C5, 0x313, 0x342),
  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(0x1F00, 0x3B9),
  919         0x1F81  => array(0x1F01, 0x3B9),
  920         0x1F82  => array(0x1F02, 0x3B9),
  921         0x1F83  => array(0x1F03, 0x3B9),
  922         0x1F84  => array(0x1F04, 0x3B9),
  923         0x1F85  => array(0x1F05, 0x3B9),
  924         0x1F86  => array(0x1F06, 0x3B9),
  925         0x1F87  => array(0x1F07, 0x3B9),
  926         0x1F88  => array(0x1F00, 0x3B9),
  927         0x1F89  => array(0x1F01, 0x3B9),
  928         0x1F8A  => array(0x1F02, 0x3B9),
  929         0x1F8B  => array(0x1F03, 0x3B9),
  930         0x1F8C  => array(0x1F04, 0x3B9),
  931         0x1F8D  => array(0x1F05, 0x3B9),
  932         0x1F8E  => array(0x1F06, 0x3B9),
  933         0x1F8F  => array(0x1F07, 0x3B9),
  934         0x1F90  => array(0x1F20, 0x3B9),
  935         0x1F91  => array(0x1F21, 0x3B9),
  936         0x1F92  => array(0x1F22, 0x3B9),
  937         0x1F93  => array(0x1F23, 0x3B9),
  938         0x1F94  => array(0x1F24, 0x3B9),
  939         0x1F95  => array(0x1F25, 0x3B9),
  940         0x1F96  => array(0x1F26, 0x3B9),
  941         0x1F97  => array(0x1F27, 0x3B9),
  942         0x1F98  => array(0x1F20, 0x3B9),
  943         0x1F99  => array(0x1F21, 0x3B9),
  944         0x1F9A  => array(0x1F22, 0x3B9),
  945         0x1F9B  => array(0x1F23, 0x3B9),
  946         0x1F9C  => array(0x1F24, 0x3B9),
  947         0x1F9D  => array(0x1F25, 0x3B9),
  948         0x1F9E  => array(0x1F26, 0x3B9),
  949         0x1F9F  => array(0x1F27, 0x3B9),
  950         0x1FA0  => array(0x1F60, 0x3B9),
  951         0x1FA1  => array(0x1F61, 0x3B9),
  952         0x1FA2  => array(0x1F62, 0x3B9),
  953         0x1FA3  => array(0x1F63, 0x3B9),
  954         0x1FA4  => array(0x1F64, 0x3B9),
  955         0x1FA5  => array(0x1F65, 0x3B9),
  956         0x1FA6  => array(0x1F66, 0x3B9),
  957         0x1FA7  => array(0x1F67, 0x3B9),
  958         0x1FA8  => array(0x1F60, 0x3B9),
  959         0x1FA9  => array(0x1F61, 0x3B9),
  960         0x1FAA  => array(0x1F62, 0x3B9),
  961         0x1FAB  => array(0x1F63, 0x3B9),
  962         0x1FAC  => array(0x1F64, 0x3B9),
  963         0x1FAD  => array(0x1F65, 0x3B9),
  964         0x1FAE  => array(0x1F66, 0x3B9),
  965         0x1FAF  => array(0x1F67, 0x3B9),
  966         0x1FB2  => array(0x1F70, 0x3B9),
  967         0x1FB3  => array(0x3B1, 0x3B9),
  968         0x1FB4  => array(0x3AC, 0x3B9),
  969         0x1FB6  => array(0x3B1, 0x342),
  970         0x1FB7  => array(0x3B1, 0x342, 0x3B9),
  971         0x1FB8  => array(0x1FB0),
  972         0x1FB9  => array(0x1FB1),
  973         0x1FBA  => array(0x1F70),
  974         0x1FBB  => array(0x1F71),
  975         0x1FBC  => array(0x3B1, 0x3B9),
  976         0x1FBE  => array(0x3B9),
  977         0x1FC2  => array(0x1F74, 0x3B9),
  978         0x1FC3  => array(0x3B7, 0x3B9),
  979         0x1FC4  => array(0x3AE, 0x3B9),
  980         0x1FC6  => array(0x3B7, 0x342),
  981         0x1FC7  => array(0x3B7, 0x342, 0x3B9),
  982         0x1FC8  => array(0x1F72),
  983         0x1FC9  => array(0x1F73),
  984         0x1FCA  => array(0x1F74),
  985         0x1FCB  => array(0x1F75),
  986         0x1FCC  => array(0x3B7, 0x3B9),
  987         0x1FD2  => array(0x3B9, 0x308, 0x300),
  988         0x1FD3  => array(0x3B9, 0x308, 0x301),
  989         0x1FD6  => array(0x3B9, 0x342),
  990         0x1FD7  => array(0x3B9, 0x308, 0x342),
  991         0x1FD8  => array(0x1FD0),
  992         0x1FD9  => array(0x1FD1),
  993         0x1FDA  => array(0x1F76),
  994         0x1FDB  => array(0x1F77),
  995         0x1FE2  => array(0x3C5, 0x308, 0x300),
  996         0x1FE3  => array(0x3C5, 0x308, 0x301),
  997         0x1FE4  => array(0x3C1, 0x313),
  998         0x1FE6  => array(0x3C5, 0x342),
  999         0x1FE7  => array(0x3C5, 0x308, 0x342),
 1000         0x1FE8  => array(0x1FE0),
 1001         0x1FE9  => array(0x1FE1),
 1002         0x1FEA  => array(0x1F7A),
 1003         0x1FEB  => array(0x1F7B),
 1004         0x1FEC  => array(0x1FE5),
 1005         0x1FF2  => array(0x1F7C, 0x3B9),
 1006         0x1FF3  => array(0x3C9, 0x3B9),
 1007         0x1FF4  => array(0x3CE, 0x3B9),
 1008         0x1FF6  => array(0x3C9, 0x342),
 1009         0x1FF7  => array(0x3C9, 0x342, 0x3B9),
 1010         0x1FF8  => array(0x1F78),
 1011         0x1FF9  => array(0x1F79),
 1012         0x1FFA  => array(0x1F7C),
 1013         0x1FFB  => array(0x1F7D),
 1014         0x1FFC  => array(0x3C9, 0x3B9),
 1015         0x20A8  => array(0x72, 0x73),
 1016         0x2102  => array(0x63),
 1017         0x2103  => array(0xB0, 0x63),
 1018         0x2107  => array(0x25B),
 1019         0x2109  => array(0xB0, 0x66),
 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(0x6E, 0x6F),
 1028         0x2119  => array(0x70),
 1029         0x211A  => array(0x71),
 1030         0x211B  => array(0x72),
 1031         0x211C  => array(0x72),
 1032         0x211D  => array(0x72),
 1033         0x2120  => array(0x73, 0x6D),
 1034         0x2121  => array(0x74, 0x65, 0x6C),
 1035         0x2122  => array(0x74, 0x6D),
 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(0x68, 0x70, 0x61),
 1092         0x3373  => array(0x61, 0x75),
 1093         0x3375  => array(0x6F, 0x76),
 1094         0x3380  => array(0x70, 0x61),
 1095         0x3381  => array(0x6E, 0x61),
 1096         0x3382  => array(0x3BC, 0x61),
 1097         0x3383  => array(0x6D, 0x61),
 1098         0x3384  => array(0x6B, 0x61),
 1099         0x3385  => array(0x6B, 0x62),
 1100         0x3386  => array(0x6D, 0x62),
 1101         0x3387  => array(0x67, 0x62),
 1102         0x338A  => array(0x70, 0x66),
 1103         0x338B  => array(0x6E, 0x66),
 1104         0x338C  => array(0x3BC, 0x66),
 1105         0x3390  => array(0x68, 0x7A),
 1106         0x3391  => array(0x6B, 0x68, 0x7A),
 1107         0x3392  => array(0x6D, 0x68, 0x7A),
 1108         0x3393  => array(0x67, 0x68, 0x7A),
 1109         0x3394  => array(0x74, 0x68, 0x7A),
 1110         0x33A9  => array(0x70, 0x61),
 1111         0x33AA  => array(0x6B, 0x70, 0x61),
 1112         0x33AB  => array(0x6D, 0x70, 0x61),
 1113         0x33AC  => array(0x67, 0x70, 0x61),
 1114         0x33B4  => array(0x70, 0x76),
 1115         0x33B5  => array(0x6E, 0x76),
 1116         0x33B6  => array(0x3BC, 0x76),
 1117         0x33B7  => array(0x6D, 0x76),
 1118         0x33B8  => array(0x6B, 0x76),
 1119         0x33B9  => array(0x6D, 0x76),
 1120         0x33BA  => array(0x70, 0x77),
 1121         0x33BB  => array(0x6E, 0x77),
 1122         0x33BC  => array(0x3BC, 0x77),
 1123         0x33BD  => array(0x6D, 0x77),
 1124         0x33BE  => array(0x6B, 0x77),
 1125         0x33BF  => array(0x6D, 0x77),
 1126         0x33C0  => array(0x6B, 0x3C9),
 1127         0x33C1  => array(0x6D, 0x3C9),
 1128         /* 0x33C2  => array(0x61, 0x2E, 0x6D, 0x2E), */
 1129         0x33C3  => array(0x62, 0x71),
 1130         0x33C6  => array(0x63, 0x2215, 0x6B, 0x67),
 1131         0x33C7  => array(0x63, 0x6F, 0x2E),
 1132         0x33C8  => array(0x64, 0x62),
 1133         0x33C9  => array(0x67, 0x79),
 1134         0x33CB  => array(0x68, 0x70),
 1135         0x33CD  => array(0x6B, 0x6B),
 1136         0x33CE  => array(0x6B, 0x6D),
 1137         0x33D7  => array(0x70, 0x68),
 1138         0x33D9  => array(0x70, 0x70, 0x6D),
 1139         0x33DA  => array(0x70, 0x72),
 1140         0x33DC  => array(0x73, 0x76),
 1141         0x33DD  => array(0x77, 0x62),
 1142         0xFB00  => array(0x66, 0x66),
 1143         0xFB01  => array(0x66, 0x69),
 1144         0xFB02  => array(0x66, 0x6C),
 1145         0xFB03  => array(0x66, 0x66, 0x69),
 1146         0xFB04  => array(0x66, 0x66, 0x6C),
 1147         0xFB05  => array(0x73, 0x74),
 1148         0xFB06  => array(0x73, 0x74),
 1149         0xFB13  => array(0x574, 0x576),
 1150         0xFB14  => array(0x574, 0x565),
 1151         0xFB15  => array(0x574, 0x56B),
 1152         0xFB16  => array(0x57E, 0x576),
 1153         0xFB17  => array(0x574, 0x56D),
 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(0x66, 0x61, 0x78),
 1689         0x3250  => array(0x70, 0x74, 0x65),
 1690         0x32CC  => array(0x68, 0x67),
 1691         0x32CE  => array(0x65, 0x76),
 1692         0x32CF  => array(0x6C, 0x74, 0x64),
 1693         0x337A  => array(0x69, 0x75),
 1694         0x33DE  => array(0x76, 0x2215, 0x6D),
 1695         0x33DF  => array(0x61, 0x2215, 0x6D)
 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($v, array('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, $input) = explode('@', $input, 2);
 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($decoded, 0, $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($v, self::$_np_map_nothing)) {
 2804                 continue;
 2805             }
 2806 
 2807             // Try to find prohibited input
 2808             if (in_array($v, self::$_np_prohibit) || in_array($v, self::$_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($v) as $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 >> 6) & 63))
 3202                     . chr(128 + ($v & 63));
 3203             } else if ($v < 1 << 21) {
 3204                 // 4 bytes
 3205                 $output .= chr(240 + ($v >> 18))
 3206                     . chr(128 + (($v >> 12) & 63))
 3207                     . chr(128 + (($v >>  6) & 63))
 3208                     . chr(128 + ($v & 63));
 3209             } else if ($v < 1 << 26) {
 3210                 // 5 bytes
 3211                 $output .= chr(248 + ($v >> 24))
 3212                     . chr(128 + (($v >> 18) & 63))
 3213                     . chr(128 + (($v >> 12) & 63))
 3214                     . chr(128 + (($v >>  6) & 63))
 3215                     . chr(128 + ($v & 63));
 3216             } else if ($v < 1 << 31) {
 3217                 // 6 bytes
 3218                 $output .= chr(252 + ($v >> 30))
 3219                     . chr(128 + (($v >> 24) & 63))
 3220                     . chr(128 + (($v >> 18) & 63))
 3221                     . chr(128 + (($v >> 12) & 63))
 3222                     . chr(128 + (($v >>  6) & 63))
 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[$signature] = Net_IDNA2::getInstance($params);
 3395         }
 3396 
 3397         return $instances[$signature];
 3398     }
 3399     // }}}
 3400 }
 3401 
 3402 ?>