001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: /*
006: * WebWork, Web Application Framework
007: *
008: * Distributable under Apache license.
009: * See terms of license at opensource.org
010: */
011: package com.opensymphony.webwork.views.util;
012:
013: /**
014: * This class handles HTML escaping of text.
015: * It was written and optimized to be as fast as possible.
016: *
017: * @author Dick Zetterberg (dick@transitor.se)
018: * @version $Revision: 1282 $
019: */
020: public class TextUtil {
021:
022: protected static final int MAX_LENGTH = 300;
023:
024: /**
025: * We use arrays of char in the lookup table because it is faster
026: * appending this to a StringBuffer than appending a String
027: */
028: protected static final char[][] _stringChars = new char[MAX_LENGTH][];
029:
030: static {
031: // Initialize the mapping table
032: initMapping();
033: }
034:
035: /**
036: * Call escapeHTML(s, false)
037: */
038: public static final String escapeHTML(String s) {
039: return escapeHTML(s, false);
040: }
041:
042: /**
043: * Escape HTML.
044: *
045: * @param s string to be escaped
046: * @param escapeEmpty if true, then empty string will be escaped.
047: */
048: public static final String escapeHTML(String s, boolean escapeEmpty) {
049: int len = s.length();
050:
051: if (len == 0) {
052: return s;
053: }
054:
055: if (!escapeEmpty) {
056: String trimmed = s.trim();
057:
058: if ((trimmed.length() == 0) || ("\"\"").equals(trimmed)) {
059: return s;
060: }
061: }
062:
063: int i = 0;
064:
065: // First loop through String and check if escaping is needed at all
066: // No buffers are copied at this time
067: do {
068: int index = s.charAt(i);
069:
070: if (index >= MAX_LENGTH) {
071: if (index != 0x20AC) { // If not euro symbol
072:
073: continue;
074: }
075:
076: break;
077: } else if (_stringChars[index] != null) {
078: break;
079: }
080: } while (++i < len);
081:
082: // If the check went to the end with no escaping then i should be == len now
083: // otherwise we must continue escaping for real
084: if (i == len) {
085: return s;
086: }
087:
088: // We found a character to escape and broke out at position i
089: // Now copy all characters before that to StringBuffer sb
090: // Since a char[] will be used for copying we might as well get
091: // a complete copy of it so that we can use array indexing instead of charAt
092: StringBuffer sb = new StringBuffer(len + 40);
093: char[] chars = new char[len];
094:
095: // Copy all chars from the String s to the chars buffer
096: s.getChars(0, len, chars, 0);
097:
098: // Append the first i characters that we have checked to the resulting StringBuffer
099: sb.append(chars, 0, i);
100:
101: int last = i;
102: char[] subst;
103:
104: for (; i < len; i++) {
105: char c = chars[i];
106: int index = c;
107:
108: if (index < MAX_LENGTH) {
109: subst = _stringChars[index];
110:
111: // It is faster to append a char[] than a String which is why we use this
112: if (subst != null) {
113: if (i > last) {
114: sb.append(chars, last, i - last);
115: }
116:
117: sb.append(subst);
118: last = i + 1;
119: }
120: }
121: // Check if it is the euro symbol. This could be changed to check in a second lookup
122: // table in case one wants to convert more characters in that area
123: else if (index == 0x20AC) {
124: if (i > last) {
125: sb.append(chars, last, i - last);
126: }
127:
128: sb.append("€");
129: last = i + 1;
130: }
131: }
132:
133: if (i > last) {
134: sb.append(chars, last, i - last);
135: }
136:
137: return sb.toString();
138: }
139:
140: protected static void addMapping(int c, String txt, String[] strings) {
141: strings[c] = txt;
142: }
143:
144: protected static void initMapping() {
145: String[] strings = new String[MAX_LENGTH];
146:
147: addMapping(0x22, """, strings); // "
148: addMapping(0x26, "&", strings); // &
149: addMapping(0x3c, "<", strings); // <
150: addMapping(0x3e, ">", strings); // >
151:
152: addMapping(0xa1, "¡", strings); //
153: addMapping(0xa2, "¢", strings); //
154: addMapping(0xa3, "£", strings); //
155: addMapping(0xa9, "©", strings); // ©
156: addMapping(0xae, "®", strings); // ®
157: addMapping(0xbf, "¿", strings); //
158:
159: addMapping(0xc0, "À", strings); // À
160: addMapping(0xc1, "Á", strings); // Á
161: addMapping(0xc2, "Â", strings); // Â
162: addMapping(0xc3, "Ã", strings); // Â
163: addMapping(0xc4, "Ä", strings); // Ä
164: addMapping(0xc5, "Å", strings); // Å
165: addMapping(0xc6, "Æ", strings); // Æ
166: addMapping(0xc7, "Ç", strings); // Ç
167: addMapping(0xc8, "È", strings); //
168: addMapping(0xc9, "É", strings); //
169: addMapping(0xca, "Ê", strings); //
170: addMapping(0xcb, "Ë", strings); //
171: addMapping(0xcc, "Ì", strings); //
172: addMapping(0xcd, "Í", strings); //
173: addMapping(0xce, "Î", strings); //
174: addMapping(0xcf, "Ï", strings); //
175:
176: addMapping(0xd0, "Ð", strings); //
177: addMapping(0xd1, "Ñ", strings); //
178: addMapping(0xd2, "Ò", strings); //
179: addMapping(0xd3, "Ó", strings); //
180: addMapping(0xd4, "Ô", strings); //
181: addMapping(0xd5, "Õ", strings); //
182: addMapping(0xd6, "Ö", strings); // Ö
183: addMapping(0xd7, "×", strings); //
184: addMapping(0xd8, "Ø", strings); //
185: addMapping(0xd9, "Ù", strings); //
186: addMapping(0xda, "Ú", strings); //
187: addMapping(0xdb, "Û", strings); //
188: addMapping(0xdc, "Ü", strings); //
189: addMapping(0xdd, "Ý", strings); //
190: addMapping(0xde, "Þ", strings); //
191: addMapping(0xdf, "ß", strings); //
192:
193: addMapping(0xe0, "à", strings); //
194: addMapping(0xe1, "á", strings); //
195: addMapping(0xe2, "â", strings); //
196: addMapping(0xe3, "ã", strings); //
197: addMapping(0xe4, "ä", strings); // ä
198: addMapping(0xe5, "å", strings); // å
199: addMapping(0xe6, "æ", strings); //
200: addMapping(0xe7, "ç", strings); //
201: addMapping(0xe8, "è", strings); //
202: addMapping(0xe9, "é", strings); //
203: addMapping(0xea, "ê", strings); //
204: addMapping(0xeb, "ë", strings); //
205: addMapping(0xec, "ì", strings); //
206: addMapping(0xed, "í", strings); //
207: addMapping(0xee, "î", strings); //
208: addMapping(0xef, "ï", strings); //
209:
210: addMapping(0xf0, "ð", strings); //
211: addMapping(0xf1, "ñ", strings); //
212: addMapping(0xf2, "ò", strings); //
213: addMapping(0xf3, "ó", strings); //
214: addMapping(0xf4, "ô", strings); //
215: addMapping(0xf5, "õ", strings); //
216: addMapping(0xf6, "ö", strings); // ö
217: addMapping(0xf7, "÷", strings); //
218: addMapping(0xf8, "ø", strings); //
219: addMapping(0xf9, "ù", strings); //
220: addMapping(0xfa, "ú", strings); //
221: addMapping(0xfb, "û", strings); //
222: addMapping(0xfc, "ü", strings); //
223: addMapping(0xfd, "ý", strings); //
224: addMapping(0xfe, "þ", strings); //
225: addMapping(0xff, "ÿ", strings); //
226:
227: for (int i = 0; i < strings.length; i++) {
228: String str = strings[i];
229:
230: if (str != null) {
231: _stringChars[i] = str.toCharArray();
232: }
233: }
234: }
235: }
|