Initiale Version
[fix-swf] / src / main / java / de / juplo / fixswf / FixSwfServlet.java
1 package de.juplo.fixswf;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.io.PrintWriter;
7 import java.util.HashMap;
8 import java.util.Map;
9 import java.util.regex.Matcher;
10 import java.util.regex.Pattern;
11 import javax.servlet.ServletConfig;
12 import javax.servlet.ServletException;
13 import javax.servlet.http.HttpServlet;
14 import javax.servlet.http.HttpServletRequest;
15 import javax.servlet.http.HttpServletResponse;
16 import org.apache.commons.fileupload.FileItemIterator;
17 import org.apache.commons.fileupload.FileItemStream;
18 import org.apache.commons.fileupload.servlet.ServletFileUpload;
19 import org.apache.commons.lang.StringEscapeUtils;
20
21 /**
22  *
23  * @author kai
24  */
25 public class FixSwfServlet extends HttpServlet
26 {
27   public final String MESSAGE_ATTRIBUTE = getClass().getCanonicalName() + ".MESSAGE";
28
29   private Map<Byte,Byte> corrections;
30   private Pattern pattern;
31
32
33   @Override
34   public void init(ServletConfig config) throws ServletException {
35     corrections = new HashMap<Byte,Byte>();
36     corrections.put((byte)12, (byte)10);
37     corrections.put((byte)14, (byte)11);
38     pattern = Pattern.compile("([^/\\\\:<>?\"]+?)(?:\\.swf)?$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
39   }
40
41   
42   /**
43    * Processes requests for both HTTP
44    * <code>GET</code> and
45    * <code>POST</code> methods.
46    *
47    * @param request servlet request
48    * @param response servlet response
49    * @throws ServletException if a servlet-specific error occurs
50    * @throws IOException if an I/O error occurs
51    */
52   protected void processRequest(
53       HttpServletRequest request,
54       HttpServletResponse response
55     )
56     throws
57       ServletException,
58       IOException
59   {
60     response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
61   }
62
63   /**
64    * Handles the HTTP
65    * <code>GET</code> method.
66    *
67    * @param request servlet request
68    * @param response servlet response
69    * @throws ServletException if a servlet-specific error occurs
70    * @throws IOException if an I/O error occurs
71    */
72   @Override
73   protected void doGet(
74       HttpServletRequest request,
75       HttpServletResponse response
76     )
77     throws
78       ServletException,
79       IOException
80   {
81     response.setContentType("text/html;charset=UTF-8");
82     PrintWriter out = response.getWriter();
83     try
84     {
85       out.println("<html>");
86       out.println("<head>");
87       out.println("<title>Fix-Swf</title>");      
88       out.println("</head>");
89       out.println("<body>");
90       if (request.getAttribute(MESSAGE_ATTRIBUTE) != null)
91       {
92         out.println("<h1>Upload-Results</h1>");
93         out.println("<p>" + StringEscapeUtils.escapeHtml((String)request.getAttribute(MESSAGE_ATTRIBUTE)) + "</p>");
94       }
95       out.println("<h1>Choose SWF-File to check/fix</h1>");
96       out.println("<p>If the file has to be fixed, the fixed version will be presented to you as a download.</p>");
97       out.println("<form action=\"\" method=\"post\" enctype=\"multipart/form-data\">");
98       out.println("<input type=\"file\" name=\"swf\" />");
99       out.println("<input type=\"submit\" name=\"submit\" value=\"Start Upload\" />");
100       out.println("</form>");
101       out.println("</body>");
102       out.println("</html>");
103     }
104     finally
105     {      
106       out.close();
107     }
108   }
109
110   /**
111    * Handles the HTTP
112    * <code>POST</code> method.
113    *
114    * @param request servlet request
115    * @param response servlet response
116    * @throws ServletException if a servlet-specific error occurs
117    * @throws IOException if an I/O error occurs
118    */
119   @Override
120   protected void doPost(
121       HttpServletRequest request,
122       HttpServletResponse response
123     )
124     throws
125       ServletException,
126       IOException
127   {
128     // Check that we have a file upload request
129     if (!ServletFileUpload.isMultipartContent(request))
130     {
131       request.setAttribute(MESSAGE_ATTRIBUTE, "No data uploaded!");
132       request.getRequestDispatcher("/").forward(request, response);
133       return;
134     }
135
136     // Create a new file upload handler
137     ServletFileUpload upload = new ServletFileUpload();
138
139     try
140     {
141       // Parse the request
142       FileItemIterator iter = upload.getItemIterator(request);
143
144       while(iter.hasNext())
145       {
146         FileItemStream item = iter.next();
147
148         if (item.isFormField())
149           continue;
150
151         if (!item.getFieldName().equals("swf"))
152           continue;
153         
154         String filename = item.getName();
155         InputStream in = item.openStream();
156         byte[] buffer = new byte[512];
157         int i;
158         i = in.read(buffer);
159
160         if (i < 4)
161         {
162           request.setAttribute(MESSAGE_ATTRIBUTE, "Not enough data uploaded!");
163           request.getRequestDispatcher("/").forward(request, response);
164           return;
165         }
166    
167         if (!corrections.containsKey(buffer[3]))
168         {
169           request.setAttribute(MESSAGE_ATTRIBUTE, "Uploaded SWF-file " + filename + " was valid!");
170           request.getRequestDispatcher("/").forward(request, response);
171           return;
172         }
173
174         /** Correct the Flash-Player-Version in Header-Byte 4 */
175         buffer[3] = corrections.get(buffer[3]);
176
177         Matcher matcher = pattern.matcher(filename);
178         if (matcher.matches())
179         {
180           filename = matcher.group(1) + "_FIXED.swf";
181         }
182         else
183         {
184           filename = "FIXED.swf";
185         }
186         
187         response.setHeader("Content-Type", "application/x-shockwave-flash");
188         response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\"");
189         OutputStream out = response.getOutputStream();
190         do
191         {
192           out.write(buffer, 0, i);
193         }
194         while ((i = in.read(buffer)) > -1);
195
196         out.close();
197       }
198     }
199     catch (Exception e)
200     {
201       request.setAttribute(MESSAGE_ATTRIBUTE, "Error while parsing upload: " + e);
202       request.getRequestDispatcher("/").forward(request, response);
203       return;
204     }
205
206     /** Fallback, if no data was found (happens when forwarding!) */
207     doGet(request, response);
208   }
209
210   /**
211    * Returns a short description of the servlet.
212    *
213    * @return a String containing servlet description
214    */
215   @Override
216   public String getServletInfo() {
217     return "This Servlet fixes the 4th byte of an uploaded SWF-file according to the SWF-filestructre specification.";
218   }
219 }