1 // Copyright (c) 2011, 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 /** 32 * Pre-packaged HTML sanitizer policies. 33 * 34 * <p> 35 * These policies can be used to sanitize content. 36 * </p> 37 * <pre> 38 * Sanitizers.FORMATTING.sanitize({@code "<b>Hello, World!</b>"}) 39 * </pre> 40 * and can be chained 41 * <pre> 42 * PolicyFactory sanitizer = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS); 43 * System.out.println(sanitizer.sanitize({@code "<p>Hello, <b>World!</b>"})); 44 * </pre> 45 * 46 * <p> 47 * For more fine-grained control over sanitization, use 48 * {@link HtmlPolicyBuilder}. 49 * </p> 50 * 51 * @author Mike Samuel <mikesamuel (at) gmail.com> 52 */ 53 public final class Sanitizers { 54 55 /** 56 * Allows common formatting elements including {@code <b>}, {@code <i>}, etc. 57 */ 58 public static final PolicyFactory FORMATTING = new HtmlPolicyBuilder() 59 .allowCommonInlineFormattingElements().toFactory(); 60 61 /** 62 * Allows common block elements including <code><p></code>, 63 * <code><h1></code>, etc. 64 */ 65 public static final PolicyFactory BLOCKS = new HtmlPolicyBuilder() 66 .allowCommonBlockElements().toFactory(); 67 68 /** 69 * Allows certain safe CSS properties in {@code style="..."} attributes. 70 */ 71 public static final PolicyFactory STYLES = new HtmlPolicyBuilder() 72 .allowStyling().toFactory(); 73 74 /** 75 * Allows HTTP, HTTPS, MAILTO, and relative links. 76 */ 77 public static final PolicyFactory LINKS = new HtmlPolicyBuilder() 78 .allowStandardUrlProtocols().allowElements("a") 79 .allowAttributes("href").onElements("a").requireRelNofollowOnLinks() 80 .toFactory(); 81 82 private static final AttributePolicy INTEGER = new AttributePolicy() { 83 public String apply( 84 String elementName, String attributeName, String value) { 85 int n = value.length(); 86 if (n == 0) { return null; } 87 for (int i = 0; i < n; ++i) { 88 char ch = value.charAt(i); 89 if (ch == '.') { 90 if (i == 0) { return null; } 91 return value.substring(0, i); // truncate to integer. 92 } else if (!('0' <= ch && ch <= '9')) { 93 return null; 94 } 95 } 96 return value; 97 } 98 }; 99 100 /** 101 * Allows {@code <img>} elements from HTTP, HTTPS, and relative sources. 102 */ 103 public static final PolicyFactory IMAGES = new HtmlPolicyBuilder() 104 .allowUrlProtocols("http", "https").allowElements("img") 105 .allowAttributes("alt", "src").onElements("img") 106 .allowAttributes("border", "height", "width").matching(INTEGER) 107 .onElements("img") 108 .toFactory(); 109 110 private Sanitizers() { 111 // Uninstantiable. 112 } 113 } 114