ElementPolicy.java revision 4e867904c8295537803c1c8a076e130df5674b58
14e867904c8295537803c1c8a076e130df5674b58mikesamuelpackage org.owasp.html; 24e867904c8295537803c1c8a076e130df5674b58mikesamuel 34e867904c8295537803c1c8a076e130df5674b58mikesamuelimport java.util.List; 44e867904c8295537803c1c8a076e130df5674b58mikesamuel 54e867904c8295537803c1c8a076e130df5674b58mikesamuelimport javax.annotation.Nullable; 64e867904c8295537803c1c8a076e130df5674b58mikesamuelimport javax.annotation.concurrent.Immutable; 74e867904c8295537803c1c8a076e130df5674b58mikesamuel 84e867904c8295537803c1c8a076e130df5674b58mikesamuel/** 94e867904c8295537803c1c8a076e130df5674b58mikesamuel * A policy that can be applied to an element to decide whether or not to 104e867904c8295537803c1c8a076e130df5674b58mikesamuel * allow it in the output, possibly after transforming attributes. 114e867904c8295537803c1c8a076e130df5674b58mikesamuel * <p> 124e867904c8295537803c1c8a076e130df5674b58mikesamuel * Element policies are applied <strong>after</strong> 134e867904c8295537803c1c8a076e130df5674b58mikesamuel * {@link AttributePolicy attribute policies} so 144e867904c8295537803c1c8a076e130df5674b58mikesamuel * they can be used to add extra attributes. 154e867904c8295537803c1c8a076e130df5674b58mikesamuel * 164e867904c8295537803c1c8a076e130df5674b58mikesamuel * @author Mike Samuel 174e867904c8295537803c1c8a076e130df5674b58mikesamuel * @see HtmlPolicyBuilder#allowElements(ElementPolicy, String...) 184e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 194e867904c8295537803c1c8a076e130df5674b58mikesamuel@TCB public interface ElementPolicy { 204e867904c8295537803c1c8a076e130df5674b58mikesamuel /** 214e867904c8295537803c1c8a076e130df5674b58mikesamuel * @param elementName the lower-case element name. 224e867904c8295537803c1c8a076e130df5674b58mikesamuel * @param attrs a list of alternating attribute names and values. 234e867904c8295537803c1c8a076e130df5674b58mikesamuel * The list may be added to or removed from. When removing, be 244e867904c8295537803c1c8a076e130df5674b58mikesamuel * careful to remove both the name and its associated value. 254e867904c8295537803c1c8a076e130df5674b58mikesamuel * 264e867904c8295537803c1c8a076e130df5674b58mikesamuel * @return {@code null} to disallow the element, or the adjusted element name. 274e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 284e867904c8295537803c1c8a076e130df5674b58mikesamuel public @Nullable String apply(String elementName, List<String> attrs); 294e867904c8295537803c1c8a076e130df5674b58mikesamuel 304e867904c8295537803c1c8a076e130df5674b58mikesamuel 314e867904c8295537803c1c8a076e130df5674b58mikesamuel /** Utilities for working with element policies. */ 324e867904c8295537803c1c8a076e130df5674b58mikesamuel public static final class Util { 334e867904c8295537803c1c8a076e130df5674b58mikesamuel private Util() { /* uninstantiable */ } 344e867904c8295537803c1c8a076e130df5674b58mikesamuel 354e867904c8295537803c1c8a076e130df5674b58mikesamuel /** 364e867904c8295537803c1c8a076e130df5674b58mikesamuel * Given zero or more element policies, returns an element policy equivalent 374e867904c8295537803c1c8a076e130df5674b58mikesamuel * to applying them in order failing early if any of them fails. 384e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 394e867904c8295537803c1c8a076e130df5674b58mikesamuel public static final ElementPolicy join(ElementPolicy... policies) { 404e867904c8295537803c1c8a076e130df5674b58mikesamuel 414e867904c8295537803c1c8a076e130df5674b58mikesamuel class PolicyJoiner { 424e867904c8295537803c1c8a076e130df5674b58mikesamuel ElementPolicy last = null; 434e867904c8295537803c1c8a076e130df5674b58mikesamuel ElementPolicy out = null; 444e867904c8295537803c1c8a076e130df5674b58mikesamuel 454e867904c8295537803c1c8a076e130df5674b58mikesamuel void join(ElementPolicy p) { 464e867904c8295537803c1c8a076e130df5674b58mikesamuel if (p == REJECT_ALL_ELEMENT_POLICY) { 474e867904c8295537803c1c8a076e130df5674b58mikesamuel out = p; 484e867904c8295537803c1c8a076e130df5674b58mikesamuel } else if (out != REJECT_ALL_ELEMENT_POLICY) { 494e867904c8295537803c1c8a076e130df5674b58mikesamuel if (p instanceof JoinedElementPolicy) { 504e867904c8295537803c1c8a076e130df5674b58mikesamuel JoinedElementPolicy jep = (JoinedElementPolicy) p; 514e867904c8295537803c1c8a076e130df5674b58mikesamuel join(jep.first); 524e867904c8295537803c1c8a076e130df5674b58mikesamuel join(jep.second); 534e867904c8295537803c1c8a076e130df5674b58mikesamuel } else if (p != last) { 544e867904c8295537803c1c8a076e130df5674b58mikesamuel last = p; 554e867904c8295537803c1c8a076e130df5674b58mikesamuel if (out == null || out == IDENTITY_ELEMENT_POLICY) { 564e867904c8295537803c1c8a076e130df5674b58mikesamuel out = p; 574e867904c8295537803c1c8a076e130df5674b58mikesamuel } else if (p != IDENTITY_ELEMENT_POLICY) { 584e867904c8295537803c1c8a076e130df5674b58mikesamuel out = new JoinedElementPolicy(out, p); 594e867904c8295537803c1c8a076e130df5674b58mikesamuel } 604e867904c8295537803c1c8a076e130df5674b58mikesamuel } 614e867904c8295537803c1c8a076e130df5674b58mikesamuel } 624e867904c8295537803c1c8a076e130df5674b58mikesamuel } 634e867904c8295537803c1c8a076e130df5674b58mikesamuel } 644e867904c8295537803c1c8a076e130df5674b58mikesamuel 654e867904c8295537803c1c8a076e130df5674b58mikesamuel PolicyJoiner pu = new PolicyJoiner(); 664e867904c8295537803c1c8a076e130df5674b58mikesamuel for (ElementPolicy policy : policies) { 674e867904c8295537803c1c8a076e130df5674b58mikesamuel if (policy == null) { continue; } 684e867904c8295537803c1c8a076e130df5674b58mikesamuel pu.join(policy); 694e867904c8295537803c1c8a076e130df5674b58mikesamuel } 704e867904c8295537803c1c8a076e130df5674b58mikesamuel return pu.out != null ? pu.out : IDENTITY_ELEMENT_POLICY; 714e867904c8295537803c1c8a076e130df5674b58mikesamuel } 724e867904c8295537803c1c8a076e130df5674b58mikesamuel 734e867904c8295537803c1c8a076e130df5674b58mikesamuel } 744e867904c8295537803c1c8a076e130df5674b58mikesamuel 754e867904c8295537803c1c8a076e130df5674b58mikesamuel public static final ElementPolicy IDENTITY_ELEMENT_POLICY 764e867904c8295537803c1c8a076e130df5674b58mikesamuel = new ElementPolicy() { 774e867904c8295537803c1c8a076e130df5674b58mikesamuel public String apply(String elementName, List<String> attrs) { 784e867904c8295537803c1c8a076e130df5674b58mikesamuel return elementName; 794e867904c8295537803c1c8a076e130df5674b58mikesamuel } 804e867904c8295537803c1c8a076e130df5674b58mikesamuel }; 814e867904c8295537803c1c8a076e130df5674b58mikesamuel 824e867904c8295537803c1c8a076e130df5674b58mikesamuel public static final ElementPolicy REJECT_ALL_ELEMENT_POLICY 834e867904c8295537803c1c8a076e130df5674b58mikesamuel = new ElementPolicy() { 844e867904c8295537803c1c8a076e130df5674b58mikesamuel public @Nullable String apply(String elementName, List<String> attrs) { 854e867904c8295537803c1c8a076e130df5674b58mikesamuel return null; 864e867904c8295537803c1c8a076e130df5674b58mikesamuel } 874e867904c8295537803c1c8a076e130df5674b58mikesamuel }; 884e867904c8295537803c1c8a076e130df5674b58mikesamuel 894e867904c8295537803c1c8a076e130df5674b58mikesamuel} 904e867904c8295537803c1c8a076e130df5674b58mikesamuel 914e867904c8295537803c1c8a076e130df5674b58mikesamuel@Immutable 924e867904c8295537803c1c8a076e130df5674b58mikesamuelfinal class JoinedElementPolicy implements ElementPolicy { 934e867904c8295537803c1c8a076e130df5674b58mikesamuel final ElementPolicy first, second; 944e867904c8295537803c1c8a076e130df5674b58mikesamuel 954e867904c8295537803c1c8a076e130df5674b58mikesamuel JoinedElementPolicy(ElementPolicy first, ElementPolicy second) { 964e867904c8295537803c1c8a076e130df5674b58mikesamuel this.first = first; 974e867904c8295537803c1c8a076e130df5674b58mikesamuel this.second = second; 984e867904c8295537803c1c8a076e130df5674b58mikesamuel } 994e867904c8295537803c1c8a076e130df5674b58mikesamuel 1004e867904c8295537803c1c8a076e130df5674b58mikesamuel public @Nullable String apply(String elementName, List<String> attrs) { 1014e867904c8295537803c1c8a076e130df5674b58mikesamuel elementName = first.apply(elementName, attrs); 1024e867904c8295537803c1c8a076e130df5674b58mikesamuel return elementName != null ? second.apply(elementName, attrs) : null; 1034e867904c8295537803c1c8a076e130df5674b58mikesamuel } 1044e867904c8295537803c1c8a076e130df5674b58mikesamuel} 105