Java tutorial
/* * Copyright 2010 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.template.soy.parsepasses.contextautoesc; import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableMap; import com.google.template.soy.data.SanitizedContent.ContentKind; import java.util.Map; import javax.annotation.Nullable; /** * Ways of escaping dynamic content in a template. * */ public enum EscapingMode { /** Encodes HTML special characters. */ ESCAPE_HTML(true, ContentKind.HTML), /** Escapes HTML except preserves ampersands and entities. */ NORMALIZE_HTML(true, null), /** Like {@link #ESCAPE_HTML} but normalizes known safe HTML since RCDATA can't contain tags. */ ESCAPE_HTML_RCDATA(true, null), /** * Encodes HTML special characters, including quotes, so that the value can appear as part of a * quoted attribute value. * This differs from {@link #ESCAPE_HTML} in that it strips tags from known safe HTML. */ ESCAPE_HTML_ATTRIBUTE(true, null), /** * Encodes HTML special characters and spaces so that the value can appear as part of an unquoted * attribute. */ ESCAPE_HTML_ATTRIBUTE_NOSPACE(true, null), /** * Only allow a valid identifier - letters, numbers, dashes, and underscores. * Throw a runtime exception otherwise. */ FILTER_HTML_ELEMENT_NAME(true, null), /** * Only allow a valid identifier - letters, numbers, dashes, and underscores * or a subset of attribute value pairs. * Throw a runtime exception otherwise. */ FILTER_HTML_ATTRIBUTES(true, null), /** * Encode all HTML special characters and quotes, and JS newlines as if to allow them to appear * literally in a JS string. */ ESCAPE_JS_STRING(false, null), /** * If a number or boolean, output as a JS literal. Otherwise surround in quotes and escape. * Make sure all HTML and space characters are quoted. */ ESCAPE_JS_VALUE(false, null), /** * Like {@link #ESCAPE_JS_STRING} but additionally escapes RegExp specials like * <code>.+*?$^[](){}</code>. */ ESCAPE_JS_REGEX(false, null), /** * Must escape all quotes, newlines, and the close parenthesis using {@code \} followed by hex * followed by a space. */ ESCAPE_CSS_STRING(true, null), /** * If the value is numeric, renders it as a numeric value so that <code>{$n}px</code> works as * expected, otherwise if it is a valid CSS identifier, outputs it without escaping, otherwise * replaces with "zSoyz" to indicate the value was rejected. */ FILTER_CSS_VALUE(false, ContentKind.CSS), /** * Percent encode all URI special characters and characters that cannot appear unescaped in a URI * such as spaces. Make sure to encode pluses and parentheses. * This corresponds to the JavaScript function {@code encodeURIComponent}. */ ESCAPE_URI(true, ContentKind.URI), /** * Percent encode non-URI characters that cannot appear unescaped in a URI such as spaces, and * encode characters that are not special in URIs that are special in languages that URIs are * embedded in such as parentheses and quotes. * * This corresponds to the JavaScript function {@code encodeURI} but additionally encodes quotes * parentheses, and percent signs that are not followed by two hex digits. * * This is not necessarily HTML embeddable because we want ampersands to get HTML-escaped. */ NORMALIZE_URI(false, ContentKind.URI), /** * Like {@link #NORMALIZE_URI}, but filters out schemes like {@code javascript:} that load code. */ FILTER_NORMALIZE_URI(false, ContentKind.URI), /** * The explicit rejection of escaping. */ NO_AUTOESCAPE(false, ContentKind.TEXT), /** * Outputs plain text and performs no escaping. Unlike noAutoescape, this will not fail if passed * SanitizedContent of kind TEXT, but this may never be used manually by the developer. This has * no escaping. */ TEXT(false, ContentKind.TEXT, true /* internal-only */); /** The Soy <code>{print}</code> directive that specifies this escaping mode. */ public final String directiveName; /** True iff the output does not contain quotes so can be embedded in HTML attribute values. */ public final boolean isHtmlEmbeddable; /** The kind of content produced by the escaping directive associated with this escaping mode. */ public final @Nullable ContentKind contentKind; /** Whether this directive is only for internal use by the contextual autoescaper. */ public final boolean isInternalOnly; EscapingMode(boolean escapesQuotes, @Nullable ContentKind contentKind, boolean internalOnly) { this.directiveName = "|" + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); this.isHtmlEmbeddable = escapesQuotes; this.contentKind = contentKind; this.isInternalOnly = internalOnly; } EscapingMode(boolean escapesQuotes, @Nullable ContentKind contentKind) { this(escapesQuotes, contentKind, false /* internal-only */); } /** * The escaping mode corresponding to the given directive or null. */ public static @Nullable EscapingMode fromDirective(String directiveName) { return DIRECTIVE_TO_ESCAPING_MODE.get(directiveName); } private static final Map<String, EscapingMode> DIRECTIVE_TO_ESCAPING_MODE; static { ImmutableMap.Builder<String, EscapingMode> builder = ImmutableMap.builder(); for (EscapingMode mode : EscapingMode.values()) { builder.put(mode.directiveName, mode); } DIRECTIVE_TO_ESCAPING_MODE = builder.build(); } }