/* * ForumRequestProcessor.java * * This work is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This work 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * Copyright (c) 2004-2007 Per Cederberg. All rights reserved. */ package org.liquidsite.app.legacy; import java.util.Date; import org.liquidsite.app.servlet.Application; import org.liquidsite.app.servlet.RequestException; import org.liquidsite.app.servlet.RequestProcessor; import org.liquidsite.core.content.Content; import org.liquidsite.core.content.ContentForum; import org.liquidsite.core.content.ContentException; import org.liquidsite.core.content.ContentManager; import org.liquidsite.core.content.ContentPost; import org.liquidsite.core.content.ContentSecurityException; import org.liquidsite.core.content.ContentTopic; import org.liquidsite.core.content.User; import org.liquidsite.core.text.PlainFormatter; import org.liquidsite.core.web.Request; import org.liquidsite.util.log.Log; /** * The forum request processor for forum posts and previews. * * @author Per Cederberg, <per at percederberg dot net> * @version 1.0 */ public class ForumRequestProcessor extends RequestProcessor { /** * The class logger. */ private static final Log LOG = new Log(ForumRequestProcessor.class); /** * Creates a new forum request processor. * * @param app the application context */ public ForumRequestProcessor(Application app) { super(app.getContentManager(), app.getBaseDir()); } /** * Destroys this request processor. This method frees all internal * resources used by this processor. */ public void destroy() { // Nothing need to be done } /** * Processes a forum request. * * @param request the request object * * @throws RequestException if the action couldn't be processed */ public void process(Request request) throws RequestException { String action = request.getParameter("liquidsite.action"); if (action.equals("forum.post")) { processPost(request); } else if (action.equals("forum.edit")) { processEdit(request); } else if (action.equals("forum.delete")) { processDelete(request); } else { LOG.warning(request + ": forum request action '" + action + "' is undefined"); throw RequestException.INTERNAL_ERROR; } } /** * Processes a forum post request action. * * @param request the request object * * @throws RequestException if the action couldn't be processed */ private void processPost(Request request) throws RequestException { ContentForum forum; ContentTopic topic; String subject; String text; String preview; String str; // Find request parameters forum = findForum(request); topic = findTopic(request, forum); str = request.getParameter("liquidsite.subject", ""); subject = PlainFormatter.clean(str); str = request.getParameter("liquidsite.textformat", ""); if (!str.equals("plain")) { LOG.warning(request + ": text format '" + str + "' is undefined"); throw RequestException.INTERNAL_ERROR; } str = request.getParameter("liquidsite.text", ""); text = PlainFormatter.clean(str); preview = request.getParameter("liquidsite.preview", ""); // Post forum message if (subject.length() <= 0) { str = "Subject must be longer than zero characters"; request.setAttribute("error", str); } else if (subject.length() > 80) { str = "Subject mustn't be longer than 80 characters"; request.setAttribute("error", str); } else if (text.length() <= 0) { str = "Text must be longer than zero characters"; request.setAttribute("error", str); } else if (preview.equals("true")) { request.setAttribute("subject", subject); request.setAttribute("text", text); request.setAttribute("previewsubject", PlainFormatter.formatHtml(subject)); request.setAttribute("previewtext", PlainFormatter.formatHtml(text)); } else { post(forum, topic, subject, text, request.getUser()); request.setAttribute("redirect", "true"); } } /** * Processes a forum edit request action. * * @param request the request object * * @throws RequestException if the action couldn't be processed */ private void processEdit(Request request) throws RequestException { ContentForum forum; ContentTopic topic; ContentPost post; String subject; String text; String preview; String str; // Find request parameters forum = findForum(request); topic = findTopic(request, forum); if (topic == null) { LOG.warning(request + ": no topic in forum edit request"); throw RequestException.INTERNAL_ERROR; } post = findPost(request, topic); if (post == null) { LOG.warning(request + ": no post in forum edit request"); throw RequestException.INTERNAL_ERROR; } str = request.getParameter("liquidsite.subject", ""); subject = PlainFormatter.clean(str); str = request.getParameter("liquidsite.textformat", ""); if (!str.equals("plain")) { LOG.warning(request + ": text format '" + str + "' is undefined"); throw RequestException.INTERNAL_ERROR; } str = request.getParameter("liquidsite.text", ""); text = PlainFormatter.clean(str); preview = request.getParameter("liquidsite.preview", ""); // Post forum message if (subject.length() <= 0) { str = "Subject must be longer than zero characters"; request.setAttribute("error", str); } else if (subject.length() > 80) { str = "Subject mustn't be longer than 80 characters"; request.setAttribute("error", str); } else if (text.length() <= 0) { str = "Text must be longer than zero characters"; request.setAttribute("error", str); } else if (preview.equals("true")) { request.setAttribute("subject", subject); request.setAttribute("text", text); request.setAttribute("previewsubject", PlainFormatter.formatHtml(subject)); request.setAttribute("previewtext", PlainFormatter.formatHtml(text)); } else { edit(forum, post, subject, text, request.getUser()); request.setAttribute("redirect", "true"); } } /** * Processes a forum delete request action. * * @param request the request object * * @throws RequestException if the action couldn't be processed */ private void processDelete(Request request) throws RequestException { ContentForum forum; ContentTopic topic; ContentPost post; // Find request parameters forum = findForum(request); topic = findTopic(request, forum); if (topic == null) { LOG.warning(request + ": no topic in forum delete request"); throw RequestException.INTERNAL_ERROR; } post = findPost(request, topic); // Delete forum message delete(forum, topic, post, request.getUser()); } /** * Finds the content forum referenced in the request. * * @param request the request object * * @return the content forum referenced in the request * * @throws RequestException if the forum couldn't be found */ private ContentForum findForum(Request request) throws RequestException { ContentManager manager = getContentManager(); User user = request.getUser(); Content content; String forum; // Find content object forum = request.getParameter("liquidsite.forum", "0"); try { content = manager.getContent(user, Integer.parseInt(forum)); } catch (NumberFormatException e) { LOG.warning(request + ": forum id '" + forum + "' is not a number"); throw RequestException.INTERNAL_ERROR; } catch (ContentException e) { LOG.error(e.getMessage()); throw RequestException.INTERNAL_ERROR; } catch (ContentSecurityException e) { LOG.info(e.getMessage()); throw RequestException.FORBIDDEN; } // Check content forum if (!(content instanceof ContentForum)) { LOG.warning(request + ": content id '" + forum + "' is not a forum"); throw RequestException.INTERNAL_ERROR; } return (ContentForum) content; } /** * Finds the content topic referenced in the request. * * @param request the request object * @param forum the content forum * * @return the content topic referenced in the request, or * null if no topic was referenced * * @throws RequestException if the topic refererenced was invalid */ private ContentTopic findTopic(Request request, ContentForum forum) throws RequestException { ContentManager manager = getContentManager(); User user = request.getUser(); Content content; String topic; int id; // Find content object topic = request.getParameter("liquidsite.topic", "0"); try { id = Integer.parseInt(topic); if (id == 0) { return null; } content = manager.getContent(user, id); } catch (NumberFormatException e) { LOG.warning(request + ": topic id '" + topic + "' is not a number"); throw RequestException.INTERNAL_ERROR; } catch (ContentException e) { LOG.error(e.getMessage()); throw RequestException.INTERNAL_ERROR; } catch (ContentSecurityException e) { LOG.info(e.getMessage()); throw RequestException.FORBIDDEN; } // Check content topic if (!(content instanceof ContentTopic)) { LOG.warning(request + ": content id '" + topic + "' is not a topic"); throw RequestException.INTERNAL_ERROR; } else if (content.getParentId() != forum.getId()) { LOG.warning(request + ": content topic '" + topic + "' does not belong to forum " + forum.getId()); throw RequestException.INTERNAL_ERROR; } return (ContentTopic) content; } /** * Finds the content post referenced in the request. * * @param request the request object * @param topic the content topic * * @return the content post referenced in the request, or * null if no post was referenced * * @throws RequestException if the post refererenced was invalid */ private ContentPost findPost(Request request, ContentTopic topic) throws RequestException { ContentManager manager = getContentManager(); User user = request.getUser(); Content content; String post; int id; // Find content object post = request.getParameter("liquidsite.post", "0"); try { id = Integer.parseInt(post); if (id == 0) { return null; } content = manager.getContent(user, id); } catch (NumberFormatException e) { LOG.warning(request + ": post id '" + post + "' is not a number"); throw RequestException.INTERNAL_ERROR; } catch (ContentException e) { LOG.error(e.getMessage()); throw RequestException.INTERNAL_ERROR; } catch (ContentSecurityException e) { LOG.info(e.getMessage()); throw RequestException.FORBIDDEN; } // Check content post if (!(content instanceof ContentPost)) { LOG.warning(request + ": content id '" + post + "' is not a post"); throw RequestException.INTERNAL_ERROR; } else if (content.getParentId() != topic.getId()) { LOG.warning(request + ": content post '" + post + "' does not belong to topic " + topic.getId()); throw RequestException.INTERNAL_ERROR; } return (ContentPost) content; } /** * Posts a message to the specified forum and topic. * * @param forum the content forum * @param topic the content topic, or null for new * @param subject the message subject * @param text the message text * @param user the user posting the message * * @throws RequestException if an error occurred while storing * the message */ private void post(ContentForum forum, ContentTopic topic, String subject, String text, User user) throws RequestException { ContentManager manager = getContentManager(); ContentPost post; try { if (topic == null) { topic = new ContentTopic(manager, forum); topic.setSubject(subject); topic.setRevisionNumber(1); topic.setOnlineDate(new Date()); topic.setComment("Forum post"); topic.save(user); } post = new ContentPost(manager, topic); post.setSubject(subject); post.setTextType(ContentPost.PLAIN_TEXT_TYPE); post.setText(text); post.setRevisionNumber(1); post.setOnlineDate(new Date()); post.setComment("Forum post"); post.save(user); } catch (ContentException e) { LOG.error(e.getMessage()); throw RequestException.INTERNAL_ERROR; } catch (ContentSecurityException e) { LOG.info(e.getMessage()); throw RequestException.FORBIDDEN; } } /** * Edits a posted message. * * @param forum the content forum * @param post the content post * @param subject the message subject * @param text the message text * @param user the user posting the message * * @throws RequestException if an error occurred while storing * the message */ private void edit(ContentForum forum, ContentPost post, String subject, String text, User user) throws RequestException { boolean moderator; if (user == null) { LOG.info("anonymous user cannot delete posts"); throw RequestException.FORBIDDEN; } try { moderator = user.isSuperUser() || forum.isModerator(user); if (!moderator && !user.equals(post.getAuthor())) { LOG.info("user '" + user + "' cannot edit post " + post + " from '" + post.getAuthorName() + "'"); throw RequestException.FORBIDDEN; } post.setSubject(subject); post.setTextType(ContentPost.PLAIN_TEXT_TYPE); post.setText(text); post.setRevisionNumber(post.getRevisionNumber() + 1); post.setComment("Forum post"); post.save(user); } catch (ContentException e) { LOG.error(e.getMessage()); throw RequestException.INTERNAL_ERROR; } catch (ContentSecurityException e) { LOG.info(e.getMessage()); throw RequestException.FORBIDDEN; } } /** * Deletes a message from the specified forum and topic. * * @param forum the content forum * @param topic the content topic * @param post the content post * @param user the user deleting the message * * @throws RequestException if an error occurred while deleting * the message */ private void delete(ContentForum forum, ContentTopic topic, ContentPost post, User user) throws RequestException { ContentManager manager = getContentManager(); Content[] posts; boolean moderator; if (user == null) { LOG.info("anonymous user cannot delete posts"); throw RequestException.FORBIDDEN; } try { moderator = user.isSuperUser() || forum.isModerator(user); if (post == null) { if (!moderator) { LOG.info("user '" + user + "' cannot delete topic " + topic); throw RequestException.FORBIDDEN; } topic.delete(user); } else { if (!moderator && !user.equals(post.getAuthor())) { LOG.info("user '" + user + "' cannot delete post " + post + " in topic " + topic); throw RequestException.FORBIDDEN; } post.delete(user); posts = manager.getContentChildren(user, topic, Content.POST_CATEGORY); if (posts.length == 0) { topic.delete(user); } } } catch (ContentException e) { LOG.error(e.getMessage()); throw RequestException.INTERNAL_ERROR; } catch (ContentSecurityException e) { LOG.info(e.getMessage()); throw RequestException.FORBIDDEN; } } }