summaryrefslogtreecommitdiffstats
path: root/java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java')
-rw-r--r--java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java82
1 files changed, 82 insertions, 0 deletions
diff --git a/java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java b/java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java
new file mode 100644
index 0000000000..cf0e51db7b
--- /dev/null
+++ b/java/com/google/gwtexpui/safehtml/client/LinkFindReplace.java
@@ -0,0 +1,82 @@
+// 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;
+ }
+}