1 // Copyright (c) 2013, Mike Samuel 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 8 // Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // Neither the name of the OWASP nor the names of its contributors may 14 // be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 // COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 // POSSIBILITY OF SUCH DAMAGE. 28 29 package org.owasp.html; 30 31 import java.util.Map; 32 import java.util.Set; 33 import java.util.SortedSet; 34 35 import javax.annotation.Nullable; 36 37 import com.google.common.collect.ImmutableMap; 38 import com.google.common.collect.ImmutableSet; 39 import com.google.common.collect.Maps; 40 import com.google.common.collect.Sets; 41 42 /** Describes the kinds of tokens a CSS property's value can safely contain. */ 43 @TCB 44 public final class CssSchema { 45 46 static final class Property { 47 /** A bitfield of BIT_* constants describing groups of allowed tokens. */ 48 final int bits; 49 /** Specific allowed values. */ 50 final ImmutableSet<String> literals; 51 /** 52 * Maps lower-case function tokens to the schema key for their parameters. 53 */ 54 final ImmutableMap<String, String> fnKeys; 55 Property( int bits, ImmutableSet<String> literals, ImmutableMap<String, String> fnKeys)56 private Property( 57 int bits, ImmutableSet<String> literals, 58 ImmutableMap<String, String> fnKeys) { 59 this.bits = bits; 60 this.literals = literals; 61 this.fnKeys = fnKeys; 62 } 63 } 64 65 static final int BIT_QUANTITY = 1; 66 static final int BIT_HASH_VALUE = 2; 67 static final int BIT_NEGATIVE = 4; 68 static final int BIT_STRING = 8; 69 static final int BIT_URL = 16; 70 static final int BIT_UNRESERVED_WORD = 64; 71 static final int BIT_UNICODE_RANGE = 128; 72 73 static final Property DISALLOWED = new Property( 74 0, ImmutableSet.<String>of(), ImmutableMap.<String, String>of()); 75 76 private final ImmutableMap<String, Property> properties; 77 CssSchema(ImmutableMap<String, Property> properties)78 private CssSchema(ImmutableMap<String, Property> properties) { 79 if (properties == null) { throw new NullPointerException(); } 80 this.properties = properties; 81 } 82 83 /** 84 * A schema that includes all and only the named properties. 85 * 86 * @param propertyNames a series of lower-case CSS property names that appear 87 * in the built-in CSS definitions. It is an error to mention an unknown 88 * property name. This class's {@code main} method will dump a list of 89 * known property names when run with zero arguments. 90 */ withProperties( Iterable<? extends String> propertyNames)91 public static CssSchema withProperties( 92 Iterable<? extends String> propertyNames) { 93 ImmutableMap.Builder<String, Property> propertiesBuilder = 94 ImmutableMap.builder(); 95 for (String propertyName : propertyNames) { 96 Property prop = DEFINITIONS.get(propertyName); 97 if (prop == null) { throw new IllegalArgumentException(propertyName); } 98 propertiesBuilder.put(propertyName, prop); 99 } 100 return new CssSchema(propertiesBuilder.build()); 101 } 102 103 /** 104 * A schema that represents the union of the input schemas. 105 * 106 * @return A schema that allows all and only CSS properties that are allowed 107 * by at least one of the inputs. 108 */ union(CssSchema... cssSchemas)109 public static CssSchema union(CssSchema... cssSchemas) { 110 if (cssSchemas.length == 1) { return cssSchemas[0]; } 111 Map<String, Property> properties = Maps.newLinkedHashMap(); 112 for (CssSchema cssSchema : cssSchemas) { 113 properties.putAll(cssSchema.properties); 114 } 115 return new CssSchema(ImmutableMap.copyOf(properties)); 116 } 117 118 /** 119 * The set of CSS properties allowed by this schema. 120 * 121 * @return an immutable set. 122 */ allowedProperties()123 public Set<String> allowedProperties() { 124 return properties.keySet(); 125 } 126 127 /** The schema for the named property or function key. */ forKey(String propertyName)128 Property forKey(String propertyName) { 129 propertyName = Strings.toLowerCase(propertyName); 130 Property property = properties.get(propertyName); 131 if (property != null) { return property; } 132 int n = propertyName.length(); 133 if (n != 0 && propertyName.charAt(0) == '-') { 134 String barePropertyName = stripVendorPrefix(propertyName); 135 property = properties.get(barePropertyName); 136 if (property != null) { return property; } 137 } 138 return DISALLOWED; 139 } 140 141 /** {@code "-moz-foo"} → {@code "foo"}. */ stripVendorPrefix(String cssKeyword)142 private static @Nullable String stripVendorPrefix(String cssKeyword) { 143 int prefixLen = 0; 144 switch (cssKeyword.charAt(1)) { 145 case 'm': 146 if (cssKeyword.startsWith("-ms-")) { 147 prefixLen = 4; 148 } else if (cssKeyword.startsWith("-moz-")) { 149 prefixLen = 5; 150 } 151 break; 152 case 'o': 153 if (cssKeyword.startsWith("-o-")) { prefixLen = 3; } 154 break; 155 case 'w': 156 if (cssKeyword.startsWith("-webkit-")) { prefixLen = 8; } 157 break; 158 default: break; 159 } 160 return prefixLen == 0 ? null : cssKeyword.substring(prefixLen); 161 } 162 163 /** Maps lower-cased CSS property names to information about them. */ 164 static final ImmutableMap<String, Property> DEFINITIONS; 165 static { 166 ImmutableMap<String, String> zeroFns = ImmutableMap.of(); 167 ImmutableMap.Builder<String, Property> builder 168 = ImmutableMap.builder(); 169 ImmutableSet<String> mozBorderRadiusLiterals0 = ImmutableSet.of("/"); 170 ImmutableSet<String> mozOpacityLiterals0 = ImmutableSet.of("inherit"); 171 ImmutableSet<String> mozOutlineLiterals0 = ImmutableSet.of( 172 "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", 173 "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", 174 "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", 175 "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", 176 "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", "darkmagenta", 177 "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon", 178 "darkseagreen", "darkslateblue", "darkslategray", "darkturquoise", 179 "darkviolet", "deeppink", "deepskyblue", "dimgray", "dodgerblue", 180 "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", 181 "ghostwhite", "gold", "goldenrod", "gray", "green", "greenyellow", 182 "honeydew", "hotpink", "indianred", "indigo", "ivory", "khaki", 183 "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", 184 "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgreen", 185 "lightgrey", "lightpink", "lightsalmon", "lightseagreen", 186 "lightskyblue", "lightslategray", "lightsteelblue", "lightyellow", 187 "lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine", 188 "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", 189 "mediumslateblue", "mediumspringgreen", "mediumturquoise", 190 "mediumvioletred", "midnightblue", "mintcream", "mistyrose", 191 "moccasin", "navajowhite", "navy", "oldlace", "olive", "olivedrab", 192 "orange", "orangered", "orchid", "palegoldenrod", "palegreen", 193 "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", 194 "pink", "plum", "powderblue", "purple", "red", "rosybrown", "royalblue", 195 "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", 196 "silver", "skyblue", "slateblue", "slategray", "snow", "springgreen", 197 "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet", 198 "wheat", "white", "whitesmoke", "yellow", "yellowgreen"); 199 ImmutableSet<String> mozOutlineLiterals1 = ImmutableSet.of( 200 "dashed", "dotted", "double", "groove", "outset", "ridge", "solid"); 201 ImmutableSet<String> mozOutlineLiterals2 = ImmutableSet.of("thick", "thin"); 202 ImmutableSet<String> mozOutlineLiterals3 = ImmutableSet.of( 203 "hidden", "inherit", "inset", "invert", "medium", "none"); 204 ImmutableMap<String, String> mozOutlineFunctions = 205 ImmutableMap.<String, String>of("rgb(", "rgb()", "rgba(", "rgba()"); 206 ImmutableSet<String> mozOutlineColorLiterals0 = 207 ImmutableSet.of("inherit", "invert"); 208 ImmutableSet<String> mozOutlineStyleLiterals0 = 209 ImmutableSet.of("hidden", "inherit", "inset", "none"); 210 ImmutableSet<String> mozOutlineWidthLiterals0 = 211 ImmutableSet.of("inherit", "medium"); 212 ImmutableSet<String> oTextOverflowLiterals0 = 213 ImmutableSet.of("clip", "ellipsis"); 214 ImmutableSet<String> azimuthLiterals0 = ImmutableSet.of( 215 "behind", "center-left", "center-right", "far-left", "far-right", 216 "left-side", "leftwards", "right-side", "rightwards"); 217 ImmutableSet<String> azimuthLiterals1 = ImmutableSet.of("left", "right"); 218 ImmutableSet<String> azimuthLiterals2 = 219 ImmutableSet.of("center", "inherit"); 220 ImmutableSet<String> backgroundLiterals0 = ImmutableSet.of( 221 "border-box", "contain", "content-box", "cover", "padding-box"); 222 ImmutableSet<String> backgroundLiterals1 = 223 ImmutableSet.of("no-repeat", "repeat-x", "repeat-y", "round", "space"); 224 ImmutableSet<String> backgroundLiterals2 = ImmutableSet.of("bottom", "top"); 225 ImmutableSet<String> backgroundLiterals3 = ImmutableSet.of( 226 ",", "/", "auto", "center", "fixed", "inherit", "local", "none", 227 "repeat", "scroll", "transparent"); 228 ImmutableMap<String, String> backgroundFunctions = 229 ImmutableMap.<String, String>builder() 230 .put("image(", "image()") 231 .put("linear-gradient(", "linear-gradient()") 232 .put("radial-gradient(", "radial-gradient()") 233 .put("repeating-linear-gradient(", "repeating-linear-gradient()") 234 .put("repeating-radial-gradient(", "repeating-radial-gradient()") 235 .put("rgb(", "rgb()").put("rgba(", "rgba()") 236 .build(); 237 ImmutableSet<String> backgroundAttachmentLiterals0 = 238 ImmutableSet.of(",", "fixed", "local", "scroll"); 239 ImmutableSet<String> backgroundColorLiterals0 = 240 ImmutableSet.of("inherit", "transparent"); 241 ImmutableSet<String> backgroundImageLiterals0 = 242 ImmutableSet.of(",", "none"); 243 ImmutableMap<String, String> backgroundImageFunctions = 244 ImmutableMap.<String, String>of( 245 "image(", "image()", 246 "linear-gradient(", "linear-gradient()", 247 "radial-gradient(", "radial-gradient()", 248 "repeating-linear-gradient(", "repeating-linear-gradient()", 249 "repeating-radial-gradient(", "repeating-radial-gradient()"); 250 ImmutableSet<String> backgroundPositionLiterals0 = ImmutableSet.of( 251 ",", "center"); 252 ImmutableSet<String> backgroundRepeatLiterals0 = ImmutableSet.of( 253 ",", "repeat"); 254 ImmutableSet<String> borderLiterals0 = ImmutableSet.of( 255 "hidden", "inherit", "inset", "medium", "none", "transparent"); 256 ImmutableSet<String> borderCollapseLiterals0 = ImmutableSet.of( 257 "collapse", "inherit", "separate"); 258 ImmutableSet<String> bottomLiterals0 = ImmutableSet.of("auto", "inherit"); 259 ImmutableSet<String> boxShadowLiterals0 = ImmutableSet.of( 260 ",", "inset", "none"); 261 ImmutableSet<String> clearLiterals0 = ImmutableSet.of( 262 "both", "inherit", "none"); 263 ImmutableMap<String, String> clipFunctions = 264 ImmutableMap.<String, String>of("rect(", "rect()"); 265 ImmutableSet<String> contentLiterals0 = ImmutableSet.of("none", "normal"); 266 ImmutableSet<String> cueLiterals0 = ImmutableSet.of("inherit", "none"); 267 ImmutableSet<String> cursorLiterals0 = ImmutableSet.of( 268 "all-scroll", "col-resize", "crosshair", "default", "e-resize", 269 "hand", "help", "move", "n-resize", "ne-resize", "no-drop", 270 "not-allowed", "nw-resize", "pointer", "progress", "row-resize", 271 "s-resize", "se-resize", "sw-resize", "text", "vertical-text", 272 "w-resize", "wait"); 273 ImmutableSet<String> cursorLiterals1 = ImmutableSet.of( 274 ",", "auto", "inherit"); 275 ImmutableSet<String> directionLiterals0 = ImmutableSet.of("ltr", "rtl"); 276 ImmutableSet<String> displayLiterals0 = ImmutableSet.of( 277 "-moz-inline-box", "-moz-inline-stack", "block", "inline", 278 "inline-block", "inline-table", "list-item", "run-in", "table", 279 "table-caption", "table-cell", "table-column", "table-column-group", 280 "table-footer-group", "table-header-group", "table-row", 281 "table-row-group"); 282 ImmutableSet<String> elevationLiterals0 = ImmutableSet.of( 283 "above", "below", "higher", "level", "lower"); 284 ImmutableSet<String> emptyCellsLiterals0 = ImmutableSet.of("hide", "show"); 285 //ImmutableMap<String, String> filterFunctions = 286 // ImmutableMap.<String, String>of("alpha(", "alpha()"); 287 ImmutableSet<String> fontLiterals0 = ImmutableSet.of( 288 "100", "200", "300", "400", "500", "600", "700", "800", "900", "bold", 289 "bolder", "lighter"); 290 ImmutableSet<String> fontLiterals1 = ImmutableSet.of( 291 "large", "larger", "small", "smaller", "x-large", "x-small", 292 "xx-large", "xx-small"); 293 ImmutableSet<String> fontLiterals2 = ImmutableSet.of( 294 "caption", "icon", "menu", "message-box", "small-caption", 295 "status-bar"); 296 ImmutableSet<String> fontLiterals3 = ImmutableSet.of( 297 "cursive", "fantasy", "monospace", "sans-serif", "serif"); 298 ImmutableSet<String> fontLiterals4 = ImmutableSet.of("italic", "oblique"); 299 ImmutableSet<String> fontLiterals5 = ImmutableSet.of( 300 ",", "/", "inherit", "medium", "normal", "small-caps"); 301 ImmutableSet<String> fontFamilyLiterals0 = ImmutableSet.of(",", "inherit"); 302 ImmutableSet<String> fontStretchLiterals0 = ImmutableSet.of( 303 "condensed", "expanded", "extra-condensed", "extra-expanded", 304 "narrower", "semi-condensed", "semi-expanded", "ultra-condensed", 305 "ultra-expanded", "wider"); 306 ImmutableSet<String> fontStretchLiterals1 = ImmutableSet.of("normal"); 307 ImmutableSet<String> fontStyleLiterals0 = ImmutableSet.of( 308 "inherit", "normal"); 309 ImmutableSet<String> fontVariantLiterals0 = ImmutableSet.of( 310 "inherit", "normal", "small-caps"); 311 ImmutableSet<String> listStyleLiterals0 = ImmutableSet.of( 312 "armenian", "cjk-decimal", "decimal", "decimal-leading-zero", "disc", 313 "disclosure-closed", "disclosure-open", "ethiopic-numeric", "georgian", 314 "hebrew", "hiragana", "hiragana-iroha", "japanese-formal", 315 "japanese-informal", "katakana", "katakana-iroha", 316 "korean-hangul-formal", "korean-hanja-formal", 317 "korean-hanja-informal", "lower-alpha", "lower-greek", "lower-latin", 318 "lower-roman", "simp-chinese-formal", "simp-chinese-informal", 319 "square", "trad-chinese-formal", "trad-chinese-informal", 320 "upper-alpha", "upper-latin", "upper-roman"); 321 ImmutableSet<String> listStyleLiterals1 = ImmutableSet.of( 322 "inside", "outside"); 323 ImmutableSet<String> listStyleLiterals2 = ImmutableSet.of( 324 "circle", "inherit", "none"); 325 ImmutableSet<String> maxHeightLiterals0 = ImmutableSet.of( 326 "auto", "inherit", "none"); 327 ImmutableSet<String> overflowLiterals0 = ImmutableSet.of( 328 "auto", "hidden", "inherit", "scroll", "visible"); 329 ImmutableSet<String> overflowXLiterals0 = ImmutableSet.of( 330 "no-content", "no-display"); 331 ImmutableSet<String> overflowXLiterals1 = ImmutableSet.of( 332 "auto", "hidden", "scroll", "visible"); 333 ImmutableSet<String> pageBreakAfterLiterals0 = ImmutableSet.of( 334 "always", "auto", "avoid", "inherit"); 335 ImmutableSet<String> pageBreakInsideLiterals0 = ImmutableSet.of( 336 "auto", "avoid", "inherit"); 337 ImmutableSet<String> pitchLiterals0 = ImmutableSet.of( 338 "high", "low", "x-high", "x-low"); 339 ImmutableSet<String> playDuringLiterals0 = ImmutableSet.of( 340 "auto", "inherit", "mix", "none", "repeat"); 341 ImmutableSet<String> positionLiterals0 = ImmutableSet.of( 342 "absolute", "relative", "static"); 343 ImmutableSet<String> speakLiterals0 = ImmutableSet.of( 344 "inherit", "none", "normal", "spell-out"); 345 ImmutableSet<String> speakHeaderLiterals0 = ImmutableSet.of( 346 "always", "inherit", "once"); 347 ImmutableSet<String> speakNumeralLiterals0 = ImmutableSet.of( 348 "continuous", "digits"); 349 ImmutableSet<String> speakPunctuationLiterals0 = ImmutableSet.of( 350 "code", "inherit", "none"); 351 ImmutableSet<String> speechRateLiterals0 = ImmutableSet.of( 352 "fast", "faster", "slow", "slower", "x-fast", "x-slow"); 353 ImmutableSet<String> tableLayoutLiterals0 = ImmutableSet.of( 354 "auto", "fixed", "inherit"); 355 ImmutableSet<String> textAlignLiterals0 = ImmutableSet.of( 356 "center", "inherit", "justify"); 357 ImmutableSet<String> textDecorationLiterals0 = ImmutableSet.of( 358 "blink", "line-through", "overline", "underline"); 359 ImmutableSet<String> textTransformLiterals0 = ImmutableSet.of( 360 "capitalize", "lowercase", "uppercase"); 361 ImmutableSet<String> textWrapLiterals0 = ImmutableSet.of( 362 "suppress", "unrestricted"); 363 ImmutableSet<String> unicodeBidiLiterals0 = ImmutableSet.of( 364 "bidi-override", "embed"); 365 ImmutableSet<String> verticalAlignLiterals0 = ImmutableSet.of( 366 "baseline", "middle", "sub", "super", "text-bottom", "text-top"); 367 ImmutableSet<String> visibilityLiterals0 = ImmutableSet.of( 368 "collapse", "hidden", "inherit", "visible"); 369 ImmutableSet<String> voiceFamilyLiterals0 = ImmutableSet.of( 370 "child", "female", "male"); 371 ImmutableSet<String> volumeLiterals0 = ImmutableSet.of( 372 "loud", "silent", "soft", "x-loud", "x-soft"); 373 ImmutableSet<String> whiteSpaceLiterals0 = ImmutableSet.of( 374 "-moz-pre-wrap", "-o-pre-wrap", "-pre-wrap", "nowrap", "pre", 375 "pre-line", "pre-wrap"); 376 ImmutableSet<String> wordWrapLiterals0 = ImmutableSet.of( 377 "break-word", "normal"); 378 ImmutableSet<String> rgb$FunLiterals0 = ImmutableSet.of(","); 379 ImmutableSet<String> linearGradient$FunLiterals0 = ImmutableSet.of( 380 ",", "to"); 381 ImmutableSet<String> radialGradient$FunLiterals0 = ImmutableSet.of( 382 "at", "closest-corner", "closest-side", "ellipse", "farthest-corner", 383 "farthest-side"); 384 ImmutableSet<String> radialGradient$FunLiterals1 = ImmutableSet.of( 385 ",", "center", "circle"); 386 ImmutableSet<String> rect$FunLiterals0 = ImmutableSet.of(",", "auto"); 387 //ImmutableSet<String> alpha$FunLiterals0 = ImmutableSet.of("=", "opacity"); 388 Property mozBorderRadius = 389 new Property(5, mozBorderRadiusLiterals0, zeroFns); 390 builder.put("-moz-border-radius", mozBorderRadius); 391 Property mozBorderRadiusBottomleft = 392 new Property(5, ImmutableSet.<String>of(), zeroFns); 393 builder.put("-moz-border-radius-bottomleft", mozBorderRadiusBottomleft); 394 Property mozOpacity = new Property(1, mozOpacityLiterals0, zeroFns); 395 builder.put("-moz-opacity", mozOpacity); 396 @SuppressWarnings("unchecked") 397 Property mozOutline = new Property( 398 7, 399 union(mozOutlineLiterals0, mozOutlineLiterals1, mozOutlineLiterals2, 400 mozOutlineLiterals3), 401 mozOutlineFunctions); 402 builder.put("-moz-outline", mozOutline); 403 @SuppressWarnings("unchecked") 404 Property mozOutlineColor = new Property( 405 2, union(mozOutlineColorLiterals0, mozOutlineLiterals0), 406 mozOutlineFunctions); 407 builder.put("-moz-outline-color", mozOutlineColor); 408 @SuppressWarnings("unchecked") 409 Property mozOutlineStyle = new Property( 410 0, union(mozOutlineLiterals1, mozOutlineStyleLiterals0), zeroFns); 411 builder.put("-moz-outline-style", mozOutlineStyle); 412 @SuppressWarnings("unchecked") 413 Property mozOutlineWidth = new Property( 414 5, union(mozOutlineLiterals2, mozOutlineWidthLiterals0), zeroFns); 415 builder.put("-moz-outline-width", mozOutlineWidth); 416 Property oTextOverflow = new Property(0, oTextOverflowLiterals0, zeroFns); 417 builder.put("-o-text-overflow", oTextOverflow); 418 @SuppressWarnings("unchecked") 419 Property azimuth = new Property( 420 5, union(azimuthLiterals0, azimuthLiterals1, azimuthLiterals2), 421 zeroFns); 422 builder.put("azimuth", azimuth); 423 @SuppressWarnings("unchecked") 424 Property background = new Property( 425 23, 426 union(azimuthLiterals1, backgroundLiterals0, backgroundLiterals1, 427 backgroundLiterals2, backgroundLiterals3, mozOutlineLiterals0), 428 backgroundFunctions); 429 builder.put("background", background); 430 builder.put("background-attachment", 431 new Property(0, backgroundAttachmentLiterals0, zeroFns)); 432 @SuppressWarnings("unchecked") 433 Property backgroundColor = new Property( 434 258, union(backgroundColorLiterals0, mozOutlineLiterals0), 435 mozOutlineFunctions); 436 builder.put("background-color", backgroundColor); 437 builder.put("background-image", 438 new Property(16, backgroundImageLiterals0, 439 backgroundImageFunctions)); 440 @SuppressWarnings("unchecked") 441 Property backgroundPosition = new Property( 442 5, 443 union(azimuthLiterals1, backgroundLiterals2, 444 backgroundPositionLiterals0), 445 zeroFns); 446 builder.put("background-position", backgroundPosition); 447 @SuppressWarnings("unchecked") 448 Property backgroundRepeat = new Property( 449 0, union(backgroundLiterals1, backgroundRepeatLiterals0), zeroFns); 450 builder.put("background-repeat", backgroundRepeat); 451 @SuppressWarnings("unchecked") 452 Property border = new Property( 453 7, 454 union(borderLiterals0, mozOutlineLiterals0, mozOutlineLiterals1, 455 mozOutlineLiterals2), 456 mozOutlineFunctions); 457 builder.put("border", border); 458 @SuppressWarnings("unchecked") 459 Property borderBottomColor = new Property( 460 2, union(backgroundColorLiterals0, mozOutlineLiterals0), 461 mozOutlineFunctions); 462 builder.put("border-bottom-color", borderBottomColor); 463 builder.put("border-collapse", 464 new Property(0, borderCollapseLiterals0, zeroFns)); 465 Property borderSpacing = new Property(5, mozOpacityLiterals0, zeroFns); 466 builder.put("border-spacing", borderSpacing); 467 Property bottom = new Property(5, bottomLiterals0, zeroFns); 468 builder.put("bottom", bottom); 469 @SuppressWarnings("unchecked") 470 Property boxShadow = new Property( 471 7, union(boxShadowLiterals0, mozOutlineLiterals0), mozOutlineFunctions); 472 builder.put("box-shadow", boxShadow); 473 @SuppressWarnings("unchecked") 474 Property captionSide = new Property( 475 0, union(backgroundLiterals2, mozOpacityLiterals0), zeroFns); 476 builder.put("caption-side", captionSide); 477 @SuppressWarnings("unchecked") 478 Property clear = new Property( 479 0, union(azimuthLiterals1, clearLiterals0), zeroFns); 480 builder.put("clear", clear); 481 builder.put("clip", new Property(0, bottomLiterals0, clipFunctions)); 482 @SuppressWarnings("unchecked") 483 Property color = new Property( 484 258, union(mozOpacityLiterals0, mozOutlineLiterals0), 485 mozOutlineFunctions); 486 builder.put("color", color); 487 builder.put("content", new Property(8, contentLiterals0, zeroFns)); 488 Property cue = new Property(16, cueLiterals0, zeroFns); 489 builder.put("cue", cue); 490 @SuppressWarnings("unchecked") 491 Property cursor = new Property( 492 272, union(cursorLiterals0, cursorLiterals1), zeroFns); 493 builder.put("cursor", cursor); 494 @SuppressWarnings("unchecked") 495 Property direction = new Property( 496 0, union(directionLiterals0, mozOpacityLiterals0), zeroFns); 497 builder.put("direction", direction); 498 @SuppressWarnings("unchecked") 499 Property display = new Property( 500 0, union(cueLiterals0, displayLiterals0), zeroFns); 501 builder.put("display", display); 502 @SuppressWarnings("unchecked") 503 Property elevation = new Property( 504 5, union(elevationLiterals0, mozOpacityLiterals0), zeroFns); 505 builder.put("elevation", elevation); 506 @SuppressWarnings("unchecked") 507 Property emptyCells = new Property( 508 0, union(emptyCellsLiterals0, mozOpacityLiterals0), zeroFns); 509 builder.put("empty-cells", emptyCells); 510 //builder.put("filter", 511 // new Property(0, ImmutableSet.<String>of(), filterFunctions)); 512 @SuppressWarnings("unchecked") 513 Property cssFloat = new Property( 514 0, union(azimuthLiterals1, cueLiterals0), zeroFns); 515 builder.put("float", cssFloat); 516 @SuppressWarnings("unchecked") 517 Property font = new Property( 518 73, 519 union(fontLiterals0, fontLiterals1, fontLiterals2, fontLiterals3, 520 fontLiterals4, fontLiterals5), 521 zeroFns); 522 builder.put("font", font); 523 @SuppressWarnings("unchecked") 524 Property fontFamily = new Property( 525 72, union(fontFamilyLiterals0, fontLiterals3), zeroFns); 526 builder.put("font-family", fontFamily); 527 @SuppressWarnings("unchecked") 528 Property fontSize = new Property( 529 1, union(fontLiterals1, mozOutlineWidthLiterals0), zeroFns); 530 builder.put("font-size", fontSize); 531 @SuppressWarnings("unchecked") 532 Property fontStretch = new Property( 533 0, union(fontStretchLiterals0, fontStretchLiterals1), zeroFns); 534 builder.put("font-stretch", fontStretch); 535 @SuppressWarnings("unchecked") 536 Property fontStyle = new Property( 537 0, union(fontLiterals4, fontStyleLiterals0), zeroFns); 538 builder.put("font-style", fontStyle); 539 builder.put("font-variant", new Property( 540 0, fontVariantLiterals0, zeroFns)); 541 @SuppressWarnings("unchecked") 542 Property fontWeight = new Property( 543 0, union(fontLiterals0, fontStyleLiterals0), zeroFns); 544 builder.put("font-weight", fontWeight); 545 Property height = new Property(5, bottomLiterals0, zeroFns); 546 builder.put("height", height); 547 Property letterSpacing = new Property(5, fontStyleLiterals0, zeroFns); 548 builder.put("letter-spacing", letterSpacing); 549 builder.put("line-height", new Property(1, fontStyleLiterals0, zeroFns)); 550 @SuppressWarnings("unchecked") 551 Property listStyle = new Property( 552 16, 553 union(listStyleLiterals0, listStyleLiterals1, listStyleLiterals2), 554 backgroundImageFunctions); 555 builder.put("list-style", listStyle); 556 builder.put("list-style-image", new Property( 557 16, cueLiterals0, backgroundImageFunctions)); 558 @SuppressWarnings("unchecked") 559 Property listStylePosition = new Property( 560 0, union(listStyleLiterals1, mozOpacityLiterals0), zeroFns); 561 builder.put("list-style-position", listStylePosition); 562 @SuppressWarnings("unchecked") 563 Property listStyleType = new Property( 564 0, union(listStyleLiterals0, listStyleLiterals2), zeroFns); 565 builder.put("list-style-type", listStyleType); 566 Property margin = new Property(1, bottomLiterals0, zeroFns); 567 builder.put("margin", margin); 568 Property maxHeight = new Property(1, maxHeightLiterals0, zeroFns); 569 builder.put("max-height", maxHeight); 570 Property opacity = new Property(1, mozOpacityLiterals0, zeroFns); 571 builder.put("opacity", opacity); 572 builder.put("overflow", new Property(0, overflowLiterals0, zeroFns)); 573 @SuppressWarnings("unchecked") 574 Property overflowX = new Property( 575 0, union(overflowXLiterals0, overflowXLiterals1), zeroFns); 576 builder.put("overflow-x", overflowX); 577 Property padding = new Property(1, mozOpacityLiterals0, zeroFns); 578 builder.put("padding", padding); 579 @SuppressWarnings("unchecked") 580 Property pageBreakAfter = new Property( 581 0, union(azimuthLiterals1, pageBreakAfterLiterals0), zeroFns); 582 builder.put("page-break-after", pageBreakAfter); 583 builder.put("page-break-inside", new Property( 584 0, pageBreakInsideLiterals0, zeroFns)); 585 @SuppressWarnings("unchecked") 586 Property pitch = new Property( 587 5, union(mozOutlineWidthLiterals0, pitchLiterals0), zeroFns); 588 builder.put("pitch", pitch); 589 builder.put("play-during", new Property( 590 16, playDuringLiterals0, zeroFns)); 591 @SuppressWarnings("unchecked") 592 Property position = new Property( 593 0, union(mozOpacityLiterals0, positionLiterals0), zeroFns); 594 builder.put("position", position); 595 builder.put("quotes", new Property(8, cueLiterals0, zeroFns)); 596 builder.put("speak", new Property(0, speakLiterals0, zeroFns)); 597 builder.put("speak-header", new Property( 598 0, speakHeaderLiterals0, zeroFns)); 599 @SuppressWarnings("unchecked") 600 Property speakNumeral = new Property( 601 0, union(mozOpacityLiterals0, speakNumeralLiterals0), zeroFns); 602 builder.put("speak-numeral", speakNumeral); 603 builder.put("speak-punctuation", new Property( 604 0, speakPunctuationLiterals0, zeroFns)); 605 @SuppressWarnings("unchecked") 606 Property speechRate = new Property( 607 5, union(mozOutlineWidthLiterals0, speechRateLiterals0), zeroFns); 608 builder.put("speech-rate", speechRate); 609 builder.put("table-layout", new Property( 610 0, tableLayoutLiterals0, zeroFns)); 611 @SuppressWarnings("unchecked") 612 Property textAlign = new Property( 613 0, union(azimuthLiterals1, textAlignLiterals0), zeroFns); 614 builder.put("text-align", textAlign); 615 @SuppressWarnings("unchecked") 616 Property textDecoration = new Property( 617 0, union(cueLiterals0, textDecorationLiterals0), zeroFns); 618 builder.put("text-decoration", textDecoration); 619 @SuppressWarnings("unchecked") 620 Property textTransform = new Property( 621 0, union(cueLiterals0, textTransformLiterals0), zeroFns); 622 builder.put("text-transform", textTransform); 623 @SuppressWarnings("unchecked") 624 Property textWrap = new Property( 625 0, union(contentLiterals0, textWrapLiterals0), zeroFns); 626 builder.put("text-wrap", textWrap); 627 @SuppressWarnings("unchecked") 628 Property unicodeBidi = new Property( 629 0, union(fontStyleLiterals0, unicodeBidiLiterals0), zeroFns); 630 builder.put("unicode-bidi", unicodeBidi); 631 @SuppressWarnings("unchecked") 632 Property verticalAlign = new Property( 633 5, 634 union(backgroundLiterals2, mozOpacityLiterals0, verticalAlignLiterals0), 635 zeroFns); 636 builder.put("vertical-align", verticalAlign); 637 builder.put("visibility", new Property(0, visibilityLiterals0, zeroFns)); 638 @SuppressWarnings("unchecked") 639 Property voiceFamily = new Property( 640 8, union(fontFamilyLiterals0, voiceFamilyLiterals0), zeroFns); 641 builder.put("voice-family", voiceFamily); 642 @SuppressWarnings("unchecked") 643 Property volume = new Property( 644 1, union(mozOutlineWidthLiterals0, volumeLiterals0), zeroFns); 645 builder.put("volume", volume); 646 @SuppressWarnings("unchecked") 647 Property whiteSpace = new Property( 648 0, union(fontStyleLiterals0, whiteSpaceLiterals0), zeroFns); 649 builder.put("white-space", whiteSpace); 650 builder.put("word-wrap", new Property(0, wordWrapLiterals0, zeroFns)); 651 builder.put("zoom", new Property(1, fontStretchLiterals1, zeroFns)); 652 Property rgb$Fun = new Property(1, rgb$FunLiterals0, zeroFns); 653 builder.put("rgb()", rgb$Fun); 654 @SuppressWarnings("unchecked") 655 Property image$Fun = new Property( 656 18, union(mozOutlineLiterals0, rgb$FunLiterals0), mozOutlineFunctions); 657 builder.put("image()", image$Fun); 658 @SuppressWarnings("unchecked") 659 Property linearGradient$Fun = new Property( 660 7, 661 union(azimuthLiterals1, backgroundLiterals2, 662 linearGradient$FunLiterals0, mozOutlineLiterals0), 663 mozOutlineFunctions); 664 builder.put("linear-gradient()", linearGradient$Fun); 665 @SuppressWarnings("unchecked") 666 Property radialGradient$Fun = new Property( 667 7, 668 union(azimuthLiterals1, backgroundLiterals2, mozOutlineLiterals0, 669 radialGradient$FunLiterals0, radialGradient$FunLiterals1), 670 mozOutlineFunctions); 671 builder.put("radial-gradient()", radialGradient$Fun); 672 builder.put("rect()", new Property(5, rect$FunLiterals0, zeroFns)); 673 //builder.put("alpha()", new Property(1, alpha$FunLiterals0, zeroFns)); 674 builder.put("-moz-border-radius-bottomright", mozBorderRadiusBottomleft); 675 builder.put("-moz-border-radius-topleft", mozBorderRadiusBottomleft); 676 builder.put("-moz-border-radius-topright", mozBorderRadiusBottomleft); 677 builder.put("-moz-box-shadow", boxShadow); 678 builder.put("-webkit-border-bottom-left-radius", mozBorderRadiusBottomleft); 679 builder.put("-webkit-border-bottom-right-radius", 680 mozBorderRadiusBottomleft); 681 builder.put("-webkit-border-radius", mozBorderRadius); 682 builder.put("-webkit-border-radius-bottom-left", mozBorderRadiusBottomleft); 683 builder.put("-webkit-border-radius-bottom-right", 684 mozBorderRadiusBottomleft); 685 builder.put("-webkit-border-radius-top-left", mozBorderRadiusBottomleft); 686 builder.put("-webkit-border-radius-top-right", mozBorderRadiusBottomleft); 687 builder.put("-webkit-border-top-left-radius", mozBorderRadiusBottomleft); 688 builder.put("-webkit-border-top-right-radius", mozBorderRadiusBottomleft); 689 builder.put("-webkit-box-shadow", boxShadow); 690 builder.put("border-bottom", border); 691 builder.put("border-bottom-left-radius", mozBorderRadiusBottomleft); 692 builder.put("border-bottom-right-radius", mozBorderRadiusBottomleft); 693 builder.put("border-bottom-style", mozOutlineStyle); 694 builder.put("border-bottom-width", mozOutlineWidth); 695 builder.put("border-color", borderBottomColor); 696 builder.put("border-left", border); 697 builder.put("border-left-color", borderBottomColor); 698 builder.put("border-left-style", mozOutlineStyle); 699 builder.put("border-left-width", mozOutlineWidth); 700 builder.put("border-radius", mozBorderRadius); 701 builder.put("border-right", border); 702 builder.put("border-right-color", borderBottomColor); 703 builder.put("border-right-style", mozOutlineStyle); 704 builder.put("border-right-width", mozOutlineWidth); 705 builder.put("border-style", mozOutlineStyle); 706 builder.put("border-top", border); 707 builder.put("border-top-color", borderBottomColor); 708 builder.put("border-top-left-radius", mozBorderRadiusBottomleft); 709 builder.put("border-top-right-radius", mozBorderRadiusBottomleft); 710 builder.put("border-top-style", mozOutlineStyle); 711 builder.put("border-top-width", mozOutlineWidth); 712 builder.put("border-width", mozOutlineWidth); 713 builder.put("cue-after", cue); 714 builder.put("cue-before", cue); 715 builder.put("left", height); 716 builder.put("margin-bottom", margin); 717 builder.put("margin-left", margin); 718 builder.put("margin-right", margin); 719 builder.put("margin-top", margin); 720 builder.put("max-width", maxHeight); 721 builder.put("min-height", margin); 722 builder.put("min-width", margin); 723 builder.put("outline", mozOutline); 724 builder.put("outline-color", mozOutlineColor); 725 builder.put("outline-style", mozOutlineStyle); 726 builder.put("outline-width", mozOutlineWidth); 727 builder.put("overflow-y", overflowX); 728 builder.put("padding-bottom", padding); 729 builder.put("padding-left", padding); 730 builder.put("padding-right", padding); 731 builder.put("padding-top", padding); 732 builder.put("page-break-before", pageBreakAfter); 733 builder.put("pause", borderSpacing); 734 builder.put("pause-after", borderSpacing); 735 builder.put("pause-before", borderSpacing); 736 builder.put("pitch-range", borderSpacing); 737 builder.put("richness", borderSpacing); 738 builder.put("right", height); 739 builder.put("stress", borderSpacing); 740 builder.put("text-indent", borderSpacing); 741 builder.put("text-overflow", oTextOverflow); 742 builder.put("text-shadow", boxShadow); 743 builder.put("top", height); 744 builder.put("width", margin); 745 builder.put("word-spacing", letterSpacing); 746 builder.put("z-index", bottom); 747 builder.put("rgba()", rgb$Fun); 748 builder.put("repeating-linear-gradient()", linearGradient$Fun); 749 builder.put("repeating-radial-gradient()", radialGradient$Fun); 750 DEFINITIONS = builder.build(); 751 } 752 union(ImmutableSet<T>.... subsets)753 private static <T> ImmutableSet<T> union(ImmutableSet<T>... subsets) { 754 ImmutableSet.Builder<T> all = ImmutableSet.builder(); 755 for (ImmutableSet<T> subset : subsets) { 756 all.addAll(subset); 757 } 758 return all.build(); 759 } 760 761 static final ImmutableSet<String> DEFAULT_WHITELIST = ImmutableSet.of( 762 "-moz-border-radius", 763 "-moz-border-radius-bottomleft", 764 "-moz-border-radius-bottomright", 765 "-moz-border-radius-topleft", 766 "-moz-border-radius-topright", 767 "-moz-box-shadow", 768 "-moz-outline", 769 "-moz-outline-color", 770 "-moz-outline-style", 771 "-moz-outline-width", 772 "-o-text-overflow", 773 "-webkit-border-bottom-left-radius", 774 "-webkit-border-bottom-right-radius", 775 "-webkit-border-radius", 776 "-webkit-border-radius-bottom-left", 777 "-webkit-border-radius-bottom-right", 778 "-webkit-border-radius-top-left", 779 "-webkit-border-radius-top-right", 780 "-webkit-border-top-left-radius", 781 "-webkit-border-top-right-radius", 782 "-webkit-box-shadow", 783 "azimuth", 784 "background", 785 "background-attachment", 786 "background-color", 787 "background-image", 788 "background-position", 789 "background-repeat", 790 "border", 791 "border-bottom", 792 "border-bottom-color", 793 "border-bottom-left-radius", 794 "border-bottom-right-radius", 795 "border-bottom-style", 796 "border-bottom-width", 797 "border-collapse", 798 "border-color", 799 "border-left", 800 "border-left-color", 801 "border-left-style", 802 "border-left-width", 803 "border-radius", 804 "border-right", 805 "border-right-color", 806 "border-right-style", 807 "border-right-width", 808 "border-spacing", 809 "border-style", 810 "border-top", 811 "border-top-color", 812 "border-top-left-radius", 813 "border-top-right-radius", 814 "border-top-style", 815 "border-top-width", 816 "border-width", 817 "box-shadow", 818 "caption-side", 819 "color", 820 "cue", 821 "cue-after", 822 "cue-before", 823 "direction", 824 "elevation", 825 "empty-cells", 826 "font", 827 "font-family", 828 "font-size", 829 "font-stretch", 830 "font-style", 831 "font-variant", 832 "font-weight", 833 "height", 834 "image()", 835 "letter-spacing", 836 "line-height", 837 "linear-gradient()", 838 "list-style", 839 "list-style-image", 840 "list-style-position", 841 "list-style-type", 842 "margin", 843 "margin-bottom", 844 "margin-left", 845 "margin-right", 846 "margin-top", 847 "max-height", 848 "max-width", 849 "min-height", 850 "min-width", 851 "outline", 852 "outline-color", 853 "outline-style", 854 "outline-width", 855 "padding", 856 "padding-bottom", 857 "padding-left", 858 "padding-right", 859 "padding-top", 860 "pause", 861 "pause-after", 862 "pause-before", 863 "pitch", 864 "pitch-range", 865 "quotes", 866 "radial-gradient()", 867 "rect()", 868 "repeating-linear-gradient()", 869 "repeating-radial-gradient()", 870 "rgb()", 871 "rgba()", 872 "richness", 873 "speak", 874 "speak-header", 875 "speak-numeral", 876 "speak-punctuation", 877 "speech-rate", 878 "stress", 879 "table-layout", 880 "text-align", 881 "text-decoration", 882 "text-indent", 883 "text-overflow", 884 "text-shadow", 885 "text-transform", 886 "text-wrap", 887 "unicode-bidi", 888 "vertical-align", 889 "voice-family", 890 "volume", 891 "white-space", 892 "width", 893 "word-spacing", 894 "word-wrap" 895 ); 896 897 /** 898 * A schema that includes only those properties on the default schema 899 * white-list. 900 */ 901 public static final CssSchema DEFAULT = 902 CssSchema.withProperties(DEFAULT_WHITELIST); 903 904 /** Dumps key and literal list to stdout for easy examination. */ main(String... argv)905 public static void main(String... argv) { 906 SortedSet<String> keys = Sets.newTreeSet(); 907 SortedSet<String> literals = Sets.newTreeSet(); 908 909 for (ImmutableMap.Entry<String, Property> e : DEFINITIONS.entrySet()) { 910 keys.add(e.getKey()); 911 literals.addAll(e.getValue().literals); 912 } 913 914 System.out.println( 915 "# Below two blocks of tokens.\n" 916 + "#\n" 917 + "# First are all property names.\n" 918 + "# Those followed by an asterisk (*) are in the default white-list.\n" 919 + "#\n" 920 + "# Second are the literal tokens recognized in any defined property\n" 921 + "# value.\n" 922 ); 923 for (String key : keys) { 924 System.out.print(key); 925 if (DEFAULT_WHITELIST.contains(key)) { System.out.print("*"); } 926 System.out.println(); 927 } 928 System.out.println(); 929 for (String literal : literals) { 930 System.out.println(literal); 931 } 932 } 933 } 934