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