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