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