php5.php 98 KB

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