/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~ Licensed to the Apache Software Foundation (ASF) under one
 ~ or more contributor license agreements.  See the NOTICE file
 ~ distributed with this work for additional information
 ~ regarding copyright ownership.  The ASF licenses this file
 ~ to you under the Apache License, Version 2.0 (the
 ~ "License"); you may not use this file except in compliance
 ~ with the License.  You may obtain a copy of the License at
 ~
 ~   http://www.apache.org/licenses/LICENSE-2.0
 ~
 ~ Unless required by applicable law or agreed to in writing,
 ~ software distributed under the License is distributed on an
 ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 ~ KIND, either express or implied.  See the License for the
 ~ specific language governing permissions and limitations
 ~ under the License.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
package org.apache.sling.xss.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.sling.xss.impl.style.CssValidator;
import org.apache.sling.xss.impl.xml.AntiSamyPolicy;
import org.apache.sling.xss.impl.xml.Attribute;
import org.apache.sling.xss.impl.xml.Tag;
import org.jetbrains.annotations.Nullable;
import org.owasp.html.AttributePolicy;
import org.owasp.html.HtmlPolicyBuilder;
import org.owasp.html.PolicyFactory;

import com.google.common.base.Predicate;

public class AntiSamyPolicyAdapter {
    private static final String ALLOW_DYNAMIC_ATTRIBUTES = "allowDynamicAttributes";
    private static final String REMOVE_TAG_ON_INVALID_ACTION = "removeTag";

    private final List<String> onInvalidRemoveTagList = new ArrayList<>();
    private final Map<String, AttributePolicy> dynamicAttributesPolicyMap = new HashMap<>();

    private PolicyFactory policyFactory;
    private CssValidator cssValidator;

    public AntiSamyPolicyAdapter(AntiSamyPolicy policy) {
        removeAttributeGuards();
        HtmlPolicyBuilder policyBuilder = new HtmlPolicyBuilder();

        cssValidator = new CssValidator(policy.getCssPolicy());

        // ------------ this is for the global attributes -------------
        Map<String, Attribute> globalAttributes = policy.getGlobalAttributes();

        for (Attribute attribute : globalAttributes.values()) {
            if (attribute.getOnInvalid().equals(REMOVE_TAG_ON_INVALID_ACTION)) {
                onInvalidRemoveTagList.add(attribute.getName());
            }

            if (CssValidator.STYLE_ATTRIBUTE_NAME.equals(attribute.getName())) {
                // we match style tags separately
                policyBuilder.allowAttributes(attribute.getName()).matching(cssValidator.newCssAttributePolicy())
                        .globally();
            } else {
                List<String> literalList = attribute.getLiterals();
                List<Pattern> patternList = attribute.getPatternList();

                if (!literalList.isEmpty() && !patternList.isEmpty()) {
                    // if both, the patterns and the literals are not empty, the value should be checked with them with an OR and not with an AND.
                    policyBuilder.allowAttributes(attribute.getName())
                        .matching(matchesPatternsOrLiterals(patternList, true, literalList))
                        .globally();
                }
                else if (!literalList.isEmpty()) {
                    policyBuilder.allowAttributes(attribute.getName())
                        .matching(true, literalList.toArray(new String[0]))
                        .globally();
                }
                else if (!patternList.isEmpty()) {
                    policyBuilder.allowAttributes(attribute.getName())
                            .matching(matchesToPatterns(patternList))
                            .globally();
                } else {
                    policyBuilder.allowAttributes(attribute.getName()).globally();
                }
            }
        }

        // ------------ this is for the allowed empty tags -------------
        List<String> allowedEmptyTags = policy.getAllowedEmptyTags();
        for (String allowedEmptyTag : allowedEmptyTags) {
            policyBuilder.allowWithoutAttributes(allowedEmptyTag);
        }

        // ------------ this is for the tag rules -------------
        Map<String, Tag> tagMap = policy.getTagRules();
        for (Map.Entry<String, Tag> tag : tagMap.entrySet()) {

            String tagAction = tag.getValue().getAction();
            switch (tagAction) {
                // Tag.action
                case AntiSamyActions.TRUNCATE:
                    policyBuilder.allowElements(tag.getValue().getName());
                    break;

                // filter: remove tags, but keep content,
                case AntiSamyActions.FILTER:
                    break;

                // remove: remove tag and contents
                case AntiSamyActions.REMOVE:
                    policyBuilder.disallowElements(tag.getValue().getName());
                    break;

                case AntiSamyActions.VALIDATE:
                case "":
                    policyBuilder.allowElements(tag.getValue().getName());
                    boolean styleSeen = false;
                    // get the allowed Attributes for the tag
                    Map<String, Attribute> allowedAttributes = tag.getValue().getAttributeMap();
                    // if there are allowed Attributes, map over them
                    for (Attribute attribute : allowedAttributes.values()) {

                        if (attribute.getOnInvalid().equals(REMOVE_TAG_ON_INVALID_ACTION)) {
                            onInvalidRemoveTagList.add(attribute.getName());
                        }

                        styleSeen = CssValidator.STYLE_ATTRIBUTE_NAME.equals(attribute.getName());

                        List<String> literalList = attribute.getLiterals();
                        List<Pattern> patternList = attribute.getPatternList();

                        if (!literalList.isEmpty() && !patternList.isEmpty()) {
                            // if both, the patterns and the literals are not empty, the value should be checked with them with an OR and not with an AND.
                            policyBuilder.allowAttributes(attribute.getName())
                                .matching(matchesPatternsOrLiterals(patternList, true, literalList))
                                .onElements(tag.getValue().getName());
                        }
                        else if (!literalList.isEmpty()) {
                            policyBuilder.allowAttributes(attribute.getName())
                                .matching(true, literalList.toArray(new String[0]))
                                .onElements(tag.getValue().getName());
                            policyBuilder.allowAttributes(attribute.getName()).onElements(tag.getValue().getName());
                        }
                        else if (!patternList.isEmpty()) {
                            policyBuilder.allowAttributes(attribute.getName())
                                    .matching(matchesToPatterns(patternList))
                                    .onElements(tag.getValue().getName());
                        }
                    }

                    if (!styleSeen) {
                        policyBuilder.allowAttributes(CssValidator.STYLE_ATTRIBUTE_NAME)
                                .matching(cssValidator.newCssAttributePolicy()).onElements(tag.getValue().getName());
                    }
                    break;

                default:
                    throw new IllegalArgumentException("No tag action found.");
            }
        }

        // disallow style tag on specific elements
        policyBuilder.disallowAttributes(CssValidator.STYLE_ATTRIBUTE_NAME)
                .onElements(cssValidator.getDisallowedTagNames().toArray(new String[0]));

        // ---------- dynamic attributes ------------
        Map<String, Attribute> dynamicAttributes = new HashMap<>();

        // checks if the dynamic attributes are allowed
        if (policy.getDirectives().get(ALLOW_DYNAMIC_ATTRIBUTES).equals("true")) {
            dynamicAttributes.putAll(policy.getDynamicAttributes());
            for (Attribute attribute : dynamicAttributes.values()) {
                if (attribute.getOnInvalid().equals(REMOVE_TAG_ON_INVALID_ACTION)) {
                    onInvalidRemoveTagList.add(attribute.getName());
                }

                List<Pattern> regexsFromAttribute = attribute.getPatternList();
                List<String> allowedValuesFromAttribute = attribute.getLiterals();

                dynamicAttributesPolicyMap.put(attribute.getName(), newDynamicAttributePolicy(regexsFromAttribute, true, allowedValuesFromAttribute));
            }
        }

        policyFactory = policyBuilder.allowTextIn(CssValidator.STYLE_TAG_NAME).toFactory();

    }

