001    // Copyright (c) 2013, Mike Samuel
002    // All rights reserved.
003    //
004    // Redistribution and use in source and binary forms, with or without
005    // modification, are permitted provided that the following conditions
006    // are met:
007    //
008    // Redistributions of source code must retain the above copyright
009    // notice, this list of conditions and the following disclaimer.
010    // Redistributions in binary form must reproduce the above copyright
011    // notice, this list of conditions and the following disclaimer in the
012    // documentation and/or other materials provided with the distribution.
013    // Neither the name of the OWASP nor the names of its contributors may
014    // be used to endorse or promote products derived from this software
015    // without specific prior written permission.
016    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
017    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
018    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
019    // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
020    // COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
021    // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
022    // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023    // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
024    // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
025    // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
026    // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
027    // POSSIBILITY OF SUCH DAMAGE.
028    
029    package org.owasp.html;
030    
031    import java.util.SortedSet;
032    
033    import com.google.common.collect.ImmutableMap;
034    import com.google.common.collect.ImmutableSet;
035    import com.google.common.collect.Sets;
036    
037    /** Describes the kinds of tokens a CSS property's value can safely contain. */
038    @TCB
039    public final class CssSchema {
040    
041      static final class Property {
042        /** A bitfield of BIT_* constants describing groups of allowed tokens. */
043        final int bits;
044        /** Specific allowed values. */
045        final ImmutableSet<String> literals;
046        /**
047         * Maps lower-case function tokens to the schema key for their parameters.
048         */
049        final ImmutableMap<String, String> fnKeys;
050    
051        private Property(
052            int bits, ImmutableSet<String> literals,
053            ImmutableMap<String, String> fnKeys) {
054          this.bits = bits;
055          this.literals = literals;
056          this.fnKeys = fnKeys;
057        }
058      }
059    
060      static final int BIT_QUANTITY = 1;
061      static final int BIT_HASH_VALUE = 2;
062      static final int BIT_NEGATIVE = 4;
063      static final int BIT_STRING = 8;
064      static final int BIT_URL = 16;
065      static final int BIT_UNRESERVED_WORD = 64;
066      static final int BIT_UNICODE_RANGE = 128;
067    
068      public static final Property DISALLOWED = new Property(
069          0, ImmutableSet.<String>of(), ImmutableMap.<String, String>of());
070    
071      private final ImmutableMap<String, Property> properties;
072    
073      CssSchema(ImmutableMap<String, Property> properties) {
074        this.properties = properties;
075      }
076    
077      /** The schema for the named property or function key. */
078      public Property forKey(String propertyName) {
079        Property property = properties.get(Strings.toLowerCase(propertyName));
080        return property == null ? DISALLOWED : property;
081      }
082    
083      /** Maps lower-cased CSS property names to information about them. */
084      private static final ImmutableMap<String, Property> DEFAULT_PROPERTIES;
085      static {
086        ImmutableMap<String, String> zeroFns = ImmutableMap.of();
087        ImmutableMap.Builder<String, Property> builder
088            = ImmutableMap.builder();
089        ImmutableSet<String> mozBorderRadiusLiterals0 = ImmutableSet.of("/");
090        ImmutableSet<String> mozOpacityLiterals0 = ImmutableSet.of("inherit");
091        ImmutableSet<String> mozOutlineLiterals0 = ImmutableSet.of(
092            "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
093            "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
094            "burlywood", "cadetblue", "chartreuse", "chocolate", "coral",
095            "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
096            "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", "darkmagenta",
097            "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon",
098            "darkseagreen", "darkslateblue", "darkslategray", "darkturquoise",
099            "darkviolet", "deeppink", "deepskyblue", "dimgray", "dodgerblue",
100            "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro",
101            "ghostwhite", "gold", "goldenrod", "gray", "green", "greenyellow",
102            "honeydew", "hotpink", "indianred", "indigo", "ivory", "khaki",
103            "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue",
104            "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgreen",
105            "lightgrey", "lightpink", "lightsalmon", "lightseagreen",
106            "lightskyblue", "lightslategray", "lightsteelblue", "lightyellow",
107            "lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine",
108            "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
109            "mediumslateblue", "mediumspringgreen", "mediumturquoise",
110            "mediumvioletred", "midnightblue", "mintcream", "mistyrose",
111            "moccasin", "navajowhite", "navy", "oldlace", "olive", "olivedrab",
112            "orange", "orangered", "orchid", "palegoldenrod", "palegreen",
113            "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru",
114            "pink", "plum", "powderblue", "purple", "red", "rosybrown", "royalblue",
115            "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna",
116            "silver", "skyblue", "slateblue", "slategray", "snow", "springgreen",
117            "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet",
118            "wheat", "white", "whitesmoke", "yellow", "yellowgreen");
119        ImmutableSet<String> mozOutlineLiterals1 = ImmutableSet.of(
120            "dashed", "dotted", "double", "groove", "outset", "ridge", "solid");
121        ImmutableSet<String> mozOutlineLiterals2 = ImmutableSet.of("thick", "thin");
122        ImmutableSet<String> mozOutlineLiterals3 = ImmutableSet.of(
123            "hidden", "inherit", "inset", "invert", "medium", "none");
124        ImmutableMap<String, String> mozOutlineFunctions =
125          ImmutableMap.<String, String>of("rgb(", "rgb()", "rgba(", "rgba()");
126        ImmutableSet<String> mozOutlineColorLiterals0 =
127          ImmutableSet.of("inherit", "invert");
128        ImmutableSet<String> mozOutlineStyleLiterals0 =
129          ImmutableSet.of("hidden", "inherit", "inset", "none");
130        ImmutableSet<String> mozOutlineWidthLiterals0 =
131          ImmutableSet.of("inherit", "medium");
132        ImmutableSet<String> oTextOverflowLiterals0 =
133          ImmutableSet.of("clip", "ellipsis");
134        ImmutableSet<String> azimuthLiterals0 = ImmutableSet.of(
135            "behind", "center-left", "center-right", "far-left", "far-right",
136            "left-side", "leftwards", "right-side", "rightwards");
137        ImmutableSet<String> azimuthLiterals1 = ImmutableSet.of("left", "right");
138        ImmutableSet<String> azimuthLiterals2 =
139          ImmutableSet.of("center", "inherit");
140        ImmutableSet<String> backgroundLiterals0 = ImmutableSet.of(
141            "border-box", "contain", "content-box", "cover", "padding-box");
142        ImmutableSet<String> backgroundLiterals1 =
143          ImmutableSet.of("no-repeat", "repeat-x", "repeat-y", "round", "space");
144        ImmutableSet<String> backgroundLiterals2 = ImmutableSet.of("bottom", "top");
145        ImmutableSet<String> backgroundLiterals3 = ImmutableSet.of(
146            ",", "/", "auto", "center", "fixed", "inherit", "local", "none",
147            "repeat", "scroll", "transparent");
148        ImmutableMap<String, String> backgroundFunctions =
149          ImmutableMap.<String, String>builder()
150          .put("image(", "image()")
151          .put("linear-gradient(", "linear-gradient()")
152          .put("radial-gradient(", "radial-gradient()")
153          .put("repeating-linear-gradient(", "repeating-linear-gradient()")
154          .put("repeating-radial-gradient(", "repeating-radial-gradient()")
155          .put("rgb(", "rgb()").put("rgba(", "rgba()")
156          .build();
157        ImmutableSet<String> backgroundAttachmentLiterals0 =
158          ImmutableSet.of(",", "fixed", "local", "scroll");
159        ImmutableSet<String> backgroundColorLiterals0 =
160          ImmutableSet.of("inherit", "transparent");
161        ImmutableSet<String> backgroundImageLiterals0 =
162          ImmutableSet.of(",", "none");
163        ImmutableMap<String, String> backgroundImageFunctions =
164          ImmutableMap.<String, String>of(
165              "image(", "image()",
166              "linear-gradient(", "linear-gradient()",
167              "radial-gradient(", "radial-gradient()",
168              "repeating-linear-gradient(", "repeating-linear-gradient()",
169              "repeating-radial-gradient(", "repeating-radial-gradient()");
170        ImmutableSet<String> backgroundPositionLiterals0 = ImmutableSet.of(
171            ",", "center");
172        ImmutableSet<String> backgroundRepeatLiterals0 = ImmutableSet.of(
173            ",", "repeat");
174        ImmutableSet<String> borderLiterals0 = ImmutableSet.of(
175            "hidden", "inherit", "inset", "medium", "none", "transparent");
176        ImmutableSet<String> borderCollapseLiterals0 = ImmutableSet.of(
177            "collapse", "inherit", "separate");
178        ImmutableSet<String> bottomLiterals0 = ImmutableSet.of("auto", "inherit");
179        ImmutableSet<String> boxShadowLiterals0 = ImmutableSet.of(
180            ",", "inset", "none");
181        //ImmutableSet<String> clearLiterals0 = ImmutableSet.of(
182        //    "both", "inherit", "none");
183        //ImmutableMap<String, String> clipFunctions =
184        //  ImmutableMap.<String, String>of("rect(", "rect()");
185        ImmutableSet<String> contentLiterals0 = ImmutableSet.of("none", "normal");
186        ImmutableSet<String> cueLiterals0 = ImmutableSet.of("inherit", "none");
187        //ImmutableSet<String> cursorLiterals0 = ImmutableSet.of(
188        //    "all-scroll", "col-resize", "crosshair", "default", "e-resize",
189        //    "hand", "help", "move", "n-resize", "ne-resize", "no-drop",
190        //    "not-allowed", "nw-resize", "pointer", "progress", "row-resize",
191        //    "s-resize", "se-resize", "sw-resize", "text", "vertical-text",
192        //    "w-resize", "wait");
193        //ImmutableSet<String> cursorLiterals1 = ImmutableSet.of(
194        //    ",", "auto", "inherit");
195        ImmutableSet<String> directionLiterals0 = ImmutableSet.of("ltr", "rtl");
196        //ImmutableSet<String> displayLiterals0 = ImmutableSet.of(
197        //    "-moz-inline-box", "-moz-inline-stack", "block", "inline",
198        //    "inline-block", "inline-table", "list-item", "run-in", "table",
199        //    "table-caption", "table-cell", "table-column", "table-column-group",
200        //    "table-footer-group", "table-header-group", "table-row",
201        //    "table-row-group");
202        ImmutableSet<String> elevationLiterals0 = ImmutableSet.of(
203            "above", "below", "higher", "level", "lower");
204        ImmutableSet<String> emptyCellsLiterals0 = ImmutableSet.of("hide", "show");
205        //ImmutableMap<String, String> filterFunctions =
206        //  ImmutableMap.<String, String>of("alpha(", "alpha()");
207        ImmutableSet<String> fontLiterals0 = ImmutableSet.of(
208            "100", "200", "300", "400", "500", "600", "700", "800", "900", "bold",
209            "bolder", "lighter");
210        ImmutableSet<String> fontLiterals1 = ImmutableSet.of(
211            "large", "larger", "small", "smaller", "x-large", "x-small",
212            "xx-large", "xx-small");
213        ImmutableSet<String> fontLiterals2 = ImmutableSet.of(
214            "caption", "icon", "menu", "message-box", "small-caption",
215            "status-bar");
216        ImmutableSet<String> fontLiterals3 = ImmutableSet.of(
217            "cursive", "fantasy", "monospace", "sans-serif", "serif");
218        ImmutableSet<String> fontLiterals4 = ImmutableSet.of("italic", "oblique");
219        ImmutableSet<String> fontLiterals5 = ImmutableSet.of(
220            ",", "/", "inherit", "medium", "normal", "small-caps");
221        ImmutableSet<String> fontFamilyLiterals0 = ImmutableSet.of(",", "inherit");
222        ImmutableSet<String> fontStretchLiterals0 = ImmutableSet.of(
223            "condensed", "expanded", "extra-condensed", "extra-expanded",
224            "narrower", "semi-condensed", "semi-expanded", "ultra-condensed",
225            "ultra-expanded", "wider");
226        ImmutableSet<String> fontStretchLiterals1 = ImmutableSet.of("normal");
227        ImmutableSet<String> fontStyleLiterals0 = ImmutableSet.of(
228            "inherit", "normal");
229        ImmutableSet<String> fontVariantLiterals0 = ImmutableSet.of(
230            "inherit", "normal", "small-caps");
231        ImmutableSet<String> listStyleLiterals0 = ImmutableSet.of(
232            "armenian", "cjk-decimal", "decimal", "decimal-leading-zero", "disc",
233            "disclosure-closed", "disclosure-open", "ethiopic-numeric", "georgian",
234            "hebrew", "hiragana", "hiragana-iroha", "japanese-formal",
235            "japanese-informal", "katakana", "katakana-iroha",
236            "korean-hangul-formal", "korean-hanja-formal",
237            "korean-hanja-informal", "lower-alpha", "lower-greek", "lower-latin",
238            "lower-roman", "simp-chinese-formal", "simp-chinese-informal",
239            "square", "trad-chinese-formal", "trad-chinese-informal",
240            "upper-alpha", "upper-latin", "upper-roman");
241        ImmutableSet<String> listStyleLiterals1 = ImmutableSet.of(
242            "inside", "outside");
243        ImmutableSet<String> listStyleLiterals2 = ImmutableSet.of(
244            "circle", "inherit", "none");
245        ImmutableSet<String> maxHeightLiterals0 = ImmutableSet.of(
246            "auto", "inherit", "none");
247        //ImmutableSet<String> overflowLiterals0 = ImmutableSet.of(
248        //    "auto", "hidden", "inherit", "scroll", "visible");
249        //ImmutableSet<String> overflowXLiterals0 = ImmutableSet.of(
250        //    "no-content", "no-display");
251        //ImmutableSet<String> overflowXLiterals1 = ImmutableSet.of(
252        //    "auto", "hidden", "scroll", "visible");
253        //ImmutableSet<String> pageBreakAfterLiterals0 = ImmutableSet.of(
254        //    "always", "auto", "avoid", "inherit");
255        //ImmutableSet<String> pageBreakInsideLiterals0 = ImmutableSet.of(
256        //    "auto", "avoid", "inherit");
257        ImmutableSet<String> pitchLiterals0 = ImmutableSet.of(
258            "high", "low", "x-high", "x-low");
259        //ImmutableSet<String> playDuringLiterals0 = ImmutableSet.of(
260        //    "auto", "inherit", "mix", "none", "repeat");
261        //ImmutableSet<String> positionLiterals0 = ImmutableSet.of(
262        //    "absolute", "relative", "static");
263        ImmutableSet<String> speakLiterals0 = ImmutableSet.of(
264            "inherit", "none", "normal", "spell-out");
265        ImmutableSet<String> speakHeaderLiterals0 = ImmutableSet.of(
266            "always", "inherit", "once");
267        ImmutableSet<String> speakNumeralLiterals0 = ImmutableSet.of(
268            "continuous", "digits");
269        ImmutableSet<String> speakPunctuationLiterals0 = ImmutableSet.of(
270            "code", "inherit", "none");
271        ImmutableSet<String> speechRateLiterals0 = ImmutableSet.of(
272            "fast", "faster", "slow", "slower", "x-fast", "x-slow");
273        ImmutableSet<String> tableLayoutLiterals0 = ImmutableSet.of(
274            "auto", "fixed", "inherit");
275        ImmutableSet<String> textAlignLiterals0 = ImmutableSet.of(
276            "center", "inherit", "justify");
277        ImmutableSet<String> textDecorationLiterals0 = ImmutableSet.of(
278            "blink", "line-through", "overline", "underline");
279        ImmutableSet<String> textTransformLiterals0 = ImmutableSet.of(
280            "capitalize", "lowercase", "uppercase");
281        ImmutableSet<String> textWrapLiterals0 = ImmutableSet.of(
282            "suppress", "unrestricted");
283        ImmutableSet<String> unicodeBidiLiterals0 = ImmutableSet.of(
284            "bidi-override", "embed");
285        ImmutableSet<String> verticalAlignLiterals0 = ImmutableSet.of(
286            "baseline", "middle", "sub", "super", "text-bottom", "text-top");
287        //ImmutableSet<String> visibilityLiterals0 = ImmutableSet.of(
288        //    "collapse", "hidden", "inherit", "visible");
289        ImmutableSet<String> voiceFamilyLiterals0 = ImmutableSet.of(
290            "child", "female", "male");
291        ImmutableSet<String> volumeLiterals0 = ImmutableSet.of(
292            "loud", "silent", "soft", "x-loud", "x-soft");
293        ImmutableSet<String> whiteSpaceLiterals0 = ImmutableSet.of(
294            "-moz-pre-wrap", "-o-pre-wrap", "-pre-wrap", "nowrap", "pre",
295            "pre-line", "pre-wrap");
296        ImmutableSet<String> wordWrapLiterals0 = ImmutableSet.of(
297            "break-word", "normal");
298        ImmutableSet<String> rgb$FunLiterals0 = ImmutableSet.of(",");
299        ImmutableSet<String> linearGradient$FunLiterals0 = ImmutableSet.of(
300            ",", "to");
301        ImmutableSet<String> radialGradient$FunLiterals0 = ImmutableSet.of(
302            "at", "closest-corner", "closest-side", "ellipse", "farthest-corner",
303            "farthest-side");
304        ImmutableSet<String> radialGradient$FunLiterals1 = ImmutableSet.of(
305            ",", "center", "circle");
306        ImmutableSet<String> rect$FunLiterals0 = ImmutableSet.of(",", "auto");
307        ImmutableSet<String> alpha$FunLiterals0 = ImmutableSet.of("=", "opacity");
308        Property mozBorderRadius =
309           new Property(5, mozBorderRadiusLiterals0, zeroFns);
310        builder.put("-moz-border-radius", mozBorderRadius);
311        Property mozBorderRadiusBottomleft =
312           new Property(5, ImmutableSet.<String>of(), zeroFns);
313        builder.put("-moz-border-radius-bottomleft", mozBorderRadiusBottomleft);
314        //CssSchema mozOpacity = new Property(1, mozOpacityLiterals0, zeroFns);
315        //builder.put("-moz-opacity", mozOpacity);
316        @SuppressWarnings("unchecked")
317        Property mozOutline = new Property(
318            7,
319            union(mozOutlineLiterals0, mozOutlineLiterals1, mozOutlineLiterals2,
320                  mozOutlineLiterals3),
321            mozOutlineFunctions);
322        builder.put("-moz-outline", mozOutline);
323        @SuppressWarnings("unchecked")
324        Property mozOutlineColor = new Property(
325            2, union(mozOutlineColorLiterals0, mozOutlineLiterals0),
326            mozOutlineFunctions);
327        builder.put("-moz-outline-color", mozOutlineColor);
328        @SuppressWarnings("unchecked")
329        Property mozOutlineStyle = new Property(
330            0, union(mozOutlineLiterals1, mozOutlineStyleLiterals0), zeroFns);
331        builder.put("-moz-outline-style", mozOutlineStyle);
332        @SuppressWarnings("unchecked")
333        Property mozOutlineWidth = new Property(
334            5, union(mozOutlineLiterals2, mozOutlineWidthLiterals0), zeroFns);
335        builder.put("-moz-outline-width", mozOutlineWidth);
336        Property oTextOverflow = new Property(0, oTextOverflowLiterals0, zeroFns);
337        builder.put("-o-text-overflow", oTextOverflow);
338        @SuppressWarnings("unchecked")
339        Property azimuth = new Property(
340            5, union(azimuthLiterals0, azimuthLiterals1, azimuthLiterals2),
341            zeroFns);
342        builder.put("azimuth", azimuth);
343        @SuppressWarnings("unchecked")
344        Property background = new Property(
345            23,
346            union(azimuthLiterals1, backgroundLiterals0, backgroundLiterals1,
347                  backgroundLiterals2, backgroundLiterals3, mozOutlineLiterals0),
348            backgroundFunctions);
349        builder.put("background", background);
350        builder.put("background-attachment",
351                    new Property(0, backgroundAttachmentLiterals0, zeroFns));
352        @SuppressWarnings("unchecked")
353        Property backgroundColor = new Property(
354            258, union(backgroundColorLiterals0, mozOutlineLiterals0),
355            mozOutlineFunctions);
356        builder.put("background-color", backgroundColor);
357        builder.put("background-image",
358                    new Property(16, backgroundImageLiterals0,
359                                 backgroundImageFunctions));
360        @SuppressWarnings("unchecked")
361        Property backgroundPosition = new Property(
362            5,
363            union(azimuthLiterals1, backgroundLiterals2,
364                  backgroundPositionLiterals0),
365            zeroFns);
366        builder.put("background-position", backgroundPosition);
367        @SuppressWarnings("unchecked")
368        Property backgroundRepeat = new Property(
369            0, union(backgroundLiterals1, backgroundRepeatLiterals0), zeroFns);
370        builder.put("background-repeat", backgroundRepeat);
371        @SuppressWarnings("unchecked")
372        Property border = new Property(
373            7,
374            union(borderLiterals0, mozOutlineLiterals0, mozOutlineLiterals1,
375                  mozOutlineLiterals2),
376            mozOutlineFunctions);
377        builder.put("border", border);
378        @SuppressWarnings("unchecked")
379        Property borderBottomColor = new Property(
380            2, union(backgroundColorLiterals0, mozOutlineLiterals0),
381            mozOutlineFunctions);
382        builder.put("border-bottom-color", borderBottomColor);
383        builder.put("border-collapse",
384                    new Property(0, borderCollapseLiterals0, zeroFns));
385        Property borderSpacing = new Property(5, mozOpacityLiterals0, zeroFns);
386        builder.put("border-spacing", borderSpacing);
387        //Property bottom = new Property(5, bottomLiterals0, zeroFns);
388        //builder.put("bottom", bottom);
389        @SuppressWarnings("unchecked")
390        Property boxShadow = new Property(
391            7, union(boxShadowLiterals0, mozOutlineLiterals0), mozOutlineFunctions);
392        builder.put("box-shadow", boxShadow);
393        @SuppressWarnings("unchecked")
394        Property captionSide = new Property(
395            0, union(backgroundLiterals2, mozOpacityLiterals0), zeroFns);
396        builder.put("caption-side", captionSide);
397        //@SuppressWarnings("unchecked")
398        //Property clear = new Property(
399        //    0, union(azimuthLiterals1, clearLiterals0), zeroFns);
400        //builder.put("clear", clear);
401        //builder.put("clip", new Property(0, bottomLiterals0, clipFunctions));
402        @SuppressWarnings("unchecked")
403        Property color = new Property(
404            258, union(mozOpacityLiterals0, mozOutlineLiterals0),
405            mozOutlineFunctions);
406        builder.put("color", color);
407        //builder.put("content", new Property(8, contentLiterals0, zeroFns));
408        Property cue = new Property(16, cueLiterals0, zeroFns);
409        builder.put("cue", cue);
410        //@SuppressWarnings("unchecked")
411        //Property cursor = new Property(
412        //    272, union(cursorLiterals0, cursorLiterals1), zeroFns);
413        //builder.put("cursor", cursor);
414        @SuppressWarnings("unchecked")
415        Property direction = new Property(
416            0, union(directionLiterals0, mozOpacityLiterals0), zeroFns);
417        builder.put("direction", direction);
418        //@SuppressWarnings("unchecked")
419        //Property display = new Property(
420        //    0, union(cueLiterals0, displayLiterals0), zeroFns);
421        //builder.put("display", display);
422        @SuppressWarnings("unchecked")
423        Property elevation = new Property(
424            5, union(elevationLiterals0, mozOpacityLiterals0), zeroFns);
425        builder.put("elevation", elevation);
426        @SuppressWarnings("unchecked")
427        Property emptyCells = new Property(
428            0, union(emptyCellsLiterals0, mozOpacityLiterals0), zeroFns);
429        builder.put("empty-cells", emptyCells);
430        //builder.put("filter",
431        //            new Property(0, ImmutableSet.<String>of(), filterFunctions));
432        //@SuppressWarnings("unchecked")
433        //Property cssFloat = new Property(
434        //    0, union(azimuthLiterals1, cueLiterals0), zeroFns);
435        //builder.put("float", cssFloat);
436        @SuppressWarnings("unchecked")
437        Property font = new Property(
438            73,
439            union(fontLiterals0, fontLiterals1, fontLiterals2, fontLiterals3,
440                  fontLiterals4, fontLiterals5),
441            zeroFns);
442        builder.put("font", font);
443        @SuppressWarnings("unchecked")
444        Property fontFamily = new Property(
445            72, union(fontFamilyLiterals0, fontLiterals3), zeroFns);
446        builder.put("font-family", fontFamily);
447        @SuppressWarnings("unchecked")
448        Property fontSize = new Property(
449            1, union(fontLiterals1, mozOutlineWidthLiterals0), zeroFns);
450        builder.put("font-size", fontSize);
451        @SuppressWarnings("unchecked")
452        Property fontStretch = new Property(
453            0, union(fontStretchLiterals0, fontStretchLiterals1), zeroFns);
454        builder.put("font-stretch", fontStretch);
455        @SuppressWarnings("unchecked")
456        Property fontStyle = new Property(
457            0, union(fontLiterals4, fontStyleLiterals0), zeroFns);
458        builder.put("font-style", fontStyle);
459        builder.put("font-variant", new Property(
460            0, fontVariantLiterals0, zeroFns));
461        @SuppressWarnings("unchecked")
462        Property fontWeight = new Property(
463            0, union(fontLiterals0, fontStyleLiterals0), zeroFns);
464        builder.put("font-weight", fontWeight);
465        Property height = new Property(5, bottomLiterals0, zeroFns);
466        builder.put("height", height);
467        Property letterSpacing = new Property(5, fontStyleLiterals0, zeroFns);
468        builder.put("letter-spacing", letterSpacing);
469        builder.put("line-height", new Property(1, fontStyleLiterals0, zeroFns));
470        @SuppressWarnings("unchecked")
471        Property listStyle = new Property(
472            16,
473            union(listStyleLiterals0, listStyleLiterals1, listStyleLiterals2),
474            backgroundImageFunctions);
475        builder.put("list-style", listStyle);
476        builder.put("list-style-image", new Property(
477            16, cueLiterals0, backgroundImageFunctions));
478        @SuppressWarnings("unchecked")
479        Property listStylePosition = new Property(
480            0, union(listStyleLiterals1, mozOpacityLiterals0), zeroFns);
481        builder.put("list-style-position", listStylePosition);
482        @SuppressWarnings("unchecked")
483        Property listStyleType = new Property(
484            0, union(listStyleLiterals0, listStyleLiterals2), zeroFns);
485        builder.put("list-style-type", listStyleType);
486        Property margin = new Property(1, bottomLiterals0, zeroFns);
487        builder.put("margin", margin);
488        Property maxHeight = new Property(1, maxHeightLiterals0, zeroFns);
489        builder.put("max-height", maxHeight);
490        //Property opacity = new Property(1, mozOpacityLiterals0, zeroFns);
491        //builder.put("opacity", opacity);
492        //builder.put("overflow", new Property(0, overflowLiterals0, zeroFns));
493        //@SuppressWarnings("unchecked")
494        //Property overflowX = new Property(
495        //    0, union(overflowXLiterals0, overflowXLiterals1), zeroFns);
496        //builder.put("overflow-x", overflowX);
497        Property padding = new Property(1, mozOpacityLiterals0, zeroFns);
498        builder.put("padding", padding);
499        //@SuppressWarnings("unchecked")
500        //Property pageBreakAfter = new Property(
501        //    0, union(azimuthLiterals1, pageBreakAfterLiterals0), zeroFns);
502        //builder.put("page-break-after", pageBreakAfter);
503        //builder.put("page-break-inside", new Property(
504        //    0, pageBreakInsideLiterals0, zeroFns));
505        @SuppressWarnings("unchecked")
506        Property pitch = new Property(
507            5, union(mozOutlineWidthLiterals0, pitchLiterals0), zeroFns);
508        builder.put("pitch", pitch);
509        //builder.put("play-during", new Property(
510        //    16, playDuringLiterals0, zeroFns));
511        //@SuppressWarnings("unchecked")
512        //Property position = new Property(
513        //    0, union(mozOpacityLiterals0, positionLiterals0), zeroFns);
514        //builder.put("position", position);
515        builder.put("quotes", new Property(8, cueLiterals0, zeroFns));
516        builder.put("speak", new Property(0, speakLiterals0, zeroFns));
517        builder.put("speak-header", new Property(
518            0, speakHeaderLiterals0, zeroFns));
519        @SuppressWarnings("unchecked")
520        Property speakNumeral = new Property(
521            0, union(mozOpacityLiterals0, speakNumeralLiterals0), zeroFns);
522        builder.put("speak-numeral", speakNumeral);
523        builder.put("speak-punctuation", new Property(
524            0, speakPunctuationLiterals0, zeroFns));
525        @SuppressWarnings("unchecked")
526        Property speechRate = new Property(
527            5, union(mozOutlineWidthLiterals0, speechRateLiterals0), zeroFns);
528        builder.put("speech-rate", speechRate);
529        builder.put("table-layout", new Property(
530            0, tableLayoutLiterals0, zeroFns));
531        @SuppressWarnings("unchecked")
532        Property textAlign = new Property(
533            0, union(azimuthLiterals1, textAlignLiterals0), zeroFns);
534        builder.put("text-align", textAlign);
535        @SuppressWarnings("unchecked")
536        Property textDecoration = new Property(
537            0, union(cueLiterals0, textDecorationLiterals0), zeroFns);
538        builder.put("text-decoration", textDecoration);
539        @SuppressWarnings("unchecked")
540        Property textTransform = new Property(
541            0, union(cueLiterals0, textTransformLiterals0), zeroFns);
542        builder.put("text-transform", textTransform);
543        @SuppressWarnings("unchecked")
544        Property textWrap = new Property(
545            0, union(contentLiterals0, textWrapLiterals0), zeroFns);
546        builder.put("text-wrap", textWrap);
547        @SuppressWarnings("unchecked")
548        Property unicodeBidi = new Property(
549            0, union(fontStyleLiterals0, unicodeBidiLiterals0), zeroFns);
550        builder.put("unicode-bidi", unicodeBidi);
551        @SuppressWarnings("unchecked")
552        Property verticalAlign = new Property(
553            5,
554            union(backgroundLiterals2, mozOpacityLiterals0, verticalAlignLiterals0),
555            zeroFns);
556        builder.put("vertical-align", verticalAlign);
557        //builder.put("visibility", new Property(0, visibilityLiterals0, zeroFns));
558        @SuppressWarnings("unchecked")
559        Property voiceFamily = new Property(
560            8, union(fontFamilyLiterals0, voiceFamilyLiterals0), zeroFns);
561        builder.put("voice-family", voiceFamily);
562        @SuppressWarnings("unchecked")
563        Property volume = new Property(
564            1, union(mozOutlineWidthLiterals0, volumeLiterals0), zeroFns);
565        builder.put("volume", volume);
566        @SuppressWarnings("unchecked")
567        Property whiteSpace = new Property(
568            0, union(fontStyleLiterals0, whiteSpaceLiterals0), zeroFns);
569        builder.put("white-space", whiteSpace);
570        builder.put("word-wrap", new Property(0, wordWrapLiterals0, zeroFns));
571        //builder.put("zoom", new Property(1, fontStretchLiterals1, zeroFns));
572        Property rgb$Fun = new Property(1, rgb$FunLiterals0, zeroFns);
573        builder.put("rgb()", rgb$Fun);
574        @SuppressWarnings("unchecked")
575        Property image$Fun = new Property(
576            18, union(mozOutlineLiterals0, rgb$FunLiterals0), mozOutlineFunctions);
577        builder.put("image()", image$Fun);
578        @SuppressWarnings("unchecked")
579        Property linearGradient$Fun = new Property(
580            7,
581            union(azimuthLiterals1, backgroundLiterals2,
582                  linearGradient$FunLiterals0, mozOutlineLiterals0),
583            mozOutlineFunctions);
584        builder.put("linear-gradient()", linearGradient$Fun);
585        @SuppressWarnings("unchecked")
586        Property radialGradient$Fun = new Property(
587            7,
588            union(azimuthLiterals1, backgroundLiterals2, mozOutlineLiterals0,
589                  radialGradient$FunLiterals0, radialGradient$FunLiterals1),
590            mozOutlineFunctions);
591        builder.put("radial-gradient()", radialGradient$Fun);
592        builder.put("rect()", new Property(5, rect$FunLiterals0, zeroFns));
593        builder.put("alpha()", new Property(1, alpha$FunLiterals0, zeroFns));
594        builder.put("-moz-border-radius-bottomright", mozBorderRadiusBottomleft);
595        builder.put("-moz-border-radius-topleft", mozBorderRadiusBottomleft);
596        builder.put("-moz-border-radius-topright", mozBorderRadiusBottomleft);
597        builder.put("-moz-box-shadow", boxShadow);
598        builder.put("-webkit-border-bottom-left-radius", mozBorderRadiusBottomleft);
599        builder.put("-webkit-border-bottom-right-radius",
600                    mozBorderRadiusBottomleft);
601        builder.put("-webkit-border-radius", mozBorderRadius);
602        builder.put("-webkit-border-radius-bottom-left", mozBorderRadiusBottomleft);
603        builder.put("-webkit-border-radius-bottom-right",
604                    mozBorderRadiusBottomleft);
605        builder.put("-webkit-border-radius-top-left", mozBorderRadiusBottomleft);
606        builder.put("-webkit-border-radius-top-right", mozBorderRadiusBottomleft);
607        builder.put("-webkit-border-top-left-radius", mozBorderRadiusBottomleft);
608        builder.put("-webkit-border-top-right-radius", mozBorderRadiusBottomleft);
609        builder.put("-webkit-box-shadow", boxShadow);
610        builder.put("border-bottom", border);
611        builder.put("border-bottom-left-radius", mozBorderRadiusBottomleft);
612        builder.put("border-bottom-right-radius", mozBorderRadiusBottomleft);
613        builder.put("border-bottom-style", mozOutlineStyle);
614        builder.put("border-bottom-width", mozOutlineWidth);
615        builder.put("border-color", borderBottomColor);
616        builder.put("border-left", border);
617        builder.put("border-left-color", borderBottomColor);
618        builder.put("border-left-style", mozOutlineStyle);
619        builder.put("border-left-width", mozOutlineWidth);
620        builder.put("border-radius", mozBorderRadius);
621        builder.put("border-right", border);
622        builder.put("border-right-color", borderBottomColor);
623        builder.put("border-right-style", mozOutlineStyle);
624        builder.put("border-right-width", mozOutlineWidth);
625        builder.put("border-style", mozOutlineStyle);
626        builder.put("border-top", border);
627        builder.put("border-top-color", borderBottomColor);
628        builder.put("border-top-left-radius", mozBorderRadiusBottomleft);
629        builder.put("border-top-right-radius", mozBorderRadiusBottomleft);
630        builder.put("border-top-style", mozOutlineStyle);
631        builder.put("border-top-width", mozOutlineWidth);
632        builder.put("border-width", mozOutlineWidth);
633        builder.put("cue-after", cue);
634        builder.put("cue-before", cue);
635        //builder.put("left", height);
636        builder.put("margin-bottom", margin);
637        builder.put("margin-left", margin);
638        builder.put("margin-right", margin);
639        builder.put("margin-top", margin);
640        builder.put("max-width", maxHeight);
641        builder.put("min-height", margin);
642        builder.put("min-width", margin);
643        builder.put("outline", mozOutline);
644        builder.put("outline-color", mozOutlineColor);
645        builder.put("outline-style", mozOutlineStyle);
646        builder.put("outline-width", mozOutlineWidth);
647        //builder.put("overflow-y", overflowX);
648        builder.put("padding-bottom", padding);
649        builder.put("padding-left", padding);
650        builder.put("padding-right", padding);
651        builder.put("padding-top", padding);
652        //builder.put("page-break-before", pageBreakAfter);
653        builder.put("pause", borderSpacing);
654        builder.put("pause-after", borderSpacing);
655        builder.put("pause-before", borderSpacing);
656        builder.put("pitch-range", borderSpacing);
657        builder.put("richness", borderSpacing);
658        //builder.put("right", height);
659        builder.put("stress", borderSpacing);
660        builder.put("text-indent", borderSpacing);
661        builder.put("text-overflow", oTextOverflow);
662        builder.put("text-shadow", boxShadow);
663        //builder.put("top", height);
664        builder.put("width", margin);
665        builder.put("word-spacing", letterSpacing);
666        //builder.put("z-index", bottom);
667        builder.put("rgba()", rgb$Fun);
668        builder.put("repeating-linear-gradient()", linearGradient$Fun);
669        builder.put("repeating-radial-gradient()", radialGradient$Fun);
670        DEFAULT_PROPERTIES = builder.build();
671      }
672    
673      private static <T> ImmutableSet<T> union(ImmutableSet<T>... subsets) {
674        ImmutableSet.Builder<T> all = ImmutableSet.builder();
675        for (ImmutableSet<T> subset : subsets) {
676          all.addAll(subset);
677        }
678        return all.build();
679      }
680    
681      static final CssSchema DEFAULT = new CssSchema(DEFAULT_PROPERTIES);
682    
683      /** Dumps key and literal list to stdout for easy examination. */
684      public static void main(String... argv) {
685        SortedSet<String> keys = Sets.newTreeSet();
686        SortedSet<String> literals = Sets.newTreeSet();
687        for (ImmutableMap.Entry<String, Property> e
688             : DEFAULT_PROPERTIES.entrySet()) {
689          keys.add(e.getKey());
690          literals.addAll(e.getValue().literals);
691        }
692        for (String key : keys) {
693          System.out.println(key);
694        }
695        System.out.println();
696        for (String literal : literals) {
697          System.out.println(literal);
698        }
699      }
700    }