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

com.liferay.portal.security.antisamy.internal.AntiSamySanitizerImpl Maven / Gradle / Ivy

There is a newer version: 6.0.36
Show newest version
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.security.antisamy.internal;

import com.liferay.petra.string.CharPool;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.sanitizer.Sanitizer;
import com.liferay.portal.kernel.sanitizer.SanitizerException;
import com.liferay.portal.kernel.util.ContentTypes;
import com.liferay.portal.kernel.util.Validator;

import java.io.InputStream;

import java.net.URL;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.owasp.validator.html.AntiSamy;
import org.owasp.validator.html.CleanResults;
import org.owasp.validator.html.Policy;

/**
 * @author Zsolt Balogh
 * @author Brian Wing Shun Chan
 */
public class AntiSamySanitizerImpl implements Sanitizer {

	public AntiSamySanitizerImpl(
		String[] blacklist, URL url, String[] whitelist) {

		try (InputStream inputStream = url.openStream()) {
			_policy = Policy.getInstance(inputStream);
		}
		catch (Exception exception) {
			throw new IllegalStateException(
				"Unable to initialize policy", exception);
		}

		if (blacklist != null) {
			for (String blacklistItem : blacklist) {
				blacklistItem = blacklistItem.trim();

				if (!blacklistItem.isEmpty()) {
					blacklistItem = _stripTrailingStar(blacklistItem);

					_blacklist.add(blacklistItem);
				}
			}
		}

		if (whitelist != null) {
			for (String whitelistItem : whitelist) {
				whitelistItem = whitelistItem.trim();

				if (!whitelistItem.isEmpty()) {
					whitelistItem = _stripTrailingStar(whitelistItem);

					_whitelist.add(whitelistItem);
				}
			}
		}
	}

	public void addPolicy(String className, URL url) {
		try (InputStream inputStream = url.openStream()) {
			Policy policy = Policy.getInstance(inputStream);

			_policies.put(className, policy);
		}
		catch (Exception exception) {
			throw new IllegalStateException(
				"Unable to initialize policy", exception);
		}
	}

	public void removePolicy(String className) {
		_policies.remove(className);
	}

	@Override
	public String sanitize(
			long companyId, long groupId, long userId, String className,
			long classPK, String contentType, String[] modes, String content,
			Map options)
		throws SanitizerException {

		if (_log.isDebugEnabled()) {
			_log.debug(
				StringBundler.concat("Sanitizing ", className, "#", classPK));
		}

		if (Validator.isNull(content) || Validator.isNull(contentType) ||
			!contentType.equals(ContentTypes.TEXT_HTML) ||
			_isWhitelisted(className, classPK)) {

			return content;
		}

		Thread currentThread = Thread.currentThread();

		ClassLoader contextClassLoader = currentThread.getContextClassLoader();

		currentThread.setContextClassLoader(
			AntiSamySanitizerImpl.class.getClassLoader());

		try {
			CleanResults cleanResults = null;

			AntiSamy antiSamy = new AntiSamy();

			if (_isConfigured(className, classPK)) {
				Policy policy = _policies.get(className);

				cleanResults = antiSamy.scan(content, policy, AntiSamy.SAX);
			}
			else {
				cleanResults = antiSamy.scan(content, _policy);
			}

			if (_log.isWarnEnabled()) {
				for (String errorMessage : cleanResults.getErrorMessages()) {
					_log.warn(errorMessage);
				}
			}

			return cleanResults.getCleanHTML();
		}
		catch (Exception exception) {
			_log.error("Unable to sanitize input", exception);

			throw new SanitizerException(exception);
		}
		finally {
			currentThread.setContextClassLoader(contextClassLoader);
		}
	}

	private boolean _isConfigured(String className, long classPK) {
		String classNameAndClassPK = className + StringPool.POUND + classPK;

		for (String policyClassName : _policies.keySet()) {
			if (classNameAndClassPK.startsWith(policyClassName)) {
				return true;
			}
		}

		return false;
	}

	private boolean _isWhitelisted(String className, long classPK) {
		String classNameAndClassPK = className + StringPool.POUND + classPK;

		for (String blacklistItem : _blacklist) {
			if (blacklistItem.equals(StringPool.STAR) ||
				classNameAndClassPK.startsWith(blacklistItem)) {

				return false;
			}
		}

		for (String whitelistItem : _whitelist) {
			if (whitelistItem.equals(StringPool.STAR) ||
				classNameAndClassPK.startsWith(whitelistItem)) {

				return true;
			}
		}

		return false;
	}

	private String _stripTrailingStar(String item) {
		if (item.equals(StringPool.STAR)) {
			return item;
		}

		char c = item.charAt(item.length() - 1);

		if (c == CharPool.STAR) {
			return item.substring(0, item.length() - 1);
		}

		return item;
	}

	private static final Log _log = LogFactoryUtil.getLog(
		AntiSamySanitizerImpl.class);

	private final List _blacklist = new ArrayList<>();
	private final Map _policies = new HashMap<>();
	private final Policy _policy;
	private final List _whitelist = new ArrayList<>();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy