1 41 package com.mvnforum.user; 42 43 import java.io.*; 44 import java.sql.Timestamp ; 45 import java.util.*; 46 47 import javax.servlet.http.HttpServletRequest ; 48 import javax.servlet.http.HttpServletResponse ; 49 50 import com.mvnforum.*; 51 import com.mvnforum.auth.*; 52 import com.mvnforum.common.PrivateMessageUtil; 53 import com.mvnforum.db.*; 54 import net.myvietnam.mvncore.exception.*; 55 import net.myvietnam.mvncore.filter.DisableHtmlTagFilter; 56 import net.myvietnam.mvncore.interceptor.InterceptorService; 57 import net.myvietnam.mvncore.service.BinaryStorage; 58 import net.myvietnam.mvncore.util.*; 59 import net.myvietnam.mvncore.web.*; 60 import net.myvietnam.mvncore.web.fileupload.FileItem; 61 import net.myvietnam.mvncore.web.fileupload.FileUploadException; 62 63 import org.apache.commons.io.IOUtils; 64 import org.apache.commons.logging.Log; 65 import org.apache.commons.logging.LogFactory; 66 67 public class PmAttachmentWebHandler { 68 69 private static Log log = LogFactory.getLog(PmAttachmentWebHandler.class); 70 71 private OnlineUserManager userManager = OnlineUserManager.getInstance(); 72 73 public PmAttachmentWebHandler() { 74 } 75 76 public void prepareAdd(GenericRequest request) 77 throws BadInputException, DatabaseException, ObjectNotFoundException, 78 AuthenticationException, AssertionException { 79 80 Locale locale = I18nUtil.getLocaleInRequest(request); 81 82 if (MVNForumConfig.getEnableMessageAttachment() == false) { 83 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.message_attachment_is_disabled"); 84 throw new AssertionException(localizedMessage); 85 } 87 88 OnlineUser onlineUser = userManager.getOnlineUser(request); 89 MVNForumPermission permission = onlineUser.getPermission(); 90 permission.ensureIsAuthenticated(); 91 permission.ensureCanUseMessage(); 92 permission.ensureCanAddMessageAttachment(); 93 94 int messageID = GenericParamUtil.getParameterInt(request, "message"); 95 MessageBean messageBean = null; 96 try { 97 messageBean = DAOFactory.getMessageDAO().getMessage(messageID); 98 } catch (ObjectNotFoundException e) { 99 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.messageid_not_exists", new Object [] {new Integer (messageID)}); 100 throw new ObjectNotFoundException(localizedMessage); 101 } 102 if (messageBean.getFolderName().equalsIgnoreCase(MVNForumConstant.MESSAGE_FOLDER_DRAFT) == false) { 103 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_add_attachment.pm_does_not_in_folder_draft"); 104 throw new BadInputException(localizedMessage); 105 } 107 108 if (messageBean.getMemberID() != onlineUser.getMemberID() ) { 109 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.pm_not_belongs_to_you"); 110 throw new BadInputException(localizedMessage); 111 } 113 114 request.setAttribute("MessageBean", messageBean); 115 } 116 117 public void processAdd(GenericRequest request, GenericResponse response) 118 throws BadInputException, CreateException, DatabaseException, IOException, ForeignKeyNotFoundException, 119 AuthenticationException, AssertionException, ObjectNotFoundException, InterceptorException { 120 121 Locale locale = I18nUtil.getLocaleInRequest(request); 122 123 if (MVNForumConfig.getEnableMessageAttachment() == false) { 124 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.message_attachment_is_disabled"); 125 throw new AssertionException(localizedMessage); 126 } 128 129 OnlineUser onlineUser = userManager.getOnlineUser(request); 130 MVNForumPermission permission = onlineUser.getPermission(); 131 permission.ensureIsAuthenticated(); 132 permission.ensureCanUseMessage(); 133 permission.ensureCanAddMessageAttachment(); 134 135 MyUtil.saveVNTyperMode(request, response); 136 137 final int UNLIMITED = -1; 138 int sizeMax = permission.canAdminSystem() ? UNLIMITED : MVNForumConfig.getMaxMessageAttachmentSize() ; 139 int sizeThreshold = 100000; 140 String tempDir = MVNForumConfig.getTempDir(); 141 142 log.debug("PmAttachmentWebHandler : process upload with temp dir = " + tempDir); 143 144 List fileItems; 145 try { 146 FileUploadParser uploadParser = FileUploadParserFactory.getFileUploadParser(); 147 fileItems = uploadParser.parseRequest(request, sizeMax, sizeThreshold, tempDir, "UTF-8"); 148 } catch (FileUploadException ex) { 149 log.error("Cannot upload", ex); 150 String localizedMessage = MVNForumResourceBundle.getString(locale, "java.io.IOException.cannot_upload", new Object [] {ex.getMessage()}); 151 throw new IOException(localizedMessage); 152 } 154 155 int messageID = 0; 157 String attachFilename = null; 158 int attachFileSize = 0; 159 String attachMimeType = null; 160 String attachDesc = null; 161 boolean attachMore = false; 162 boolean markAsQuote = false; 163 boolean addToSentFolder = false; 164 165 FileItem attachFileItem = null; 166 167 String actionParam = URLResolverFactory.getURLResolver().getActionParam(); 168 for (int i = 0; i < fileItems.size(); i++ ) { 169 FileItem currentFileItem = (FileItem)fileItems.get(i); 170 String fieldName = currentFileItem.getFieldName(); 171 if (fieldName.equals("AddToSentFolder")) { 172 String content = currentFileItem.getString("utf-8"); 173 addToSentFolder = (content.length() > 0); 174 log.debug("addToSentFolder = " + addToSentFolder); 175 } else if (fieldName.equals("AttachMore")) { 176 String content = currentFileItem.getString("utf-8"); 177 attachMore = (content.length() > 0); 178 log.debug("attachMore = " + attachMore); 179 } else if (fieldName.equals("MarkAsQuote")) { 180 String content = currentFileItem.getString("utf-8"); 181 markAsQuote = (content.length() > 0); 182 log.debug("markAsQuote = " + markAsQuote); 183 } else if (fieldName.equals("MessageID")) { 184 String content = currentFileItem.getString("utf-8"); 185 messageID = Integer.parseInt(content); 186 log.debug("messageID = " + messageID); 187 } else if (fieldName.equals("AttachDesc")) { 188 String content = currentFileItem.getString("utf-8"); 189 attachDesc = DisableHtmlTagFilter.filter(content); 190 log.debug("attachDesc = " + attachDesc); 191 attachDesc = InterceptorService.getInstance().validateContent(attachDesc); 192 } else if (fieldName.equals("vnselector")) { 193 } else if (fieldName.equals("AttachFilename")) { 195 if (currentFileItem.isFormField() == true) { 196 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.cannot_process_uploaded_attach_file_with_form_field"); 197 throw new AssertionException(localizedMessage); 198 } 200 attachMimeType = currentFileItem.getContentType(); 201 attachMimeType = DisableHtmlTagFilter.filter(attachMimeType); 202 attachFileSize = (int)currentFileItem.getSize(); 203 if (attachFileSize == 0) { 204 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_process_upload_with_file_size_is_zero"); 205 throw new BadInputException(localizedMessage); 206 } 208 String fullFilePath = currentFileItem.getName(); 209 attachFilename = FileUtil.getFileName(fullFilePath); 210 attachFilename = DisableHtmlTagFilter.filter(attachFilename); 211 log.debug("attachFilename = " + attachFilename); 212 213 attachFileItem = currentFileItem; 215 } else if (fieldName.equals(actionParam)) { 216 } else { 218 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.cannot_process_field_name", new Object [] {fieldName}); 219 throw new AssertionException(localizedMessage); 220 } 222 } Timestamp now = DateUtil.getCurrentGMTTimestamp(); 224 225 MessageBean messageBean = null; 227 try { 228 messageBean = DAOFactory.getMessageDAO().getMessage(messageID); 229 } catch (ObjectNotFoundException e) { 230 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.messageid_not_exists", new Object [] {new Integer (messageID)}); 231 throw new ObjectNotFoundException(localizedMessage); 232 } 233 234 if (messageBean.getFolderName().equalsIgnoreCase(MVNForumConstant.MESSAGE_FOLDER_DRAFT) == false) { 235 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.cannot_add_attachment.pm_does_not_in_folder_draft"); 236 throw new BadInputException(localizedMessage); 237 } 239 240 int logonMemberID = onlineUser.getMemberID(); 241 242 if (messageBean.getMemberID() != logonMemberID ) { 244 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.pm_not_belongs_to_you"); 245 throw new BadInputException(localizedMessage); 246 } 248 249 if (messageBean.getMessageSenderID() != logonMemberID ) { 251 throw new AssertionException("Assertion: The MessageSenderID must equals the current logined user."); 252 } 253 if (messageBean.getMessageSenderName().equals(onlineUser.getMemberName()) == false) { 254 throw new AssertionException("Assertion: The MessageSenderName must equals the current logined user."); 255 } 256 258 String creationIP = request.getRemoteAddr(); 261 Timestamp attachCreationDate= now; 262 Timestamp attachModifiedDate= now; 263 int attachDownloadCount = 0; 264 int attachOption = 0; int attachStatus = 0; int attachID = DAOFactory.getPmAttachmentDAO().create(logonMemberID, attachFilename, 267 attachFileSize, attachMimeType, attachDesc, 268 creationIP, attachCreationDate, attachModifiedDate, 269 attachDownloadCount, attachOption, attachStatus); 270 try { 271 DAOFactory.getPmAttachMessageDAO().create(messageID, attachID, 0, 0, 0); 272 } catch (DuplicateKeyException ex) { 273 throw new AssertionException("DuplicateKeyException when create PmAttachMessage"); 275 } 276 277 try { 278 BinaryStorage binaryStorage = ManagerFactory.getBinaryStorage(); 282 binaryStorage.storeData(BinaryStorage.CATEGORY_PM_ATTACHMENT, String.valueOf(attachID), attachFilename, 283 attachFileItem.getInputStream(), attachFileSize, 0, 0, attachMimeType, creationIP); 284 285 } catch (Exception ex) { 286 log.error("Cannot save the attachment file", ex); 287 DAOFactory.getPmAttachMessageDAO().delete(messageID, attachID); 288 DAOFactory.getPmAttachmentDAO().delete(attachID); 289 String localizedMessage = MVNForumResourceBundle.getString(locale, "java.io.IOException.cannot_save_attach_file"); 290 throw new IOException(localizedMessage); 291 } 293 294 int attachCount = DAOFactory.getPmAttachMessageDAO().getNumberOfBeans_inMessage(messageID); 296 297 try { 298 DAOFactory.getMessageDAO().updateAttachCount(messageID, attachCount); 299 } catch (ObjectNotFoundException e) { 300 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.messageid_not_exists", new Object [] {new Integer (messageID)}); 301 throw new ObjectNotFoundException(localizedMessage); 302 } 303 int maxPrivateMessage = MVNForumConfig.getMaxPrivateMessage(); 304 305 if (attachMore == false) { 307 String [] receivedMembers = StringUtil.getStringArrays(messageBean.getMessageToList(), messageBean.getMessageCcList(), messageBean.getMessageBccList(), ";"); 308 Hashtable receivers = MyUtil.checkMembers(receivedMembers, locale); 309 int messageType = messageBean.getMessageType(); 310 if (markAsQuote) { 311 messageType = MessageBean.MESSAGE_TYPE_QUOTE; 314 } 315 Collection attachBeans = DAOFactory.getPmAttachmentDAO().getPmAttachments_inMessage(messageBean.getMessageID()); 317 StringBuffer overQuotaReceivers = new StringBuffer (128); 318 for (Enumeration enumeration = receivers.keys(); enumeration.hasMoreElements(); ) { 319 int receivedMemberID = ((Integer )enumeration.nextElement()).intValue(); 320 String receivedMemberName = (String )receivers.get(new Integer (receivedMemberID)); 321 322 int receiverMessageCount = DAOFactory.getMessageDAO().getNumberOfNonPublicMessages_inMember(receivedMemberID); 323 if (receiverMessageCount >= maxPrivateMessage) { 324 if (overQuotaReceivers.length() > 0) { 325 overQuotaReceivers.append(", "); 326 } 327 overQuotaReceivers.append(receivedMemberName); 328 continue; 329 } 330 331 int eachMessageID = DAOFactory.getMessageDAO().create(MVNForumConstant.MESSAGE_FOLDER_INBOX, receivedMemberID, logonMemberID, 333 messageBean.getMessageSenderName(), messageBean.getMessageToList(), messageBean.getMessageCcList(), 334 messageBean.getMessageBccList(), messageBean.getMessageTopic(), messageBean.getMessageBody(), 335 messageType, messageBean.getMessageOption(), messageBean.getMessageStatus(), 336 MessageBean.MESSAGE_READ_STATUS_DEFAULT, messageBean.getMessageNotify(), messageBean.getMessageIcon(), 337 attachCount, creationIP, now); 338 339 if (logonMemberID != receivedMemberID) { 341 DAOFactory.getMessageStatisticsDAO().create(logonMemberID, receivedMemberID, now, 342 messageBean.getMessageAttachCount(), messageBean.getMessageType(), 343 messageBean.getMessageOption(), messageBean.getMessageStatus()); 344 } 345 for (Iterator attachIter = attachBeans.iterator(); attachIter.hasNext(); ) { 347 PmAttachmentBean pmAttachBean = (PmAttachmentBean)attachIter.next(); 348 try { 349 DAOFactory.getPmAttachMessageDAO().create(eachMessageID, pmAttachBean.getPmAttachID(), 0, 0, 0); 350 } catch (DuplicateKeyException ex) { 351 throw new AssertionException("DuplicateKeyException when create PmAttachMessage"); 353 } 354 } 355 } request.setAttribute("OverQuotaReceivers", overQuotaReceivers.toString()); 357 358 if (addToSentFolder) { 359 int senderMessageCount = DAOFactory.getMessageDAO().getNumberOfNonPublicMessages_inMember(logonMemberID); 360 if (senderMessageCount < maxPrivateMessage) { 361 messageType = MessageBean.MESSAGE_TYPE_DEFAULT; int sentMessageID = DAOFactory.getMessageDAO().create(MVNForumConstant.MESSAGE_FOLDER_SENT, logonMemberID, logonMemberID, 363 messageBean.getMessageSenderName(), messageBean.getMessageToList(), messageBean.getMessageCcList(), 364 messageBean.getMessageBccList(), messageBean.getMessageTopic(), messageBean.getMessageBody(), 365 messageType, messageBean.getMessageOption(), messageBean.getMessageStatus(), 366 MessageBean.MESSAGE_READ_STATUS_DEFAULT, messageBean.getMessageNotify(), messageBean.getMessageIcon(), 367 attachCount, creationIP, now); 368 369 for (Iterator attachIter = attachBeans.iterator(); attachIter.hasNext(); ) { 370 PmAttachmentBean pmAttachBean = (PmAttachmentBean)attachIter.next(); 371 try { 372 DAOFactory.getPmAttachMessageDAO().create(sentMessageID, pmAttachBean.getPmAttachID(), 0, 0, 0); 373 } catch (DuplicateKeyException ex) { 374 throw new AssertionException("DuplicateKeyException when create PmAttachMessage"); 376 } 377 } 378 } else { 379 request.setAttribute("AddSentFolderOverQuota", Boolean.TRUE); 380 } 381 } 383 PrivateMessageUtil.deleteMessageInDatabase(messageID, logonMemberID); 385 } 387 request.setAttribute("MessageID", String.valueOf(messageID)); 388 request.setAttribute("AttachMore", new Boolean (attachMore)); 389 request.setAttribute("AddToSentFolder", new Boolean (addToSentFolder)); 390 request.setAttribute("MarkAsQuote", new Boolean (markAsQuote)); 391 } 392 393 public void downloadAttachment(HttpServletRequest request, HttpServletResponse response) 394 throws BadInputException, DatabaseException, ObjectNotFoundException, 395 IOException, AuthenticationException, AssertionException { 396 397 Locale locale = I18nUtil.getLocaleInRequest(request); 398 399 if (MVNForumConfig.getEnableMessageAttachment() == false) { 400 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.AssertionException.message_attachment_is_disabled"); 401 throw new AssertionException(localizedMessage); 402 } 404 405 OnlineUser onlineUser = userManager.getOnlineUser(request); 406 MVNForumPermission permission = onlineUser.getPermission(); 407 permission.ensureIsAuthenticated(); 408 permission.ensureCanUseMessage(); 409 410 int attachID = ParamUtil.getParameterInt(request, "attach"); 411 int messageID = ParamUtil.getParameterInt(request, "message"); 412 413 PmAttachmentBean pmAttachBean = null; 414 try { 415 pmAttachBean = DAOFactory.getPmAttachmentDAO().getPmAttachment(attachID); 416 } catch (ObjectNotFoundException e) { 417 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.attachmentid_not_exists", new Object [] {new Integer (attachID)}); 418 throw new ObjectNotFoundException(localizedMessage); 419 } 420 421 MessageBean messageBean = null; 422 try { 423 messageBean = DAOFactory.getMessageDAO().getMessage(messageID); 424 } catch (ObjectNotFoundException e) { 425 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.messageid_not_exists", new Object [] {new Integer (messageID)}); 426 throw new ObjectNotFoundException(localizedMessage); 427 } 428 429 boolean isPublicMessage = (messageBean.getMessageType() == MessageBean.MESSAGE_TYPE_PUBLIC); 431 432 if ((messageBean.getMemberID() != onlineUser.getMemberID()) && !isPublicMessage) { 433 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.BadInputException.pm_not_belongs_to_you"); 434 throw new BadInputException(localizedMessage); 435 } 437 438 DAOFactory.getPmAttachMessageDAO().findByPrimaryKey(messageID, attachID); 440 441 InputStream inputStream = null; 442 OutputStream outputStream = null; 443 try { 444 452 453 try { 456 DAOFactory.getPmAttachmentDAO().increaseDownloadCount(attachID); 457 } catch (ObjectNotFoundException e) { 458 String localizedMessage = MVNForumResourceBundle.getString(locale, "mvncore.exception.ObjectNotFoundException.attachmentid_not_exists", new Object [] {new Integer (attachID)}); 459 throw new ObjectNotFoundException(localizedMessage); 460 } 461 462 response.setContentType(pmAttachBean.getPmAttachMimeType()); 463 response.setHeader("Location", pmAttachBean.getPmAttachFilename()); 464 465 if (pmAttachBean.getPmAttachMimeType().startsWith("image/")) { 467 long cacheTime = DateUtil.DAY * 30 / 1000; response.setHeader("Cache-Control", "max-age=" + cacheTime); 469 } 470 471 response.setHeader("Content-Disposition", "attachment; filename=" + pmAttachBean.getPmAttachFilename()); 472 473 try { 475 BinaryStorage binaryStorage = ManagerFactory.getBinaryStorage(); 476 inputStream = binaryStorage.getInputStream(BinaryStorage.CATEGORY_PM_ATTACHMENT, String.valueOf(attachID), null); 477 478 outputStream = response.getOutputStream(); 479 IOUtils.copy(inputStream, outputStream); 481 } catch (IOException ex) { 482 log.error("Error while trying to send PM attachment file from server: attachID = " + attachID + ".", ex); 484 } 485 outputStream.flush(); 486 outputStream.close(); 487 outputStream = null; } catch (IOException ex) { 489 throw ex; 490 } finally { 491 if (inputStream != null) { 492 try { 493 inputStream.close(); 494 } catch (IOException ex) { } 495 } 496 if (outputStream != null) { 497 try { 498 outputStream.close(); 499 } catch (IOException ex) { } 500 } 501 } 502 } 503 504 void deleteOrphanPmAttachment() throws DatabaseException, AssertionException { 505 506 Collection attachBeans = DAOFactory.getPmAttachmentDAO().getOrphanPmAttachments(); 507 508 for (Iterator iter = attachBeans.iterator(); iter.hasNext(); ) { 510 PmAttachmentBean pmAttachmentBean = (PmAttachmentBean)iter.next(); 511 int pmAttachID = pmAttachmentBean.getPmAttachID(); 512 int messageCount = DAOFactory.getPmAttachMessageDAO().getNumberOfBeans_inPmAttach(pmAttachID); 513 if (messageCount > 0) { 514 throw new AssertionException("This PmAttachID [" + pmAttachID + "] is not orphan because MessageCount = " + messageCount + ". Please report this to mvnForum Developers"); 516 } 517 } 518 519 BinaryStorage binaryStorage = ManagerFactory.getBinaryStorage(); 520 for (Iterator iter = attachBeans.iterator(); iter.hasNext(); ) { 522 PmAttachmentBean pmAttachmentBean = (PmAttachmentBean)iter.next(); 523 int pmAttachID = pmAttachmentBean.getPmAttachID(); 524 log.debug("About to delete orphan PmAttachment with ID = " + pmAttachID); 525 526 try { 529 binaryStorage.deleteData(BinaryStorage.CATEGORY_PM_ATTACHMENT, String.valueOf(pmAttachID), null); 530 } catch (IOException e) { 531 log.warn("Cannot BinaryStorage.deleteData with PmAttachID = " + pmAttachID, e); 533 } 534 535 try { 536 DAOFactory.getPmAttachmentDAO().delete(pmAttachID); 537 } catch (Exception ex) { 538 log.warn("Cannot delete message attachment in database with PmAttachID = " + pmAttachID, ex); 539 } 540 } 541 } 542 } 543 | Popular Tags |