001/** 002 * Copyright 2005-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kew.notes.web; 017 018import org.apache.log4j.Logger; 019import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator; 020import org.kuali.rice.kew.api.WorkflowRuntimeException; 021import org.kuali.rice.kew.doctype.SecuritySession; 022import org.kuali.rice.kew.notes.Attachment; 023import org.kuali.rice.kew.notes.service.NoteService; 024import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 025import org.kuali.rice.kew.service.KEWServiceLocator; 026import org.kuali.rice.kew.api.KewApiConstants; 027import org.kuali.rice.krad.UserSession; 028import org.kuali.rice.krad.util.KRADConstants; 029 030import javax.servlet.ServletException; 031import javax.servlet.http.HttpServlet; 032import javax.servlet.http.HttpServletRequest; 033import javax.servlet.http.HttpServletResponse; 034import java.io.BufferedInputStream; 035import java.io.BufferedOutputStream; 036import java.io.File; 037import java.io.FileInputStream; 038import java.io.IOException; 039import java.io.OutputStream; 040 041 042 043 044/** 045 * A servlet which can be used to retrieve attachments from Notes. 046 * 047 * @author Kuali Rice Team (rice.collab@kuali.org) 048 */ 049public class AttachmentServlet extends HttpServlet { 050 051 private static final long serialVersionUID = -1918858512573502697L; 052 public static final String ATTACHMENT_ID_KEY = "attachmentId"; 053 054 // TODO This should probably be put into KewApiConstants when contributed back 055 // to Rice 1.0.3 056 private static final Logger LOG = Logger.getLogger(AttachmentServlet.class); 057 058 @Override 059 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 060 String attachmentId = request.getParameter(ATTACHMENT_ID_KEY); 061 if (attachmentId == null) { 062 throw new ServletException("No 'attachmentId' was specified."); 063 } 064 065 boolean secureChecks = false; 066 String secureAttachmentsParam = null; 067 try { 068 secureAttachmentsParam = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KewApiConstants.KEW_NAMESPACE, "All", KewApiConstants.SECURE_ATTACHMENTS_PARAM); 069 } catch (Exception e) { 070 LOG.info("Attempted to retrieve parameter value, but could not. Defaulting to unsecured attachment retrieval. " + e.getMessage()); 071 } 072 if (secureAttachmentsParam != null && secureAttachmentsParam.equals("Y")) { 073 secureChecks = true; 074 } 075 try { 076 UserSession userSession = (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY); 077 if (userSession != null) {// If we can get a valid userSession object off the Http request... 078 079 NoteService noteService = KEWServiceLocator.getNoteService(); 080 Attachment attachment = noteService.findAttachment(attachmentId); 081 File file = noteService.findAttachmentFile(attachment); 082 083 DocumentRouteHeaderValue routeHeader = KEWServiceLocator.getRouteHeaderService().getRouteHeader(noteService.getNoteByNoteId(attachment.getNoteId()).getDocumentId()); 084 085 if(!secureChecks || routeHeader != null){// If we can get a valid routeHeader based on the requested attachment ID 086 boolean authorized = KEWServiceLocator.getDocumentSecurityService().routeLogAuthorized(userSession.getPrincipalId(), routeHeader, new SecuritySession(userSession.getPrincipalId())); 087 boolean customAttributeAuthorized = false; 088 if(routeHeader.getCustomNoteAttribute() != null){ 089 routeHeader.getCustomNoteAttribute().setUserSession(userSession); 090 customAttributeAuthorized = routeHeader.getCustomNoteAttribute().isAuthorizedToRetrieveAttachments(); 091 } 092 if(!secureChecks || (authorized && customAttributeAuthorized)){//If this user can see this document, they can get the attachment(s) 093 response.setContentLength((int)file.length()); 094 response.setContentType(attachment.getMimeType()); 095 response.setHeader("Content-disposition", "attachment; filename=\"" + attachment.getFileName() + "\""); 096 FileInputStream attachmentFile = new FileInputStream(file); 097 BufferedInputStream inputStream = new BufferedInputStream(attachmentFile); 098 OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); 099 100 try { 101 int c; 102 while ((c = inputStream.read()) != -1) { 103 outputStream.write(c); 104 } 105 } finally { 106 inputStream.close(); 107 } 108 outputStream.close(); 109 } else {// Throw a forbidden page back, they were not approved by DocumentSecurityService 110 LOG.error("Attempt to access attachmentId:"+ attachmentId + " from documentId:" + routeHeader.getDocumentId() + " from unauthorized user: " + userSession.getPrincipalId()); 111 response.sendError(HttpServletResponse.SC_FORBIDDEN); 112 return; 113 } 114 } else {// Throw a not found, couldn't get a valid routeHeader 115 LOG.error("Caught Null Pointer trying to determine routeHeader for requested attachmentId:" + attachmentId); 116 response.sendError(HttpServletResponse.SC_NOT_FOUND); 117 return; 118 } 119 } else {// Throw a bad request, we couldn't find a valid user session 120 LOG.error("Attempt to access attachmentId:" + attachmentId + " with invalid UserSession"); 121 response.sendError(HttpServletResponse.SC_BAD_REQUEST); 122 return; 123 } 124 } catch (Exception e) {// Catch any error, log it. Send a not found, and throw up the exception. 125 LOG.error("Problem retrieving requested attachmentId:" + attachmentId, e); 126 throw new WorkflowRuntimeException(e); 127 } 128 } 129 @Override 130 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 131 doPost(request, response); 132 } 133 134}