1
22
23 package com.liferay.portlet.messageboards.util;
24
25 import com.liferay.portal.kernel.util.GetterUtil;
26 import com.liferay.portal.kernel.util.HtmlUtil;
27 import com.liferay.portal.kernel.util.StringPool;
28 import com.liferay.portal.kernel.util.StringUtil;
29
30 import java.util.HashMap;
31 import java.util.Map;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36
42 public class BBCodeUtil {
43
44 static Map<Integer, String> fontSizes = new HashMap<Integer, String>();
45
46 static Map<String, String> listStyles = new HashMap<String, String>();
47
48 static String[][] emoticons = {
49 {"angry.gif", ":angry:"},
50 {"bashful.gif", ":bashful:"},
51 {"big_grin.gif", ":grin:"},
52 {"blink.gif", ":blink:"},
53 {"blush.gif", ":*)"},
54 {"bored.gif", ":bored:"},
55 {"closed_eyes.gif", "-_-"},
56 {"cold.gif", ":cold:"},
57 {"cool.gif", "B)"},
58 {"darth_vader.gif", ":vader:"},
59 {"dry.gif", "<_<"},
60 {"exclamation.gif", ":what:"},
61 {"girl.gif", ":girl:"},
62 {"glare.gif", ">_>"},
63 {"happy.gif", ":)"},
64 {"huh.gif", ":huh:"},
65 {"in_love.gif", "<3"},
66 {"karate_kid.gif", ":kid:"},
67 {"kiss.gif", ":#"},
68 {"laugh.gif", ":lol:"},
69 {"mad.gif", ":mad:"},
70 {"mellow.gif", ":mellow:"},
71 {"ninja.gif", ":ph34r:"},
72 {"oh_my.gif", ":O"},
73 {"pac_man.gif", ":V"},
74 {"roll_eyes.gif", ":rolleyes:"},
75 {"sad.gif", ":("},
76 {"sleep.gif", ":sleep:"},
77 {"smile.gif", ":D"},
78 {"smug.gif", ":smug:"},
79 {"suspicious.gif", "8o"},
80 {"tongue.gif", ":P"},
81 {"unsure.gif", ":unsure:"},
82 {"wacko.gif", ":wacko:"},
83 {"wink.gif", ":wink:"},
84 {"wub.gif", ":wub:"}
85 };
86
87 static {
88 fontSizes.put(new Integer(1), "<span style='font-size: 0.7em';>");
89 fontSizes.put(new Integer(2), "<span style='font-size: 0.8em';>");
90 fontSizes.put(new Integer(3), "<span style='font-size: 0.9em';>");
91 fontSizes.put(new Integer(4), "<span style='font-size: 1.0em';>");
92 fontSizes.put(new Integer(5), "<span style='font-size: 1.1em';>");
93 fontSizes.put(new Integer(6), "<span style='font-size: 1.3em';>");
94 fontSizes.put(new Integer(7), "<span style='font-size: 1.5em';>");
95
96 listStyles.put("1", "<ol style='list-style-type: decimal';>");
97 listStyles.put("i", "<ol style='list-style-type: lower-roman';>");
98 listStyles.put("I", "<ol style='list-style-type: upper-roman';>");
99 listStyles.put("a", "<ol style='list-style-type: lower-alpha';>");
100 listStyles.put("A", "<ol style='list-style-type: upper-alpha';>");
101
102 for (int i = 0; i < emoticons.length; i++) {
103 String[] emoticon = emoticons[i];
104
105 String image = emoticon[0];
106 String code = emoticon[1];
107
108 emoticon[0] =
109 "<img alt='emoticon' src='@theme_images_path@/emoticons/" +
110 image + "' />";
111 emoticon[1] = HtmlUtil.escape(code);
112 }
113 }
114
115 public static final String[][] EMOTICONS = emoticons;
116
117 public static String getHTML(String bbcode) {
118 String html = HtmlUtil.escape(bbcode);
119
120 html = StringUtil.replace(html, _BBCODE_TAGS, _HTML_TAGS);
121
122 for (int i = 0; i < emoticons.length; i++) {
123 String[] emoticon = emoticons[i];
124
125 html = StringUtil.replace(html, emoticon[1], emoticon[0]);
126 }
127
128 BBCodeTag tag = null;
129
130 StringBuilder sb = null;
131
132 while ((tag = getFirstTag(html, "code")) != null) {
133 String preTag = html.substring(0, tag.getStartPos());
134 String postTag = html.substring(tag.getEndPos());
135
136 String code = tag.getElement().replaceAll(
137 "\t", StringPool.FOUR_SPACES);
138 String[] lines = code.split("\\n");
139 int digits = String.valueOf(lines.length + 1).length();
140
141 sb = new StringBuilder(preTag);
142
143 sb.append("<div class='code'>");
144
145 for (int i = 0; i < lines.length; i++) {
146 String index = String.valueOf(i + 1);
147 int ld = index.length();
148
149 sb.append("<span class='code-lines'>");
150
151 for (int j = 0; j < digits - ld; j++) {
152 sb.append(" ");
153 }
154
155 lines[i] = StringUtil.replace(lines[i], " ",
156 StringPool.NBSP + StringPool.SPACE + StringPool.NBSP);
157 lines[i] = StringUtil.replace(lines[i], " ",
158 StringPool.NBSP + StringPool.SPACE);
159
160 sb.append(index + "</span>");
161 sb.append(lines[i]);
162
163 if (index.length() < lines.length) {
164 sb.append("<br />");
165 }
166 }
167
168 sb.append("</div>");
169 sb.append(postTag);
170
171 html = sb.toString();
172 }
173
174 while ((tag = getFirstTag(html, "color")) != null) {
175 String preTag = html.substring(0, tag.getStartPos());
176 String postTag = html.substring(tag.getEndPos());
177
178 sb = new StringBuilder(preTag);
179
180 if (tag.hasParameter()) {
181 sb.append("<span style='color: ");
182 sb.append(tag.getParameter() + ";'>");
183 sb.append(tag.getElement() + "</span>");
184 }
185 else {
186 sb.append(tag.getElement());
187 }
188
189 sb.append(postTag);
190
191 html = sb.toString();
192 }
193
194 while ((tag = getFirstTag(html, "email")) != null) {
195 String preTag = html.substring(0, tag.getStartPos());
196 String postTag = html.substring(tag.getEndPos());
197
198 String mailto = GetterUtil.getString(
199 tag.getParameter(), tag.getElement().trim());
200
201 sb = new StringBuilder(preTag);
202
203 sb.append("<a href='mailto: " + mailto + "'>");
204 sb.append(tag.getElement() + "</a>");
205 sb.append(postTag);
206
207 html = sb.toString();
208 }
209
210 while ((tag = getFirstTag(html, "font")) != null) {
211 String preTag = html.substring(0, tag.getStartPos());
212 String postTag = html.substring(tag.getEndPos());
213
214 sb = new StringBuilder(preTag);
215
216 if (tag.hasParameter()) {
217 sb.append("<span style='font-family: ");
218 sb.append(tag.getParameter() + "';>");
219 sb.append(tag.getElement() + "</span>");
220 }
221 else {
222 sb.append(tag.getElement());
223 }
224
225 sb.append(postTag);
226
227 html = sb.toString();
228 }
229
230 while ((tag = getFirstTag(html, "img")) != null) {
231 String preTag = html.substring(0, tag.getStartPos());
232 String postTag = html.substring(tag.getEndPos());
233
234 sb = new StringBuilder(preTag);
235
236 sb.append("<img alt='' src='" + tag.getElement().trim() + "' />");
237 sb.append(postTag);
238
239 html = sb.toString();
240 }
241
242 while ((tag = getFirstTag(html, "list")) != null) {
243 String preTag = html.substring(0, tag.getStartPos());
244 String postTag = html.substring(tag.getEndPos());
245
246 String[] items = StringUtil.split(tag.getElement(), "[*]");
247
248 sb = new StringBuilder(preTag);
249
250 if (tag.hasParameter() &&
251 listStyles.containsKey(tag.getParameter())) {
252
253 sb.append(listStyles.get(tag.getParameter()));
254
255 for (int i = 0; i < items.length; i++) {
256 if (items[i].trim().length() > 0) {
257 sb.append("<li>" + items[i].trim() + "</li>");
258 }
259 }
260
261 sb.append("</ol>");
262 }
263 else {
264 sb.append("<ul style='list-style-type: disc';>");
265
266 for (int i = 0; i < items.length; i++) {
267 if (items[i].trim().length() > 0) {
268 sb.append("<li>" + items[i].trim() + "</li>");
269 }
270 }
271
272 sb.append("</ul>");
273 }
274
275 sb.append(postTag);
276
277 html = sb.toString();
278 }
279
280 while ((tag = getFirstTag(html, "quote")) != null) {
281 String preTag = html.substring(0, tag.getStartPos());
282 String postTag = html.substring(tag.getEndPos());
283
284 sb = new StringBuilder(preTag);
285
286 if (tag.hasParameter()) {
287 sb.append("<div class='quote-title'>");
288 sb.append(tag.getParameter() + ":</div>");
289 }
290
291 sb.append("<div class='quote'>");
292 sb.append("<div class='quote-content'>");
293 sb.append(tag.getElement());
294 sb.append("</div></div>");
295 sb.append(postTag);
296
297 html = sb.toString();
298 }
299
300 while ((tag = getFirstTag(html, "size")) != null) {
301 String preTag = html.substring(0, tag.getStartPos());
302 String postTag = html.substring(tag.getEndPos());
303
304 sb = new StringBuilder(preTag);
305
306 if (tag.hasParameter()) {
307 Integer size = new Integer(
308 GetterUtil.getInteger(tag.getParameter()));
309
310 if (size.intValue() > 7) {
311 size = new Integer(7);
312 }
313
314 if (fontSizes.containsKey(size)) {
315 sb.append(fontSizes.get(size));
316 sb.append(tag.getElement() + "</span>");
317 }
318 else {
319 sb.append(tag.getElement());
320 }
321 }
322 else {
323 sb.append(tag.getElement());
324 }
325
326 sb.append(postTag);
327
328 html = sb.toString();
329 }
330
331 while ((tag = getFirstTag(html, "url")) != null) {
332 String preTag = html.substring(0, tag.getStartPos());
333 String postTag = html.substring(tag.getEndPos());
334
335 String url = GetterUtil.getString(
336 tag.getParameter(), tag.getElement().trim());
337
338 sb = new StringBuilder(preTag);
339
340 sb.append("<a href='" + url + "'>");
341 sb.append(tag.getElement() + "</a>");
342 sb.append(postTag);
343
344 html = sb.toString();
345 }
346
347 html = StringUtil.replace(html, "\n", "<br />");
348
349 return html;
350 }
351
352 public static BBCodeTag getFirstTag(String bbcode, String name) {
353 BBCodeTag tag = new BBCodeTag();
354
355 String begTag = "[" + name;
356 String endTag = "[/" + name + "]";
357
358 String preTag = StringUtil.extractFirst(bbcode, begTag);
359
360 if (preTag == null) {
361 return null;
362 }
363
364 if (preTag.length() != bbcode.length()) {
365 tag.setStartPos(preTag.length());
366
367 String remainder = bbcode.substring(
368 preTag.length() + begTag.length());
369
370 int cb = remainder.indexOf("]");
371 int end = remainder.indexOf(endTag);
372
373 if (cb > 0 && remainder.startsWith("=")) {
374 tag.setParameter(remainder.substring(1, cb));
375 tag.setElement(remainder.substring(cb + 1, end));
376 }
377 else if (cb == 0) {
378 try {
379 tag.setElement(remainder.substring(1, end));
380 }
381 catch (StringIndexOutOfBoundsException sioobe) {
382 _log.error(bbcode);
383
384 throw sioobe;
385 }
386 }
387 }
388
389 if (tag.hasElement()) {
390 int length =
391 begTag.length() + 1 + tag.getElement().length() +
392 endTag.length();
393
394 if (tag.hasParameter()) {
395 length += 1 + tag.getParameter().length();
396 }
397
398 tag.setEndPos(tag.getStartPos() + length);
399
400 return tag;
401 }
402
403 return null;
404 }
405
406 private static final String[] _BBCODE_TAGS = {
407 "[b]", "[/b]", "[i]", "[/i]", "[u]", "[/u]", "[s]", "[/s]",
408 "[img]", "[/img]",
409 "[left]", "[center]", "[right]", "[indent]",
410 "[/left]", "[/center]", "[/right]", "[/indent]", "[tt]", "[/tt]"
411 };
412
413 private static final String[] _HTML_TAGS = {
414 "<b>", "</b>", "<i>", "</i>", "<u>", "</u>", "<strike>", "</strike>",
415 "<img alt='' src='", "' />",
416 "<div style='text-align: left'>", "<div style='text-align: center'>",
417 "<div style='text-align: right'>", "<div style='margin-left: 15px'>",
418 "</div>", "</div>", "</div>", "</div>", "<tt>", "</tt>"
419 };
420
421 private static Log _log = LogFactory.getLog(BBCodeUtil.class);
422
423 }