diff --git a/Clover/app/src/main/AndroidManifest.xml b/Clover/app/src/main/AndroidManifest.xml index d3e9e81e..f8d3ed0b 100644 --- a/Clover/app/src/main/AndroidManifest.xml +++ b/Clover/app/src/main/AndroidManifest.xml @@ -77,6 +77,8 @@ along with this program. If not, see . + + diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/PostLinkable.java b/Clover/app/src/main/java/org/floens/chan/core/model/PostLinkable.java index ea93d1ce..ee3df216 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/model/PostLinkable.java +++ b/Clover/app/src/main/java/org/floens/chan/core/model/PostLinkable.java @@ -31,6 +31,7 @@ import org.floens.chan.ui.theme.Theme; * PostCell has a {@link PostCell.PostViewMovementMethod}, that searches spans at the location the TextView was tapped, * and handled if it was a PostLinkable. */ +@SuppressWarnings("JavadocReference") public class PostLinkable extends ClickableSpan { public enum Type { QUOTE, LINK, SPOILER, THREAD diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/parser/CommentParser.java b/Clover/app/src/main/java/org/floens/chan/core/site/parser/CommentParser.java index 25e0d35a..70b3cab4 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/parser/CommentParser.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/parser/CommentParser.java @@ -53,6 +53,7 @@ public class CommentParser { private Pattern colorPattern = Pattern.compile("color:#([0-9a-fA-F]+)"); private Map> rules = new HashMap<>(); + private List internalDomains = new ArrayList<>(0); public CommentParser() { // Required tags. @@ -101,6 +102,10 @@ public class CommentParser { this.fullQuotePattern = fullQuotePattern; } + public void addInternalDomain(String domain) { + this.internalDomains.add(domain); + } + public CharSequence handleTag(PostParser.Callback callback, Theme theme, Post.Builder post, @@ -233,11 +238,29 @@ public class CommentParser { public Link matchAnchor(Post.Builder post, CharSequence text, Element anchor, PostParser.Callback callback) { String href = anchor.attr("href"); + // For inner links we handle it as relative (for sites that have multiple domains). + String path = ""; + if (href.startsWith("//") || href.startsWith("http://") || href.startsWith("https://")) { + int offset = href.startsWith("//") ? 2 : (href.startsWith("http://") ? 7 : 8); + + String domain = href.substring(Math.min(href.length(), offset), + Math.min(href.length(), href.indexOf('/', offset))); + // Whitelisting domains is optional. + // If you don't specify it it will purely use the quote patterns to match. + if (internalDomains.isEmpty() || internalDomains.contains(domain)) { + int pathStart = href.indexOf('/', offset); + if (pathStart >= 0) { + path = href.substring(pathStart); + } + } + } else { + path = href; + } PostLinkable.Type t; Object value; - Matcher externalMatcher = fullQuotePattern.matcher(href); + Matcher externalMatcher = fullQuotePattern.matcher(path); if (externalMatcher.matches()) { String board = externalMatcher.group(1); int threadId = Integer.parseInt(externalMatcher.group(2)); @@ -251,12 +274,12 @@ public class CommentParser { value = new PostLinkable.ThreadLink(board, threadId, postId); } } else { - Matcher quoteMatcher = quotePattern.matcher(href); + Matcher quoteMatcher = quotePattern.matcher(path); if (quoteMatcher.matches()) { t = PostLinkable.Type.QUOTE; value = Integer.parseInt(quoteMatcher.group(1)); } else { - // normal link + // normal link, use original href t = PostLinkable.Type.LINK; value = href; } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java index fc4a3ed3..5d161d02 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java @@ -40,6 +40,7 @@ import org.floens.chan.core.site.SiteRequestModifier; import org.floens.chan.core.site.SiteSetting; import org.floens.chan.core.site.SiteUrlHandler; import org.floens.chan.core.site.common.CommonReplyHttpCall; +import org.floens.chan.core.site.common.DefaultPostParser; import org.floens.chan.core.site.common.FutabaChanReader; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.HttpCall; @@ -47,6 +48,7 @@ import org.floens.chan.core.site.http.LoginRequest; import org.floens.chan.core.site.http.LoginResponse; import org.floens.chan.core.site.http.Reply; import org.floens.chan.core.site.parser.ChanReader; +import org.floens.chan.core.site.parser.CommentParser; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.Logger; @@ -77,7 +79,9 @@ public class Chan4 extends SiteBase { public boolean respondsTo(HttpUrl url) { return url.host().equals("4chan.org") || url.host().equals("www.4chan.org") || - url.host().equals("boards.4chan.org"); + url.host().equals("boards.4chan.org") || + url.host().equals("www.4channel.org") || + url.host().equals("boards.4channel.org"); } @Override @@ -562,7 +566,15 @@ public class Chan4 extends SiteBase { @Override public ChanReader chanReader() { - return new FutabaChanReader(); + CommentParser commentParser = new CommentParser(); + commentParser.addDefaultRules(); + commentParser.addInternalDomain("4chan.org"); + commentParser.addInternalDomain("www.4chan.org"); + commentParser.addInternalDomain("boards.4chan.org"); + commentParser.addInternalDomain("4channel.org"); + commentParser.addInternalDomain("www.4channel.org"); + commentParser.addInternalDomain("boards.4channel.org"); + return new FutabaChanReader(new DefaultPostParser(commentParser)); } @Override