diff --git a/src/main/java/org/olat/commons/info/ui/_content/display.html b/src/main/java/org/olat/commons/info/ui/_content/display.html index 4d97378f596318334c054fb2b21b02657db3f565..48a59149058eb01c79f8ba3c4b356653ff4b40c6 100644 --- a/src/main/java/org/olat/commons/info/ui/_content/display.html +++ b/src/main/java/org/olat/commons/info/ui/_content/display.html @@ -25,7 +25,7 @@ <p class="o_item_info">$info.getInfos()#if($info.isModified()), <span class="o_item_info_mod">$info.getModifier()</span>#end</p> <p></p> #if($info.getMessage()) - <p>$info.getMessage()</p> + <p>$r.formatURLsAsLinks($info.getMessage())</p> #end </div> #end diff --git a/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java b/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java index d34891a9ccf2835f32e030b102526fb7a9b2ab42..4c5911ed0e3340e0a224e71f7f679d694159f9cb 100644 --- a/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java +++ b/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java @@ -595,6 +595,17 @@ public class VelocityRenderDecorator { return Formatter.formatLatexFormulas(htmlFragment); } + /** + * Search in given text fragment for URL's and surround them with clickable + * HTML link objects. + * + * @param textFragment + * @return text with clickable links + */ + public static String formatURLsAsLinks(String textFragment) { + return Formatter.formatURLsAsLinks(textFragment); + } + /** * Strips all HTML tags from the source string. * diff --git a/src/main/java/org/olat/core/util/Formatter.java b/src/main/java/org/olat/core/util/Formatter.java index d7846d37f69bc5aed9b690ce83a6fa1aad341ee4..88313599e71fd0f1fe7314717a63f0242ecdb0ad 100644 --- a/src/main/java/org/olat/core/util/Formatter.java +++ b/src/main/java/org/olat/core/util/Formatter.java @@ -35,9 +35,12 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.commons.lang.StringEscapeUtils; import org.olat.core.commons.chiefcontrollers.BaseChiefController; +import org.olat.core.helpers.Settings; import org.olat.core.logging.LogDelegator; /** @@ -515,6 +518,55 @@ public class Formatter extends LogDelegator { return htmlFragment; } + + // Pattern to find URL's in text + private static final Pattern urlPattern = Pattern.compile("((http[s]*://|www\\.)[-A-Za-z0-9+&@#/%?=~_|!:,\\.;]+[-A-Za-z0-9+&@#/%=~_|]*)"); + + /** + * Search in given text fragment for URL's and surround them with clickable + * HTML link objects. + * + * @param textFragment + * @return text with clickable links + */ + public static String formatURLsAsLinks(String textFragment) { + Matcher matcher = urlPattern.matcher(textFragment); + + StringBuffer sb = new StringBuffer(); + int pos = 0; + while (matcher.find()) { + // Add text since last match and set end of current patch as new end + // of this match + sb.append(textFragment.substring(pos, matcher.start())); + pos = matcher.end(); + // The URL is in group1, the other groups are ignored + String url = matcher.group(1); + // Fix URL's without protocol, assume http + if (!url.startsWith("http")) { + url = "http://" + url; + } + // Fix URL's at end of a sentence + if (url.endsWith(",") || url.endsWith(".")) { + url = url.substring(0, url.length()-1); + pos--; + } + sb.append("<a href=\""); + sb.append(url); + sb.append("\""); + // OpenOLAT URL's are opened in same window, all other URL's in separate window + if (!url.startsWith(Settings.getServerContextPathURI())) { + sb.append(" target=\"_blank\" class=\"b_link_extern\""); + } + sb.append(">"); + sb.append(url); + sb.append("</a>"); + } + // Add rest of text + sb.append(textFragment.substring(pos)); + // + return sb.toString(); + } + /** * Round a double value to a double value with given number of * figures after comma