1 11 12 package org.jivesoftware.util; 13 14 import java.io.UnsupportedEncodingException ; 15 import java.security.MessageDigest ; 16 import java.security.NoSuchAlgorithmException ; 17 import java.text.BreakIterator ; 18 import java.util.ArrayList ; 19 import java.util.Date ; 20 import java.util.Locale ; 21 import java.util.Random ; 22 23 26 public class StringUtils { 27 28 private static final char[] QUOTE_ENCODE = """.toCharArray(); 30 private static final char[] AMP_ENCODE = "&".toCharArray(); 31 private static final char[] LT_ENCODE = "<".toCharArray(); 32 private static final char[] GT_ENCODE = ">".toCharArray(); 33 34 42 public static final String replace(String string, String oldString, String newString) { 43 if (string == null) { 44 return null; 45 } 46 int i = 0; 47 if ((i = string.indexOf(oldString, i)) >= 0) { 49 char[] string2 = string.toCharArray(); 51 char[] newString2 = newString.toCharArray(); 52 int oLength = oldString.length(); 53 StringBuilder buf = new StringBuilder (string2.length); 54 buf.append(string2, 0, i).append(newString2); 55 i += oLength; 56 int j = i; 57 while ((i = string.indexOf(oldString, i)) > 0) { 59 buf.append(string2, j, i - j).append(newString2); 60 i += oLength; 61 j = i; 62 } 63 buf.append(string2, j, string2.length - j); 64 return buf.toString(); 65 } 66 return string; 67 } 68 69 78 public static final String replaceIgnoreCase(String line, String oldString, 79 String newString) { 80 if (line == null) { 81 return null; 82 } 83 String lcLine = line.toLowerCase(); 84 String lcOldString = oldString.toLowerCase(); 85 int i = 0; 86 if ((i = lcLine.indexOf(lcOldString, i)) >= 0) { 87 char[] line2 = line.toCharArray(); 88 char[] newString2 = newString.toCharArray(); 89 int oLength = oldString.length(); 90 StringBuilder buf = new StringBuilder (line2.length); 91 buf.append(line2, 0, i).append(newString2); 92 i += oLength; 93 int j = i; 94 while ((i = lcLine.indexOf(lcOldString, i)) > 0) { 95 buf.append(line2, j, i - j).append(newString2); 96 i += oLength; 97 j = i; 98 } 99 buf.append(line2, j, line2.length - j); 100 return buf.toString(); 101 } 102 return line; 103 } 104 105 117 public static final String replaceIgnoreCase(String line, String oldString, 118 String newString, int[] count) { 119 if (line == null) { 120 return null; 121 } 122 String lcLine = line.toLowerCase(); 123 String lcOldString = oldString.toLowerCase(); 124 int i = 0; 125 if ((i = lcLine.indexOf(lcOldString, i)) >= 0) { 126 int counter = 1; 127 char[] line2 = line.toCharArray(); 128 char[] newString2 = newString.toCharArray(); 129 int oLength = oldString.length(); 130 StringBuilder buf = new StringBuilder (line2.length); 131 buf.append(line2, 0, i).append(newString2); 132 i += oLength; 133 int j = i; 134 while ((i = lcLine.indexOf(lcOldString, i)) > 0) { 135 counter++; 136 buf.append(line2, j, i - j).append(newString2); 137 i += oLength; 138 j = i; 139 } 140 buf.append(line2, j, line2.length - j); 141 count[0] = counter; 142 return buf.toString(); 143 } 144 return line; 145 } 146 147 156 public static final String replace(String line, String oldString, 157 String newString, int[] count) { 158 if (line == null) { 159 return null; 160 } 161 int i = 0; 162 if ((i = line.indexOf(oldString, i)) >= 0) { 163 int counter = 1; 164 char[] line2 = line.toCharArray(); 165 char[] newString2 = newString.toCharArray(); 166 int oLength = oldString.length(); 167 StringBuilder buf = new StringBuilder (line2.length); 168 buf.append(line2, 0, i).append(newString2); 169 i += oLength; 170 int j = i; 171 while ((i = line.indexOf(oldString, i)) > 0) { 172 counter++; 173 buf.append(line2, j, i - j).append(newString2); 174 i += oLength; 175 j = i; 176 } 177 buf.append(line2, j, line2.length - j); 178 count[0] = counter; 179 return buf.toString(); 180 } 181 return line; 182 } 183 184 191 public static final String stripTags(String in) { 192 if (in == null) { 193 return null; 194 } 195 char ch; 196 int i = 0; 197 int last = 0; 198 char[] input = in.toCharArray(); 199 int len = input.length; 200 StringBuilder out = new StringBuilder ((int)(len * 1.3)); 201 for (; i < len; i++) { 202 ch = input[i]; 203 if (ch > '>') { 204 continue; 205 } 206 else if (ch == '<') { 207 if (i + 3 < len && input[i + 1] == 'b' && input[i + 2] == 'r' && input[i + 3] == '>') { 208 i += 3; 209 continue; 210 } 211 if (i > last) { 212 out.append(input, last, i - last); 213 } 214 last = i + 1; 215 } 216 else if (ch == '>') { 217 last = i + 1; 218 } 219 } 220 if (last == 0) { 221 return in; 222 } 223 if (i > last) { 224 out.append(input, last, i - last); 225 } 226 return out.toString(); 227 } 228 229 238 public static final String escapeHTMLTags(String in) { 239 if (in == null) { 240 return null; 241 } 242 char ch; 243 int i = 0; 244 int last = 0; 245 char[] input = in.toCharArray(); 246 int len = input.length; 247 StringBuilder out = new StringBuilder ((int)(len * 1.3)); 248 for (; i < len; i++) { 249 ch = input[i]; 250 if (ch > '>') { 251 continue; 252 } 253 else if (ch == '<') { 254 if (i > last) { 255 out.append(input, last, i - last); 256 } 257 last = i + 1; 258 out.append(LT_ENCODE); 259 } 260 else if (ch == '>') { 261 if (i > last) { 262 out.append(input, last, i - last); 263 } 264 last = i + 1; 265 out.append(GT_ENCODE); 266 } 267 } 268 if (last == 0) { 269 return in; 270 } 271 if (i > last) { 272 out.append(input, last, i - last); 273 } 274 return out.toString(); 275 } 276 277 280 private static MessageDigest digest = null; 281 282 306 public synchronized static final String hash(String data) { 307 if (digest == null) { 308 try { 309 digest = MessageDigest.getInstance("MD5"); 310 } 311 catch (NoSuchAlgorithmException nsae) { 312 Log.error("Failed to load the MD5 MessageDigest. " + 313 "Jive will be unable to function normally.", nsae); 314 } 315 } 316 try { 318 digest.update(data.getBytes("utf-8")); 319 } 320 catch (UnsupportedEncodingException e) { 321 Log.error(e); 322 } 323 return encodeHex(digest.digest()); 324 } 325 326 337 public static final String encodeHex(byte[] bytes) { 338 StringBuilder buf = new StringBuilder (bytes.length * 2); 339 int i; 340 341 for (i = 0; i < bytes.length; i++) { 342 if (((int)bytes[i] & 0xff) < 0x10) { 343 buf.append("0"); 344 } 345 buf.append(Long.toString((int)bytes[i] & 0xff, 16)); 346 } 347 return buf.toString(); 348 } 349 350 357 public static final byte[] decodeHex(String hex) { 358 char[] chars = hex.toCharArray(); 359 byte[] bytes = new byte[chars.length / 2]; 360 int byteCount = 0; 361 for (int i = 0; i < chars.length; i += 2) { 362 int newByte = 0x00; 363 newByte |= hexCharToByte(chars[i]); 364 newByte <<= 4; 365 newByte |= hexCharToByte(chars[i + 1]); 366 bytes[byteCount] = (byte)newByte; 367 byteCount++; 368 } 369 return bytes; 370 } 371 372 379 private static final byte hexCharToByte(char ch) { 380 switch (ch) { 381 case '0': 382 return 0x00; 383 case '1': 384 return 0x01; 385 case '2': 386 return 0x02; 387 case '3': 388 return 0x03; 389 case '4': 390 return 0x04; 391 case '5': 392 return 0x05; 393 case '6': 394 return 0x06; 395 case '7': 396 return 0x07; 397 case '8': 398 return 0x08; 399 case '9': 400 return 0x09; 401 case 'a': 402 return 0x0A; 403 case 'b': 404 return 0x0B; 405 case 'c': 406 return 0x0C; 407 case 'd': 408 return 0x0D; 409 case 'e': 410 return 0x0E; 411 case 'f': 412 return 0x0F; 413 } 414 return 0x00; 415 } 416 417 427 433 public static String encodeBase64(String data) { 434 byte[] bytes = null; 435 try { 436 bytes = data.getBytes("ISO-8859-1"); 437 } 438 catch (UnsupportedEncodingException uee) { 439 Log.error(uee); 440 } 441 return encodeBase64(bytes); 442 } 443 444 450 public static String encodeBase64(byte[] data) { 451 int c; 452 int len = data.length; 453 StringBuilder ret = new StringBuilder (((len / 3) + 1) * 4); 454 for (int i = 0; i < len; ++i) { 455 c = (data[i] >> 2) & 0x3f; 456 ret.append(cvt.charAt(c)); 457 c = (data[i] << 4) & 0x3f; 458 if (++i < len) 459 c |= (data[i] >> 4) & 0x0f; 460 461 ret.append(cvt.charAt(c)); 462 if (i < len) { 463 c = (data[i] << 2) & 0x3f; 464 if (++i < len) 465 c |= (data[i] >> 6) & 0x03; 466 467 ret.append(cvt.charAt(c)); 468 } 469 else { 470 ++i; 471 ret.append((char)fillchar); 472 } 473 474 if (i < len) { 475 c = data[i] & 0x3f; 476 ret.append(cvt.charAt(c)); 477 } 478 else { 479 ret.append((char)fillchar); 480 } 481 } 482 return ret.toString(); 483 } 484 485 491 public static String decodeBase64(String data) { 492 byte[] bytes = null; 493 try { 494 bytes = data.getBytes("ISO-8859-1"); 495 } 496 catch (UnsupportedEncodingException uee) { 497 Log.error(uee); 498 } 499 return decodeBase64(bytes); 500 } 501 502 508 public static String decodeBase64(byte[] data) { 509 int c, c1; 510 int len = data.length; 511 StringBuilder ret = new StringBuilder ((len * 3) / 4); 512 for (int i = 0; i < len; ++i) { 513 c = cvt.indexOf(data[i]); 514 ++i; 515 c1 = cvt.indexOf(data[i]); 516 c = ((c << 2) | ((c1 >> 4) & 0x3)); 517 ret.append((char)c); 518 if (++i < len) { 519 c = data[i]; 520 if (fillchar == c) 521 break; 522 523 c = cvt.indexOf(c); 524 c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); 525 ret.append((char)c1); 526 } 527 528 if (++i < len) { 529 c1 = data[i]; 530 if (fillchar == c1) 531 break; 532 533 c1 = cvt.indexOf(c1); 534 c = ((c << 6) & 0xc0) | c1; 535 ret.append((char)c); 536 } 537 } 538 return ret.toString(); 539 } 540 541 private static final int fillchar = '='; 542 private static final String cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 543 + "abcdefghijklmnopqrstuvwxyz" 544 + "0123456789+/"; 545 546 556 public static final String [] toLowerCaseWordArray(String text) { 557 if (text == null || text.length() == 0) { 558 return new String [0]; 559 } 560 561 ArrayList wordList = new ArrayList (); 562 BreakIterator boundary = BreakIterator.getWordInstance(); 563 boundary.setText(text); 564 int start = 0; 565 566 for (int end = boundary.next(); end != BreakIterator.DONE; 567 start = end, end = boundary.next()) { 568 String tmp = text.substring(start, end).trim(); 569 tmp = replace(tmp, "+", ""); 571 tmp = replace(tmp, "/", ""); 572 tmp = replace(tmp, "\\", ""); 573 tmp = replace(tmp, "#", ""); 574 tmp = replace(tmp, "*", ""); 575 tmp = replace(tmp, ")", ""); 576 tmp = replace(tmp, "(", ""); 577 tmp = replace(tmp, "&", ""); 578 if (tmp.length() > 0) { 579 wordList.add(tmp); 580 } 581 } 582 return (String [])wordList.toArray(new String [wordList.size()]); 583 } 584 585 590 private static Random randGen = new Random (); 591 592 598 private static char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" + 599 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); 600 601 614 public static final String randomString(int length) { 615 if (length < 1) { 616 return null; 617 } 618 char[] randBuffer = new char[length]; 620 for (int i = 0; i < randBuffer.length; i++) { 621 randBuffer[i] = numbersAndLetters[randGen.nextInt(71)]; 622 } 623 return new String (randBuffer); 624 } 625 626 643 public static final String chopAtWord(String string, int length) { 644 if (string == null || string.length() == 0) { 645 return string; 646 } 647 648 char[] charArray = string.toCharArray(); 649 int sLength = string.length(); 650 if (length < sLength) { 651 sLength = length; 652 } 653 654 for (int i = 0; i < sLength - 1; i++) { 657 if (charArray[i] == '\r' && charArray[i + 1] == '\n') { 659 return string.substring(0, i + 1); 660 } 661 else if (charArray[i] == '\n') { 663 return string.substring(0, i); 664 } 665 } 666 if (charArray[sLength - 1] == '\n') { 668 return string.substring(0, sLength - 1); 669 } 670 671 if (string.length() < length) { 674 return string; 675 } 676 677 for (int i = length - 1; i > 0; i--) { 679 if (charArray[i] == ' ') { 680 return string.substring(0, i).trim(); 681 } 682 } 683 684 return string.substring(0, length); 687 } 688 689 702 public static String wordWrap(String input, int width, Locale locale) { 703 if (input == null) { 705 return ""; 706 } 707 else if (width < 5) { 708 return input; 709 } 710 else if (width >= input.length()) { 711 return input; 712 } 713 714 if (locale == null) { 716 locale = JiveGlobals.getLocale(); 717 } 718 719 StringBuilder buf = new StringBuilder (input); 720 boolean endOfLine = false; 721 int lineStart = 0; 722 723 for (int i = 0; i < buf.length(); i++) { 724 if (buf.charAt(i) == '\n') { 725 lineStart = i + 1; 726 endOfLine = true; 727 } 728 729 if (i > lineStart + width - 1) { 731 if (!endOfLine) { 732 int limit = i - lineStart - 1; 733 BreakIterator breaks = BreakIterator.getLineInstance(locale); 734 breaks.setText(buf.substring(lineStart, i)); 735 int end = breaks.last(); 736 737 if (end == limit + 1) { 741 if (!Character.isWhitespace(buf.charAt(lineStart + end))) { 742 end = breaks.preceding(end - 1); 743 } 744 } 745 746 if (end != BreakIterator.DONE && end == limit + 1) { 748 buf.replace(lineStart + end, lineStart + end + 1, "\n"); 749 lineStart = lineStart + end; 750 } 751 else if (end != BreakIterator.DONE && end != 0) { 753 buf.insert(lineStart + end, '\n'); 754 lineStart = lineStart + end + 1; 755 } 756 else { 757 buf.insert(i, '\n'); 758 lineStart = i + 1; 759 } 760 } 761 else { 762 buf.insert(i, '\n'); 763 lineStart = i + 1; 764 endOfLine = false; 765 } 766 } 767 } 768 769 return buf.toString(); 770 } 771 772 778 public static final String escapeForSQL(String string) { 779 if (string == null) { 780 return null; 781 } 782 else if (string.length() == 0) { 783 return string; 784 } 785 786 char ch; 787 char[] input = string.toCharArray(); 788 int i = 0; 789 int last = 0; 790 int len = input.length; 791 StringBuilder out = null; 792 for (; i < len; i++) { 793 ch = input[i]; 794 795 if (ch == '\'') { 796 if (out == null) { 797 out = new StringBuilder (len + 2); 798 } 799 if (i > last) { 800 out.append(input, last, i - last); 801 } 802 last = i + 1; 803 out.append('\'').append('\''); 804 } 805 } 806 807 if (out == null) { 808 return string; 809 } 810 else if (i > last) { 811 out.append(input, last, i - last); 812 } 813 814 return out.toString(); 815 } 816 817 824 public static final String escapeForXML(String string) { 825 if (string == null) { 826 return null; 827 } 828 char ch; 829 int i = 0; 830 int last = 0; 831 char[] input = string.toCharArray(); 832 int len = input.length; 833 StringBuilder out = new StringBuilder ((int)(len * 1.3)); 834 for (; i < len; i++) { 835 ch = input[i]; 836 if (ch > '>') { 837 continue; 838 } 839 else if (ch == '<') { 840 if (i > last) { 841 out.append(input, last, i - last); 842 } 843 last = i + 1; 844 out.append(LT_ENCODE); 845 } 846 else if (ch == '&') { 847 if (i > last) { 848 out.append(input, last, i - last); 849 } 850 last = i + 1; 851 out.append(AMP_ENCODE); 852 } 853 else if (ch == '"') { 854 if (i > last) { 855 out.append(input, last, i - last); 856 } 857 last = i + 1; 858 out.append(QUOTE_ENCODE); 859 } 860 } 861 if (last == 0) { 862 return string; 863 } 864 if (i > last) { 865 out.append(input, last, i - last); 866 } 867 return out.toString(); 868 } 869 870 877 public static final String unescapeFromXML(String string) { 878 string = replace(string, "<", "<"); 879 string = replace(string, ">", ">"); 880 string = replace(string, """, "\""); 881 return replace(string, "&", "&"); 882 } 883 884 private static final char[] zeroArray = 885 "0000000000000000000000000000000000000000000000000000000000000000".toCharArray(); 886 887 900 public static final String zeroPadString(String string, int length) { 901 if (string == null || string.length() > length) { 902 return string; 903 } 904 StringBuilder buf = new StringBuilder (length); 905 buf.append(zeroArray, 0, length - string.length()).append(string); 906 return buf.toString(); 907 } 908 909 915 public static final String dateToMillis(Date date) { 916 return zeroPadString(Long.toString(date.getTime()), 15); 917 } 918 } | Popular Tags |