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.ugc;
029
030import org.opencms.file.CmsObject;
031import org.opencms.file.CmsResource;
032import org.opencms.gwt.CmsGwtService;
033import org.opencms.gwt.CmsRpcException;
034import org.opencms.main.CmsException;
035import org.opencms.main.CmsLog;
036import org.opencms.main.OpenCms;
037import org.opencms.ugc.shared.CmsUgcConstants;
038import org.opencms.ugc.shared.CmsUgcContent;
039import org.opencms.ugc.shared.CmsUgcException;
040import org.opencms.ugc.shared.rpc.I_CmsUgcEditService;
041import org.opencms.util.CmsUUID;
042import org.opencms.xml.content.CmsXmlContentErrorHandler;
043
044import java.io.IOException;
045import java.util.Collections;
046import java.util.Map;
047import java.util.Set;
048
049import org.apache.commons.fileupload2.core.AbstractFileUpload;
050import org.apache.commons.fileupload2.jakarta.servlet5.JakartaServletRequestContext;
051import org.apache.commons.logging.Log;
052
053import com.google.common.collect.Maps;
054
055import jakarta.servlet.ServletException;
056import jakarta.servlet.http.HttpServletRequest;
057import jakarta.servlet.http.HttpServletResponse;
058
059/**
060 * The form editing service.<p>
061 */
062public class CmsUgcEditService extends CmsGwtService implements I_CmsUgcEditService {
063
064    /** Log instance for this class. */
065    private static final Log LOG = CmsLog.getLog(CmsUgcEditService.class);
066
067    /** The serial version id. */
068    private static final long serialVersionUID = 5479252081304867604L;
069
070    /**
071     * @see org.opencms.gwt.CmsGwtService#checkPermissions(org.opencms.file.CmsObject)
072     */
073    @Override
074    public void checkPermissions(CmsObject cms) {
075
076        // don't do permission checks, since this service should be available to "Guest" users from the frontend
077    }
078
079    /**
080     * @see org.opencms.ugc.shared.rpc.I_CmsUgcEditService#destroySession(org.opencms.util.CmsUUID)
081     */
082    public void destroySession(CmsUUID sessionId) throws CmsUgcException {
083
084        try {
085            CmsUgcSession formSession = getFormSession(sessionId);
086            getRequest().getSession().removeAttribute("" + sessionId);
087            if (formSession != null) {
088                formSession.onSessionDestroyed();
089            }
090
091        } catch (Exception e) {
092            error(e);
093        }
094    }
095
096    /**
097     * @see org.opencms.gwt.CmsGwtService#error(java.lang.Throwable)
098     */
099    @Override
100    public void error(Throwable t) throws CmsUgcException {
101
102        logError(t);
103        CmsUgcException exception = t instanceof CmsUgcException ? (CmsUgcException)t : new CmsUgcException(t);
104        throw exception;
105    }
106
107    /**
108     * @see org.opencms.ugc.shared.rpc.I_CmsUgcEditService#getContent(org.opencms.util.CmsUUID)
109     */
110    public CmsUgcContent getContent(CmsUUID sessionId) throws CmsUgcException {
111
112        CmsUgcContent formContent = null;
113        try {
114            CmsUgcSession session = CmsUgcSessionFactory.getInstance().getSession(getRequest(), sessionId);
115            formContent = readContent(session, session.getResource());
116        } catch (Exception e) {
117            error(e);
118        }
119
120        return formContent;
121    }
122
123    /**
124     * @see org.opencms.ugc.shared.rpc.I_CmsUgcEditService#getLink(java.lang.String)
125     */
126    public String getLink(String path) {
127
128        return OpenCms.getLinkManager().substituteLink(getCmsObject(), path);
129    }
130
131    /**
132     * @see org.opencms.ugc.shared.rpc.I_CmsUgcEditService#saveContent(org.opencms.util.CmsUUID, java.util.Map)
133     */
134    public Map<String, String> saveContent(CmsUUID sessionId, Map<String, String> contentValues)
135    throws CmsUgcException {
136
137        Map<String, String> result = null;
138        try {
139            CmsUgcSession session = getFormSession(sessionId);
140            if ((session != null) && sessionId.equals(session.getId())) {
141
142                CmsXmlContentErrorHandler errorHandler = session.saveContent(contentValues);
143                if (errorHandler.hasErrors()) {
144                    result = errorHandler.getErrors(session.getMessageLocale());
145                } else {
146                    session.finish();
147                    result = Collections.emptyMap();
148                }
149            } else {
150                // invalid session
151
152            }
153        } catch (Exception e) {
154            error(e);
155        }
156        return result;
157    }
158
159    /**
160     * @see org.opencms.ugc.shared.rpc.I_CmsUgcEditService#uploadFiles(org.opencms.util.CmsUUID, java.util.Set, java.lang.String)
161     */
162    public Map<String, String> uploadFiles(
163        final CmsUUID sessionId,
164        final Set<String> fieldNames,
165        final String formDataId)
166    throws CmsRpcException {
167
168        try {
169            final CmsUgcSession session = getFormSession(sessionId);
170            final Map<String, String> result = Maps.newHashMap();
171
172            session.getFormUploadHelper().consumeFormData(formDataId, new I_CmsFormDataHandler() {
173
174                @SuppressWarnings("synthetic-access")
175                public void handleFormData(Map<String, I_CmsFormDataItem> items) throws Exception {
176
177                    for (String fieldName : fieldNames) {
178                        I_CmsFormDataItem item = items.get(fieldName);
179                        if (item != null) {
180                            CmsResource createdResource = session.createUploadResource(
181                                item.getFieldName(),
182                                item.getFileName(),
183                                item.getData());
184                            String sitePath = session.getCmsObject().getSitePath(createdResource);
185                            result.put(fieldName, sitePath);
186                        } else {
187                            LOG.debug(formDataId + ": requested upload for field " + fieldName + " which was empty.");
188                        }
189                    }
190                }
191            });
192            return result;
193        } catch (Exception e) {
194            error(e);
195            return null; // will never be reached
196
197        }
198    }
199
200    /**
201     * @see org.opencms.ugc.shared.rpc.I_CmsUgcEditService#validateContent(org.opencms.util.CmsUUID, java.util.Map)
202     */
203    public Map<String, String> validateContent(CmsUUID sessionId, Map<String, String> contentValues)
204    throws CmsUgcException {
205
206        Map<String, String> result = Maps.newHashMap();
207        try {
208            CmsUgcSession session = getFormSession(sessionId);
209            if ((session != null) && sessionId.equals(session.getId())) {
210                CmsXmlContentErrorHandler errorHandler = session.validateContent(contentValues);
211                result = errorHandler.getErrors(session.getMessageLocale());
212            } else {
213                // invalid session
214
215            }
216        } catch (Exception e) {
217            error(e);
218        }
219        return result;
220    }
221
222    /**
223     * Handles all multipart requests.<p>
224     *
225     * @param request the request
226     * @param response the response
227     */
228    protected void handleUpload(HttpServletRequest request, HttpServletResponse response) {
229
230        String sessionIdStr = request.getParameter(CmsUgcConstants.PARAM_SESSION_ID);
231        CmsUUID sessionId = new CmsUUID(sessionIdStr);
232        CmsUgcSession session = CmsUgcSessionFactory.getInstance().getSession(request, sessionId);
233        session.getFormUploadHelper().processFormSubmitRequest(request);
234    }
235
236    /**
237     * @see jakarta.servlet.http.HttpServlet#service(jakarta.servlet.http.HttpServletRequest, jakarta.servlet.http.HttpServletResponse)
238     */
239    @Override
240    protected void service(HttpServletRequest request, HttpServletResponse response)
241    throws ServletException, IOException {
242
243        boolean isMultiPart = AbstractFileUpload.isMultipartContent(new JakartaServletRequestContext(request));
244
245        if (isMultiPart) {
246            try {
247                handleUpload(request, response);
248            } finally {
249                clearThreadStorage();
250            }
251        } else {
252            super.service(request, response);
253        }
254    }
255
256    /**
257     * Gets the form session  with the given id.<p>
258     *
259     * @param sessionId the session id
260     *
261     * @return the form session
262     */
263    private CmsUgcSession getFormSession(CmsUUID sessionId) {
264
265        return CmsUgcSessionFactory.getInstance().getSession(getRequest(), sessionId);
266    }
267
268    /**
269     * Reads the form content information.<p>
270     *
271     * @param session the editing session
272     * @param resource the edited resource
273     *
274     * @return the form content
275     *
276     * @throws CmsException if reading the info fails
277     */
278    private CmsUgcContent readContent(CmsUgcSession session, CmsResource resource) throws CmsException {
279
280        CmsUgcContent formContent = new CmsUgcContent();
281        Map<String, String> contentValues = session.getValues();
282        formContent.setContentValues(contentValues);
283        formContent.setSessionId(session.getId());
284        formContent.setResourceType(OpenCms.getResourceManager().getResourceType(resource).getTypeName());
285        formContent.setSitePath(getCmsObject().getSitePath(resource));
286        formContent.setStrucureId(resource.getStructureId());
287        return formContent;
288    }
289
290}