• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.functions.escape;
18 
19 import com.google.clearsilver.jsilver.functions.TextFilter;
20 
21 import java.io.IOException;
22 
23 /**
24  * This function will be used to sanitize variables in 'style' attributes. It strips out any
25  * characters that are not part of a whitelist of safe characters. This replicates the autoescaping
26  * behavior of Clearsilver.
27  *
28  * It does not extend SimpleEscapingFunction because SimpleEscapingFunction requires a blacklist of
29  * characters to escape. The StyleAttrEscapeFunction instead applies a whitelist, and strips out any
30  * characters not in the whitelist.
31  */
32 public class StyleEscapeFunction implements TextFilter {
33 
34   private static final boolean[] UNQUOTED_VALID_CHARS;
35   private static final boolean[] VALID_CHARS;
36   private static final int MAX_CHARS = 0x80;
37 
38   static {
39     // Allow characters likely to occur inside a style property value.
40     // Refer http://www.w3.org/TR/CSS21/ for more details.
41     String SPECIAL_CHARS = "_.,!#%- ";
42     String UNQUOTED_SPECIAL_CHARS = "_.,!#%-";
43 
44     VALID_CHARS = new boolean[MAX_CHARS];
45     UNQUOTED_VALID_CHARS = new boolean[MAX_CHARS];
46 
47     for (int n = 0; n < MAX_CHARS; n++) {
48       VALID_CHARS[n] = false;
49       UNQUOTED_VALID_CHARS[n] = false;
50 
51       if (Character.isLetterOrDigit(n)) {
52         VALID_CHARS[n] = true;
53         UNQUOTED_VALID_CHARS[n] = true;
54       } else {
55         if (SPECIAL_CHARS.indexOf(n) != -1) {
56           VALID_CHARS[n] = true;
57         }
58 
59         if (UNQUOTED_SPECIAL_CHARS.indexOf(n) != -1) {
60           UNQUOTED_VALID_CHARS[n] = true;
61         }
62       }
63     }
64   }
65 
66   private final boolean[] validChars;
67 
68   /**
69    * isUnquoted should be true if the function is escaping a string that will appear inside an
70    * unquoted style attribute.
71    *
72    */
StyleEscapeFunction(boolean isUnquoted)73   public StyleEscapeFunction(boolean isUnquoted) {
74     if (isUnquoted) {
75       validChars = UNQUOTED_VALID_CHARS;
76     } else {
77       validChars = VALID_CHARS;
78     }
79   }
80 
filter(String in, Appendable out)81   public void filter(String in, Appendable out) throws IOException {
82     for (char c : in.toCharArray()) {
83       if (c < MAX_CHARS && validChars[c]) {
84         out.append(c);
85       } else if (c >= MAX_CHARS) {
86         out.append(c);
87       }
88     }
89   }
90 
dumpInfo()91   public void dumpInfo() {
92     for (int i = 0; i < MAX_CHARS; i++) {
93       System.out.println(i + "(" + (char) i + ")" + " :" + VALID_CHARS[i]);
94     }
95   }
96 }
97