All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.owasp.validator.html.model.Attribute Maven / Gradle / Ivy

There is a newer version: 6.0.36
Show newest version
/*
 * Copyright (c) 2007-2013, Arshan Dabirsiaghi, Jason Li, Kristian Rosenvold
 * 
 * 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 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 OWNER 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.validator.html.model;

import java.util.*;
import java.util.regex.Pattern;

import static org.owasp.validator.html.model.Tag.ANY_NORMAL_WHITESPACES;
import static org.owasp.validator.html.model.Tag.ATTRIBUTE_DIVIDER;
import static org.owasp.validator.html.model.Tag.CLOSE_ATTRIBUTE;

/**
 * A model for HTML attributes and the "rules" they must follow (either literals or regular expressions) in
 * order to be considered valid.
 * 
 * @author Arshan Dabirsiaghi
 * @author Kristian Rosenvold
 *
 */

public class Attribute  {

	private final String name;
	private final String description;
	private final String onInvalid;
    private final List allowedValues;
    private final Pattern[] allowedRegExps;
    private final Set allowedValuesLower;

    public Attribute(String name, List allowedRegexps, List allowedValues, String onInvalidStr, String description) {
        this.name = name;
        this.allowedRegExps = allowedRegexps.toArray(new Pattern[ allowedRegexps.size()]);
        this.allowedValues = Collections.unmodifiableList( allowedValues);
        Set allowedValuesLower = new HashSet();
        for (String allowedValue : allowedValues) {
            allowedValuesLower.add( allowedValue.toLowerCase());
        }

        this.allowedValuesLower = allowedValuesLower;
        this.onInvalid = onInvalidStr;
        this.description = description;
    }

    public boolean matchesAllowedExpression(String value){
        String input = value.toLowerCase();
        for (Pattern pattern : allowedRegExps) {
            if (pattern != null && pattern.matcher(input).matches()) {
                return true;
            }
        }
        return false;
    }

    public boolean containsAllowedValue(String valueInLowerCase){
        return allowedValuesLower.contains(valueInLowerCase);
    }

	public String getName() {
		return name;
	}

    /**
	 * 
	 * @return The onInvalid value a tag could have, from the list of "filterTag", "removeTag" and "removeAttribute" 
	 */
	public String getOnInvalid() {
		return onInvalid;
	}


    public Attribute mutate(String onInvalid, String description)  {
        return new Attribute(name, Arrays.asList(allowedRegExps), allowedValues, onInvalid != null && onInvalid.length() != 0 ? onInvalid : this.onInvalid,
                description != null && description.length() != 0 ? description : this.description);
    }

    public String matcherRegEx(boolean hasNext){
        // 

StringBuilder regExp = new StringBuilder(); regExp.append(this.getName()).append(ANY_NORMAL_WHITESPACES).append("=").append(ANY_NORMAL_WHITESPACES).append("\"").append(Tag.OPEN_ATTRIBUTE); boolean hasRegExps = allowedRegExps.length > 0; if (allowedRegExps.length + allowedValues.size() > 0) { /* * Go through and add static values to the regular expression. */ Iterator allowedValues = this.allowedValues.iterator(); while (allowedValues.hasNext()) { String allowedValue = allowedValues.next(); regExp.append(Tag.escapeRegularExpressionCharacters(allowedValue)); if (allowedValues.hasNext() || hasRegExps) { regExp.append(ATTRIBUTE_DIVIDER); } } /* * Add the regular expressions for this attribute value to the mother regular expression. */ Iterator allowedRegExps = Arrays.asList(this.allowedRegExps).iterator(); while (allowedRegExps.hasNext()) { Pattern allowedRegExp = allowedRegExps.next(); regExp.append(allowedRegExp.pattern()); if (allowedRegExps.hasNext()) { regExp.append(ATTRIBUTE_DIVIDER); } } if (this.allowedRegExps.length + this.allowedValues.size() > 0) { regExp.append(CLOSE_ATTRIBUTE); } regExp.append("\"" + ANY_NORMAL_WHITESPACES); if (hasNext) { regExp.append(ATTRIBUTE_DIVIDER); } } return regExp.toString(); } /** * This method takes the current rel attribute values and, depending on which ones to add, * appends the corresponding values if they are not already present. It is meant to be used with anchor tags. * * @param addNofollow Specifies if "nofollow" value should be added in case it is not present. * @param addNoopenerAndNoreferrer Specifies if "noopener noreferrer" value should be added in case * it is not present. * @param currentRelValue Current rel attribute value, it will be merged with the values specified * from the previous parameters. * @return The new rel attribute value to replace in an anchor tag. */ public static String mergeRelValuesInAnchor(boolean addNofollow, boolean addNoopenerAndNoreferrer, String currentRelValue) { String newRelValue = ""; if (currentRelValue == null || currentRelValue.isEmpty()) { if (addNofollow) newRelValue = "nofollow"; if (addNoopenerAndNoreferrer) newRelValue += " noopener noreferrer"; } else { ArrayList relTokens = new ArrayList<>(); newRelValue = currentRelValue; for (String value: currentRelValue.split(" ")) { relTokens.add(value.toLowerCase()); } if (addNofollow && !relTokens.contains("nofollow")) { newRelValue += " nofollow"; } if (addNoopenerAndNoreferrer) { if (!relTokens.contains("noopener")){ newRelValue += " noopener"; } if (!relTokens.contains("noreferrer")){ newRelValue += " noreferrer"; } } } return newRelValue.trim(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy