Mercurial Hosting > nabble
view src/nabble/model/MessageFormatImpls.java @ 47:72765b66e2c3
remove mailing list code
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 18 Jun 2021 17:44:24 -0600 |
parents | 7ecd1a4ef557 |
children |
line wrap: on
line source
package nabble.model; import fschmidt.html.Html; import fschmidt.html.HtmlTag; import fschmidt.html.HtmlTextContainer; import fschmidt.util.java.HtmlUtils; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; final class MessageFormatImpls { private MessageFormatImpls() {} // never private static final Pattern urlPtn = Pattern.compile( "\\bhttps?://[^\\s\\p{Z}<>\"{}|\\\\^\\[\\]`]*[^\\s\\p{Z}<>\"{}|\\\\^\\[\\]`~,.?\\)]" ); private static abstract class InputFormat extends Message.Format { InputFormat(char code,String name) { super(code,name); } protected final String getText(String msg, Message.Source source) { return MessageUtils.htmlToText(MessageUtils.newHtml(msg)); } protected final String getTextWithoutQuotes(String msg, Message.Source source) { return MessageUtils.getTextWithoutQuotes(msg); } protected final String getEmail(String msg,int i) { Html list = MessageUtils.newHtml(msg); return MessageFormatImpls.getEmail(list,i); } } static final Message.Format TEXT = new InputFormat('t',"text") { protected Html parse(String msg,Message.Source source) { Html html = MessageUtils.newHtml(msg); nestIgnoredBlocks(html); encodeUnallowedTags(html); convertLinks(html); textToHtml(html); unnestIgnoredBlocks(html); return html; } protected Html parseForMailText(String msg,Message.Source source) { Html html = MessageUtils.newHtml(msg); changeUnallowedTagsToStrings(html); return html; } }; static void convertLinks(Html list) { boolean convertLinks = true; for( ListIterator<Object> i=list.listIterator(); i.hasNext(); ) { Object o = i.next(); if( o instanceof HtmlTag ) { HtmlTag tag = (HtmlTag)o; String name = tag.getName().toLowerCase(); if( name.equals("a") || name.equals("nabble_a") ) { convertLinks = false; } else if( name.equals("/a") || name.equals("/nabble_a") ) { convertLinks = true; } } else if( convertLinks && o instanceof String ) { String s = (String)o; i.remove(); for( Object o2 : convertLinks(s) ) { i.add(o2); } } } } static Html convertLinks(String s) { Html list = new Html(); Matcher m = urlPtn.matcher(s); int i = 0; while( m.find() ) { String s2 = s.substring(i,m.start()); if( s2.length() > 0 ) list.add(s2); String url = m.group(); HtmlTag tag = new HtmlTag("a"); tag.setAttribute("href",HtmlTag.quote(url)); list.add(tag); list.add(url); list.add(_a); i = m.end(); } String s2 = s.substring(i); if( s2.length() > 0 ) list.add(s2); return list; } private static final Set<String> asBlock = new HashSet<String>(Arrays.asList( "table", "/table", "thead", "/thead", "tbody", "/tbody", "tr", "/tr", "th", "/th", "td", "/td" )); static void textToHtml(Html list) { boolean isBlock = false; int n = list.size(); for( int i=0; i<n; i++ ) { Object o = list.get(i); if( o instanceof String ) { String s = (String)o; Html l = textToHtml(s,isBlock); list.remove(i); list.addAll(i,l); int d = l.size() - 1; i += d; n += d; } isBlock = false; if( o instanceof HtmlTag ) { HtmlTag tag = (HtmlTag)o; String name = tag.getName().toLowerCase(); if( name.charAt(0) == '/' && Message.htmlSeparators.get(name) == "\n" || asBlock.contains(name) ) { isBlock = true; } } else if( o instanceof HtmlTextContainer ) { isBlock = true; // } else if( o instanceof Html ) { // isBlock = true; } } } private static final HtmlTag br = new HtmlTag("br/"); private static Html textToHtml(String s,boolean isAfterBlock) { s = encodeHtml(s); Html list = new Html(); StringBuilder buf = new StringBuilder(); final char[] a = s.toCharArray(); boolean isLineStart = true; for (char c : a) { switch (c) { case '\r': buf.append( c ); break; case '\n': buf.append( c ); String t = buf.toString(); if( t.trim().length() > 0 ) list.add(t); if( isAfterBlock ) isAfterBlock = false; else list.add( br ); isLineStart = true; buf.setLength(0); break; case '\t': if( isLineStart ) { buf.append( " " ); } else { buf.append( '\t' ); } break; case ' ': if( isLineStart ) { buf.append( " " ); isLineStart = false; } else if( buf.charAt(buf.length()-1)==' ' ) { buf.append( " " ); } else { buf.append( ' ' ); } break; default: buf.append( c ); isLineStart = false; isAfterBlock = false; } } if( buf.length() > 0 ) list.add( buf.toString() ); return list; } static final Message.Format HTML = new InputFormat('h',"html") { protected Html parse(String msg,Message.Source source) { return MessageUtils.newHtml(msg); } protected Html parseForMailText(String msg,Message.Source source) { return MessageUtils.newHtml(msg); } }; private static final HtmlTag _a = new HtmlTag("/a"); static String getEmail(Html list,int iEmail) { int count = 0; int n = list.size() - 3 + 1; for( int i=0; i<n; i++ ) { Object o = list.get(i); if( !(o instanceof HtmlTag) ) continue; HtmlTag tag = (HtmlTag)o; if( !tag.getName().toLowerCase().equals("email") ) continue; o = list.get(i+1); if( !(o instanceof String) ) continue; String email = (String)o; o = list.get(i+2); if( !(o instanceof HtmlTag) ) continue; HtmlTag endTag = (HtmlTag)o; if( !endTag.getName().toLowerCase().equals("/email") ) continue; if( count++ == iEmail ) return email; i += 2; } return null; } static String encodeHtml(String s) { char[] a = s.toCharArray(); StringBuilder buf = new StringBuilder(); for( int i=0; i<a.length; i++ ) { char c = a[i]; switch(c) { /* case '&': buf.append("&"); break; */ case '<': buf.append("<"); break; case '>': buf.append(">"); break; case '"': buf.append("""); break; default: buf.append(c); } } return buf.toString(); } private static final List<String> ignoredTags = Arrays.asList( "nabble_embed" ); private static void nestIgnoredBlocks(Html html) { outer: for( String tagName : ignoredTags ) { String endTagName = "/" + tagName; for( ListIterator<Object> i=html.listIterator(); i.hasNext(); ) { Object obj = i.next(); if( obj instanceof HtmlTag ) { HtmlTag tag = (HtmlTag)obj; if( tag.getName().equalsIgnoreCase(tagName) ) { Html block = new Html(); i.remove(); block.add(obj); while(true) { if( !i.hasNext() ) { // unclosed i.add(HtmlUtils.htmlEncode(block.toString())); continue outer; } obj = i.next(); i.remove(); block.add(obj); if( obj instanceof HtmlTag ) { tag = (HtmlTag)obj; if( tag.getName().equalsIgnoreCase(endTagName) ) { i.add(block); break; } } } } } } } } private static void unnestIgnoredBlocks(Html html) { for( ListIterator<Object> i=html.listIterator(); i.hasNext(); ) { Object obj = i.next(); if( obj instanceof Html ) { Html block = (Html)obj; i.remove(); for( Object obj2 : block ) { i.add(obj2); } } } } private static final Set<String> allowedTextTags = new HashSet<String>(); static { for( String tag : new String[]{ "b", "i", "quote", "email", "img", "a", "font", "span", "smiley", "nabble_img", "nabble_a", "object", "param", "embed", "raw", "nabble_embed", "h1", "h2", "h3", "h4", "h5", "h6", "table", "thead", "tbody", "tr", "th", "td", } ) { allowedTextTags.add(tag); allowedTextTags.add("/"+tag); } } private static void encodeUnallowedTags(Html html) { for( ListIterator<Object> i=html.listIterator(); i.hasNext(); ) { Object obj = i.next(); if( obj instanceof HtmlTag ) { HtmlTag tag = (HtmlTag)obj; if( !allowedTextTags.contains( tag.getName().toLowerCase() ) ) { i.remove(); i.add( HtmlUtils.htmlEncode(tag.toString()) ); } } } } private static void changeUnallowedTagsToStrings(Html html) { for( ListIterator<Object> i=html.listIterator(); i.hasNext(); ) { Object obj = i.next(); if( obj instanceof HtmlTag ) { HtmlTag tag = (HtmlTag)obj; if( !allowedTextTags.contains( tag.getName().toLowerCase() ) ) { i.remove(); i.add( tag.toString() ); } } } } }