001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://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: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://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.ade.upload;
029
030import org.opencms.configuration.CmsParameterConfiguration;
031import org.opencms.file.CmsObject;
032import org.opencms.gwt.shared.CmsUploadRestrictionInfo;
033import org.opencms.main.CmsLog;
034import org.opencms.main.OpenCms;
035import org.opencms.security.CmsRole;
036
037import java.util.Arrays;
038import java.util.HashSet;
039import java.util.Map;
040import java.util.Set;
041import java.util.concurrent.ExecutionException;
042import java.util.concurrent.TimeUnit;
043import java.util.stream.Collectors;
044
045import org.apache.commons.logging.Log;
046
047import com.google.common.cache.Cache;
048import com.google.common.cache.CacheBuilder;
049
050/**
051 * Default implementation for upload restrictions uses restriction entries from opencms-workplace.xml.
052 *
053 * <p>This class directly takes parameters configured via param elements in opencms-workplace.xml and interprets them as restriction
054 * entries. The parameter name is interpreted as the path, and the parameter value
055 */
056public class CmsDefaultUploadRestriction implements I_CmsUploadRestriction {
057
058    /** Sitemap attribute to control the allowed upload extensions. */
059    public static final String ATTR_UPLOAD_EXTENSIONS = "upload.extensions";
060
061    /** Logger for this class. */
062    @SuppressWarnings("unused")
063    private static final Log LOG = CmsLog.getLog(CmsDefaultUploadRestriction.class);
064
065    /** The internal CmsObject. */
066    private CmsObject m_cms;
067
068    /** The configuration. */
069    private CmsParameterConfiguration m_config = new CmsParameterConfiguration();
070
071    /** Cache for upload restrictions - caches just a single value. */
072    private Cache<String, CmsUploadRestrictionInfo> m_cache = CacheBuilder.newBuilder().expireAfterWrite(
073        1,
074        TimeUnit.SECONDS).build();
075
076    /**
077     * Creates a new instance.
078     */
079    public CmsDefaultUploadRestriction() {
080
081    }
082
083    /**
084     * Utility method for creating an upload restriction that doesn't restrict anything.
085     *
086     * @return the unrestricted upload restriction
087     */
088    public static I_CmsUploadRestriction unrestricted() {
089
090        CmsDefaultUploadRestriction result = new CmsDefaultUploadRestriction();
091        result.addConfigurationParameter("/", CmsUploadRestrictionInfo.UNRESTRICTED_UPLOADS);
092        return result;
093    }
094
095    /**
096     * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#addConfigurationParameter(java.lang.String, java.lang.String)
097     */
098    public void addConfigurationParameter(String paramName, String paramValue) {
099
100        m_config.add(paramName, paramValue);
101    }
102
103    /**
104     * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#getConfiguration()
105     */
106    public CmsParameterConfiguration getConfiguration() {
107
108        return m_config;
109    }
110
111    /**
112     * @see org.opencms.ade.upload.I_CmsUploadRestriction#getUploadRestrictionInfo(org.opencms.file.CmsObject)
113     */
114    public CmsUploadRestrictionInfo getUploadRestrictionInfo(CmsObject cms) {
115
116        if ((m_cms != null)
117            && !OpenCms.getRoleManager().hasRole(cms, CmsRole.ROOT_ADMIN) // root admins may have to upload arbitrary files for things like updates / administration stuff
118            && !cms.getRequestContext().getCurrentProject().isOnlineProject()) {
119            try {
120                // The cache is just for a single value - use the empty string as a dummy key
121                CmsUploadRestrictionInfo result = m_cache.get("", () -> computeUploadRestriction(cms));
122                return result;
123            } catch (ExecutionException e) {
124                return new CmsUploadRestrictionInfo.Builder().add(
125                    "/",
126                    CmsUploadRestrictionInfo.UNRESTRICTED_UPLOADS).build();
127            }
128        }
129        return new CmsUploadRestrictionInfo.Builder().add("/", CmsUploadRestrictionInfo.UNRESTRICTED_UPLOADS).build();
130    }
131
132    /**
133     * @see org.opencms.configuration.I_CmsConfigurationParameterHandler#initConfiguration()
134     */
135    public void initConfiguration() {
136
137        // do nothing
138    }
139
140    /**
141     * @see org.opencms.configuration.I_CmsNeedsAdminCmsObject#setAdminCmsObject(org.opencms.file.CmsObject)
142     */
143    public void setAdminCmsObject(CmsObject adminCms) {
144
145        m_cms = adminCms;
146    }
147
148    /**
149     * Calculates the upload restriction data based on the configuration in opencms-workplace.xml and the current sitemap config.
150     *
151     * @param cms the current CMS context
152     * @return the upload restriction data
153     */
154    private CmsUploadRestrictionInfo computeUploadRestriction(CmsObject cms) {
155
156        CmsUploadRestrictionInfo.Builder builder = new CmsUploadRestrictionInfo.Builder();
157        for (Map.Entry<String, String> entry : m_config.entrySet()) {
158            String key = entry.getKey();
159            String value = entry.getValue();
160            if (key.startsWith("/")) {
161                builder.add(key, value);
162            }
163        }
164        Map<String, String> extensionsMap = OpenCms.getADEManager().getSitemapAttributeValuesByPath(
165            cms,
166            ATTR_UPLOAD_EXTENSIONS);
167        for (Map.Entry<String, String> entry : extensionsMap.entrySet()) {
168            String path = entry.getKey();
169            String typesStr = entry.getValue();
170            typesStr = typesStr.trim();
171            if (!("".equals(typesStr))) {
172                Set<String> extensions = Arrays.asList(typesStr.split(",")).stream().map(
173                    token -> token.trim().replaceFirst("^\\.", "")).collect(Collectors.toSet());
174                builder.add(path, Boolean.TRUE, extensions);
175            } else {
176                builder.add(path, Boolean.FALSE, new HashSet<>());
177            }
178        }
179        CmsUploadRestrictionInfo result = builder.build();
180        return result;
181    }
182
183}