| /* | |
| * Copyright 2011 Google Inc. | |
| * | |
| * 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.gwt.safehtml.shared; | |
| import com.google.gwt.core.client.GWT; | |
| import com.google.gwt.thirdparty.guava.common.base.Preconditions; | |
| import java.net.URI; | |
| import java.net.URISyntaxException; | |
| /** | |
| * SafeUri utilities whose implementation differs between Development and Production Mode. | |
| * | |
| * <p> | |
| * This class has a super-source peer that provides the Production Mode implementation. | |
| * | |
| * <p> | |
| * Do not use this class - it is used for implementation only, and its methods may change in the | |
| * future. | |
| */ | |
| public class SafeUriHostedModeUtils { | |
| /** | |
| * All valid Web Addresses discrete characters, i.e. the reserved, iunreserved, href-ucschar, and | |
| * href-pct-form productions from RFC 3986 and RFC 3987bis, with the exception of character | |
| * ranges. | |
| * | |
| * @see <a href="http://tools.ietf.org/html/rfc3986#section-2">RFC 3986</a> | |
| * @see <a href="http://tools.ietf.org/html/draft-ietf-iri-3987bis-05#section-7.2">RFC 3987bis Web Addresses</a> | |
| */ | |
| static final String HREF_DISCRETE_UCSCHAR = ":/?#[]@!$&'()*+,;=" // reserved | |
| + "-._~" // iunreserved | |
| + " <>\"{}|\\^`" // href-ucschar | |
| + "%"; // href-pct-form | |
| /** | |
| * Name of system property that if set, enables checks in server-side code (even if assertions are | |
| * disabled). | |
| */ | |
| public static final String FORCE_CHECK_VALID_URI = "com.google.gwt.safehtml.ForceCheckValidUri"; | |
| private static boolean forceCheckValidUri; | |
| static { | |
| setForceCheckValidUriFromProperty(); | |
| } | |
| /** | |
| * Tests whether all characters in the given URI are valid Web Addresses characters. | |
| */ | |
| // @VisibleForTesting | |
| public static boolean isValidUriCharset(String uri) { | |
| int len = uri.length(); | |
| int i = 0; | |
| while (i < len) { | |
| int codePoint = uri.codePointAt(i); | |
| i += Character.charCount(codePoint); | |
| if (Character.isSupplementaryCodePoint(codePoint)) { | |
| continue; | |
| } | |
| if (HREF_DISCRETE_UCSCHAR.indexOf(codePoint) >= 0) { | |
| continue; | |
| } | |
| // iunreserved ranges | |
| if (('a' <= codePoint && codePoint <= 'z') || ('A' <= codePoint && codePoint <= 'Z') | |
| || ('0' <= codePoint && codePoint <= '9')) { | |
| continue; | |
| } | |
| // href-ucschar ranges | |
| if ((0 <= codePoint && codePoint <= 0x1F) || (0x7F <= codePoint && codePoint <= 0xD7FF) | |
| || (0xE000 <= codePoint && codePoint <= 0xFFFD)) { | |
| continue; | |
| } | |
| return false; | |
| } | |
| return true; | |
| } | |
| /** | |
| * Checks if the provided URI is a valid Web Address (per RFC 3987bis). | |
| * | |
| * @param uri the URL to check | |
| */ | |
| public static void maybeCheckValidUri(String uri) { | |
| if (GWT.isClient() || forceCheckValidUri) { | |
| Preconditions.checkArgument(isValidUri(uri), "String is not a valid URI: %s", uri); | |
| } else { | |
| assert isValidUri(uri) : "String is not a valid URI: " + uri; | |
| } | |
| } | |
| /** | |
| * Sets a global flag that controls whether or not {@link #maybeCheckValidUri(String)} should | |
| * perform its check in a server-side environment. | |
| * | |
| * @param check if true, perform server-side checks. | |
| */ | |
| public static void setForceCheckValidUri(boolean check) { | |
| forceCheckValidUri = check; | |
| } | |
| /** | |
| * Sets a global flag that controls whether or not {@link #maybeCheckValidUri(String)} should | |
| * perform its check in a server-side environment from the value of the {@value | |
| * FORCE_CHECK_VALID_URI} property. | |
| */ | |
| // The following annotation causes javadoc to crash on Mac OS X 10.5.8, | |
| // using java 1.5.0_24. | |
| // | |
| // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6442982 | |
| // | |
| // @VisibleForTesting | |
| public static void setForceCheckValidUriFromProperty() { | |
| forceCheckValidUri = System.getProperty(FORCE_CHECK_VALID_URI) != null; | |
| } | |
| private static boolean isValidUri(String uri) { | |
| if (!isValidUriCharset(uri)) { | |
| return false; | |
| } | |
| // pre-process to turn href-ucschars into ucschars, and encode to URI. | |
| uri = UriUtils.encodeAllowEscapes(uri); | |
| try { | |
| new URI(uri); | |
| return true; | |
| } catch (URISyntaxException e) { | |
| return false; | |
| } | |
| } | |
| } |