blob: eaa4f23030634c87f6df11ff6f9b7b9ef7217779 [file] [log] [blame]
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.regexp.shared.RegExp;
/**
* A Find/Replace pair whose replacement string is a link.
* <p>
* It is safe to pass arbitrary user-provided links to this class. Links are
* sanitized as follows:
* <ul>
* <li>Only http(s) and mailto links are supported; any other scheme results in
* an {@link IllegalArgumentException} from {@link #replace(String)}.
* <li>Special characters in the link after regex replacement are escaped with
* {@link SafeHtmlBuilder}.</li>
* </ul>
*/
public class LinkFindReplace implements FindReplace {
public static boolean hasValidScheme(String link) {
int colon = link.indexOf(':');
if (colon < 0) {
return true;
}
String scheme = link.substring(0, colon);
return "http".equalsIgnoreCase(scheme)
|| "https".equalsIgnoreCase(scheme)
|| "mailto".equalsIgnoreCase(scheme);
}
private RegExp pat;
private String link;
protected LinkFindReplace() {
}
/**
* @param regex regular expression pattern to match substrings with.
* @param repl replacement link href. Capture groups within
* <code>regex</code> can be referenced with <code>$<i>n</i></code>.
*/
public LinkFindReplace(String find, String link) {
this.pat = RegExp.compile(find);
this.link = link;
}
@Override
public RegExp pattern() {
return pat;
}
@Override
public String replace(String input) {
String href = pat.replace(input, link);
if (!hasValidScheme(href)) {
throw new IllegalArgumentException(
"Invalid scheme (" + toString() + "): " + href);
}
String result = new SafeHtmlBuilder()
.openAnchor()
.setAttribute("href", href)
.append(SafeHtml.asis(input))
.closeAnchor()
.asString();
return result;
}
@Override
public String toString() {
return "find = " + pat.getSource() + ", link = " + link;
}
}