// Copyright (c) 2011, Mike Samuel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// Neither the name of the OWASP nor the names of its contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package org.owasp.html;

import java.util.Map;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

/**
 * A factory that can be used to link a sanitizer to an output receiver and that
 * provides a convenient <code>{@link PolicyFactory#sanitize sanitize}</code>
 * method and a <code>{@link PolicyFactory#and and}</code> method to compose
 * policies.
 *
 * @author Mike Samuel <mikesamuel@gmail.com>
 */
@ThreadSafe
@Immutable
@TCB
public final class PolicyFactory
    implements Function<HtmlStreamEventReceiver, HtmlSanitizer.Policy> {

  private final ImmutableMap<String, ElementAndAttributePolicies> policies;
  private final ImmutableMap<String, AttributePolicy> globalAttrPolicies;
  private final ImmutableSet<String> textContainers;

  PolicyFactory(
      ImmutableMap<String, ElementAndAttributePolicies> policies,
      ImmutableSet<String> textContainers,
      ImmutableMap<String, AttributePolicy> globalAttrPolicies) {
    this.policies = policies;
    this.textContainers = textContainers;
    this.globalAttrPolicies = globalAttrPolicies;
  }

  /** Produces a sanitizer that emits tokens to {@code out}. */
  public HtmlSanitizer.Policy apply(@Nonnull HtmlStreamEventReceiver out) {
    return new ElementAndAttributePolicyBasedSanitizerPolicy(
        out, policies, textContainers);
  }

  /**
   * Produces a sanitizer that emits tokens to {@code out} and that notifies
   * any {@code listener} of any dropped tags and attributes.
   * @param out a renderer that receives approved tokens only.
   * @param listener if non-null, receives notifications of tags and attributes
   *     that were rejected by the policy.  This may tie into intrusion
   *     detection systems.
   * @param context if {@code (listener != null)} then the context value passed
   *     with notifications.  This can be used to let the listener know from
   *     which connection or request the questionable HTML was received.
   */
  public <CTX> HtmlSanitizer.Policy apply(
      HtmlStreamEventReceiver out, @Nullable HtmlChangeListener<CTX> listener,
      @Nullable CTX context) {
    if (listener == null) {
      return apply(out);
    } else {
      HtmlChangeReporter<CTX> r = new HtmlChangeReporter<CTX>(
          out, listener, context);
      r.setPolicy(apply(r.getWrappedRenderer()));
      return r.getWrappedPolicy();
    }
  }

  /** A convenience function that sanitizes a string of HTML. */
  public String sanitize(@Nullable String html) {
    return sanitize(html, null, null);
  }

  /**
   * A convenience function that sanitizes a string of HTML and reports
   * the names of rejected element and attributes to listener.
   * @param html the string of HTML to sanitize.
   * @param listener if non-null, receives notifications of tags and attributes
   *     that were rejected by the policy.  This may tie into intrusion
   *     detection systems.
   * @param context if {@code (listener != null)} then the context value passed
   *     with notifications.  This can be used to let the listener know from
   *     which connection or request the questionable HTML was received.
   * @return a string of HTML that complies with this factory's policy.
   */
  public <CTX> String sanitize(
      @Nullable String html,
      @Nullable HtmlChangeListener<CTX> listener, @Nullable CTX context) {
    if (html == null) { return ""; }
    StringBuilder out = new StringBuilder(html.length());
    HtmlSanitizer.sanitize(
        html,
        apply(HtmlStreamRenderer.create(out, Handler.DO_NOTHING),
              listener, context));
    return out.toString();
  }

  /**
   * Produces a factory that allows the union of the grants, and intersects
   * policies where they overlap on a particular granted attribute or element
   * name.
   */
  public PolicyFactory and(PolicyFactory f) {
    ImmutableMap.Builder<String, ElementAndAttributePolicies> b
        = ImmutableMap.builder();
    // Merge this and f into a map of element names to attribute policies.
    for (Map.Entry<String, ElementAndAttributePolicies> e
        : policies.entrySet()) {
      String elName = e.getKey();
      ElementAndAttributePolicies p = e.getValue();
      ElementAndAttributePolicies q = f.policies.get(elName);
      if (q != null) {
        p = p.and(q);
      } else {
        // Mix in any globals that are not already taken into account in this.
        p = p.andGlobals(f.globalAttrPolicies);
      }
      b.put(elName, p);
    }
    // Handle keys that are in f but not in this.
    for (Map.Entry<String, ElementAndAttributePolicies> e
        : f.policies.entrySet()) {
      String elName = e.getKey();
      if (!policies.containsKey(elName)) {
        ElementAndAttributePolicies p = e.getValue();
        // Mix in any globals that are not already taken into account in this.
        p = p.andGlobals(f.globalAttrPolicies);
        b.put(elName, p);
      }
    }
    ImmutableSet<String> textContainers;
    if (this.textContainers.containsAll(f.textContainers)) {
      textContainers = this.textContainers;
    } else if (f.textContainers.containsAll(this.textContainers)) {
      textContainers = f.textContainers;
    } else {
      textContainers = ImmutableSet.<String>builder()
        .addAll(this.textContainers)
        .addAll(f.textContainers)
        .build();
    }
    ImmutableMap<String, AttributePolicy> allGlobalAttrPolicies;
    if (f.globalAttrPolicies.isEmpty()) {
      allGlobalAttrPolicies = this.globalAttrPolicies;
    } else if (this.globalAttrPolicies.isEmpty()) {
      allGlobalAttrPolicies = f.globalAttrPolicies;
    } else {
      ImmutableMap.Builder<String, AttributePolicy> ab = ImmutableMap.builder();
      for (Map.Entry<String, AttributePolicy> e
          : this.globalAttrPolicies.entrySet()) {
        String attrName = e.getKey();
        ab.put(
            attrName,
            AttributePolicy.Util.join(
                e.getValue(), f.globalAttrPolicies.get(attrName)));
      }
      for (Map.Entry<String, AttributePolicy> e
          : f.globalAttrPolicies.entrySet()) {
        String attrName = e.getKey();
        if (!this.globalAttrPolicies.containsKey(attrName)) {
          ab.put(attrName, e.getValue());
        }
      }
      allGlobalAttrPolicies = ab.build();
    }
    return new PolicyFactory(b.build(), textContainers, allGlobalAttrPolicies);
  }
}
