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