View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.util;
23  
24  import java.util.regex.Pattern;
25  
26  import org.owasp.html.HtmlPolicyBuilder;
27  import org.owasp.html.PolicyFactory;
28  import org.owasp.html.Sanitizers;
29  import org.primefaces.util.LangUtils;
30  
31  public class HtmlSanitizer {
32  
33      private static final PolicyFactory HTML_IMAGES_SANITIZER = new HtmlPolicyBuilder()
34                  .allowUrlProtocols("data", "http", "https")
35                  .allowElements("img")
36                  .allowAttributes("src")
37                  .matching(Pattern.compile("^(data:image/(gif|png|jpeg|webp|svg)[,;]|http|https|mailto|//).+", Pattern.CASE_INSENSITIVE))
38                  .onElements("img")
39                  .allowAttributes(
40                              "data-rotate",
41                              "data-proportion",
42                              "data-rotatex",
43                              "data-rotatey",
44                              "data-size",
45                              "data-align",
46                              "data-percentage",
47                              "data-index",
48                              "data-file-name",
49                              "data-file-size",
50                              "data-origin")
51                  .onElements("img")
52                  .toFactory();
53  
54      private static final PolicyFactory HTML_MEDIA_SANITIZER = new HtmlPolicyBuilder()
55                  .allowUrlProtocols("data", "http", "https")
56                  .allowElements("video", "audio", "source", "iframe", "figure")
57                  .allowAttributes("controls", "width", "height", "origin-size", "src", "allowfullscreen", "class", "style", "data-proportion", "data-align",
58                              "data-percentage", " data-size", "data-file-name", "data-file-size", "data-origin", "data-rotate", "data-index")
59                  .onElements("video", "audio", "source", "iframe", "figure")
60                  .toFactory();
61  
62      private static final PolicyFactory HTML_LINKS_SANITIZER = Sanitizers.LINKS
63                  .and(new HtmlPolicyBuilder()
64                              .allowElements("a")
65                              .allowAttributes("target")
66                              .onElements("a")
67                              .toFactory());
68  
69      private static final PolicyFactory HTML_STYLES_SANITIZER = Sanitizers.STYLES
70                  .and(new HtmlPolicyBuilder()
71                              .allowElements("table", "span", "li", "p", "pre", "div", "hr")
72                              .allowAttributes("class", "style", "contenteditable")
73                              .onElements("table", "span", "li", "p", "pre", "div", "hr")
74                              .toFactory());
75  
76      private static final PolicyFactory HTML_DENY_ALL_SANITIZER = new HtmlPolicyBuilder().toFactory();
77  
78      private HtmlSanitizer() {
79  
80      }
81  
82      public static String sanitizeHtml(String value,
83                  boolean allowBlocks,
84                  boolean allowFormatting,
85                  boolean allowLinks,
86                  boolean allowStyles,
87                  boolean allowImages,
88                  boolean allowTables,
89                  boolean allowMedia) {
90  
91          if (LangUtils.isBlank(value)) {
92              return value;
93          }
94  
95          PolicyFactory sanitizer = HTML_DENY_ALL_SANITIZER;
96          if (allowBlocks) {
97              sanitizer = sanitizer.and(Sanitizers.BLOCKS);
98          }
99          if (allowFormatting) {
100             sanitizer = sanitizer.and(Sanitizers.FORMATTING);
101         }
102         if (allowLinks) {
103             sanitizer = sanitizer.and(HTML_LINKS_SANITIZER);
104         }
105         if (allowStyles) {
106             sanitizer = sanitizer.and(HTML_STYLES_SANITIZER);
107         }
108         if (allowImages) {
109             sanitizer = sanitizer.and(HTML_IMAGES_SANITIZER);
110         }
111         if (allowMedia) {
112             sanitizer = sanitizer.and(HTML_MEDIA_SANITIZER);
113         }
114         if (allowTables) {
115             sanitizer = sanitizer.and(Sanitizers.TABLES);
116         }
117 
118         return sanitizer.sanitize(value);
119     }
120 
121 }