1 7 package com.ibm.icu.text; 8 9 import java.io.IOException ; 10 import java.io.InputStream ; 11 import java.util.MissingResourceException ; 12 13 import com.ibm.icu.impl.ICUData; 14 import com.ibm.icu.impl.ICUResourceBundle; 15 16 40 public final class IDNA { 41 42 43 private static char[] ACE_PREFIX = new char[]{ 0x0078,0x006E,0x002d,0x002d } ; 44 private static final int ACE_PREFIX_LENGTH = 4; 45 46 private static final int MAX_LABEL_LENGTH = 63; 47 private static final int HYPHEN = 0x002D; 48 private static final int CAPITAL_A = 0x0041; 49 private static final int CAPITAL_Z = 0x005A; 50 private static final int LOWER_CASE_DELTA = 0x0020; 51 private static final int FULL_STOP = 0x002E; 52 53 60 public static final int DEFAULT = 0x0000; 61 67 public static final int ALLOW_UNASSIGNED = 0x0001; 68 74 public static final int USE_STD3_RULES = 0x0002; 75 76 private static final IDNA singleton = new IDNA(); 80 81 private StringPrep namePrep; 83 84 85 private IDNA(){ 86 try{ 87 InputStream stream = ICUData.getRequiredStream(ICUResourceBundle.ICU_BUNDLE+"/uidna.spp"); 88 namePrep = new StringPrep(stream); 89 stream.close(); 90 }catch (IOException e){ 91 throw new MissingResourceException (e.toString(),"",""); 92 } 93 } 94 95 private static boolean startsWithPrefix(StringBuffer src){ 96 boolean startsWithPrefix = true; 97 98 if(src.length() < ACE_PREFIX_LENGTH){ 99 return false; 100 } 101 for(int i=0; i<ACE_PREFIX_LENGTH;i++){ 102 if(toASCIILower(src.charAt(i)) != ACE_PREFIX[i]){ 103 startsWithPrefix = false; 104 } 105 } 106 return startsWithPrefix; 107 } 108 109 private static char toASCIILower(char ch){ 110 if(CAPITAL_A <= ch && ch <= CAPITAL_Z){ 111 return (char)(ch + LOWER_CASE_DELTA); 112 } 113 return ch; 114 } 115 116 private static StringBuffer toASCIILower(StringBuffer src){ 117 StringBuffer dest = new StringBuffer (); 118 for(int i=0; i<src.length();i++){ 119 dest.append(toASCIILower(src.charAt(i))); 120 } 121 return dest; 122 } 123 124 private static int compareCaseInsensitiveASCII(StringBuffer s1, StringBuffer s2){ 125 char c1,c2; 126 int rc; 127 for(int i =0;;i++) { 128 129 if(i == s1.length()) { 130 return 0; 131 } 132 133 c1 = s1.charAt(i); 134 c2 = s2.charAt(i); 135 136 137 if(c1!=c2) { 138 rc=toASCIILower(c1)-toASCIILower(c2); 139 if(rc!=0) { 140 return rc; 141 } 142 } 143 } 144 } 145 146 private static int getSeparatorIndex(char[] src,int start, int limit){ 147 for(; start<limit;start++){ 148 if(isLabelSeparator(src[start])){ 149 return start; 150 } 151 } 152 return start; 154 } 155 156 174 175 176 private static boolean isLDHChar(int ch){ 177 if(ch>0x007A){ 179 return false; 180 } 181 if( (ch==0x002D) || 183 (0x0030 <= ch && ch <= 0x0039) || 184 (0x0041 <= ch && ch <= 0x005A) || 185 (0x0061 <= ch && ch <= 0x007A) 186 ){ 187 return true; 188 } 189 return false; 190 } 191 192 200 private static boolean isLabelSeparator(int ch){ 201 switch(ch){ 202 case 0x002e: 203 case 0x3002: 204 case 0xFF0E: 205 case 0xFF61: 206 return true; 207 default: 208 return false; 209 } 210 } 211 212 237 public static StringBuffer convertToASCII(String src, int options) 238 throws StringPrepParseException{ 239 UCharacterIterator iter = UCharacterIterator.getInstance(src); 240 return convertToASCII(iter,options); 241 } 242 243 268 public static StringBuffer convertToASCII(StringBuffer src, int options) 269 throws StringPrepParseException{ 270 UCharacterIterator iter = UCharacterIterator.getInstance(src); 271 return convertToASCII(iter,options); 272 } 273 274 299 public static StringBuffer convertToASCII(UCharacterIterator src, int options) 300 throws StringPrepParseException{ 301 302 boolean[] caseFlags = null; 303 304 boolean srcIsASCII = true; 306 boolean srcIsLDH = true; 308 309 boolean useSTD3ASCIIRules = ((options & USE_STD3_RULES) != 0); 311 int ch; 312 while((ch = src.next())!= UCharacterIterator.DONE){ 314 if(ch> 0x7f){ 315 srcIsASCII = false; 316 } 317 } 318 int failPos = -1; 319 src.setToStart(); 320 StringBuffer processOut = null; 321 if(!srcIsASCII){ 323 processOut = singleton.namePrep.prepare(src, options); 325 }else{ 326 processOut = new StringBuffer (src.getText()); 327 } 328 int poLen = processOut.length(); 329 330 if(poLen==0){ 331 throw new StringPrepParseException("Found zero length lable after NamePrep.",StringPrepParseException.ZERO_LENGTH_LABEL); 332 } 333 StringBuffer dest = new StringBuffer (); 334 335 srcIsASCII = true; 337 338 for(int j=0;j<poLen;j++ ){ 340 ch=processOut.charAt(j); 341 if(ch > 0x7F){ 342 srcIsASCII = false; 343 }else if(isLDHChar(ch)==false){ 344 srcIsLDH = false; 348 failPos = j; 349 } 350 } 351 352 if(useSTD3ASCIIRules == true){ 353 if( srcIsLDH == false 355 || processOut.charAt(0) == HYPHEN 356 || processOut.charAt(processOut.length()-1) == HYPHEN){ 357 358 359 if(srcIsLDH==false){ 360 throw new StringPrepParseException( "The input does not conform to the STD 3 ASCII rules", 361 StringPrepParseException.STD3_ASCII_RULES_ERROR, 362 processOut.toString(), 363 (failPos>0) ? (failPos-1) : failPos); 364 }else if(processOut.charAt(0) == HYPHEN){ 365 throw new StringPrepParseException("The input does not conform to the STD 3 ASCII rules", 366 StringPrepParseException.STD3_ASCII_RULES_ERROR,processOut.toString(),0); 367 368 }else{ 369 throw new StringPrepParseException("The input does not conform to the STD 3 ASCII rules", 370 StringPrepParseException.STD3_ASCII_RULES_ERROR, 371 processOut.toString(), 372 (poLen>0) ? poLen-1 : poLen); 373 374 } 375 } 376 } 377 if(srcIsASCII){ 378 dest = processOut; 379 }else{ 380 if(!startsWithPrefix(processOut)){ 382 383 caseFlags = new boolean[poLen]; 385 386 StringBuffer punyout = Punycode.encode(processOut,caseFlags); 387 388 StringBuffer lowerOut = toASCIILower(punyout); 390 391 dest.append(ACE_PREFIX,0,ACE_PREFIX_LENGTH); 393 dest.append(lowerOut); 395 }else{ 396 397 throw new StringPrepParseException("The input does not start with the ACE Prefix.", 398 StringPrepParseException.ACE_PREFIX_ERROR,processOut.toString(),0); 399 } 400 } 401 if(dest.length() > MAX_LABEL_LENGTH){ 402 throw new StringPrepParseException("The labels in the input are too long. Length > 64.", 403 StringPrepParseException.LABEL_TOO_LONG_ERROR,dest.toString(),0); 404 } 405 return dest; 406 } 407 408 438 public static StringBuffer convertIDNToASCII(UCharacterIterator src, int options) 439 throws StringPrepParseException{ 440 return convertIDNToASCII(src.getText(), options); 441 } 442 443 473 public static StringBuffer convertIDNToASCII(StringBuffer src, int options) 474 throws StringPrepParseException{ 475 return convertIDNToASCII(src.toString(), options); 476 } 477 478 508 public static StringBuffer convertIDNToASCII(String src,int options) 509 throws StringPrepParseException{ 510 511 char[] srcArr = src.toCharArray(); 512 StringBuffer result = new StringBuffer (); 513 int sepIndex=0; 514 int oldSepIndex=0; 515 for(;;){ 516 sepIndex = getSeparatorIndex(srcArr,sepIndex,srcArr.length); 517 String label = new String (srcArr,oldSepIndex,sepIndex-oldSepIndex); 518 if(!(label.length()==0 && sepIndex==srcArr.length)){ 520 UCharacterIterator iter = UCharacterIterator.getInstance(label); 521 result.append(convertToASCII(iter,options)); 522 } 523 if(sepIndex==srcArr.length){ 524 break; 525 } 526 527 sepIndex++; 529 oldSepIndex = sepIndex; 530 result.append((char)FULL_STOP); 531 } 532 return result; 533 } 534 535 536 561 public static StringBuffer convertToUnicode(String src, int options) 562 throws StringPrepParseException{ 563 UCharacterIterator iter = UCharacterIterator.getInstance(src); 564 return convertToUnicode(iter,options); 565 } 566 567 592 public static StringBuffer convertToUnicode(StringBuffer src, int options) 593 throws StringPrepParseException{ 594 UCharacterIterator iter = UCharacterIterator.getInstance(src); 595 return convertToUnicode(iter,options); 596 } 597 598 623 public static StringBuffer convertToUnicode(UCharacterIterator src, int options) 624 throws StringPrepParseException{ 625 626 boolean[] caseFlags = null; 627 628 boolean srcIsASCII = true; 630 boolean srcIsLDH = true; 632 633 boolean useSTD3ASCIIRules = ((options & USE_STD3_RULES) != 0); 635 636 int failPos = -1; 637 int ch; 638 int saveIndex = src.getIndex(); 639 while((ch=src.next())!= UCharacterIterator.DONE){ 641 if(ch>0x7F){ 642 srcIsASCII = false; 643 }else if((srcIsLDH = isLDHChar(ch))==false){ 644 failPos = src.getIndex(); 645 } 646 } 647 StringBuffer processOut; 648 649 if(srcIsASCII == false){ 650 try { 651 src.setIndex(saveIndex); 653 processOut = singleton.namePrep.prepare(src,options); 654 } catch (StringPrepParseException ex) { 655 return new StringBuffer (src.getText()); 656 } 657 658 }else{ 659 processOut = new StringBuffer (src.getText()); 661 } 662 669 if(startsWithPrefix(processOut)){ 671 StringBuffer decodeOut = null; 672 673 String temp = processOut.substring(ACE_PREFIX_LENGTH,processOut.length()); 675 676 try { 678 decodeOut = Punycode.decode(new StringBuffer (temp),caseFlags); 679 } catch (StringPrepParseException e) { 680 decodeOut = null; 681 } 682 683 if (decodeOut != null) { 685 StringBuffer toASCIIOut = convertToASCII(decodeOut, options); 686 687 if(compareCaseInsensitiveASCII(processOut, toASCIIOut) !=0){ 689 decodeOut = null; 692 } 693 } 694 695 if (decodeOut != null) { 697 return decodeOut; 698 } 699 } 700 701 730 return new StringBuffer (src.getText()); 731 } 732 733 760 public static StringBuffer convertIDNToUnicode(UCharacterIterator src, int options) 761 throws StringPrepParseException{ 762 return convertIDNToUnicode(src.getText(), options); 763 } 764 765 792 public static StringBuffer convertIDNToUnicode(StringBuffer src, int options) 793 throws StringPrepParseException{ 794 return convertIDNToUnicode(src.toString(), options); 795 } 796 797 824 public static StringBuffer convertIDNToUnicode(String src, int options) 825 throws StringPrepParseException{ 826 827 char[] srcArr = src.toCharArray(); 828 StringBuffer result = new StringBuffer (); 829 int sepIndex=0; 830 int oldSepIndex=0; 831 for(;;){ 832 sepIndex = getSeparatorIndex(srcArr,sepIndex,srcArr.length); 833 String label = new String (srcArr,oldSepIndex,sepIndex-oldSepIndex); 834 if(label.length()==0 && sepIndex!=srcArr.length ){ 835 throw new StringPrepParseException("Found zero length lable after NamePrep.",StringPrepParseException.ZERO_LENGTH_LABEL); 836 } 837 UCharacterIterator iter = UCharacterIterator.getInstance(label); 838 result.append(convertToUnicode(iter,options)); 839 if(sepIndex==srcArr.length){ 840 break; 841 } 842 sepIndex++; 844 oldSepIndex =sepIndex; 845 result.append((char)FULL_STOP); 846 } 847 return result; 848 } 849 850 878 public static int compare(StringBuffer s1, StringBuffer s2, int options) 880 throws StringPrepParseException{ 881 if(s1==null || s2 == null){ 882 throw new IllegalArgumentException ("One of the source buffers is null"); 883 } 884 StringBuffer s1Out = convertIDNToASCII(s1.toString(),options); 885 StringBuffer s2Out = convertIDNToASCII(s2.toString(), options); 886 return compareCaseInsensitiveASCII(s1Out,s2Out); 887 } 888 889 917 public static int compare(String s1, String s2, int options) 919 throws StringPrepParseException{ 920 if(s1==null || s2 == null){ 921 throw new IllegalArgumentException ("One of the source buffers is null"); 922 } 923 StringBuffer s1Out = convertIDNToASCII(s1, options); 924 StringBuffer s2Out = convertIDNToASCII(s2, options); 925 return compareCaseInsensitiveASCII(s1Out,s2Out); 926 } 927 955 public static int compare(UCharacterIterator s1, UCharacterIterator s2, int options) 957 throws StringPrepParseException{ 958 if(s1==null || s2 == null){ 959 throw new IllegalArgumentException ("One of the source buffers is null"); 960 } 961 StringBuffer s1Out = convertIDNToASCII(s1.getText(), options); 962 StringBuffer s2Out = convertIDNToASCII(s2.getText(), options); 963 return compareCaseInsensitiveASCII(s1Out,s2Out); 964 } 965 } 966 | Popular Tags |