diff --git a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java
index 23d87a8a..b171dac2 100644
--- a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java
+++ b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java
@@ -80,7 +80,7 @@ public class Application {
new DocumentApi(config).bindPath("/api/document").on(server);
new UserLegacy(config).bindPath("/legacy/user").on(server);
new NotesLegacy(config).bindPath("/legacy/notes").on(server);
- new MarkdownApi().bindPath("/api/markdown").on(server);
+ new MarkdownApi(config).bindPath("/api/markdown").on(server);
new NoteModule(config).bindPath("/api/notes").on(server);
new StockModule(config).bindPath("/api/stock").on(server);
new PollModule(config).bindPath("/api/poll").on(server);
diff --git a/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java b/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java
index c71b9c32..8a94feca 100644
--- a/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java
+++ b/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java
@@ -3,21 +3,34 @@ package de.srsoftware.umbrella.markdown;
import static de.srsoftware.tools.MimeType.MIME_HTML;
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
+import static de.srsoftware.umbrella.core.constants.Field.BASE_URL;
+import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingField;
import com.sun.net.httpserver.HttpExchange;
+import de.srsoftware.configuration.Configuration;
import de.srsoftware.tools.Path;
import de.srsoftware.umbrella.core.BaseHandler;
import de.srsoftware.umbrella.core.ModuleRegistry;
import de.srsoftware.umbrella.core.Util;
import de.srsoftware.umbrella.core.api.MarkdownService;
+import de.srsoftware.umbrella.core.constants.Field;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.io.IOException;
+import java.util.Optional;
+import java.util.regex.Pattern;
public class MarkdownApi extends BaseHandler implements MarkdownService {
+ private static Pattern ANCHOR = Pattern.compile("(?is)]*>.*?");
+ private static Pattern HREF = Pattern.compile("(?i)\\bhref\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))");
+ private static Pattern TARGET = Pattern.compile("(?i)\\btarget\\s*=");
+ private final String baseUrl;
- public MarkdownApi() {
+ public MarkdownApi(Configuration config) {
super();
+ Optional baseUrl = config.get(BASE_URL);
+ if (baseUrl.isEmpty()) throw missingField(BASE_URL);
+ this.baseUrl = baseUrl.get();
ModuleRegistry.add(this);
}
@@ -29,6 +42,24 @@ public class MarkdownApi extends BaseHandler implements MarkdownService {
if (user.isEmpty()) throw UmbrellaException.forbidden("You must be logged in to use the markdown renderer!");
var rendered = Util.markdown(body(ex));
+ var anchors = ANCHOR.matcher(rendered);
+ while (anchors.find()){
+ String anchor = anchors.group();
+ var urls = HREF.matcher(anchor);
+ if (!urls.find()) continue; // no url → nothing to do
+
+ var href = urls.group(1) != null ? urls.group(1) : (urls.group(2) != null ? urls.group(2) : urls.group(3));
+ var target = TARGET.matcher(anchor);
+ if (target.find()) continue; // target already set → leave untouched
+
+ if (!href.startsWith("http")) continue; // relative url? good!
+
+ if (!href.startsWith(baseUrl)) { // add target
+ var replacement = "