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 = "