    public PolicyFactory getHtmlCleanerPolicyFactory() {
        return policyFactory;
    }

    public Map<String, AttributePolicy> getDynamicAttributesPolicyMap() {
        return dynamicAttributesPolicyMap;
    }

    public List<String> getOnInvalidRemoveTagList() {
        return onInvalidRemoveTagList;
    }

    public CssValidator getCssValidator() {
        return cssValidator;
    }

    private static Predicate<String> matchesToPatterns(List<Pattern> patternList) {
        return new Predicate<String>() {
            @Override
            public boolean apply(String s) {
                for (Pattern pattern : patternList) {
                    if (pattern.matcher(s).matches()) {
                        return true;
                    }
                }
                return false;
            }
        };
    }

    private static Predicate<String> matchesPatternsOrLiterals(List<Pattern> patternList, boolean ignoreCase, List<String> literalList) {
        return new Predicate<String>() {
            @Override
            public boolean apply(String s) {
                // check if the string matches to the pattern or one of the literal
                s = ignoreCase ? s.toLowerCase() : s;
                return matchesToPatterns(patternList).apply(s) || literalList.contains(s);
            }
        };
    }

    public AttributePolicy newDynamicAttributePolicy(final List<Pattern> patternList, final boolean ignoreCase, final List<String> literalList) {
        return new AttributePolicy() {
            @Override
            public @Nullable String apply(String elementName, String attributeName, String value) {
                if (!literalList.isEmpty() && !patternList.isEmpty()) {
                    return matchesPatternsOrLiterals(patternList, ignoreCase, literalList).apply(value) ? value : null;

                } else if (!literalList.isEmpty()) {
                    value = ignoreCase ? value.toLowerCase() : value;
                    return literalList.contains(value) ? value : null;

                } else if (!patternList.isEmpty()) {
                    return matchesToPatterns(patternList).apply(value) ? value : null;
                }
                return null;
            }
        };
    }

    // java html sanitizer has some default Attribute Guards, which we don't want.
    // So we are removing them here
    private void removeAttributeGuards() {
        try {
            Field guards = HtmlPolicyBuilder.class.getDeclaredField("ATTRIBUTE_GUARDS");
            letMeIn(guards);
            guards.set(null, new HashMap<>());
        } catch (ReflectiveOperationException e) {
            throw new IllegalStateException(e);
        }
    }

    private void letMeIn(Field inaccessible) throws ReflectiveOperationException {
        if (!inaccessible.isAccessible())
            inaccessible.setAccessible(true);
        if ((inaccessible.getModifiers() & Modifier.FINAL) != 0) {
            Field modifiersField = null;
            try { 
                modifiersField = Field.class.getDeclaredField("modifiers");
            } catch ( NoSuchFieldException e ) {
                // fallback for Java 12+
                Method getDeclaredFields = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
                getDeclaredFields.setAccessible(true);
                Field[] fields = (Field[]) getDeclaredFields.invoke(Field.class, false);
                for ( Field field : fields ) {
                    if ( "modifiers".equals(field.getName()) ) {
                        modifiersField = field;
                    }
                }
            }
            if ( modifiersField == null )
                throw new IllegalAccessException("Unable to locate modifiers field " + Field.class.getName() + ", aborting setup");
            modifiersField.setAccessible(true);
            modifiersField.setInt(inaccessible, inaccessible.getModifiers() & ~Modifier.FINAL);
        }
    }
}