1 /*
2 * Copyright (c) 2002-2021, City of Paris
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice
10 * and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice
13 * and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * License 1.0
33 */
34 package fr.paris.lutece.plugins.blog.web;
35
36 import fr.paris.lutece.plugins.blog.business.DocContent;
37 import fr.paris.lutece.plugins.blog.business.DocContentHome;
38 import fr.paris.lutece.portal.service.util.AppLogService;
39 import fr.paris.lutece.portal.service.util.AppPropertiesService;
40
41 import org.apache.commons.lang3.StringUtils;
42
43 import java.io.IOException;
44 import java.io.OutputStream;
45
46 import javax.servlet.ServletException;
47 import javax.servlet.http.HttpServlet;
48 import javax.servlet.http.HttpServletRequest;
49 import javax.servlet.http.HttpServletResponse;
50
51 /**
52 * Servlet serving ticketing files
53 */
54 public class BlogFileServlet extends HttpServlet
55 {
56 /**
57 * Generated serial Id
58 */
59 private static final long serialVersionUID = -3589685443968252550L;
60
61 // Parameters
62 public static final String PARAMETER_ID_FILE = "id_file";
63
64 // Other constants
65 public static final String URL_SERVLET = "servlet/plugins/blog/file";
66 private static final String LOG_UNKNOWN_ID_RESPONSE = "Calling Blogd file servlet with unknown id file : ";
67 private static final String LOG_WRONG_ID_RESPONSE = "Calling Blogd file servlet with wrong format for parameter " + PARAMETER_ID_FILE + " : ";
68 private static final String PROPERTY_MAX_AGE = "blog.fileServlet.maxAge";
69 private static final long DEFAULT_MAX_AGE = 60L * 60 * 24 * 7; // 1 week
70 private static final long MAX_AGE = AppPropertiesService.getPropertyLong( PROPERTY_MAX_AGE, DEFAULT_MAX_AGE );
71
72 /**
73 * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
74 *
75 * @param request
76 * servlet request
77 * @param httpResponse
78 * servlet response
79 * @throws ServletException
80 * the servlet Exception
81 * @throws IOException
82 * the io exception
83 */
84 protected void processRequest( HttpServletRequest request, HttpServletResponse httpResponse ) throws ServletException, IOException
85 {
86 String strIdFile = request.getParameter( PARAMETER_ID_FILE );
87 if ( !StringUtils.isEmpty( strIdFile ) && StringUtils.isNumeric( strIdFile ) )
88 {
89 int nIdResponse = Integer.parseInt( strIdFile );
90
91 DocContent docContent = DocContentHome.getDocsContent( nIdResponse );
92
93 if ( docContent == null )
94 {
95 AppLogService.error( LOG_UNKNOWN_ID_RESPONSE + strIdFile );
96 throw new ServletException( LOG_UNKNOWN_ID_RESPONSE + strIdFile );
97 }
98
99 httpResponse.setHeader( "Content-Disposition", "attachment; filename=\"" + docContent.getTextValue( ) + "\";" );
100 httpResponse.setHeader( "Content-type", docContent.getValueContentType( ) );
101 httpResponse.addHeader( "Content-Encoding", "UTF-8" );
102 httpResponse.addHeader( "Cache-Control", "public,max-age=" + MAX_AGE );
103
104 try ( OutputStream os = httpResponse.getOutputStream( ) )
105 {
106 os.write( docContent.getBinaryValue( ) );
107 // We do not close the output stream in finaly clause because it is
108 // the response stream,
109 // and an error message needs to be displayed if an exception occurs
110 }
111 catch( IOException e )
112 {
113 AppLogService.error( e.getStackTrace( ), e );
114 }
115 }
116 else
117 {
118 AppLogService.error( LOG_WRONG_ID_RESPONSE + strIdFile );
119 throw new ServletException( );
120 }
121 }
122
123 /**
124 * Handles the HTTP <code>GET</code> method.
125 *
126 * @param request
127 * servlet request
128 * @param response
129 * servlet response
130 * @throws ServletException
131 * the servlet Exception
132 * @throws IOException
133 * the io exception
134 */
135 @Override
136 protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
137 {
138 processRequest( request, response );
139 }
140
141 /**
142 * Handles the HTTP <code>POST</code> method.
143 *
144 * @param request
145 * servlet request
146 * @param response
147 * servlet response
148 * @throws ServletException
149 * the servlet Exception
150 * @throws IOException
151 * the io exception
152 */
153 @Override
154 protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
155 {
156 processRequest( request, response );
157 }
158
159 /**
160 * Returns a short description of the servlet.
161 *
162 * @return message
163 */
164 @Override
165 public String getServletInfo( )
166 {
167 return "Servlet serving file content";
168 }
169
170 }