001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portlet.messageboards.util;
022:
023: import com.liferay.portal.kernel.util.GetterUtil;
024: import com.liferay.portal.kernel.util.StringMaker;
025: import com.liferay.portal.kernel.util.StringPool;
026: import com.liferay.portal.kernel.util.StringUtil;
027: import com.liferay.util.Html;
028:
029: import java.util.HashMap;
030: import java.util.Map;
031:
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034:
035: /**
036: * <a href="BBCodeUtil.java.html"><b><i>View Source</i></b></a>
037: *
038: * @author Alexander Chow
039: *
040: */
041: public class BBCodeUtil {
042:
043: static Map fontSizes = new HashMap();
044:
045: static Map listStyles = new HashMap();
046:
047: static String[][] emoticons = { { "angry.gif", ":angry:" },
048: { "bashful.gif", ":bashful:" },
049: { "big_grin.gif", ":grin:" }, { "blink.gif", ":blink:" },
050: { "blush.gif", ":*)" }, { "bored.gif", ":bored:" },
051: { "closed_eyes.gif", "-_-" }, { "cold.gif", ":cold:" },
052: { "cool.gif", "B)" }, { "darth_vader.gif", ":vader:" },
053: { "dry.gif", "<_<" }, { "exclamation.gif", ":what:" },
054: { "girl.gif", ":girl:" }, { "glare.gif", ">_>" },
055: { "happy.gif", ":)" }, { "huh.gif", ":huh:" },
056: { "in_love.gif", "<3" }, { "karate_kid.gif", ":kid:" },
057: { "kiss.gif", ":#" }, { "laugh.gif", ":lol:" },
058: { "mad.gif", ":mad:" }, { "mellow.gif", ":mellow:" },
059: { "ninja.gif", ":ph34r:" }, { "oh_my.gif", ":O" },
060: { "pac_man.gif", ":V" }, { "roll_eyes.gif", ":rolleyes:" },
061: { "sad.gif", ":(" }, { "sleep.gif", ":sleep:" },
062: { "smile.gif", ":D" }, { "smug.gif", ":smug:" },
063: { "suspicious.gif", "8o" }, { "tongue.gif", ":P" },
064: { "unsure.gif", ":unsure:" }, { "wacko.gif", ":wacko:" },
065: { "wink.gif", ":wink:" }, { "wub.gif", ":wub:" } };
066:
067: static {
068: fontSizes.put(new Integer(1),
069: "<span style='font-size: 0.7em';>");
070: fontSizes.put(new Integer(2),
071: "<span style='font-size: 0.8em';>");
072: fontSizes.put(new Integer(3),
073: "<span style='font-size: 0.9em';>");
074: fontSizes.put(new Integer(4),
075: "<span style='font-size: 1.0em';>");
076: fontSizes.put(new Integer(5),
077: "<span style='font-size: 1.1em';>");
078: fontSizes.put(new Integer(6),
079: "<span style='font-size: 1.3em';>");
080: fontSizes.put(new Integer(7),
081: "<span style='font-size: 1.5em';>");
082:
083: listStyles.put("1", "<ol style='list-style-type: decimal';>");
084: listStyles.put("i",
085: "<ol style='list-style-type: lower-roman';>");
086: listStyles.put("I",
087: "<ol style='list-style-type: upper-roman';>");
088: listStyles.put("a",
089: "<ol style='list-style-type: lower-alpha';>");
090: listStyles.put("A",
091: "<ol style='list-style-type: upper-alpha';>");
092:
093: for (int i = 0; i < emoticons.length; i++) {
094: String[] emoticon = emoticons[i];
095:
096: String image = emoticon[0];
097: String code = emoticon[1];
098:
099: emoticon[0] = "<img src='@theme_images_path@/emoticons/"
100: + image + "' />";
101: emoticon[1] = Html.escape(code);
102: }
103: }
104:
105: public static final String[][] EMOTICONS = emoticons;
106:
107: public static String getHTML(String bbcode) {
108: String html = Html.escape(bbcode);
109:
110: html = StringUtil.replace(html, _BBCODE_TAGS, _HTML_TAGS);
111:
112: for (int i = 0; i < emoticons.length; i++) {
113: String[] emoticon = emoticons[i];
114:
115: html = StringUtil.replace(html, emoticon[1], emoticon[0]);
116: }
117:
118: BBCodeTag tag = null;
119:
120: StringMaker sm = null;
121:
122: while ((tag = getFirstTag(html, "code")) != null) {
123: String preTag = html.substring(0, tag.getStartPos());
124: String postTag = html.substring(tag.getEndPos());
125:
126: String code = tag.getElement().replaceAll("\t", " ");
127: String[] lines = code.split("\\n");
128: int digits = Integer.toString(lines.length + 1).length();
129:
130: sm = new StringMaker(preTag);
131:
132: sm.append("<div class='message-board-code'>");
133:
134: for (int i = 0; i < lines.length; i++) {
135: String index = Integer.toString(i + 1);
136: int ld = index.length();
137:
138: sm.append("<span class='message-board-code-lines'>");
139:
140: for (int j = 0; j < digits - ld; j++) {
141: sm.append(" ");
142: }
143:
144: lines[i] = StringUtil.replace(lines[i], " ",
145: StringPool.NBSP + StringPool.SPACE
146: + StringPool.NBSP);
147: lines[i] = StringUtil.replace(lines[i], " ",
148: StringPool.NBSP + StringPool.SPACE);
149:
150: sm.append(index + "</span>");
151: sm.append(lines[i]);
152:
153: if (index.length() < lines.length) {
154: sm.append("<br />");
155: }
156: }
157:
158: sm.append("</div>");
159: sm.append(postTag);
160:
161: html = sm.toString();
162: }
163:
164: while ((tag = getFirstTag(html, "color")) != null) {
165: String preTag = html.substring(0, tag.getStartPos());
166: String postTag = html.substring(tag.getEndPos());
167:
168: sm = new StringMaker(preTag);
169:
170: if (tag.hasParameter()) {
171: sm.append("<span style='color: ");
172: sm.append(tag.getParameter() + ";'>");
173: sm.append(tag.getElement() + "</span>");
174: } else {
175: sm.append(tag.getElement());
176: }
177:
178: sm.append(postTag);
179:
180: html = sm.toString();
181: }
182:
183: while ((tag = getFirstTag(html, "email")) != null) {
184: String preTag = html.substring(0, tag.getStartPos());
185: String postTag = html.substring(tag.getEndPos());
186:
187: String mailto = GetterUtil.getString(tag.getParameter(),
188: tag.getElement().trim());
189:
190: sm = new StringMaker(preTag);
191:
192: sm.append("<a href='mailto: " + mailto + "'>");
193: sm.append(tag.getElement() + "</a>");
194: sm.append(postTag);
195:
196: html = sm.toString();
197: }
198:
199: while ((tag = getFirstTag(html, "font")) != null) {
200: String preTag = html.substring(0, tag.getStartPos());
201: String postTag = html.substring(tag.getEndPos());
202:
203: sm = new StringMaker(preTag);
204:
205: if (tag.hasParameter()) {
206: sm.append("<span style='font-family: ");
207: sm.append(tag.getParameter() + "';>");
208: sm.append(tag.getElement() + "</span>");
209: } else {
210: sm.append(tag.getElement());
211: }
212:
213: sm.append(postTag);
214:
215: html = sm.toString();
216: }
217:
218: while ((tag = getFirstTag(html, "img")) != null) {
219: String preTag = html.substring(0, tag.getStartPos());
220: String postTag = html.substring(tag.getEndPos());
221:
222: sm = new StringMaker(preTag);
223:
224: sm.append("<img src='" + tag.getElement().trim() + "' />");
225: sm.append(postTag);
226:
227: html = sm.toString();
228: }
229:
230: while ((tag = getFirstTag(html, "list")) != null) {
231: String preTag = html.substring(0, tag.getStartPos());
232: String postTag = html.substring(tag.getEndPos());
233:
234: String[] items = StringUtil.split(tag.getElement(), "[*]");
235:
236: sm = new StringMaker(preTag);
237:
238: if (tag.hasParameter()
239: && listStyles.containsKey(tag.getParameter())) {
240:
241: sm.append(listStyles.get(tag.getParameter()));
242:
243: for (int i = 0; i < items.length; i++) {
244: if (items[i].trim().length() > 0) {
245: sm.append("<li>" + items[i].trim() + "</li>");
246: }
247: }
248:
249: sm.append("</ol>");
250: } else {
251: sm.append("<ul style='list-style-type: disc';>");
252:
253: for (int i = 0; i < items.length; i++) {
254: if (items[i].trim().length() > 0) {
255: sm.append("<li>" + items[i].trim() + "</li>");
256: }
257: }
258:
259: sm.append("</ul>");
260: }
261:
262: sm.append(postTag);
263:
264: html = sm.toString();
265: }
266:
267: while ((tag = getFirstTag(html, "quote")) != null) {
268: String preTag = html.substring(0, tag.getStartPos());
269: String postTag = html.substring(tag.getEndPos());
270:
271: sm = new StringMaker(preTag);
272:
273: if (tag.hasParameter()) {
274: sm.append("<div class='message-board-quote-title'>");
275: sm.append(tag.getParameter() + ":</div>");
276: }
277:
278: sm.append("<div class='message-board-quote'>");
279: sm.append("<div class='message-board-quote-content'>");
280: sm.append(tag.getElement());
281: sm.append("</div></div>");
282: sm.append(postTag);
283:
284: html = sm.toString();
285: }
286:
287: while ((tag = getFirstTag(html, "size")) != null) {
288: String preTag = html.substring(0, tag.getStartPos());
289: String postTag = html.substring(tag.getEndPos());
290:
291: sm = new StringMaker(preTag);
292:
293: if (tag.hasParameter()) {
294: Integer size = new Integer(GetterUtil.getInteger(tag
295: .getParameter()));
296:
297: if (size.intValue() > 7) {
298: size = new Integer(7);
299: }
300:
301: if (fontSizes.containsKey(size)) {
302: sm.append(fontSizes.get(size));
303: sm.append(tag.getElement() + "</span>");
304: } else {
305: sm.append(tag.getElement());
306: }
307: } else {
308: sm.append(tag.getElement());
309: }
310:
311: sm.append(postTag);
312:
313: html = sm.toString();
314: }
315:
316: while ((tag = getFirstTag(html, "url")) != null) {
317: String preTag = html.substring(0, tag.getStartPos());
318: String postTag = html.substring(tag.getEndPos());
319:
320: String url = GetterUtil.getString(tag.getParameter(), tag
321: .getElement().trim());
322:
323: sm = new StringMaker(preTag);
324:
325: sm.append("<a href='" + url + "'>");
326: sm.append(tag.getElement() + "</a>");
327: sm.append(postTag);
328:
329: html = sm.toString();
330: }
331:
332: html = StringUtil.replace(html, "\n", "<br />");
333:
334: return html;
335: }
336:
337: public static BBCodeTag getFirstTag(String bbcode, String name) {
338: BBCodeTag tag = new BBCodeTag();
339:
340: String begTag = "[" + name;
341: String endTag = "[/" + name + "]";
342:
343: String preTag = StringUtil.extractFirst(bbcode, begTag);
344:
345: if (preTag == null) {
346: return null;
347: }
348:
349: if (preTag.length() != bbcode.length()) {
350: tag.setStartPos(preTag.length());
351:
352: String remainder = bbcode.substring(preTag.length()
353: + begTag.length());
354:
355: int cb = remainder.indexOf("]");
356: int end = remainder.indexOf(endTag);
357:
358: if (cb > 0 && remainder.startsWith("=")) {
359: tag.setParameter(remainder.substring(1, cb));
360: tag.setElement(remainder.substring(cb + 1, end));
361: } else if (cb == 0) {
362: try {
363: tag.setElement(remainder.substring(1, end));
364: } catch (StringIndexOutOfBoundsException sioobe) {
365: _log.error(bbcode);
366:
367: throw sioobe;
368: }
369: }
370: }
371:
372: if (tag.hasElement()) {
373: int length = begTag.length() + 1
374: + tag.getElement().length() + endTag.length();
375:
376: if (tag.hasParameter()) {
377: length += 1 + tag.getParameter().length();
378: }
379:
380: tag.setEndPos(tag.getStartPos() + length);
381:
382: return tag;
383: }
384:
385: return null;
386: }
387:
388: private static final String[] _BBCODE_TAGS = { "[b]", "[/b]",
389: "[i]", "[/i]", "[u]", "[/u]", "[s]", "[/s]", "[img]",
390: "[/img]", "[left]", "[center]", "[right]", "[indent]",
391: "[/left]", "[/center]", "[/right]", "[/indent]" };
392:
393: private static final String[] _HTML_TAGS = { "<b>", "</b>", "<i>",
394: "</i>", "<u>", "</u>", "<strike>", "</strike>",
395: "<img src='", "' />", "<div style='text-align: left'>",
396: "<div style='text-align: center'>",
397: "<div style='text-align: right'>",
398: "<div style='margin-left: 15px'>", "</div>", "</div>",
399: "</div>", "</div>" };
400:
401: private static Log _log = LogFactory.getLog(BBCodeUtil.class);
402:
403: }
|