001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ugc; 029 030import org.opencms.json.JSONException; 031import org.opencms.json.JSONObject; 032import org.opencms.ugc.CmsUgcValueTransformerConfiguration.CmsUgcSingleValueTransformer.TransformType; 033 034import java.util.Collections; 035import java.util.HashMap; 036import java.util.Map; 037import java.util.Set; 038 039/** 040 * Wrapper for a value transformer configuration that is provided in content's schema file 041 * in the parameters section as follows: 042 * 043 * <pre> 044 * <parameters> 045 * <param name="ugc.values.transformer"> 046 * { 047 * "Paragraph/Text": { 048 * "transformer": "antisamy" 049 * }, 050 * "Title": { 051 * "transformer": "antisamy", 052 * "config": { 053 * "policy": "/system/modules/my.module/resources/ugc/antisamy-policy.xml" 054 * } 055 * }, 056 * "Author": { 057 * "transformer": "none" 058 * }, 059 * "Email": { 060 * "transformer": "escape" 061 * } 062 * } 063 * </param> 064 * </parameter> 065 * </pre> 066 * 067 * The configuration defines how values that are added via UGC at a certain path have to be transformed, primarily to not cause XSS or other issues. 068 */ 069public class CmsUgcValueTransformerConfiguration { 070 071 /** 072 * The transformer for a single value. 073 */ 074 public static class CmsUgcSingleValueTransformer { 075 076 /** 077 * The transformer type. 078 */ 079 public static enum TransformType { 080 /** XML escape the value */ 081 escape, 082 /** Clean the value via AntiSamy */ 083 antisamy, 084 /** Leave the value unchanged. */ 085 none 086 } 087 088 /** The default single value transformer. */ 089 public static CmsUgcSingleValueTransformer DEFAULT = new CmsUgcSingleValueTransformer(TransformType.escape); 090 /** The mapping type. */ 091 private TransformType m_type; 092 /** The (optional) additional configuration for the mapping type. */ 093 private JSONObject m_config; 094 095 /** 096 * Creates a new mapping security value of the provided type. 097 * @param type the mapping type. 098 */ 099 public CmsUgcSingleValueTransformer(TransformType type) { 100 101 m_type = type == null ? TransformType.escape : type; 102 } 103 104 /** 105 * Creates a new mapping security value of the provided type. 106 * @param type the mapping type. 107 * @param config the (optional) additional configuration for the mapping. 108 */ 109 public CmsUgcSingleValueTransformer(TransformType type, JSONObject config) { 110 111 m_type = type; 112 m_config = TransformType.antisamy.equals(m_type) ? config : null; 113 } 114 115 /** 116 * @return the optional configuration for the mapping security. 117 */ 118 public JSONObject getConfig() { 119 120 return m_config; 121 } 122 123 /** 124 * @return the type of the mapping security 125 */ 126 public TransformType getType() { 127 128 return m_type; 129 } 130 } 131 132 /** JSON key in the transformer configuration. */ 133 private static final String JSON_KEY_TRANSFORMER = "transformer"; 134 135 /** JSON key in the transformer configuration. */ 136 private static final String JSON_KEY_CONFIG = "config"; 137 138 /** The default tranformer configuration. */ 139 public static final CmsUgcValueTransformerConfiguration DEFAULT = new CmsUgcValueTransformerConfiguration(); 140 141 /** The resource's transformer map with the explicitly specified transformers. */ 142 private Map<String, CmsUgcSingleValueTransformer> m_transformerMap; 143 144 /** 145 * Wraps the provided transformer configuration 146 * @param config the configuration to wrap 147 * @throws JSONException thrown if the configuration is not a valid JSON 148 * @throws IllegalArgumentException thrown if the configuration values are not as expected 149 */ 150 public CmsUgcValueTransformerConfiguration(String config) 151 throws JSONException, IllegalArgumentException { 152 153 if (config != null) { 154 JSONObject security = new JSONObject(config); 155 Set<String> paths = security.keySet(); 156 Map<String, CmsUgcSingleValueTransformer> mappingSecurity = new HashMap<>(paths.size()); 157 for (String path : paths) { 158 JSONObject pathConfig = security.getJSONObject(path); 159 String adjustment = pathConfig.getString(JSON_KEY_TRANSFORMER); 160 JSONObject mappingConfig = pathConfig.optJSONObject(JSON_KEY_CONFIG); 161 mappingSecurity.put( 162 path, 163 new CmsUgcSingleValueTransformer(TransformType.valueOf(adjustment), mappingConfig)); 164 } 165 m_transformerMap = mappingSecurity; 166 } else { 167 m_transformerMap = Collections.emptyMap(); 168 } 169 } 170 171 /** 172 * Constructor for the default configuration. 173 */ 174 private CmsUgcValueTransformerConfiguration() { 175 176 m_transformerMap = Collections.emptyMap(); 177 } 178 179 /** 180 * Returns the transformer for the provided XML path. 181 * @param path the XML path to get the value transformer for. 182 * @return the transformer for the provided XML path. 183 */ 184 public CmsUgcSingleValueTransformer getTransformer(String path) { 185 186 return m_transformerMap.getOrDefault(path, CmsUgcSingleValueTransformer.DEFAULT); 187 } 188}