Index: kernel-impl/src/main/java/org/sakaiproject/util/impl/FormattedTextImpl.java =================================================================== --- kernel-impl/src/main/java/org/sakaiproject/util/impl/FormattedTextImpl.java (revision 127810) +++ kernel-impl/src/main/java/org/sakaiproject/util/impl/FormattedTextImpl.java (working copy) @@ -34,6 +34,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.validator.UrlValidator; import org.w3c.dom.Element; import org.owasp.validator.html.AntiSamy; @@ -1330,6 +1331,32 @@ } } + /* (non-Javadoc) + * @see org.sakaiproject.util.api.FormattedText#validateURL(java.lang.String) + */ + public boolean validateURL(String urlToValidate) { + if (StringUtils.isBlank(urlToValidate)) return false; + + // For a protocol-relative URL, we validate with protocol attached + // RFC 1808 Section 4 + if ((urlToValidate.startsWith("//")) && (urlToValidate.indexOf("://") == -1)) + { + urlToValidate = "http:" + urlToValidate; + } + + // For a site-relative URL, we validate with host name and protocol attached + // SAK-13787 SAK-23752 + if ((urlToValidate.startsWith("/")) && (urlToValidate.indexOf("://") == -1)) + { + urlToValidate = "http://127.0.0.1:8080" + urlToValidate; + } + + // Validate the url + UrlValidator urlValidator = new UrlValidator(); + return urlValidator.isValid(urlToValidate); + } + + // PRIVATE STUFF /** Index: kernel-impl/pom.xml =================================================================== --- kernel-impl/pom.xml (revision 127810) +++ kernel-impl/pom.xml (working copy) @@ -118,6 +118,11 @@ commons-lang + commons-validator + commons-validator + 1.3.1 + + net.sf.opencsv opencsv Index: api/src/main/java/org/sakaiproject/util/api/MockFormattedText.java =================================================================== --- api/src/main/java/org/sakaiproject/util/api/MockFormattedText.java (revision 127810) +++ api/src/main/java/org/sakaiproject/util/api/MockFormattedText.java (working copy) @@ -172,4 +172,9 @@ return value; } + public boolean validateURL(String urlToValidate) { + log.warn(WARNING); + return false; + } + } Index: api/src/main/java/org/sakaiproject/util/api/FormattedText.java =================================================================== --- api/src/main/java/org/sakaiproject/util/api/FormattedText.java (revision 127810) +++ api/src/main/java/org/sakaiproject/util/api/FormattedText.java (working copy) @@ -296,7 +296,7 @@ * previous form. * * @param value - * @return + * @return converted text */ public String convertOldFormattedText(String value); @@ -356,4 +356,15 @@ */ public String escapeUrl(String value); + /** + * General utility to validate a URL. + * The idea is to encode the rules we have for URLs we are willing + * to put in src="URL" or href="URL" places within our code, + * relative URLs must start with "/" + * + * @param urlToValidate a URL that might be placed in Sakai content + * @return true if the URL is valid OR false if it fails the tests + */ + public boolean validateURL(String urlToValidate); + } \ No newline at end of file Index: kernel-util/src/main/java/org/sakaiproject/util/FormattedText.java =================================================================== --- kernel-util/src/main/java/org/sakaiproject/util/FormattedText.java (revision 127810) +++ kernel-util/src/main/java/org/sakaiproject/util/FormattedText.java (working copy) @@ -161,4 +161,11 @@ return getFormattedText().decodeNumericCharacterReferences(value); } + /** + * @see org.sakaiproject.util.api.FormattedText#validateURL(String) + */ + public static boolean validateURL(String urlToValidate) { + return getFormattedText().validateURL(urlToValidate); + } + } \ No newline at end of file