001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.messageboards.action;
016    
017    import com.liferay.portal.kernel.captcha.CaptchaConfigurationException;
018    import com.liferay.portal.kernel.captcha.CaptchaMaxChallengesException;
019    import com.liferay.portal.kernel.captcha.CaptchaTextException;
020    import com.liferay.portal.kernel.captcha.CaptchaUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.portlet.LiferayWindowState;
023    import com.liferay.portal.kernel.sanitizer.SanitizerException;
024    import com.liferay.portal.kernel.servlet.SessionErrors;
025    import com.liferay.portal.kernel.upload.LiferayFileItemException;
026    import com.liferay.portal.kernel.upload.UploadException;
027    import com.liferay.portal.kernel.upload.UploadPortletRequest;
028    import com.liferay.portal.kernel.util.Constants;
029    import com.liferay.portal.kernel.util.ObjectValuePair;
030    import com.liferay.portal.kernel.util.ParamUtil;
031    import com.liferay.portal.kernel.util.StreamUtil;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.workflow.WorkflowConstants;
035    import com.liferay.portal.security.auth.PrincipalException;
036    import com.liferay.portal.security.permission.ActionKeys;
037    import com.liferay.portal.security.permission.PermissionChecker;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.service.ServiceContextFactory;
040    import com.liferay.portal.struts.PortletAction;
041    import com.liferay.portal.theme.ThemeDisplay;
042    import com.liferay.portal.util.PortalUtil;
043    import com.liferay.portal.util.PropsValues;
044    import com.liferay.portal.util.WebKeys;
045    import com.liferay.portlet.ActionResponseImpl;
046    import com.liferay.portlet.asset.AssetCategoryException;
047    import com.liferay.portlet.asset.AssetTagException;
048    import com.liferay.portlet.documentlibrary.DuplicateFileException;
049    import com.liferay.portlet.documentlibrary.FileExtensionException;
050    import com.liferay.portlet.documentlibrary.FileNameException;
051    import com.liferay.portlet.documentlibrary.FileSizeException;
052    import com.liferay.portlet.documentlibrary.antivirus.AntivirusScannerException;
053    import com.liferay.portlet.messageboards.LockedThreadException;
054    import com.liferay.portlet.messageboards.MBGroupServiceSettings;
055    import com.liferay.portlet.messageboards.MessageBodyException;
056    import com.liferay.portlet.messageboards.MessageSubjectException;
057    import com.liferay.portlet.messageboards.NoSuchMessageException;
058    import com.liferay.portlet.messageboards.RequiredMessageException;
059    import com.liferay.portlet.messageboards.model.MBMessage;
060    import com.liferay.portlet.messageboards.service.MBMessageServiceUtil;
061    import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
062    import com.liferay.portlet.messageboards.service.MBThreadServiceUtil;
063    import com.liferay.portlet.messageboards.service.permission.MBMessagePermission;
064    
065    import java.io.InputStream;
066    
067    import java.util.ArrayList;
068    import java.util.List;
069    
070    import javax.portlet.ActionRequest;
071    import javax.portlet.ActionResponse;
072    import javax.portlet.PortletConfig;
073    import javax.portlet.PortletURL;
074    import javax.portlet.RenderRequest;
075    import javax.portlet.RenderResponse;
076    import javax.portlet.WindowState;
077    
078    import org.apache.struts.action.ActionForm;
079    import org.apache.struts.action.ActionForward;
080    import org.apache.struts.action.ActionMapping;
081    
082    /**
083     * @author Brian Wing Shun Chan
084     * @author Daniel Sanz
085     * @author Shuyang Zhou
086     */
087    public class EditMessageAction extends PortletAction {
088    
089            @Override
090            public void processAction(
091                            ActionMapping actionMapping, ActionForm actionForm,
092                            PortletConfig portletConfig, ActionRequest actionRequest,
093                            ActionResponse actionResponse)
094                    throws Exception {
095    
096                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
097    
098                    MBMessage message = null;
099    
100                    try {
101                            UploadException uploadException =
102                                    (UploadException)actionRequest.getAttribute(
103                                            WebKeys.UPLOAD_EXCEPTION);
104    
105                            if (uploadException != null) {
106                                    if (uploadException.isExceededLiferayFileItemSizeLimit()) {
107                                            throw new LiferayFileItemException();
108                                    }
109                                    else if (uploadException.isExceededSizeLimit()) {
110                                            throw new FileSizeException(uploadException.getCause());
111                                    }
112    
113                                    throw new PortalException(uploadException.getCause());
114                            }
115                            else if (cmd.equals(Constants.ADD) ||
116                                             cmd.equals(Constants.UPDATE)) {
117    
118                                    message = updateMessage(actionRequest, actionResponse);
119                            }
120                            else if (cmd.equals(Constants.DELETE)) {
121                                    deleteMessage(actionRequest);
122                            }
123                            else if (cmd.equals(Constants.LOCK)) {
124                                    lockThreads(actionRequest);
125                            }
126                            else if (cmd.equals(Constants.SUBSCRIBE)) {
127                                    subscribeMessage(actionRequest);
128                            }
129                            else if (cmd.equals(Constants.UNLOCK)) {
130                                    unlockThreads(actionRequest);
131                            }
132                            else if (cmd.equals(Constants.UNSUBSCRIBE)) {
133                                    unsubscribeMessage(actionRequest);
134                            }
135    
136                            if (Validator.isNotNull(cmd)) {
137                                    WindowState windowState = actionRequest.getWindowState();
138    
139                                    if (!windowState.equals(LiferayWindowState.POP_UP)) {
140                                            String redirect = getRedirect(
141                                                    actionRequest, actionResponse, message);
142    
143                                            sendRedirect(actionRequest, actionResponse, redirect);
144                                    }
145                                    else {
146                                            String redirect = PortalUtil.escapeRedirect(
147                                                    ParamUtil.getString(actionRequest, "redirect"));
148    
149                                            if (Validator.isNotNull(redirect)) {
150                                                    actionResponse.sendRedirect(redirect);
151                                            }
152                                    }
153                            }
154                    }
155                    catch (Exception e) {
156                            if (e instanceof NoSuchMessageException ||
157                                    e instanceof PrincipalException ||
158                                    e instanceof RequiredMessageException) {
159    
160                                    SessionErrors.add(actionRequest, e.getClass());
161    
162                                    setForward(actionRequest, "portlet.message_boards.error");
163                            }
164                            else if (e instanceof AntivirusScannerException ||
165                                             e instanceof CaptchaConfigurationException ||
166                                             e instanceof CaptchaMaxChallengesException ||
167                                             e instanceof CaptchaTextException ||
168                                             e instanceof DuplicateFileException ||
169                                             e instanceof FileExtensionException ||
170                                             e instanceof FileNameException ||
171                                             e instanceof FileSizeException ||
172                                             e instanceof LiferayFileItemException ||
173                                             e instanceof LockedThreadException ||
174                                             e instanceof MessageBodyException ||
175                                             e instanceof MessageSubjectException ||
176                                             e instanceof SanitizerException) {
177    
178                                    UploadException uploadException =
179                                            (UploadException)actionRequest.getAttribute(
180                                                    WebKeys.UPLOAD_EXCEPTION);
181    
182                                    if (uploadException != null) {
183                                            String uploadExceptionRedirect = ParamUtil.getString(
184                                                    actionRequest, "uploadExceptionRedirect");
185    
186                                            actionResponse.sendRedirect(uploadExceptionRedirect);
187                                    }
188    
189                                    if (e instanceof AntivirusScannerException) {
190                                            SessionErrors.add(actionRequest, e.getClass(), e);
191                                    }
192                                    else {
193                                            SessionErrors.add(actionRequest, e.getClass());
194                                    }
195                            }
196                            else if (e instanceof AssetCategoryException ||
197                                             e instanceof AssetTagException) {
198    
199                                    SessionErrors.add(actionRequest, e.getClass(), e);
200                            }
201                            else {
202                                    Throwable cause = e.getCause();
203    
204                                    if (cause instanceof SanitizerException) {
205                                            SessionErrors.add(actionRequest, SanitizerException.class);
206                                    }
207                                    else {
208                                            throw e;
209                                    }
210                            }
211                    }
212            }
213    
214            @Override
215            public ActionForward render(
216                            ActionMapping actionMapping, ActionForm actionForm,
217                            PortletConfig portletConfig, RenderRequest renderRequest,
218                            RenderResponse renderResponse)
219                    throws Exception {
220    
221                    try {
222                            ActionUtil.getMessage(renderRequest);
223                    }
224                    catch (Exception e) {
225                            if (e instanceof NoSuchMessageException ||
226                                    e instanceof PrincipalException) {
227    
228                                    SessionErrors.add(renderRequest, e.getClass());
229    
230                                    return actionMapping.findForward(
231                                            "portlet.message_boards.error");
232                            }
233                            else {
234                                    throw e;
235                            }
236                    }
237    
238                    return actionMapping.findForward(
239                            getForward(renderRequest, "portlet.message_boards.edit_message"));
240            }
241    
242            protected void deleteMessage(ActionRequest actionRequest) throws Exception {
243                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
244    
245                    MBMessageServiceUtil.deleteMessage(messageId);
246            }
247    
248            protected String getRedirect(
249                    ActionRequest actionRequest, ActionResponse actionResponse,
250                    MBMessage message) {
251    
252                    if (message == null) {
253                            String redirect = ParamUtil.getString(actionRequest, "redirect");
254    
255                            return redirect;
256                    }
257    
258                    int workflowAction = ParamUtil.getInteger(
259                            actionRequest, "workflowAction", WorkflowConstants.ACTION_PUBLISH);
260    
261                    if (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT) {
262                            return getSaveAndContinueRedirect(
263                                    actionRequest, actionResponse, message);
264                    }
265                    else if (message == null) {
266                            return ParamUtil.getString(actionRequest, "redirect");
267                    }
268    
269                    ActionResponseImpl actionResponseImpl =
270                            (ActionResponseImpl)actionResponse;
271    
272                    PortletURL portletURL = actionResponseImpl.createRenderURL();
273    
274                    portletURL.setParameter(
275                            "struts_action", "/message_boards/view_message");
276                    portletURL.setParameter(
277                            "messageId", String.valueOf(message.getMessageId()));
278    
279                    return portletURL.toString();
280            }
281    
282            protected String getSaveAndContinueRedirect(
283                    ActionRequest actionRequest, ActionResponse actionResponse,
284                    MBMessage message) {
285    
286                    String redirect = ParamUtil.getString(actionRequest, "redirect");
287    
288                    boolean preview = ParamUtil.getBoolean(actionRequest, "preview");
289    
290                    PortletURL portletURL =
291                            ((ActionResponseImpl)actionResponse).createRenderURL();
292    
293                    portletURL.setParameter(
294                            "struts_action", "/message_boards/edit_message");
295                    portletURL.setParameter("redirect", redirect);
296                    portletURL.setParameter(
297                            "messageId", String.valueOf(message.getMessageId()));
298                    portletURL.setParameter("preview", String.valueOf(preview));
299    
300                    return portletURL.toString();
301            }
302    
303            protected void lockThreads(ActionRequest actionRequest) throws Exception {
304                    long threadId = ParamUtil.getLong(actionRequest, "threadId");
305    
306                    if (threadId > 0) {
307                            MBThreadServiceUtil.lockThread(threadId);
308                    }
309                    else {
310                            long[] threadIds = StringUtil.split(
311                                    ParamUtil.getString(actionRequest, "threadIds"), 0L);
312    
313                            for (int i = 0; i < threadIds.length; i++) {
314                                    MBThreadServiceUtil.lockThread(threadIds[i]);
315                            }
316                    }
317            }
318    
319            protected void subscribeMessage(ActionRequest actionRequest)
320                    throws Exception {
321    
322                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
323    
324                    MBMessageServiceUtil.subscribeMessage(messageId);
325            }
326    
327            protected void unlockThreads(ActionRequest actionRequest) throws Exception {
328                    long threadId = ParamUtil.getLong(actionRequest, "threadId");
329    
330                    if (threadId > 0) {
331                            MBThreadServiceUtil.unlockThread(threadId);
332                    }
333                    else {
334                            long[] threadIds = StringUtil.split(
335                                    ParamUtil.getString(actionRequest, "threadIds"), 0L);
336    
337                            for (int i = 0; i < threadIds.length; i++) {
338                                    MBThreadServiceUtil.unlockThread(threadIds[i]);
339                            }
340                    }
341            }
342    
343            protected void unsubscribeMessage(ActionRequest actionRequest)
344                    throws Exception {
345    
346                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
347    
348                    MBMessageServiceUtil.unsubscribeMessage(messageId);
349            }
350    
351            protected MBMessage updateMessage(
352                            ActionRequest actionRequest, ActionResponse actionResponse)
353                    throws Exception {
354    
355                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
356                            WebKeys.THEME_DISPLAY);
357    
358                    long messageId = ParamUtil.getLong(actionRequest, "messageId");
359    
360                    long groupId = themeDisplay.getScopeGroupId();
361                    long categoryId = ParamUtil.getLong(actionRequest, "mbCategoryId");
362                    long threadId = ParamUtil.getLong(actionRequest, "threadId");
363                    long parentMessageId = ParamUtil.getLong(
364                            actionRequest, "parentMessageId");
365                    String subject = ParamUtil.getString(actionRequest, "subject");
366                    String body = ParamUtil.getString(actionRequest, "body");
367    
368                    MBGroupServiceSettings mbGroupServiceSettings =
369                            MBGroupServiceSettings.getInstance(groupId);
370    
371                    List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
372                            new ArrayList<>(5);
373    
374                    try {
375                            UploadPortletRequest uploadPortletRequest =
376                                    PortalUtil.getUploadPortletRequest(actionRequest);
377    
378                            for (int i = 1; i <= 5; i++) {
379                                    String fileName = uploadPortletRequest.getFileName(
380                                            "msgFile" + i);
381                                    InputStream inputStream = uploadPortletRequest.getFileAsStream(
382                                            "msgFile" + i);
383    
384                                    if ((inputStream == null) || Validator.isNull(fileName)) {
385                                            continue;
386                                    }
387    
388                                    ObjectValuePair<String, InputStream> inputStreamOVP =
389                                            new ObjectValuePair<>(fileName, inputStream);
390    
391                                    inputStreamOVPs.add(inputStreamOVP);
392                            }
393    
394                            boolean question = ParamUtil.getBoolean(actionRequest, "question");
395                            boolean anonymous = ParamUtil.getBoolean(
396                                    actionRequest, "anonymous");
397                            double priority = ParamUtil.getDouble(actionRequest, "priority");
398                            boolean allowPingbacks = ParamUtil.getBoolean(
399                                    actionRequest, "allowPingbacks");
400    
401                            ServiceContext serviceContext = ServiceContextFactory.getInstance(
402                                    MBMessage.class.getName(), actionRequest);
403    
404                            boolean preview = ParamUtil.getBoolean(actionRequest, "preview");
405    
406                            serviceContext.setAttribute("preview", preview);
407    
408                            MBMessage message = null;
409    
410                            if (messageId <= 0) {
411                                    if (PropsValues.
412                                                    CAPTCHA_CHECK_PORTLET_MESSAGE_BOARDS_EDIT_MESSAGE) {
413    
414                                            CaptchaUtil.check(actionRequest);
415                                    }
416    
417                                    if (threadId <= 0) {
418    
419                                            // Post new thread
420    
421                                            message = MBMessageServiceUtil.addMessage(
422                                                    groupId, categoryId, subject, body,
423                                                    mbGroupServiceSettings.getMessageFormat(),
424                                                    inputStreamOVPs, anonymous, priority, allowPingbacks,
425                                                    serviceContext);
426    
427                                            if (question) {
428                                                    MBThreadLocalServiceUtil.updateQuestion(
429                                                            message.getThreadId(), true);
430                                            }
431                                    }
432                                    else {
433    
434                                            // Post reply
435    
436                                            message = MBMessageServiceUtil.addMessage(
437                                                    parentMessageId, subject, body,
438                                                    mbGroupServiceSettings.getMessageFormat(),
439                                                    inputStreamOVPs, anonymous, priority, allowPingbacks,
440                                                    serviceContext);
441                                    }
442                            }
443                            else {
444                                    List<String> existingFiles = new ArrayList<>();
445    
446                                    for (int i = 1; i <= 5; i++) {
447                                            String path = ParamUtil.getString(
448                                                    actionRequest, "existingPath" + i);
449    
450                                            if (Validator.isNotNull(path)) {
451                                                    existingFiles.add(path);
452                                            }
453                                    }
454    
455                                    // Update message
456    
457                                    message = MBMessageServiceUtil.updateMessage(
458                                            messageId, subject, body, inputStreamOVPs, existingFiles,
459                                            priority, allowPingbacks, serviceContext);
460    
461                                    if (message.isRoot()) {
462                                            MBThreadLocalServiceUtil.updateQuestion(
463                                                    message.getThreadId(), question);
464                                    }
465                            }
466    
467                            PermissionChecker permissionChecker =
468                                    themeDisplay.getPermissionChecker();
469    
470                            boolean subscribe = ParamUtil.getBoolean(
471                                    actionRequest, "subscribe");
472    
473                            if (!preview && subscribe &&
474                                    MBMessagePermission.contains(
475                                            permissionChecker, message, ActionKeys.SUBSCRIBE)) {
476    
477                                    MBMessageServiceUtil.subscribeMessage(message.getMessageId());
478                            }
479    
480                            return message;
481                    }
482                    finally {
483                            for (ObjectValuePair<String, InputStream> inputStreamOVP :
484                                            inputStreamOVPs) {
485    
486                                    InputStream inputStream = inputStreamOVP.getValue();
487    
488                                    StreamUtil.cleanUp(inputStream);
489                            }
490                    }
491            }
492    
493    }