1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.clearsilver.jsilver.autoescape; 18 19 import com.google.clearsilver.jsilver.exceptions.JSilverAutoEscapingException; 20 21 public enum EscapeMode { 22 ESCAPE_NONE("none", false), ESCAPE_HTML("html", false), ESCAPE_JS("js", false), ESCAPE_URL("url", 23 false), ESCAPE_IS_CONSTANT("constant", false), 24 25 // These modes are used as starting modes, and a parser parses the 26 // subsequent template contents to determine the right escaping command to use. 27 ESCAPE_AUTO("auto", true), // Identical to ESCAPE_AUTO_HTML 28 ESCAPE_AUTO_HTML("auto_html", true), ESCAPE_AUTO_JS("auto_js", true), ESCAPE_AUTO_JS_UNQUOTED( 29 "auto_js_unquoted", true), ESCAPE_AUTO_STYLE("auto_style", true), ESCAPE_AUTO_ATTR( 30 "auto_attr", true), ESCAPE_AUTO_UNQUOTED_ATTR("auto_attr_unquoted", true), ESCAPE_AUTO_ATTR_URI( 31 "auto_attr_uri", true), ESCAPE_AUTO_UNQUOTED_ATTR_URI("auto_attr_uri_unquoted", true), ESCAPE_AUTO_ATTR_URI_START( 32 "auto_attr_uri_start", true), ESCAPE_AUTO_UNQUOTED_ATTR_URI_START( 33 "auto_attr_uri_start_unquoted", true), ESCAPE_AUTO_ATTR_JS("auto_attr_js", true), ESCAPE_AUTO_ATTR_UNQUOTED_JS( 34 "auto_attr_unquoted_js", true), ESCAPE_AUTO_UNQUOTED_ATTR_JS("auto_attr_js_unquoted", true), ESCAPE_AUTO_UNQUOTED_ATTR_UNQUOTED_JS( 35 "auto_attr_js_unquoted_js", true), ESCAPE_AUTO_ATTR_CSS("auto_attr_style", true), ESCAPE_AUTO_UNQUOTED_ATTR_CSS( 36 "auto_attr_style_unquoted", true); 37 38 private String escapeCmd; 39 private boolean autoEscaper; 40 EscapeMode(String escapeCmd, boolean autoEscaper)41 private EscapeMode(String escapeCmd, boolean autoEscaper) { 42 this.escapeCmd = escapeCmd; 43 this.autoEscaper = autoEscaper; 44 } 45 46 /** 47 * This function maps the type of escaping requested (escapeCmd) to the appropriate EscapeMode. If 48 * no explicit escaping is requested, but doAutoEscape is true, the function chooses auto escaping 49 * (EscapeMode.ESCAPE_AUTO). This mirrors the behaviour of ClearSilver. 50 * 51 * @param escapeCmd A string indicating type of escaping requested. 52 * @param doAutoEscape Whether auto escaping should be applied if escapeCmd is null. Corresponds 53 * to the Config.AutoEscape HDF variable. 54 * @return 55 */ computeEscapeMode(String escapeCmd, boolean doAutoEscape)56 public static EscapeMode computeEscapeMode(String escapeCmd, boolean doAutoEscape) { 57 EscapeMode escapeMode; 58 59 // If defined, the explicit escaping mode (configured using "Config.VarEscapeMode") 60 // takes preference over auto escaping 61 if (escapeCmd != null) { 62 for (EscapeMode e : EscapeMode.values()) { 63 if (e.escapeCmd.equals(escapeCmd)) { 64 return e; 65 } 66 } 67 throw new JSilverAutoEscapingException("Invalid escaping mode specified: " + escapeCmd); 68 69 } else { 70 if (doAutoEscape) { 71 escapeMode = ESCAPE_AUTO; 72 } else { 73 escapeMode = ESCAPE_NONE; 74 } 75 return escapeMode; 76 } 77 } 78 79 /** 80 * Calls {@link #computeEscapeMode(String, boolean)} with {@code doAutoEscape = false}. 81 * 82 * @param escapeCmd A string indicating type of escaping requested. 83 * @return EscapeMode 84 * @throws JSilverAutoEscapingException if {@code escapeCmd} is not recognized. 85 */ computeEscapeMode(String escapeCmd)86 public static EscapeMode computeEscapeMode(String escapeCmd) { 87 return computeEscapeMode(escapeCmd, false); 88 } 89 90 /** 91 * Computes the EscapeMode of the result of concatenating two values. The EscapeModes of the two 92 * values are provided by {@code left} and {@code right} respectively. For now, if either of the 93 * values was escaped or a constant, we return {@code ESCAPE_IS_CONSTANT}. This is how ClearSilver 94 * behaves. 95 * 96 * @return {@code ESCAPE_NONE} if either of the values was not escaped or constant. {@code 97 * ESCAPE_IS_CONSTANT} otherwise. 98 */ combineModes(EscapeMode left, EscapeMode right)99 public static EscapeMode combineModes(EscapeMode left, EscapeMode right) { 100 if (left.equals(ESCAPE_NONE) || right.equals(ESCAPE_NONE)) { 101 // If either of the values has not been escaped, 102 // do not trust the result. 103 return ESCAPE_NONE; 104 } else { 105 // For now, indicate that this result is always safe in all contexts. 106 // This is what ClearSilver does. We may introduce a stricter autoescape 107 // rule later on which also requires that the escaping be the same as the 108 // context its used in. 109 return ESCAPE_IS_CONSTANT; 110 } 111 } 112 isAutoEscapingMode()113 public boolean isAutoEscapingMode() { 114 return autoEscaper; 115 } 116 117 // TODO: Simplify enum names, and just use toString() instead. getEscapeCommand()118 public String getEscapeCommand() { 119 return escapeCmd; 120 } 121 } 122