android-ibc-forum

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit c3c04b3359b7beb9e831a190b3ab2cbc222a3df3
parent 6f4813a0242ef6a25f3cb1298029513e187be320
Author: Jan Dankert <devnull@localhost>
Date:   Wed, 10 Oct 2012 00:01:28 +0200

Neuer BBCodeConverter.

Diffstat:
src/BBCodeTest.java | 41+++++++++++++++++++++++++++++++++++++++++
src/de/mtbnews/android/adapter/BBCodeConverter.java | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/mtbnews/android/adapter/ListEntryContentAdapter.java | 32+++++++++++++++++---------------
src/de/mtbnews/android/adapter/ProcessBBCode.java | 547-------------------------------------------------------------------------------
4 files changed, 206 insertions(+), 562 deletions(-)

diff --git a/src/BBCodeTest.java b/src/BBCodeTest.java @@ -0,0 +1,41 @@ +import de.mtbnews.android.adapter.BBCodeConverter; +import junit.framework.TestCase; + +public class BBCodeTest extends TestCase +{ + public void testQuote() throws Exception + { + + String in = "[quotE=Schrott]Hallo[/Quote]Hallo [B]Du[/b]."; + String out = "<blockquote>Hallo</blockquote>Hallo <b>Du</b>."; + testInOut(in, out); + } + + public void testLink() throws Exception + { + + String in = "[url]http://example.com/image.png[/url]."; + String out = "<a href=\"http://example.com/image.png\">http://example.com/image.png</a>."; + testInOut(in, out); + + in = "[url=http://example.com/image.png]haha[/url]."; + out = "<a href=\"http://example.com/image.png\">haha</a>."; + testInOut(in, out); + } + + public void testImage() throws Exception + { + + String in = "[img]http://example.com/image.png[/imG]."; + String out = "<a href=\"http://example.com/image.png\">Bild anzeigen</a>."; + testInOut(in, out); + } + + + private void testInOut(String in, String out) throws Exception + { + BBCodeConverter bbCodeConverter = new BBCodeConverter(); + String processed = bbCodeConverter.process(in); + assertEquals(out, processed); + } +} diff --git a/src/de/mtbnews/android/adapter/BBCodeConverter.java b/src/de/mtbnews/android/adapter/BBCodeConverter.java @@ -0,0 +1,148 @@ +package de.mtbnews.android.adapter; + +import java.util.regex.Pattern; + +import de.mtbnews.android.util.IBC; + +/** + * @author Jan Dankert + */ +public class BBCodeConverter +{ + private static final String CR_LF = "(?:\r\n|\r|\n)?"; + + /** */ + private boolean acceptHTML = false; + + /** */ + private boolean acceptBBCode = true; + + /** + * @param acceptBBCode + * the new acceptBBCode value + */ + public void setAcceptBBCode(boolean acceptBBCode) + { + this.acceptBBCode = acceptBBCode; + } + + /** + * @param acceptHTML + * the new acceptHTML value + */ + public void setAcceptHTML(boolean acceptHTML) + { + this.acceptHTML = acceptHTML; + } + + /** + * @param string + * @return HTML-formated message + */ + public String process(String string) + { + string = string.replaceAll("(\r\n|\n\r|\n|\r)", "<br />"); + + string = processTag(string, + "\\[color=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/color\\]", + "<span style='color:$1'>$2</span>"); + + string = processTag(string, "\\[quote.*\\](.*?)\\[/quote\\]", + "<blockquote>$1</blockquote>"); + + string = processTag(string, + "\\[list=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/list\\]", + "<ul>$2</ul>"); + + // str = str.replaceAll("(\r\n|\n\r|\n|\r)", "<br>"); + + // [color] + // [size] + string = processTag(string, + "\\[size=['\"]?([0-9]|[1-2][0-9])['\"]?\\](.*?)\\[/size\\]", + "<span style='font-size:$1px'>$2</span>"); + + string = processTag(string, + "\\[mention=['\"]?([0-9]+)['\"]?\\](.*?)\\[/mention\\]", + "<a href=\"" + IBC.IBC_FORUM_URL + "member.php?u=$1\">&rarr;$2</a>"); + + // [b][u][i] + string = processTag(string, "\\[b\\](.*?)\\[/b\\]", "<b>$1</b>"); + string = processTag(string, "\\[u\\](.*?)\\[/u\\]", "<u>$1</u>"); + string = processTag(string, "\\[i\\](.*?)\\[/i\\]", "<i>$1</i>"); + + // Smileys (very poor implementation) + string = processTag(string, ":daumen:", "+1"); + string = processTag(string, ":love:", "&hearts;"); + string = processTag(string, "[*]", "&bull;"); + + // [img] + string = processTag(string, "\\[img\\](.*?)\\[/img\\]", + "<a href=\"$1\">Bild anzeigen</a>"); + + // [url] + string = processTag(string, "\\[url\\](.*?)\\[/url\\]", + "<a href=\"$1\">$1</a>"); + string = processTag(string, + "\\[url=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/url\\]", + "<a href=\"$1\">$2</a>"); + string = processTag(string, + "\\[yt.*\\](.*?)\\[/yt\\]", + "<a href=\"http://www.youtube.com/watch?v=$2\">Video bei Youtube anzeigen</a>"); + + // [email] + string = processTag(string, "\\[email\\](.*?)\\[/email\\]", + "<a href='mailto:$1'>$1</a>"); + + return string; + } + + private static String processTag(String text, String pattern, + String replaceWith) + { + return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(text) + .replaceAll(replaceWith); + } + + /** + * @param content + * @return - + */ + private static String escapeBBcode(String content) + { + // escaping single characters + content = content.replaceAll("[", "&#91;"); + content = content.replaceAll("]", "&#93"); + content = content.replaceAll("\t", "&nbsp; &nbsp;"); + + // taking off start and end line breaks + content = content.replaceAll("\\A\r\n|\\A\r|\\A\n|\r\n\\z|\r\\z|\n\\z", + ""); + + // replacing spaces for &nbsp; to keep indentation + content = content.replaceAll(" ", "&nbsp; "); + content = content.replaceAll(" ", " &nbsp;"); + + return content; + } + + /** + * @param content + * @return - + */ + private static String escapeHtml(String content) + { + // escaping single characters + content = content.replaceAll("&", "&amp;"); + content = content.replaceAll("<", "&lt;"); + content = content.replaceAll(">", "&gt;"); + + // replacing line breaks for <br> + // content = content.replaceAll("\r\n", "<br>"); + // content = replaceAll(content, "\n\r".toCharArray(), new String[] { + // "<br>", "<br>" }); + + return content; + } + +} diff --git a/src/de/mtbnews/android/adapter/ListEntryContentAdapter.java b/src/de/mtbnews/android/adapter/ListEntryContentAdapter.java @@ -11,6 +11,7 @@ import android.content.SharedPreferences; import android.graphics.Typeface; import android.text.Html; import android.text.format.DateFormat; +import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,7 +19,6 @@ import android.widget.BaseAdapter; import android.widget.TextView; import de.mtbnews.android.IBCApplication; import de.mtbnews.android.R; -import de.mtbnews.android.image.URLImageParser; import de.mtbnews.android.tapatalk.wrapper.ListEntry; /** @@ -157,25 +157,27 @@ public class ListEntryContentAdapter extends BaseAdapter // .create(); // html = create.process(e.getContent()); html = e.getContent(); - html = new ProcessBBCode().preparePostText(html); - - Html.ImageGetter imageGetter = null; - if (prefs.getBoolean("load_images", false)) - // imageGetter = new ImageGetter(); - imageGetter = new URLImageParser(viewHolder.desc, mContext); - - viewHolder.desc.setText(Html.fromHtml(html.toString(), - imageGetter, null)); + html = new BBCodeConverter().process(html); + + // Html.ImageGetter imageGetter = null; + // if (prefs.getBoolean("load_images", false)) + // // imageGetter = new ImageGetter(); + // imageGetter = new URLImageParser(viewHolder.desc, mContext); + + // viewHolder.desc.setText(Html.fromHtml(html.toString(), + // imageGetter, null)); + viewHolder.desc.setText(Html.fromHtml(html)); + viewHolder.desc.setMovementMethod(LinkMovementMethod.getInstance()); + //viewHolder.desc.setAutoLinkMask(Linkify.ALL); } else if (containsHtml) { + final CharSequence html = e.getContent(); - Html.ImageGetter imageGetter = null; - if (prefs.getBoolean("load_images", false)) - imageGetter = new URLImageParser(viewHolder.desc, mContext); + // if (prefs.getBoolean("load_images", false)) + // imageGetter = new URLImageParser(viewHolder.desc, mContext); - viewHolder.desc.setText(Html.fromHtml(html.toString(), - imageGetter, null)); + viewHolder.desc.setText(Html.fromHtml(html.toString())); } else { diff --git a/src/de/mtbnews/android/adapter/ProcessBBCode.java b/src/de/mtbnews/android/adapter/ProcessBBCode.java @@ -1,547 +0,0 @@ -package de.mtbnews.android.adapter; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Set; -import java.util.Stack; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/* - * Copyright 2004 JavaFree.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * $Id: ProcessBBCode.java,v 1.18.2.2.4.5 2008/10/07 23:06:16 daltoncamargo Exp - * $ - * - * @author Dalton Camargo - <a href="mailto:dalton@javabb.org">dalton@javabb.org - * </a> <br> - * @author Ronald Tetsuo Miura - */ -public class ProcessBBCode implements Serializable -{ - /** - * - */ - private static final long serialVersionUID = 1L; - - private static final String CR_LF = "(?:\r\n|\r|\n)?"; - - /** */ - private boolean acceptHTML = false; - - /** */ - private boolean acceptBBCode = true; - - /** - * @return acceptBBCode - */ - public boolean getAcceptBBCode() - { - return acceptBBCode; - } - - /** - * @param acceptBBCode - * the new acceptBBCode value - */ - public void setAcceptBBCode(boolean acceptBBCode) - { - this.acceptBBCode = acceptBBCode; - } - - /** - * @return htmlAccepted - */ - public boolean getAcceptHTML() - { - return acceptHTML; - } - - /** - * @param acceptHTML - * the new acceptHTML value - */ - public void setAcceptHTML(boolean acceptHTML) - { - this.acceptHTML = acceptHTML; - } - - /** - * @param texto - * @return TODO unuseful parameters. - */ - public String preparePostText(String texto) - { - if (!getAcceptHTML()) - { - texto = escapeHtml(texto); - } - if (getAcceptBBCode()) - { - texto = process(texto); - } - return texto; - } - - /** - * @param string - * @return HTML-formated message - */ - private String process(String string) - { - string = string.replaceAll("(\r\n|\n\r|\n|\r)", "<br>"); - - StringBuffer buffer = new StringBuffer(string); - processCode(buffer); - - /* - * processNestedTags( buffer, "quote", - * "<table width='90%' cellspacing='1' cellpadding='1' border='0' " + - * "align='center'><tr><td><span class='genmed'><b>{BBCODE_PARAM}:</b></span></td></tr></table><table width='90%' cellspacing='1' cellpadding='1' border='0' align='center'><tr><td class='quote' bgcolor='#F3F5FF'>" - * , " &nbsp;</td></tr></table>", - * "<table width='90%' cellspacing='1' cellpadding='3' border='0' " + - * "align='center'><tr><td><span class='genmed'><b>Quote:</b></span></td></tr><tr><td class='quote'>" - * , " &nbsp;</td></tr></table>", "[*]", false, true, true); - */ - - processNestedTags( - buffer, - "quote", - "</p><blockquote><div class='term'><b>{BBCODE_PARAM}:</b></div><div class='definition'><div><div>", - "</div></div></div></blockquote><p>", - "</p><blockquote><div class='term'><b>Quote:</b></div><div class='definition'><div><div>", - " </div></div></div></blockquote><p>", "[*]", false, true, true); - - processNestedTags(buffer, "list", "<ol type=\"{BBCODE_PARAM}\">", - "</ol>", "<ul>", "</ul>", "<li>", true, true, true); - - String str = buffer.toString(); - - // str = str.replaceAll("(\r\n|\n\r|\n|\r)", "<br>"); - - // [color] - str = str.replaceAll( - "\\[color=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/color\\]", - "<span style='color:$1'>$2</span>"); - - // [size] - str = str.replaceAll( - "\\[size=['\"]?([0-9]|[1-2][0-9])['\"]?\\](.*?)\\[/size\\]", - "<span style='font-size:$1px'>$2</span>"); - - // [b][u][i] - str = str.replaceAll("\\[b\\](.*?)\\[/b\\]", "<b>$1</b>"); - str = str.replaceAll("\\[u\\](.*?)\\[/u\\]", "<u>$1</u>"); - str = str.replaceAll("\\[i\\](.*?)\\[/i\\]", "<i>$1</i>"); - - // [img] - str = str.replaceAll("\\[img\\](.*?)\\[/img\\]", - "<img src='$1' border='0' alt='0'>"); - - // [url] - str = str.replaceAll("\\[url\\](.*?)\\[/url\\]", - "<a href='$1' target='_blank'>$1</a>"); - str = str.replaceAll( - "\\[url=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/url\\]", - "<a href=\"$1\" target=\"_new\">$2</a>"); - - // [email] - str = str.replaceAll("\\[email\\](.*?)\\[/email\\]", - "<a href='mailto:$1'>$1</a>"); - - return str; - } - - private static void processCode(StringBuffer buffer) - { - int start = buffer.indexOf("[code]"); - int end; - - for (; (start >= 0) && (start < buffer.length()); start = buffer - .indexOf("[code]", end)) - { - - end = buffer.indexOf("[/code]", start); - - if (end < 0) - { - break; - } - - end += "[/code]".length(); - - String content = buffer.substring(start + "[code]".length(), end - - "[/code]".length()); - content = escapeBBcode(content); - - /* - * String replacement = "<!-- [ -code- ] --></span>" // + - * "<table width='90%' cellspacing='1' cellpadding='3' border='0' align='center'>" - * + "<tr><td><span class='genmed'><b>Code:</b></span></td></tr>" + - * "<tr><td class='code'>" + content + - * "</td></tr></table><span class='postbody'><!-- [/ -code- ] -->"; - */ - - content = content.replaceAll("<br>", "\n"); - - String replacement = "<!-- [ -code- ] -->" // - + "<textarea name=\"code\" id=\"code\" class=\"java:nocontrols:nogutter\" rows=\"15\" cols=\"100\">" - + content + "</textarea><!-- [/ -code- ] -->"; - - /* - * String replacement = "</span>" // + - * "<!-- [ -code- ] --><pre class=\"brush: java;\">" + content + - * "</pre><span class='postbody'><!-- [/ -code- ] -->"; - */ - - buffer.replace(start, end, replacement); - - end = start + replacement.length(); - } - } - - /** - * @param content - * @return - - */ - public static String escapeBBcode(String content) - { - // escaping single characters - content = replaceAll(content, "[]\t".toCharArray(), new String[] { - "&#91;", "&#93;", "&nbsp; &nbsp;" }); - - // taking off start and end line breaks - content = content.replaceAll("\\A\r\n|\\A\r|\\A\n|\r\n\\z|\r\\z|\n\\z", - ""); - - // replacing spaces for &nbsp; to keep indentation - content = content.replaceAll(" ", "&nbsp; "); - content = content.replaceAll(" ", " &nbsp;"); - - return content; - } - - /** - * @param content - * @return - - */ - private static String escapeHtml(String content) - { - // escaping single characters - content = replaceAll(content, "&<>".toCharArray(), new String[] { - "&amp;", "&lt;", "&gt;" }); - - // replacing line breaks for <br> - // content = content.replaceAll("\r\n", "<br>"); - // content = replaceAll(content, "\n\r".toCharArray(), new String[] { - // "<br>", "<br>" }); - - return content; - } - - private static String replaceAll(String str, char[] chars, - String[] replacement) - { - - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < str.length(); i++) - { - char c = str.charAt(i); - boolean matched = false; - for (int j = 0; j < chars.length; j++) - { - if (c == chars[j]) - { - buffer.append(replacement[j]); - matched = true; - } - } - if (!matched) - { - buffer.append(c); - } - } - return buffer.toString(); - } - - /** - * @param buffer - * @param tagName - * @param openSubstWithParam - * @param closeSubstWithParam - * @param openSubstWithoutParam - * @param closeSubstWithoutParam - * @param internalSubst - * @param processInternalTags - * @param acceptParam - * @param requiresQuotedParam - */ - private static void processNestedTags(StringBuffer buffer, String tagName, - String openSubstWithParam, String closeSubstWithParam, - String openSubstWithoutParam, String closeSubstWithoutParam, - String internalSubst, boolean processInternalTags, - boolean acceptParam, boolean requiresQuotedParam) - { - String str = buffer.toString(); - - Stack openStack = new Stack(); - Set subsOpen = new HashSet(); - Set subsClose = new HashSet(); - Set subsInternal = new HashSet(); - - String openTag = CR_LF - + "\\[" - + tagName - + (acceptParam ? (requiresQuotedParam ? "(?:=\"(.*?)\")?" - : "(?:=\"?(.*?)\"?)?") : "") + "\\]" + CR_LF; - String closeTag = CR_LF + "\\[/" + tagName + "\\]" + CR_LF; - String internTag = CR_LF + "\\[\\*\\]" + CR_LF; - - String patternString = "(" + openTag + ")|(" + closeTag + ")"; - - if (processInternalTags) - { - patternString += "|(" + internTag + ")"; - } - - Pattern tagsPattern = Pattern.compile(patternString); - Matcher matcher = tagsPattern.matcher(str); - - int openTagGroup; - int paramGroup; - int closeTagGroup; - int internalTagGroup; - - if (acceptParam) - { - openTagGroup = 1; - paramGroup = 2; - closeTagGroup = 3; - internalTagGroup = 4; - } - else - { - openTagGroup = 1; - paramGroup = -1; // INFO - closeTagGroup = 2; - internalTagGroup = 3; - } - - while (matcher.find()) - { - int length = matcher.end() - matcher.start(); - MutableCharSequence matchedSeq = new MutableCharSequence(str, - matcher.start(), length); - - // test opening tags - if (matcher.group(openTagGroup) != null) - { - if (acceptParam && (matcher.group(paramGroup) != null)) - { - matchedSeq.param = matcher.group(paramGroup); - } - - openStack.push(matchedSeq); - - // test closing tags - } - else if ((matcher.group(closeTagGroup) != null) - && !openStack.isEmpty()) - { - MutableCharSequence openSeq = (MutableCharSequence) openStack - .pop(); - - if (acceptParam) - { - matchedSeq.param = openSeq.param; - } - - subsOpen.add(openSeq); - subsClose.add(matchedSeq); - - // test internal tags - } - else if (processInternalTags - && (matcher.group(internalTagGroup) != null) - && (!openStack.isEmpty())) - { - subsInternal.add(matchedSeq); - } - else - { - // assert (false); - } - } - - LinkedList subst = new LinkedList(); - subst.addAll(subsOpen); - subst.addAll(subsClose); - subst.addAll(subsInternal); - - Collections.sort(subst, new Comparator() - { - public int compare(Object o1, Object o2) - { - MutableCharSequence s1 = (MutableCharSequence) o1; - MutableCharSequence s2 = (MutableCharSequence) o2; - return -(s1.start - s2.start); - } - }); - - buffer.delete(0, buffer.length()); - - int start = 0; - - while (!subst.isEmpty()) - { - MutableCharSequence seq = (MutableCharSequence) subst.removeLast(); - buffer.append(str.substring(start, seq.start)); - - if (subsClose.contains(seq)) - { - if (seq.param != null) - { - buffer.append(closeSubstWithParam); - } - else - { - buffer.append(closeSubstWithoutParam); - } - } - else if (subsInternal.contains(seq)) - { - buffer.append(internalSubst); - } - else if (subsOpen.contains(seq)) - { - Matcher m = Pattern.compile(openTag).matcher( - str.substring(seq.start, seq.start + seq.length)); - - if (m.matches()) - { - if (acceptParam && (seq.param != null)) - { - buffer.append( // - openSubstWithParam.replaceAll( - "\\{BBCODE_PARAM\\}", seq.param - .replaceAll("\\$", ""))); - } - else - { - buffer.append(openSubstWithoutParam); - } - } - } - - start = seq.start + seq.length; - } - - buffer.append(str.substring(start)); - } - - static class MutableCharSequence implements CharSequence - { - /** */ - public CharSequence base; - - /** */ - public int start; - - /** */ - public int length; - - /** */ - public String param = null; - - /** - */ - public MutableCharSequence() - { - // - } - - /** - * @param base - * @param start - * @param length - */ - public MutableCharSequence(CharSequence base, int start, int length) - { - reset(base, start, length); - } - - /** - * @see java.lang.CharSequence#length() - */ - public int length() - { - return this.length; - } - - /** - * @see java.lang.CharSequence#charAt(int) - */ - public char charAt(int index) - { - return this.base.charAt(this.start + index); - } - - /** - * @see java.lang.CharSequence#subSequence(int, int) - */ - public CharSequence subSequence(int pStart, int end) - { - return new MutableCharSequence(this.base, this.start + pStart, - this.start + (end - pStart)); - } - - /** - * @param pBase - * @param pStart - * @param pLength - * @return - - */ - public CharSequence reset(CharSequence pBase, int pStart, int pLength) - { - this.base = pBase; - this.start = pStart; - this.length = pLength; - - return this; - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() - { - StringBuffer sb = new StringBuffer(); - - for (int i = this.start; i < (this.start + this.length); i++) - { - sb.append(this.base.charAt(i)); - } - - return sb.toString(); - } - - } - -}