blob: cf0e51db7be0740ea10659403958f29ac3fb7bcf [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}.
* </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 find regular expression pattern to match substrings with.
* @param link replacement link href. Capture groups within {@code find} can be referenced with
* {@code $<i>n</i>}.
*/
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);
}
return new SafeHtmlBuilder()
.openAnchor()
.setAttribute("href", href)
.append(SafeHtml.asis(input))
.closeAnchor()
.asString();
}
@Override
public String toString() {
return "find = " + pat.getSource() + ", link = " + link;
}
}