/* */ package com.ibm.icu.text;
/* */
/* */ import com.ibm.icu.impl.ICUData;
/* */ import com.ibm.icu.impl.Trie2;
/* */ import com.ibm.icu.impl.Trie2Writable;
/* */ import com.ibm.icu.impl.Trie2_16;
/* */ import com.ibm.icu.lang.UCharacter;
/* */ import com.ibm.icu.lang.UScript;
/* */ import com.ibm.icu.util.ULocale;
/* */ import java.io.BufferedInputStream;
/* */ import java.io.ByteArrayInputStream;
/* */ import java.io.ByteArrayOutputStream;
/* */ import java.io.DataInputStream;
/* */ import java.io.DataOutputStream;
/* */ import java.io.IOException;
/* */ import java.io.InputStream;
/* */ import java.io.LineNumberReader;
/* */ import java.io.Reader;
/* */ import java.text.ParseException;
/* */ import java.util.Collections;
/* */ import java.util.Comparator;
/* */ import java.util.Hashtable;
/* */ import java.util.LinkedHashSet;
/* */ import java.util.Set;
/* */ import java.util.Vector;
/* */ import java.util.regex.Matcher;
/* */ import java.util.regex.Pattern;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public class SpoofChecker
/* */ {
/* */ public static final int SINGLE_SCRIPT_CONFUSABLE = 1;
/* */ public static final int MIXED_SCRIPT_CONFUSABLE = 2;
/* */ public static final int WHOLE_SCRIPT_CONFUSABLE = 4;
/* */ public static final int ANY_CASE = 8;
/* */ public static final int SINGLE_SCRIPT = 16;
/* */ public static final int INVISIBLE = 32;
/* */ public static final int CHAR_LIMIT = 64;
/* */ public static final int ALL_CHECKS = 127;
/* */ static final int MAGIC = 944111087;
/* */ private int fMagic;
/* */ private int fChecks;
/* */ private SpoofData fSpoofData;
/* */ private Set<ULocale> fAllowedLocales;
/* */ private UnicodeSet fAllowedCharsSet;
/* */ static final int SL_TABLE_FLAG = 16777216;
/* */ static final int SA_TABLE_FLAG = 33554432;
/* */ static final int ML_TABLE_FLAG = 67108864;
/* */ static final int MA_TABLE_FLAG = 134217728;
/* */ static final int KEY_MULTIPLE_VALUES = 268435456;
/* */ static final int KEY_LENGTH_SHIFT = 29;
/* */
/* */ public static class Builder
/* */ {
/* */ int fMagic;
/* */ int fChecks;
/* */ SpoofChecker.SpoofData fSpoofData;
/* */ UnicodeSet fAllowedCharsSet;
/* */ Set<ULocale> fAllowedLocales;
/* */
/* */ public Builder()
/* */ {
/* 272 */ this.fMagic = 944111087;
/* 273 */ this.fChecks = 127;
/* 274 */ this.fSpoofData = null;
/* 275 */ this.fAllowedCharsSet = new UnicodeSet(0, 1114111);
/* 276 */ this.fAllowedLocales = new LinkedHashSet();
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public Builder(SpoofChecker src)
/* */ {
/* 288 */ this.fMagic = src.fMagic;
/* 289 */ this.fChecks = src.fChecks;
/* 290 */ this.fSpoofData = null;
/* 291 */ this.fAllowedCharsSet = src.fAllowedCharsSet.cloneAsThawed();
/* 292 */ this.fAllowedLocales = new LinkedHashSet();
/* 293 */ this.fAllowedLocales.addAll(src.fAllowedLocales);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public SpoofChecker build()
/* */ {
/* 304 */ if (this.fSpoofData == null) {
/* */ try {
/* 306 */ this.fSpoofData = SpoofChecker.SpoofData.getDefault();
/* */ } catch (IOException e) {
/* 308 */ return null;
/* */ }
/* */ }
/* 311 */ if (!SpoofChecker.SpoofData.validateDataVersion(this.fSpoofData.fRawData)) {
/* 312 */ return null;
/* */ }
/* 314 */ SpoofChecker result = new SpoofChecker(null);
/* 315 */ result.fMagic = this.fMagic;
/* 316 */ result.fChecks = this.fChecks;
/* 317 */ result.fSpoofData = this.fSpoofData;
/* 318 */ result.fAllowedCharsSet = ((UnicodeSet)this.fAllowedCharsSet.clone());
/* 319 */ result.fAllowedCharsSet.freeze();
/* 320 */ result.fAllowedLocales = this.fAllowedLocales;
/* 321 */ return result;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public Builder setData(Reader confusables, Reader confusablesWholeScript)
/* */ throws ParseException, IOException
/* */ {
/* 343 */ this.fSpoofData = new SpoofChecker.SpoofData();
/* 344 */ ByteArrayOutputStream bos = new ByteArrayOutputStream();
/* 345 */ DataOutputStream os = new DataOutputStream(bos);
/* */
/* 347 */ ConfusabledataBuilder.buildConfusableData(this.fSpoofData, confusables);
/* 348 */ WSConfusableDataBuilder.buildWSConfusableData(this.fSpoofData, os, confusablesWholeScript);
/* 349 */ return this;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public Builder setChecks(int checks)
/* */ {
/* 365 */ if (0 != (checks & 0xFFFFFF80)) {
/* 366 */ throw new IllegalArgumentException("Bad Spoof Checks value.");
/* */ }
/* 368 */ this.fChecks = (checks & 0x7F);
/* 369 */ return this;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public Builder setAllowedLocales(Set<ULocale> locales)
/* */ {
/* 402 */ this.fAllowedCharsSet.clear();
/* */
/* 404 */ for (ULocale locale : locales)
/* */ {
/* */
/* 407 */ addScriptChars(locale, this.fAllowedCharsSet);
/* */ }
/* */
/* */
/* */
/* 412 */ this.fAllowedLocales = new LinkedHashSet();
/* 413 */ if (locales.size() == 0) {
/* 414 */ this.fAllowedCharsSet.add(0, 1114111);
/* 415 */ this.fChecks &= 0xFFFFFFBF;
/* 416 */ return this;
/* */ }
/* */
/* */
/* */
/* 421 */ UnicodeSet tempSet = new UnicodeSet();
/* 422 */ tempSet.applyIntPropertyValue(4106, 0);
/* 423 */ this.fAllowedCharsSet.addAll(tempSet);
/* 424 */ tempSet.applyIntPropertyValue(4106, 1);
/* 425 */ this.fAllowedCharsSet.addAll(tempSet);
/* */
/* */
/* 428 */ this.fAllowedLocales.addAll(locales);
/* 429 */ this.fChecks |= 0x40;
/* 430 */ return this;
/* */ }
/* */
/* */
/* */
/* */ private void addScriptChars(ULocale locale, UnicodeSet allowedChars)
/* */ {
/* 437 */ int[] scripts = UScript.getCode(locale);
/* 438 */ UnicodeSet tmpSet = new UnicodeSet();
/* */
/* 440 */ for (int i = 0; i < scripts.length; i++) {
/* 441 */ tmpSet.applyIntPropertyValue(4106, scripts[i]);
/* 442 */ allowedChars.addAll(tmpSet);
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public Builder setAllowedChars(UnicodeSet chars)
/* */ {
/* 462 */ this.fAllowedCharsSet = chars.cloneAsThawed();
/* 463 */ this.fAllowedLocales = new LinkedHashSet();
/* 464 */ this.fChecks |= 0x40;
/* 465 */ return this;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private static class WSConfusableDataBuilder
/* */ {
/* 505 */ static String parseExp = "(?m)^([ \\t]*(?:#.*?)?)$|^(?:\\s*([0-9A-F]{4,})(?:..([0-9A-F]{4,}))?\\s*;\\s*([A-Za-z]+)\\s*;\\s*([A-Za-z]+)\\s*;\\s*(?:(A)|(L))[ \\t]*(?:#.*?)?)$|^(.*?)$";
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ static void readWholeFileToString(Reader reader, StringBuffer buffer)
/* */ throws IOException
/* */ {
/* 532 */ LineNumberReader lnr = new LineNumberReader(reader);
/* */ for (;;) {
/* 534 */ String line = lnr.readLine();
/* 535 */ if (line == null) {
/* */ break;
/* */ }
/* 538 */ buffer.append(line);
/* 539 */ buffer.append('\n');
/* */ }
/* */ }
/* */
/* */
/* */ static void buildWSConfusableData(SpoofChecker.SpoofData fSpoofData, DataOutputStream os, Reader confusablesWS)
/* */ throws ParseException, IOException
/* */ {
/* 547 */ Pattern parseRegexp = null;
/* 548 */ StringBuffer input = new StringBuffer();
/* 549 */ int lineNum = 0;
/* */
/* 551 */ Vector<BuilderScriptSet> scriptSets = null;
/* 552 */ int rtScriptSetsCount = 2;
/* */
/* 554 */ Trie2Writable anyCaseTrie = new Trie2Writable(0, 0);
/* 555 */ Trie2Writable lowerCaseTrie = new Trie2Writable(0, 0);
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 570 */ scriptSets = new Vector();
/* 571 */ scriptSets.addElement(null);
/* 572 */ scriptSets.addElement(null);
/* */
/* 574 */ readWholeFileToString(confusablesWS, input);
/* */
/* 576 */ parseRegexp = Pattern.compile(parseExp);
/* */
/* */
/* */
/* */
/* 581 */ if (input.charAt(0) == 65279) {
/* 582 */ input.setCharAt(0, ' ');
/* */ }
/* */
/* */
/* 586 */ Matcher matcher = parseRegexp.matcher(input);
/* 587 */ while (matcher.find()) {
/* 588 */ lineNum++;
/* 589 */ if (matcher.start(1) < 0)
/* */ {
/* */
/* */
/* 593 */ if (matcher.start(8) >= 0)
/* */ {
/* 595 */ throw new ParseException("ConfusablesWholeScript, line " + lineNum + ": Unrecognized input: " + matcher.group(), matcher.start());
/* */ }
/* */
/* */
/* */
/* */
/* 601 */ int startCodePoint = Integer.parseInt(matcher.group(2), 16);
/* 602 */ if (startCodePoint > 1114111) {
/* 603 */ throw new ParseException("ConfusablesWholeScript, line " + lineNum + ": out of range code point: " + matcher.group(2), matcher.start(2));
/* */ }
/* */
/* 606 */ int endCodePoint = startCodePoint;
/* 607 */ if (matcher.start(3) >= 0) {
/* 608 */ endCodePoint = Integer.parseInt(matcher.group(3), 16);
/* */ }
/* 610 */ if (endCodePoint > 1114111) {
/* 611 */ throw new ParseException("ConfusablesWholeScript, line " + lineNum + ": out of range code point: " + matcher.group(3), matcher.start(3));
/* */ }
/* */
/* */
/* */
/* 616 */ String srcScriptName = matcher.group(4);
/* 617 */ String targScriptName = matcher.group(5);
/* 618 */ int srcScript = UCharacter.getPropertyValueEnum(4106, srcScriptName);
/* 619 */ int targScript = UCharacter.getPropertyValueEnum(4106, targScriptName);
/* 620 */ if (srcScript == -1) {
/* 621 */ throw new ParseException("ConfusablesWholeScript, line " + lineNum + ": Invalid script code t: " + matcher.group(4), matcher.start(4));
/* */ }
/* */
/* 624 */ if (targScript == -1) {
/* 625 */ throw new ParseException("ConfusablesWholeScript, line " + lineNum + ": Invalid script code t: " + matcher.group(5), matcher.start(5));
/* */ }
/* */
/* */
/* */
/* 630 */ Trie2Writable table = anyCaseTrie;
/* 631 */ if (matcher.start(7) >= 0) {
/* 632 */ table = lowerCaseTrie;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 645 */ for (int cp = startCodePoint; cp <= endCodePoint; cp++) {
/* 646 */ int setIndex = table.get(cp);
/* 647 */ BuilderScriptSet bsset = null;
/* 648 */ if (setIndex > 0) {
/* 649 */ assert (setIndex < scriptSets.size());
/* 650 */ bsset = (BuilderScriptSet)scriptSets.elementAt(setIndex);
/* */ } else {
/* 652 */ bsset = new BuilderScriptSet();
/* 653 */ bsset.codePoint = cp;
/* 654 */ bsset.trie = table;
/* 655 */ bsset.sset = new SpoofChecker.ScriptSet();
/* 656 */ setIndex = scriptSets.size();
/* 657 */ bsset.index = setIndex;
/* 658 */ bsset.rindex = 0;
/* 659 */ scriptSets.addElement(bsset);
/* 660 */ table.set(cp, setIndex);
/* */ }
/* 662 */ bsset.sset.Union(targScript);
/* 663 */ bsset.sset.Union(srcScript);
/* */
/* 665 */ int cpScript = UScript.getScript(cp);
/* 666 */ if (cpScript != srcScript)
/* */ {
/* 668 */ throw new ParseException("ConfusablesWholeScript, line " + lineNum + ": Mismatch between source script and code point " + Integer.toString(cp, 16), matcher.start(5));
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 684 */ rtScriptSetsCount = 2;
/* 685 */ for (int outeri = 2; outeri < scriptSets.size(); outeri++) {
/* 686 */ BuilderScriptSet outerSet = (BuilderScriptSet)scriptSets.elementAt(outeri);
/* 687 */ if (outerSet.index == outeri)
/* */ {
/* */
/* */
/* */
/* */
/* 693 */ outerSet.rindex = (rtScriptSetsCount++);
/* 694 */ for (int inneri = outeri + 1; inneri < scriptSets.size(); inneri++) {
/* 695 */ BuilderScriptSet innerSet = (BuilderScriptSet)scriptSets.elementAt(inneri);
/* 696 */ if ((outerSet.sset.equals(innerSet.sset)) && (outerSet.sset != innerSet.sset)) {
/* 697 */ innerSet.sset = outerSet.sset;
/* 698 */ innerSet.index = outeri;
/* 699 */ innerSet.rindex = outerSet.rindex;
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 715 */ for (int i = 2; i < scriptSets.size(); i++) {
/* 716 */ BuilderScriptSet bSet = (BuilderScriptSet)scriptSets.elementAt(i);
/* 717 */ if (bSet.rindex != i) {
/* 718 */ bSet.trie.set(bSet.codePoint, bSet.rindex);
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 730 */ UnicodeSet ignoreSet = new UnicodeSet();
/* 731 */ ignoreSet.applyIntPropertyValue(4106, 0);
/* 732 */ UnicodeSet inheritedSet = new UnicodeSet();
/* 733 */ inheritedSet.applyIntPropertyValue(4106, 1);
/* 734 */ ignoreSet.addAll(inheritedSet);
/* 735 */ for (int rn = 0; rn < ignoreSet.getRangeCount(); rn++) {
/* 736 */ int rangeStart = ignoreSet.getRangeStart(rn);
/* 737 */ int rangeEnd = ignoreSet.getRangeEnd(rn);
/* 738 */ anyCaseTrie.setRange(rangeStart, rangeEnd, 1, true);
/* 739 */ lowerCaseTrie.setRange(rangeStart, rangeEnd, 1, true);
/* */ }
/* */
/* */
/* */
/* */
/* 745 */ anyCaseTrie.toTrie2_16().serialize(os);
/* 746 */ lowerCaseTrie.toTrie2_16().serialize(os);
/* */
/* 748 */ fSpoofData.fRawData.fScriptSetsLength = rtScriptSetsCount;
/* 749 */ int rindex = 2;
/* 750 */ for (int i = 2; i < scriptSets.size(); i++) {
/* 751 */ BuilderScriptSet bSet = (BuilderScriptSet)scriptSets.elementAt(i);
/* 752 */ if (bSet.rindex >= rindex)
/* */ {
/* */
/* */
/* */
/* 757 */ assert (rindex == bSet.rindex);
/* 758 */ bSet.sset.output(os);
/* 759 */ rindex++;
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */ private static class BuilderScriptSet
/* */ {
/* */ int codePoint;
/* */
/* */
/* */ Trie2Writable trie;
/* */
/* */
/* */ SpoofChecker.ScriptSet sset;
/* */
/* */
/* */ int index;
/* */
/* */
/* */ int rindex;
/* */
/* */
/* */ BuilderScriptSet()
/* */ {
/* 785 */ this.codePoint = -1;
/* 786 */ this.trie = null;
/* 787 */ this.sset = null;
/* 788 */ this.index = 0;
/* 789 */ this.rindex = 0;
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */ private static class ConfusabledataBuilder
/* */ {
/* */ private SpoofChecker.SpoofData fSpoofData;
/* */
/* */
/* */
/* */ private ByteArrayOutputStream bos;
/* */
/* */
/* */ private DataOutputStream os;
/* */
/* */
/* */ private Hashtable<Integer, SPUString> fSLTable;
/* */
/* */
/* */ private Hashtable<Integer, SPUString> fSATable;
/* */
/* */
/* */ private Hashtable<Integer, SPUString> fMLTable;
/* */
/* */
/* */ private Hashtable<Integer, SPUString> fMATable;
/* */
/* */
/* */ private UnicodeSet fKeySet;
/* */
/* */
/* */ private StringBuffer fStringTable;
/* */
/* */
/* */ private Vector<Integer> fKeyVec;
/* */
/* */
/* */ private Vector<Integer> fValueVec;
/* */
/* */
/* */ private Vector<Integer> fStringLengthsTable;
/* */
/* */
/* */ private SPUStringPool stringPool;
/* */
/* */
/* */ private Pattern fParseLine;
/* */
/* */
/* */ private Pattern fParseHexNum;
/* */
/* */
/* */ private int fLineNum;
/* */
/* */
/* */
/* */ ConfusabledataBuilder(SpoofChecker.SpoofData spData, ByteArrayOutputStream bos)
/* */ {
/* 851 */ this.bos = bos;
/* 852 */ this.os = new DataOutputStream(bos);
/* 853 */ this.fSpoofData = spData;
/* 854 */ this.fSLTable = new Hashtable();
/* 855 */ this.fSATable = new Hashtable();
/* 856 */ this.fMLTable = new Hashtable();
/* 857 */ this.fMATable = new Hashtable();
/* 858 */ this.fKeySet = new UnicodeSet();
/* 859 */ this.fKeyVec = new Vector();
/* 860 */ this.fValueVec = new Vector();
/* 861 */ this.stringPool = new SPUStringPool();
/* */ }
/* */
/* */ void build(Reader confusables) throws ParseException, IOException {
/* 865 */ StringBuffer fInput = new StringBuffer();
/* 866 */ SpoofChecker.Builder.WSConfusableDataBuilder.readWholeFileToString(confusables, fInput);
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 877 */ this.fParseLine = Pattern.compile("(?m)^[ \\t]*([0-9A-Fa-f]+)[ \\t]+;[ \\t]*([0-9A-Fa-f]+(?:[ \\t]+[0-9A-Fa-f]+)*)[ \\t]*;\\s*(?:(SL)|(SA)|(ML)|(MA))[ \\t]*(?:#.*?)?$|^([ \\t]*(?:#.*?)?)$|^(.*?)$");
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 887 */ this.fParseHexNum = Pattern.compile("\\s*([0-9A-F]+)");
/* */
/* */
/* */
/* 891 */ if (fInput.charAt(0) == 65279) {
/* 892 */ fInput.setCharAt(0, ' ');
/* */ }
/* */
/* */
/* 896 */ Matcher matcher = this.fParseLine.matcher(fInput);
/* 897 */ while (matcher.find()) {
/* 898 */ this.fLineNum += 1;
/* 899 */ if (matcher.start(7) < 0)
/* */ {
/* */
/* */
/* 903 */ if (matcher.start(8) >= 0)
/* */ {
/* */
/* 906 */ throw new ParseException("Confusables, line " + this.fLineNum + ": Unrecognized Line: " + matcher.group(8), matcher.start(8));
/* */ }
/* */
/* */
/* */
/* */
/* */
/* 913 */ int keyChar = Integer.parseInt(matcher.group(1), 16);
/* 914 */ if (keyChar > 1114111) {
/* 915 */ throw new ParseException("Confusables, line " + this.fLineNum + ": Bad code point: " + matcher.group(1), matcher.start(1));
/* */ }
/* */
/* 918 */ Matcher m = this.fParseHexNum.matcher(matcher.group(2));
/* */
/* 920 */ StringBuilder mapString = new StringBuilder();
/* 921 */ while (m.find()) {
/* 922 */ int c = Integer.parseInt(m.group(1), 16);
/* 923 */ if (keyChar > 1114111) {
/* 924 */ throw new ParseException("Confusables, line " + this.fLineNum + ": Bad code point: " + Integer.toString(c, 16), matcher.start(2));
/* */ }
/* */
/* 927 */ mapString.appendCodePoint(c);
/* */ }
/* 929 */ assert (mapString.length() >= 1);
/* */
/* */
/* */
/* */
/* 934 */ SPUString smapString = this.stringPool.addString(mapString.toString());
/* */
/* */
/* 937 */ Hashtable<Integer, SPUString> table = matcher.start(6) >= 0 ? this.fMATable : matcher.start(5) >= 0 ? this.fMLTable : matcher.start(4) >= 0 ? this.fSATable : matcher.start(3) >= 0 ? this.fSLTable : null;
/* */
/* */
/* 940 */ assert (table != null);
/* 941 */ table.put(Integer.valueOf(keyChar), smapString);
/* 942 */ this.fKeySet.add(keyChar);
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 958 */ this.stringPool.sort();
/* 959 */ this.fStringTable = new StringBuffer();
/* 960 */ this.fStringLengthsTable = new Vector();
/* 961 */ int previousStringLength = 0;
/* 962 */ int previousStringIndex = 0;
/* 963 */ int poolSize = this.stringPool.size();
/* */
/* 965 */ for (int i = 0; i < poolSize; i++) {
/* 966 */ SPUString s = this.stringPool.getByIndex(i);
/* 967 */ int strLen = s.fStr.length();
/* 968 */ int strIndex = this.fStringTable.length();
/* 969 */ assert (strLen >= previousStringLength);
/* 970 */ if (strLen == 1)
/* */ {
/* */
/* */
/* */
/* */
/* */
/* 977 */ s.fStrTableIndex = s.fStr.charAt(0);
/* */ } else {
/* 979 */ if ((strLen > previousStringLength) && (previousStringLength >= 4)) {
/* 980 */ this.fStringLengthsTable.addElement(Integer.valueOf(previousStringIndex));
/* 981 */ this.fStringLengthsTable.addElement(Integer.valueOf(previousStringLength));
/* */ }
/* 983 */ s.fStrTableIndex = strIndex;
/* 984 */ this.fStringTable.append(s.fStr);
/* */ }
/* 986 */ previousStringLength = strLen;
/* 987 */ previousStringIndex = strIndex;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* 994 */ if (previousStringLength >= 4) {
/* 995 */ this.fStringLengthsTable.addElement(Integer.valueOf(previousStringIndex));
/* 996 */ this.fStringLengthsTable.addElement(Integer.valueOf(previousStringLength));
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 1011 */ for (int range = 0; range < this.fKeySet.getRangeCount(); range++)
/* */ {
/* */
/* */
/* 1015 */ for (int keyChar = this.fKeySet.getRangeStart(range); keyChar <= this.fKeySet.getRangeEnd(range); keyChar++) {
/* 1016 */ addKeyEntry(keyChar, this.fSLTable, 16777216);
/* 1017 */ addKeyEntry(keyChar, this.fSATable, 33554432);
/* 1018 */ addKeyEntry(keyChar, this.fMLTable, 67108864);
/* 1019 */ addKeyEntry(keyChar, this.fMATable, 134217728);
/* */ }
/* */ }
/* */
/* */
/* 1024 */ outputData();
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ void addKeyEntry(int keyChar, Hashtable<Integer, SPUString> table, int tableFlag)
/* */ {
/* 1042 */ SPUString targetMapping = (SPUString)table.get(Integer.valueOf(keyChar));
/* 1043 */ if (targetMapping == null)
/* */ {
/* */
/* */
/* */
/* 1048 */ return;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* 1055 */ boolean keyHasMultipleValues = false;
/* */
/* 1057 */ for (int i = this.fKeyVec.size() - 1; i >= 0; i--) {
/* 1058 */ int key = ((Integer)this.fKeyVec.elementAt(i)).intValue();
/* 1059 */ if ((key & 0xFFFFFF) != keyChar) {
/* */ break;
/* */ }
/* */
/* */
/* */
/* 1065 */ String mapping = getMapping(i);
/* 1066 */ if (mapping.equals(targetMapping.fStr))
/* */ {
/* */
/* */
/* */
/* 1071 */ key |= tableFlag;
/* 1072 */ this.fKeyVec.setElementAt(Integer.valueOf(key), i);
/* 1073 */ return;
/* */ }
/* 1075 */ keyHasMultipleValues = true;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* 1082 */ int newKey = keyChar | tableFlag;
/* 1083 */ if (keyHasMultipleValues) {
/* 1084 */ newKey |= 0x10000000;
/* */ }
/* 1086 */ int adjustedMappingLength = targetMapping.fStr.length() - 1;
/* 1087 */ if (adjustedMappingLength > 3) {
/* 1088 */ adjustedMappingLength = 3;
/* */ }
/* 1090 */ newKey |= adjustedMappingLength << 29;
/* */
/* 1092 */ int newData = targetMapping.fStrTableIndex;
/* */
/* 1094 */ this.fKeyVec.addElement(Integer.valueOf(newKey));
/* 1095 */ this.fValueVec.addElement(Integer.valueOf(newData));
/* */
/* */
/* */
/* */
/* 1100 */ if (keyHasMultipleValues) {
/* 1101 */ int previousKeyIndex = this.fKeyVec.size() - 2;
/* 1102 */ int previousKey = ((Integer)this.fKeyVec.elementAt(previousKeyIndex)).intValue();
/* 1103 */ previousKey |= 0x10000000;
/* 1104 */ this.fKeyVec.setElementAt(Integer.valueOf(previousKey), previousKeyIndex);
/* */ }
/* */ }
/* */
/* */
/* */ String getMapping(int index)
/* */ {
/* 1111 */ int key = ((Integer)this.fKeyVec.elementAt(index)).intValue();
/* 1112 */ int value = ((Integer)this.fValueVec.elementAt(index)).intValue();
/* 1113 */ int length = SpoofChecker.getKeyLength(key);
/* */
/* 1115 */ switch (length) {
/* */ case 0:
/* 1117 */ char[] cs = { (char)value };
/* 1118 */ return new String(cs);
/* */ case 1:
/* */ case 2:
/* 1121 */ return this.fStringTable.substring(value, value + length + 1);
/* */ case 3:
/* 1123 */ length = 0;
/* */
/* 1125 */ for (int i = 0; i < this.fStringLengthsTable.size(); i += 2) {
/* 1126 */ int lastIndexWithLen = ((Integer)this.fStringLengthsTable.elementAt(i)).intValue();
/* 1127 */ if (value <= lastIndexWithLen) {
/* 1128 */ length = ((Integer)this.fStringLengthsTable.elementAt(i + 1)).intValue();
/* 1129 */ break;
/* */ }
/* */ }
/* 1132 */ assert (length >= 3);
/* 1133 */ return this.fStringTable.substring(value, value + length);
/* */ }
/* 1135 */ if (!$assertionsDisabled) { throw new AssertionError();
/* */ }
/* 1137 */ return new String();
/* */ }
/* */
/* */
/* */
/* */
/* */ void outputData()
/* */ throws IOException
/* */ {
/* 1146 */ SpoofChecker.SpoofDataHeader rawData = this.fSpoofData.fRawData;
/* */
/* */
/* */
/* 1150 */ int numKeys = this.fKeyVec.size();
/* */
/* 1152 */ int previousKey = 0;
/* 1153 */ rawData.output(this.os);
/* 1154 */ rawData.fCFUKeys = this.os.size();
/* 1155 */ assert (rawData.fCFUKeys == 128);
/* 1156 */ rawData.fCFUKeysSize = numKeys;
/* 1157 */ for (int i = 0; i < numKeys; i++) {
/* 1158 */ int key = ((Integer)this.fKeyVec.elementAt(i)).intValue();
/* 1159 */ assert ((key & 0xFFFFFF) >= (previousKey & 0xFFFFFF));
/* 1160 */ assert ((key & 0xFF000000) != 0);
/* 1161 */ this.os.writeInt(key);
/* 1162 */ previousKey = key;
/* */ }
/* */
/* */
/* 1166 */ int numValues = this.fValueVec.size();
/* 1167 */ assert (numKeys == numValues);
/* 1168 */ rawData.fCFUStringIndex = this.os.size();
/* 1169 */ rawData.fCFUStringIndexSize = numValues;
/* 1170 */ for (i = 0; i < numValues; i++) {
/* 1171 */ int value = ((Integer)this.fValueVec.elementAt(i)).intValue();
/* 1172 */ assert (value < 65535);
/* 1173 */ this.os.writeShort((short)value);
/* */ }
/* */
/* */
/* */
/* 1178 */ int stringsLength = this.fStringTable.length();
/* */
/* */
/* 1181 */ String strings = this.fStringTable.toString();
/* 1182 */ rawData.fCFUStringTable = this.os.size();
/* 1183 */ rawData.fCFUStringTableLen = stringsLength;
/* 1184 */ for (i = 0; i < stringsLength; i++) {
/* 1185 */ this.os.writeChar(strings.charAt(i));
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 1194 */ int lengthTableLength = this.fStringLengthsTable.size();
/* 1195 */ int previousLength = 0;
/* */
/* */
/* */
/* 1199 */ rawData.fCFUStringLengthsSize = (lengthTableLength / 2);
/* 1200 */ rawData.fCFUStringLengths = this.os.size();
/* 1201 */ for (i = 0; i < lengthTableLength; i += 2) {
/* 1202 */ int offset = ((Integer)this.fStringLengthsTable.elementAt(i)).intValue();
/* 1203 */ int length = ((Integer)this.fStringLengthsTable.elementAt(i + 1)).intValue();
/* 1204 */ assert (offset < stringsLength);
/* 1205 */ assert (length < 40);
/* 1206 */ assert (length > previousLength);
/* 1207 */ this.os.writeShort((short)offset);
/* 1208 */ this.os.writeShort((short)length);
/* 1209 */ previousLength = length;
/* */ }
/* */
/* 1212 */ this.os.flush();
/* 1213 */ DataInputStream is = new DataInputStream(new ByteArrayInputStream(this.bos.toByteArray()));
/* 1214 */ is.mark(Integer.MAX_VALUE);
/* 1215 */ this.fSpoofData.initPtrs(is);
/* */ }
/* */
/* */ public static void buildConfusableData(SpoofChecker.SpoofData spData, Reader confusables) throws IOException, ParseException
/* */ {
/* 1220 */ ByteArrayOutputStream bos = new ByteArrayOutputStream();
/* 1221 */ ConfusabledataBuilder builder = new ConfusabledataBuilder(spData, bos);
/* 1222 */ builder.build(confusables);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */ private static class SPUString
/* */ {
/* */ String fStr;
/* */
/* */
/* */
/* */ int fStrTableIndex;
/* */
/* */
/* */
/* */
/* */ SPUString(String s)
/* */ {
/* 1242 */ this.fStr = s;
/* 1243 */ this.fStrTableIndex = 0;
/* */ }
/* */ }
/* */
/* */
/* */ private static class SPUStringComparator
/* */ implements Comparator<SpoofChecker.Builder.ConfusabledataBuilder.SPUString>
/* */ {
/* */ public int compare(SpoofChecker.Builder.ConfusabledataBuilder.SPUString sL, SpoofChecker.Builder.ConfusabledataBuilder.SPUString sR)
/* */ {
/* 1253 */ int lenL = sL.fStr.length();
/* 1254 */ int lenR = sR.fStr.length();
/* 1255 */ if (lenL < lenR)
/* 1256 */ return -1;
/* 1257 */ if (lenL > lenR) {
/* 1258 */ return 1;
/* */ }
/* 1260 */ return sL.fStr.compareTo(sR.fStr);
/* */ }
/* */ }
/* */
/* */
/* */ private static class SPUStringPool
/* */ {
/* */ private Vector<SpoofChecker.Builder.ConfusabledataBuilder.SPUString> fVec;
/* */
/* */ private Hashtable<String, SpoofChecker.Builder.ConfusabledataBuilder.SPUString> fHash;
/* */
/* */ public SPUStringPool()
/* */ {
/* 1273 */ this.fVec = new Vector();
/* 1274 */ this.fHash = new Hashtable();
/* */ }
/* */
/* */ public int size() {
/* 1278 */ return this.fVec.size();
/* */ }
/* */
/* */ public SpoofChecker.Builder.ConfusabledataBuilder.SPUString getByIndex(int index)
/* */ {
/* 1283 */ SpoofChecker.Builder.ConfusabledataBuilder.SPUString retString = (SpoofChecker.Builder.ConfusabledataBuilder.SPUString)this.fVec.elementAt(index);
/* 1284 */ return retString;
/* */ }
/* */
/* */
/* */
/* */ public SpoofChecker.Builder.ConfusabledataBuilder.SPUString addString(String src)
/* */ {
/* 1291 */ SpoofChecker.Builder.ConfusabledataBuilder.SPUString hashedString = (SpoofChecker.Builder.ConfusabledataBuilder.SPUString)this.fHash.get(src);
/* 1292 */ if (hashedString == null) {
/* 1293 */ hashedString = new SpoofChecker.Builder.ConfusabledataBuilder.SPUString(src);
/* 1294 */ this.fHash.put(src, hashedString);
/* 1295 */ this.fVec.addElement(hashedString);
/* */ }
/* 1297 */ return hashedString;
/* */ }
/* */
/* */ public void sort()
/* */ {
/* 1302 */ Collections.sort(this.fVec, new SpoofChecker.Builder.ConfusabledataBuilder.SPUStringComparator(null));
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public int getChecks()
/* */ {
/* 1320 */ return this.fChecks;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public Set<ULocale> getAllowedLocales()
/* */ {
/* 1338 */ return this.fAllowedLocales;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public UnicodeSet getAllowedChars()
/* */ {
/* 1353 */ return this.fAllowedCharsSet;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public static class CheckResult
/* */ {
/* */ public int checks;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public int position;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public CheckResult()
/* */ {
/* 1388 */ this.checks = 0;
/* 1389 */ this.position = 0;
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public boolean failsChecks(String text, CheckResult checkResult)
/* */ {
/* 1407 */ int length = text.length();
/* */
/* 1409 */ int result = 0;
/* 1410 */ int failPos = Integer.MAX_VALUE;
/* */
/* */
/* */
/* */
/* */
/* */
/* 1417 */ int scriptCount = -1;
/* */
/* 1419 */ if (0 != (this.fChecks & 0x10)) {
/* 1420 */ scriptCount = scriptScan(text, checkResult);
/* */
/* */
/* 1423 */ if (scriptCount >= 2)
/* */ {
/* */
/* 1426 */ result |= 0x10;
/* */ }
/* */ }
/* */ int i;
/* 1430 */ if (0 != (this.fChecks & 0x40))
/* */ {
/* */
/* 1433 */ for (i = 0; i < length;)
/* */ {
/* 1435 */ int c = Character.codePointAt(text, i);
/* 1436 */ i = Character.offsetByCodePoints(text, i, 1);
/* 1437 */ if (!this.fAllowedCharsSet.contains(c)) {
/* 1438 */ result |= 0x40;
/* 1439 */ if (i < failPos) {
/* 1440 */ failPos = i;
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */
/* 1447 */ if (0 != (this.fChecks & 0x26))
/* */ {
/* 1449 */ String nfdText = Normalizer.normalize(text, Normalizer.NFD, 0);
/* */ int firstNonspacingMark;
/* 1451 */ boolean haveMultipleMarks; UnicodeSet marksSeenSoFar; int i; if (0 != (this.fChecks & 0x20))
/* */ {
/* */
/* */
/* */
/* */
/* 1457 */ firstNonspacingMark = 0;
/* 1458 */ haveMultipleMarks = false;
/* 1459 */ marksSeenSoFar = new UnicodeSet();
/* */
/* 1461 */ for (i = 0; i < length;)
/* */ {
/* 1463 */ int c = Character.codePointAt(nfdText, i);
/* 1464 */ i = Character.offsetByCodePoints(nfdText, i, 1);
/* 1465 */ if (Character.getType(c) != 6) {
/* 1466 */ firstNonspacingMark = 0;
/* 1467 */ if (haveMultipleMarks) {
/* 1468 */ marksSeenSoFar.clear();
/* 1469 */ haveMultipleMarks = false;
/* */ }
/* */
/* */ }
/* 1473 */ else if (firstNonspacingMark == 0) {
/* 1474 */ firstNonspacingMark = c;
/* */ }
/* */ else {
/* 1477 */ if (!haveMultipleMarks) {
/* 1478 */ marksSeenSoFar.add(firstNonspacingMark);
/* 1479 */ haveMultipleMarks = true;
/* */ }
/* 1481 */ if (marksSeenSoFar.contains(c))
/* */ {
/* */
/* 1484 */ result |= 0x20;
/* 1485 */ failPos = i;
/* 1486 */ break;
/* */ }
/* 1488 */ marksSeenSoFar.add(c);
/* */ }
/* */ }
/* */ }
/* 1492 */ if (0 != (this.fChecks & 0x6))
/* */ {
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 1514 */ if (scriptCount == -1) {
/* 1515 */ scriptCount = scriptScan(text, null);
/* */ }
/* */
/* 1518 */ ScriptSet scripts = new ScriptSet();
/* 1519 */ wholeScriptCheck(nfdText, scripts);
/* 1520 */ int confusableScriptCount = scripts.countMembers();
/* */
/* */
/* */
/* 1524 */ if ((0 != (this.fChecks & 0x4)) && (confusableScriptCount >= 2) && (scriptCount == 1)) {
/* 1525 */ result |= 0x4;
/* */ }
/* */
/* 1528 */ if ((0 != (this.fChecks & 0x2)) && (confusableScriptCount >= 1) && (scriptCount > 1)) {
/* 1529 */ result |= 0x2;
/* */ }
/* */ }
/* */ }
/* 1533 */ if (checkResult != null) {
/* 1534 */ checkResult.checks = result;
/* 1535 */ if (failPos != Integer.MAX_VALUE) {
/* 1536 */ checkResult.position = failPos;
/* */ }
/* */ }
/* 1539 */ return 0 != result;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public boolean failsChecks(String text)
/* */ {
/* 1553 */ return failsChecks(text, null);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public int areConfusable(String s1, String s2)
/* */ {
/* 1588 */ if ((this.fChecks & 0x7) == 0) {
/* 1589 */ throw new IllegalArgumentException("No confusable checks are enabled.");
/* */ }
/* 1591 */ int flagsForSkeleton = this.fChecks & 0x8;
/* */
/* */
/* */
/* 1595 */ int result = 0;
/* 1596 */ int s1ScriptCount = scriptScan(s1, null);
/* 1597 */ int s2ScriptCount = scriptScan(s2, null);
/* */
/* 1599 */ if (0 != (this.fChecks & 0x1))
/* */ {
/* 1601 */ if ((s1ScriptCount <= 1) && (s2ScriptCount <= 1)) {
/* 1602 */ flagsForSkeleton |= 0x1;
/* 1603 */ String s1Skeleton = getSkeleton(flagsForSkeleton, s1);
/* 1604 */ String s2Skeleton = getSkeleton(flagsForSkeleton, s2);
/* 1605 */ if ((s1Skeleton.length() == s2Skeleton.length()) && (s1Skeleton.equals(s2Skeleton))) {
/* 1606 */ result |= 0x1;
/* */ }
/* */ }
/* */ }
/* */
/* 1611 */ if (0 != (result & 0x1))
/* */ {
/* */
/* */
/* */
/* */
/* 1617 */ return result;
/* */ }
/* */
/* */
/* */
/* */
/* 1623 */ boolean possiblyWholeScriptConfusables = (s1ScriptCount <= 1) && (s2ScriptCount <= 1) && (0 != (this.fChecks & 0x4));
/* */
/* */
/* */
/* 1627 */ if ((0 != (this.fChecks & 0x2)) || (possiblyWholeScriptConfusables))
/* */ {
/* */
/* */
/* */
/* */
/* 1633 */ flagsForSkeleton &= 0xFFFFFFFE;
/* 1634 */ String s1Skeleton = getSkeleton(flagsForSkeleton, s1);
/* 1635 */ String s2Skeleton = getSkeleton(flagsForSkeleton, s2);
/* 1636 */ if ((s1Skeleton.length() == s2Skeleton.length()) && (s1Skeleton.equals(s2Skeleton))) {
/* 1637 */ result |= 0x2;
/* 1638 */ if (possiblyWholeScriptConfusables) {
/* 1639 */ result |= 0x4;
/* */ }
/* */ }
/* */ }
/* 1643 */ return result;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public String getSkeleton(int type, String s)
/* */ {
/* 1668 */ if ((type & 0xFFFFFFF6) != 0)
/* */ {
/* 1670 */ return null;
/* */ }
/* */
/* 1673 */ int tableMask = 0;
/* 1674 */ switch (type) {
/* */ case 0:
/* 1676 */ tableMask = 67108864;
/* 1677 */ break;
/* */ case 1:
/* 1679 */ tableMask = 16777216;
/* 1680 */ break;
/* */ case 8:
/* 1682 */ tableMask = 134217728;
/* 1683 */ break;
/* */ case 9:
/* 1685 */ tableMask = 33554432;
/* 1686 */ break;
/* */ case 2: case 3: case 4: case 5:
/* */ case 6: case 7: default:
/* 1689 */ return null;
/* */ }
/* */
/* */
/* 1693 */ String nfdInput = Normalizer.normalize(s, Normalizer.NFD, 0);
/* 1694 */ int normalizedLen = nfdInput.length();
/* */
/* */
/* */
/* 1698 */ int inputIndex = 0;
/* 1699 */ StringBuilder skelStr = new StringBuilder();
/* 1700 */ while (inputIndex < normalizedLen)
/* */ {
/* 1702 */ int c = Character.codePointAt(nfdInput, inputIndex);
/* 1703 */ inputIndex = Character.offsetByCodePoints(nfdInput, inputIndex, 1);
/* 1704 */ confusableLookup(c, tableMask, skelStr);
/* */ }
/* */
/* 1707 */ String result = skelStr.toString();
/* */
/* */
/* */
/* */
/* 1712 */ if (!Normalizer.isNormalized(result, Normalizer.NFD, 0)) {
/* 1713 */ String normedResult = Normalizer.normalize(result, Normalizer.NFD, 0);
/* 1714 */ result = normedResult;
/* */ }
/* 1716 */ return result;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private void confusableLookup(int inChar, int tableMask, StringBuilder dest)
/* */ {
/* 1729 */ int low = 0;
/* 1730 */ int mid = 0;
/* 1731 */ int limit = this.fSpoofData.fRawData.fCFUKeysSize;
/* */
/* 1733 */ boolean foundChar = false;
/* */ do
/* */ {
/* 1736 */ int delta = (limit - low) / 2;
/* 1737 */ mid = low + delta;
/* 1738 */ int midc = this.fSpoofData.fCFUKeys[mid] & 0x1FFFFF;
/* 1739 */ if (inChar == midc) {
/* 1740 */ foundChar = true;
/* 1741 */ break; }
/* 1742 */ if (inChar < midc) {
/* 1743 */ limit = mid;
/* */
/* */ }
/* */ else
/* */ {
/* 1748 */ low = mid + 1;
/* */ }
/* 1750 */ } while (low < limit);
/* 1751 */ if (!foundChar) {
/* 1752 */ dest.appendCodePoint(inChar);
/* 1753 */ return;
/* */ }
/* */
/* 1756 */ boolean foundKey = false;
/* 1757 */ int keyFlags = this.fSpoofData.fCFUKeys[mid] & 0xFF000000;
/* 1758 */ if ((keyFlags & tableMask) == 0)
/* */ {
/* */
/* 1761 */ if (0 != (keyFlags & 0x10000000))
/* */ {
/* 1763 */ for (int altMid = mid - 1; (this.fSpoofData.fCFUKeys[altMid] & 0xFFFFFF) == inChar; altMid--) {
/* 1764 */ keyFlags = this.fSpoofData.fCFUKeys[altMid] & 0xFF000000;
/* 1765 */ if (0 != (keyFlags & tableMask)) {
/* 1766 */ mid = altMid;
/* 1767 */ foundKey = true;
/* 1768 */ break;
/* */ }
/* */ }
/* 1771 */ if (!foundKey) {
/* 1772 */ for (altMid = mid + 1; (this.fSpoofData.fCFUKeys[altMid] & 0xFFFFFF) == inChar; altMid++) {
/* 1773 */ keyFlags = this.fSpoofData.fCFUKeys[altMid] & 0xFF000000;
/* 1774 */ if (0 != (keyFlags & tableMask)) {
/* 1775 */ mid = altMid;
/* 1776 */ foundKey = true;
/* 1777 */ break;
/* */ }
/* */ }
/* */ }
/* */ }
/* 1782 */ if (!foundKey)
/* */ {
/* */
/* 1785 */ dest.appendCodePoint(inChar);
/* 1786 */ return;
/* */ }
/* */ }
/* */
/* 1790 */ int stringLen = getKeyLength(keyFlags) + 1;
/* 1791 */ int keyTableIndex = mid;
/* */
/* */
/* */
/* 1795 */ short value = this.fSpoofData.fCFUValues[keyTableIndex];
/* 1796 */ if (stringLen == 1) {
/* 1797 */ dest.append((char)value);
/* 1798 */ return;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 1811 */ if (stringLen == 4) {
/* 1812 */ int stringLengthsLimit = this.fSpoofData.fRawData.fCFUStringLengthsSize;
/* 1813 */ for (int ix = 0; ix < stringLengthsLimit; ix++) {
/* 1814 */ if (this.fSpoofData.fCFUStringLengths[ix].fLastString >= value) {
/* 1815 */ stringLen = this.fSpoofData.fCFUStringLengths[ix].fStrLength;
/* 1816 */ break;
/* */ }
/* */ }
/* 1819 */ assert (ix < stringLengthsLimit);
/* */ }
/* */
/* 1822 */ assert (value + stringLen <= this.fSpoofData.fRawData.fCFUStringTableLen);
/* 1823 */ dest.append(this.fSpoofData.fCFUStrings, value, stringLen);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ void wholeScriptCheck(CharSequence text, ScriptSet result)
/* */ {
/* 1837 */ int inputIdx = 0;
/* */
/* */
/* 1840 */ Trie2 table = 0 != (this.fChecks & 0x8) ? this.fSpoofData.fAnyCaseTrie : this.fSpoofData.fLowerCaseTrie;
/* 1841 */ result.setAll();
/* 1842 */ while (inputIdx < text.length()) {
/* 1843 */ int c = Character.codePointAt(text, inputIdx);
/* 1844 */ inputIdx = Character.offsetByCodePoints(text, inputIdx, 1);
/* 1845 */ int index = table.get(c);
/* 1846 */ if (index == 0)
/* */ {
/* */
/* */
/* */
/* 1851 */ int cpScript = UScript.getScript(c);
/* 1852 */ assert (cpScript > 1);
/* 1853 */ result.intersect(cpScript);
/* 1854 */ } else if (index != 1)
/* */ {
/* */
/* 1857 */ result.intersect(this.fSpoofData.fScriptSets[index]);
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ int scriptScan(CharSequence text, CheckResult checkResult)
/* */ {
/* 1875 */ int inputIdx = 0;
/* */
/* 1877 */ int scriptCount = 0;
/* 1878 */ int lastScript = -1;
/* 1879 */ int sc = -1;
/* 1880 */ while ((inputIdx < text.length()) && (scriptCount < 2)) {
/* 1881 */ int c = Character.codePointAt(text, inputIdx);
/* 1882 */ inputIdx = Character.offsetByCodePoints(text, inputIdx, 1);
/* 1883 */ sc = UScript.getScript(c);
/* 1884 */ if ((sc != 0) && (sc != 1) && (sc != 103))
/* */ {
/* */
/* */
/* */
/* */
/* */
/* */
/* 1892 */ if ((sc == 22) || (sc == 20) || (sc == 18)) {
/* 1893 */ sc = 17;
/* */ }
/* 1895 */ if (sc != lastScript) {
/* 1896 */ scriptCount++;
/* 1897 */ lastScript = sc;
/* */ }
/* */ } }
/* 1900 */ if ((scriptCount == 2) && (checkResult != null)) {
/* 1901 */ checkResult.position = inputIdx;
/* */ }
/* 1903 */ return scriptCount;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ static final int getKeyLength(int x)
/* */ {
/* 1973 */ return x >> 29 & 0x3;
/* */ }
/* */
/* */
/* */
/* */
/* */ private static class SpoofDataHeader
/* */ {
/* */ int fMagic;
/* */
/* */
/* 1984 */ byte[] fFormatVersion = new byte[4];
/* */
/* */
/* */ int fLength;
/* */
/* */
/* */ int fCFUKeys;
/* */
/* */
/* */ int fCFUKeysSize;
/* */
/* */ int fCFUStringIndex;
/* */
/* */ int fCFUStringIndexSize;
/* */
/* */ int fCFUStringTable;
/* */
/* */ int fCFUStringTableLen;
/* */
/* */ int fCFUStringLengths;
/* */
/* */ int fCFUStringLengthsSize;
/* */
/* */ int fAnyCaseTrie;
/* */
/* */ int fAnyCaseTrieLength;
/* */
/* */ int fLowerCaseTrie;
/* */
/* */ int fLowerCaseTrieLength;
/* */
/* */ int fScriptSets;
/* */
/* */ int fScriptSetsLength;
/* */
/* 2019 */ int[] unused = new int[15];
/* */
/* */ public SpoofDataHeader() {}
/* */
/* */ public SpoofDataHeader(DataInputStream dis)
/* */ throws IOException
/* */ {
/* 2026 */ this.fMagic = dis.readInt();
/* 2027 */ for (int i = 0; i < this.fFormatVersion.length; i++) {
/* 2028 */ this.fFormatVersion[i] = dis.readByte();
/* */ }
/* 2030 */ this.fLength = dis.readInt();
/* 2031 */ this.fCFUKeys = dis.readInt();
/* 2032 */ this.fCFUKeysSize = dis.readInt();
/* 2033 */ this.fCFUStringIndex = dis.readInt();
/* 2034 */ this.fCFUStringIndexSize = dis.readInt();
/* 2035 */ this.fCFUStringTable = dis.readInt();
/* 2036 */ this.fCFUStringTableLen = dis.readInt();
/* 2037 */ this.fCFUStringLengths = dis.readInt();
/* 2038 */ this.fCFUStringLengthsSize = dis.readInt();
/* 2039 */ this.fAnyCaseTrie = dis.readInt();
/* 2040 */ this.fAnyCaseTrieLength = dis.readInt();
/* 2041 */ this.fLowerCaseTrie = dis.readInt();
/* 2042 */ this.fLowerCaseTrieLength = dis.readInt();
/* 2043 */ this.fScriptSets = dis.readInt();
/* 2044 */ this.fScriptSetsLength = dis.readInt();
/* 2045 */ for (i = 0; i < this.unused.length; i++) {
/* 2046 */ this.unused[i] = dis.readInt();
/* */ }
/* */ }
/* */
/* */ public void output(DataOutputStream os) throws IOException
/* */ {
/* 2052 */ os.writeInt(this.fMagic);
/* 2053 */ for (int i = 0; i < this.fFormatVersion.length; i++) {
/* 2054 */ os.writeByte(this.fFormatVersion[i]);
/* */ }
/* 2056 */ os.writeInt(this.fLength);
/* 2057 */ os.writeInt(this.fCFUKeys);
/* 2058 */ os.writeInt(this.fCFUKeysSize);
/* 2059 */ os.writeInt(this.fCFUStringIndex);
/* 2060 */ os.writeInt(this.fCFUStringIndexSize);
/* 2061 */ os.writeInt(this.fCFUStringTable);
/* 2062 */ os.writeInt(this.fCFUStringTableLen);
/* 2063 */ os.writeInt(this.fCFUStringLengths);
/* 2064 */ os.writeInt(this.fCFUStringLengthsSize);
/* 2065 */ os.writeInt(this.fAnyCaseTrie);
/* 2066 */ os.writeInt(this.fAnyCaseTrieLength);
/* 2067 */ os.writeInt(this.fLowerCaseTrie);
/* 2068 */ os.writeInt(this.fLowerCaseTrieLength);
/* 2069 */ os.writeInt(this.fScriptSets);
/* 2070 */ os.writeInt(this.fScriptSetsLength);
/* 2071 */ for (i = 0; i < this.unused.length; i++) {
/* 2072 */ os.writeInt(this.unused[i]);
/* */ }
/* */ }
/* */ }
/* */
/* */ private static class SpoofData
/* */ {
/* */ SpoofChecker.SpoofDataHeader fRawData;
/* */ int[] fCFUKeys;
/* */ short[] fCFUValues;
/* */ SpoofStringLengthsElement[] fCFUStringLengths;
/* */ char[] fCFUStrings;
/* */ Trie2 fAnyCaseTrie;
/* */ Trie2 fLowerCaseTrie;
/* */ SpoofChecker.ScriptSet[] fScriptSets;
/* */
/* */ public static SpoofData getDefault() throws IOException
/* */ {
/* 2090 */ InputStream is = ICUData.getRequiredStream("data/icudt48b/confusables.cfu");
/* */
/* 2092 */ SpoofData This = new SpoofData(is);
/* 2093 */ return This;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public SpoofData()
/* */ {
/* 2103 */ this.fRawData = new SpoofChecker.SpoofDataHeader();
/* */
/* 2105 */ this.fRawData.fMagic = 944111087;
/* 2106 */ this.fRawData.fFormatVersion[0] = 1;
/* 2107 */ this.fRawData.fFormatVersion[1] = 0;
/* 2108 */ this.fRawData.fFormatVersion[2] = 0;
/* 2109 */ this.fRawData.fFormatVersion[3] = 0;
/* */ }
/* */
/* */
/* */
/* */ public SpoofData(InputStream is)
/* */ throws IOException
/* */ {
/* 2117 */ DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
/* 2118 */ dis.skip(128L);
/* 2119 */ assert (dis.markSupported());
/* 2120 */ dis.mark(Integer.MAX_VALUE);
/* */
/* 2122 */ this.fRawData = new SpoofChecker.SpoofDataHeader(dis);
/* 2123 */ initPtrs(dis);
/* */ }
/* */
/* */
/* */ static boolean validateDataVersion(SpoofChecker.SpoofDataHeader rawData)
/* */ {
/* 2129 */ if ((rawData == null) || (rawData.fMagic != 944111087) || (rawData.fFormatVersion[0] > 1) || (rawData.fFormatVersion[1] > 0))
/* */ {
/* 2131 */ return false;
/* */ }
/* 2133 */ return true;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ void initPtrs(DataInputStream dis)
/* */ throws IOException
/* */ {
/* 2149 */ this.fCFUKeys = null;
/* 2150 */ this.fCFUValues = null;
/* 2151 */ this.fCFUStringLengths = null;
/* 2152 */ this.fCFUStrings = null;
/* */
/* */
/* */
/* */
/* 2157 */ dis.reset();
/* 2158 */ dis.skip(this.fRawData.fCFUKeys);
/* 2159 */ if (this.fRawData.fCFUKeys != 0) {
/* 2160 */ this.fCFUKeys = new int[this.fRawData.fCFUKeysSize];
/* 2161 */ for (int i = 0; i < this.fRawData.fCFUKeysSize; i++) {
/* 2162 */ this.fCFUKeys[i] = dis.readInt();
/* */ }
/* */ }
/* */
/* 2166 */ dis.reset();
/* 2167 */ dis.skip(this.fRawData.fCFUStringIndex);
/* 2168 */ if (this.fRawData.fCFUStringIndex != 0) {
/* 2169 */ this.fCFUValues = new short[this.fRawData.fCFUStringIndexSize];
/* 2170 */ for (int i = 0; i < this.fRawData.fCFUStringIndexSize; i++) {
/* 2171 */ this.fCFUValues[i] = dis.readShort();
/* */ }
/* */ }
/* */
/* 2175 */ dis.reset();
/* 2176 */ dis.skip(this.fRawData.fCFUStringTable);
/* 2177 */ if (this.fRawData.fCFUStringTable != 0) {
/* 2178 */ this.fCFUStrings = new char[this.fRawData.fCFUStringTableLen];
/* 2179 */ for (int i = 0; i < this.fRawData.fCFUStringTableLen; i++) {
/* 2180 */ this.fCFUStrings[i] = dis.readChar();
/* */ }
/* */ }
/* */
/* 2184 */ dis.reset();
/* 2185 */ dis.skip(this.fRawData.fCFUStringLengths);
/* 2186 */ if (this.fRawData.fCFUStringLengths != 0) {
/* 2187 */ this.fCFUStringLengths = new SpoofStringLengthsElement[this.fRawData.fCFUStringLengthsSize];
/* 2188 */ for (int i = 0; i < this.fRawData.fCFUStringLengthsSize; i++) {
/* 2189 */ this.fCFUStringLengths[i] = new SpoofStringLengthsElement(null);
/* 2190 */ this.fCFUStringLengths[i].fLastString = dis.readShort();
/* 2191 */ this.fCFUStringLengths[i].fStrLength = dis.readShort();
/* */ }
/* */ }
/* */
/* 2195 */ dis.reset();
/* 2196 */ dis.skip(this.fRawData.fAnyCaseTrie);
/* 2197 */ if ((this.fAnyCaseTrie == null) && (this.fRawData.fAnyCaseTrie != 0)) {
/* 2198 */ this.fAnyCaseTrie = Trie2.createFromSerialized(dis);
/* */ }
/* 2200 */ dis.reset();
/* 2201 */ dis.skip(this.fRawData.fLowerCaseTrie);
/* 2202 */ if ((this.fLowerCaseTrie == null) && (this.fRawData.fLowerCaseTrie != 0)) {
/* 2203 */ this.fLowerCaseTrie = Trie2.createFromSerialized(dis);
/* */ }
/* */
/* 2206 */ dis.reset();
/* 2207 */ dis.skip(this.fRawData.fScriptSets);
/* 2208 */ if (this.fRawData.fScriptSets != 0) {
/* 2209 */ this.fScriptSets = new SpoofChecker.ScriptSet[this.fRawData.fScriptSetsLength];
/* 2210 */ for (int i = 0; i < this.fRawData.fScriptSetsLength; i++) {
/* 2211 */ this.fScriptSets[i] = new SpoofChecker.ScriptSet(dis);
/* */ }
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private static class SpoofStringLengthsElement
/* */ {
/* */ short fLastString;
/* */
/* */
/* */
/* */
/* */
/* */ short fStrLength;
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private static class ScriptSet
/* */ {
/* */ public ScriptSet() {}
/* */
/* */
/* */
/* */
/* */
/* */ public ScriptSet(DataInputStream dis)
/* */ throws IOException
/* */ {
/* 2249 */ for (int j = 0; j < this.bits.length; j++) {
/* 2250 */ this.bits[j] = dis.readInt();
/* */ }
/* */ }
/* */
/* */ public void output(DataOutputStream os) throws IOException {
/* 2255 */ for (int i = 0; i < this.bits.length; i++) {
/* 2256 */ os.writeInt(this.bits[i]);
/* */ }
/* */ }
/* */
/* */ public boolean equals(ScriptSet other) {
/* 2261 */ for (int i = 0; i < this.bits.length; i++) {
/* 2262 */ if (this.bits[i] != other.bits[i]) {
/* 2263 */ return false;
/* */ }
/* */ }
/* 2266 */ return true;
/* */ }
/* */
/* */ public void Union(int script) {
/* 2270 */ int index = script / 32;
/* 2271 */ int bit = 1 << (script & 0x1F);
/* 2272 */ assert (index < this.bits.length * 4 * 4);
/* 2273 */ this.bits[index] |= bit;
/* */ }
/* */
/* */ public void Union(ScriptSet other)
/* */ {
/* 2278 */ for (int i = 0; i < this.bits.length; i++) {
/* 2279 */ this.bits[i] |= other.bits[i];
/* */ }
/* */ }
/* */
/* */ public void intersect(ScriptSet other) {
/* 2284 */ for (int i = 0; i < this.bits.length; i++) {
/* 2285 */ this.bits[i] &= other.bits[i];
/* */ }
/* */ }
/* */
/* */ public void intersect(int script) {
/* 2290 */ int index = script / 32;
/* 2291 */ int bit = 1 << (script & 0x1F);
/* 2292 */ assert (index < this.bits.length * 4 * 4);
/* */
/* 2294 */ for (int i = 0; i < index; i++) {
/* 2295 */ this.bits[i] = 0;
/* */ }
/* 2297 */ this.bits[index] &= bit;
/* 2298 */ for (i = index + 1; i < this.bits.length; i++) {
/* 2299 */ this.bits[i] = 0;
/* */ }
/* */ }
/* */
/* */ public void setAll() {
/* 2304 */ for (int i = 0; i < this.bits.length; i++) {
/* 2305 */ this.bits[i] = -1;
/* */ }
/* */ }
/* */
/* */ public void resetAll()
/* */ {
/* 2311 */ for (int i = 0; i < this.bits.length; i++) {
/* 2312 */ this.bits[i] = 0;
/* */ }
/* */ }
/* */
/* */
/* */ public int countMembers()
/* */ {
/* 2319 */ int count = 0;
/* 2320 */ for (int i = 0; i < this.bits.length; i++) {
/* 2321 */ int x = this.bits[i];
/* 2322 */ while (x > 0) {
/* 2323 */ count++;
/* 2324 */ x &= x - 1;
/* */ }
/* */ }
/* 2327 */ return count;
/* */ }
/* */
/* 2330 */ private int[] bits = new int[6];
/* */ }
/* */ }
/* Location: C:\Users\Ethan\Desktop\FontZip\FontTool\sfnttool.jar!\com\ibm\icu\text\SpoofChecker.class
* Java compiler version: 5 (49.0)
* JD-Core Version: 0.7.1
*/