/*
 * 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;
    }
  }
}
