Java tutorial
/* * Copyright 1998-2012 Linux.org.ru * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ru.org.linux.topic; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.validation.Errors; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartRequest; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.RedirectView; import ru.org.linux.auth.CaptchaService; import ru.org.linux.auth.FloodProtector; import ru.org.linux.auth.IPBlockDao; import ru.org.linux.auth.IPBlockInfo; import ru.org.linux.csrf.CSRFNoAuto; import ru.org.linux.csrf.CSRFProtectionService; import ru.org.linux.gallery.Image; import ru.org.linux.gallery.Screenshot; import ru.org.linux.group.BadGroupException; import ru.org.linux.group.Group; import ru.org.linux.group.GroupDao; import ru.org.linux.group.GroupPermissionService; import ru.org.linux.poll.Poll; import ru.org.linux.poll.PollVariant; import ru.org.linux.search.SearchQueueSender; import ru.org.linux.section.Section; import ru.org.linux.section.SectionService; import ru.org.linux.site.ScriptErrorException; import ru.org.linux.site.Template; import ru.org.linux.spring.Configuration; import ru.org.linux.tag.TagService; import ru.org.linux.user.User; import ru.org.linux.user.UserDao; import ru.org.linux.user.UserPropertyEditor; import ru.org.linux.util.BadImageException; import ru.org.linux.util.ExceptionBindingErrorProcessor; import ru.org.linux.util.UtilException; import ru.org.linux.util.bbcode.LorCodeService; import ru.org.linux.util.formatter.ToLorCodeFormatter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.validation.Valid; import java.beans.PropertyEditorSupport; import java.io.File; import java.io.IOException; import java.util.*; @Controller public class AddTopicController { private static final Log logger = LogFactory.getLog(AddTopicController.class); private SearchQueueSender searchQueueSender; @Autowired private CaptchaService captcha; private FloodProtector dupeProtector; private IPBlockDao ipBlockDao; private GroupDao groupDao; @Autowired private SectionService sectionService; @Autowired private TagService tagService; private UserDao userDao; @Autowired private TopicPrepareService prepareService; private TopicDao messageDao; private ToLorCodeFormatter toLorCodeFormatter; @Autowired private LorCodeService lorCodeService; @Autowired private GroupPermissionService groupPermissionService; @Autowired private Configuration configuration; @Autowired private AddTopicRequestValidator addTopicRequestValidator; public static final int MAX_MESSAGE_LENGTH_ANONYMOUS = 8196; public static final int MAX_MESSAGE_LENGTH = 32768; @Autowired public void setSearchQueueSender(SearchQueueSender searchQueueSender) { this.searchQueueSender = searchQueueSender; } @Autowired public void setDupeProtector(FloodProtector dupeProtector) { this.dupeProtector = dupeProtector; } @Autowired public void setIpBlockDao(IPBlockDao ipBlockDao) { this.ipBlockDao = ipBlockDao; } @Autowired public void setGroupDao(GroupDao groupDao) { this.groupDao = groupDao; } @Autowired public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Autowired public void setMessageDao(TopicDao messageDao) { this.messageDao = messageDao; } @Autowired public void setToLorCodeFormatter(ToLorCodeFormatter toLorCodeFormatter) { this.toLorCodeFormatter = toLorCodeFormatter; } @ModelAttribute("ipBlockInfo") private IPBlockInfo loadIPBlock(HttpServletRequest request) { return ipBlockDao.getBlockInfo(request.getRemoteAddr()); } @RequestMapping(value = "/add.jsp", method = RequestMethod.GET) public ModelAndView add(@Valid @ModelAttribute("form") AddTopicRequest form, HttpServletRequest request) { Map<String, Object> params = new HashMap<String, Object>(); Template tmpl = Template.getTemplate(request); if (form.getMode() == null) { form.setMode(tmpl.getFormatMode()); } prepareModel(form, params, tmpl.getCurrentUser()); Group group = form.getGroup(); if (tmpl.isSessionAuthorized() && !groupPermissionService.isTopicPostingAllowed(group, tmpl.getCurrentUser())) { ModelAndView errorView = new ModelAndView("errors/good-penguin"); errorView.addObject("msgHeader", "?? ? ? ? "); errorView.addObject("msgMessage", groupPermissionService.getPostScoreInfo(group)); return errorView; } return new ModelAndView("add", params); } private String processMessage(String msg, String mode) { if (msg == null) { return ""; } if ("ntobr".equals(mode)) { return toLorCodeFormatter.format(msg, false); } else { return msg; } } private void prepareModel(AddTopicRequest form, Map<String, Object> params, User currentUser) { Group group = form.getGroup(); if (group != null) { params.put("group", group); params.put("postscoreInfo", groupPermissionService.getPostScoreInfo(group)); Section section = sectionService.getSection(group.getSectionId()); params.put("section", section); params.put("addportal", sectionService.getAddInfo(group.getSectionId())); params.put("imagepost", groupPermissionService.isImagePostingAllowed(section, currentUser)); } params.put("topTags", tagService.getTopTags()); } @RequestMapping(value = "/add.jsp", method = RequestMethod.POST) @CSRFNoAuto public ModelAndView doAdd(HttpServletRequest request, @Valid @ModelAttribute("form") AddTopicRequest form, BindingResult errors, @ModelAttribute("ipBlockInfo") IPBlockInfo ipBlockInfo) throws Exception { Map<String, Object> params = new HashMap<String, Object>(); Template tmpl = Template.getTemplate(request); HttpSession session = request.getSession(); String image = processUploadImage(request); Group group = form.getGroup(); prepareModel(form, params, tmpl.getCurrentUser()); Section section = null; if (group != null) { section = sectionService.getSection(group.getSectionId()); } User user; if (!tmpl.isSessionAuthorized()) { if (form.getNick() != null) { user = form.getNick(); } else { user = userDao.getAnonymous(); } if (form.getPassword() == null) { errors.rejectValue("password", null, "?? ?"); } } else { user = tmpl.getCurrentUser(); } user.checkBlocked(errors); IPBlockDao.checkBlockIP(ipBlockInfo, errors, user); if (group != null && !groupPermissionService.isTopicPostingAllowed(group, user)) { errors.reject(null, "?? ? ? ? "); } String message = processMessage(form.getMsg(), form.getMode()); if (user.isAnonymous()) { if (message.length() > MAX_MESSAGE_LENGTH_ANONYMOUS) { errors.rejectValue("msg", null, " ?"); } } else { if (message.length() > MAX_MESSAGE_LENGTH) { errors.rejectValue("msg", null, " ?"); } } Screenshot scrn = null; if (section != null && groupPermissionService.isImagePostingAllowed(section, tmpl.getCurrentUser())) { scrn = processUpload(session, image, errors); if (section.isImagepost() && scrn == null && !errors.hasErrors()) { errors.reject(null, " ??"); } } Poll poll = null; if (section != null && section.isPollPostAllowed()) { poll = preparePollPreview(form); } Topic previewMsg = null; if (group != null) { previewMsg = new Topic(form, user, request.getRemoteAddr()); Image imageObject = null; if (scrn != null) { imageObject = new Image(0, 0, "gallery/preview/" + scrn.getMainFile().getName(), "gallery/preview/" + scrn.getIconFile().getName()); } params.put("message", prepareService.prepareTopicPreview(previewMsg, tagService.parseSanitizeTags(form.getTags()), poll, request.isSecure(), message, imageObject)); } if (!form.isPreviewMode() && !errors.hasErrors()) { CSRFProtectionService.checkCSRF(request, errors); } if (!form.isPreviewMode() && !errors.hasErrors() && !tmpl.isSessionAuthorized() || ipBlockInfo.isCaptchaRequired()) { captcha.checkCaptcha(request, errors); } if (!form.isPreviewMode() && !errors.hasErrors()) { dupeProtector.checkDuplication(request.getRemoteAddr(), false, errors); } if (!form.isPreviewMode() && !errors.hasErrors() && group != null && section != null) { session.removeAttribute("image"); Set<User> userRefs = lorCodeService.getReplierFromMessage(message); int msgid = messageDao.addMessage(request, form, message, group, user, scrn, previewMsg, userRefs); searchQueueSender.updateMessageOnly(msgid); Random random = new Random(); String messageUrl = "view-message.jsp?msgid=" + msgid; if (!section.isPremoderated()) { return new ModelAndView(new RedirectView(messageUrl + "&nocache=" + random.nextInt())); } params.put("moderated", section.isPremoderated()); params.put("url", messageUrl); return new ModelAndView("add-done-moderated", params); } else { return new ModelAndView("add", params); } } private static Poll preparePollPreview(AddTopicRequest form) { List<PollVariant> variants = new ArrayList<PollVariant>(form.getPoll().length); for (String item : form.getPoll()) { if (!Strings.isNullOrEmpty(item)) { variants.add(new PollVariant(0, item)); } } return new Poll(0, 0, form.isMultiSelect(), false, variants); } @RequestMapping("/add-section.jsp") public ModelAndView showForm(@RequestParam("section") int sectionId) { Map<String, Object> params = new HashMap<String, Object>(); params.put("sectionId", sectionId); Section section = sectionService.getSection(sectionId); params.put("section", section); params.put("info", sectionService.getAddInfo(section.getId())); params.put("groups", groupDao.getGroups(section)); return new ModelAndView("add-section", params); } @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Group.class, new PropertyEditorSupport() { @Override public void setAsText(String text) throws IllegalArgumentException { try { setValue(groupDao.getGroup(Integer.parseInt(text))); } catch (BadGroupException e) { throw new IllegalArgumentException(e); } } @Override public String getAsText() { if (getValue() == null) { return null; } else { return Integer.toString(((Group) getValue()).getId()); } } }); binder.registerCustomEditor(User.class, new UserPropertyEditor(userDao)); } @InitBinder("form") public void requestValidator(WebDataBinder binder) { binder.setValidator(addTopicRequestValidator); binder.setBindingErrorProcessor(new ExceptionBindingErrorProcessor()); } @ModelAttribute("modes") public Map<String, String> getModes() { return ImmutableMap.of("lorcode", "LORCODE", "ntobr", "User line break"); } /** * * * @param session * @return <icon, image, previewImagePath> or null * @throws IOException * @throws UtilException */ private Screenshot processUpload(HttpSession session, String image, Errors errors) throws IOException, UtilException { if (session == null) { return null; } Screenshot screenShot = null; if (image != null && !image.isEmpty()) { File uploadedFile = new File(image); try { screenShot = Screenshot.createScreenshot(uploadedFile, errors, configuration.getHTMLPathPrefix() + "/gallery/preview"); if (screenShot != null) { logger.info("SCREEN: " + uploadedFile.getAbsolutePath() + "\nINFO: SCREEN: " + image); session.setAttribute("image", screenShot); } } catch (BadImageException e) { errors.reject(null, "? : " + e.getMessage()); } } else if (session.getAttribute("image") != null && !"".equals(session.getAttribute("image"))) { screenShot = (Screenshot) session.getAttribute("image"); if (!screenShot.getMainFile().exists()) { screenShot = null; } } return screenShot; } private String processUploadImage(HttpServletRequest request) throws IOException, ScriptErrorException { if (request instanceof MultipartHttpServletRequest) { MultipartFile multipartFile = ((MultipartRequest) request).getFile("image"); if (multipartFile != null && !multipartFile.isEmpty()) { File uploadedFile = File.createTempFile("preview", "", new File(configuration.getPathPrefix() + "/linux-storage/tmp/")); String image = uploadedFile.getPath(); if ((uploadedFile.canWrite() || uploadedFile.createNewFile())) { try { logger.debug("Transfering upload to: " + image); multipartFile.transferTo(uploadedFile); return image; } catch (Exception e) { throw new ScriptErrorException("Failed to write uploaded file", e); } } else { logger.info("Bad target file name: " + image); } } } return null; } }