/** * Process the call to the servlet. * * <p>With regard to reading data from the request, a {@link javax.servlet.ServletInputStream} * object for binary data can be obtained by {@link HttpServletRequest#getInputStream()} or a * {@link java.io.BufferedReader} can be obtained for character data by using {@link * HttpServletRequest#getReader}. * * <p>With regard to writing data to the response a {@link javax.servlet.ServletOutputStream} * object for binary data can be obtained using {@link HttpServletResponse#getOutputStream()} * while a {@link java.io.PrintWriter} object can be obtained using {@link * HttpServletResponse#getWriter()}. * * <p>The {@link java.io.ByteArrayOutputStream} class can be used as a means of collecting the * bytes contained in the attached file. * * <p>It would be desirable to have tests for enctype and method. * * @param req Request object * @param res Response object * @throws IOException if io problems */ public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { ThisPage thisPage = new ThisPage(req, res, config); GenericPrinter output = thisPage.getPrinter(); if (!req.getMethod().equalsIgnoreCase("post")) { output.println("<html><head>"); output.println("<title>Must use POST method</title>"); output.println("</head><body>"); output.println("<h1>Must use POST method</h1>"); output.println("<p>Request used " + req.getMethod() + " method</p>"); output.println("<p>Must use POST method</p>"); output.println("</body></html>"); thisPage.sendContents(); return; } else if (req.getHeader("content-type") == null) { output.println("<html><head>"); output.println("<title>Missing content-type header</title>"); output.println("</head><body>"); output.println("<h1>Missing content-type header</h1>"); output.println( "<p>Must use content-type header " + "to specify multipart/form-data encoding</p>"); output.println("</body></html>"); thisPage.sendContents(); return; } else if (!req.getHeader("content-type").toLowerCase().startsWith("multipart/form-data")) { output.println("<html><head>"); output.println("<title>Must use multipart/form-data encoding</title>"); output.println("</head><body>"); output.println("<h1>Must use multipart/form-data encoding</h1>"); output.println("<p>content-type is " + req.getHeader("content-type") + " </p>"); output.println("<p>Must use multipart/form-data encoding</p>"); output.println("</body></html>"); thisPage.sendContents(); return; } String boundary = extractBoundary(req); if (boundary == null) { thisPage.addMessage("Unable to extract boundary value"); thisPage.addMessage(req.getHeader("content-type")); thisPage.errorMessage(); return; } int counter = 0; byte buffer[] = new byte[4096]; byte extract[]; int bytesRead = -1; ServletInputStream input = req.getInputStream(); bytesRead = input.readLine(buffer, 0, buffer.length); if (!new String(buffer, 0, bytesRead, "ISO8859_1").startsWith("--" + boundary)) { thisPage.addMessage( "Should be separator " + "--" + boundary + " : " + " found " + new String(buffer, 0, bytesRead)); thisPage.errorMessage(); return; } while (true) { counter++; Contents part = new Contents(); thisPage.addMessage("Starting part " + Integer.toString(counter) + " of form"); while (true) { bytesRead = input.readLine(buffer, 0, buffer.length); if (bytesRead < 0) { thisPage.addMessage("Unexpected end of packet"); thisPage.errorMessage(); return; } else { String value = new String(buffer, 0, bytesRead, "ISO8859_1"); if (value.endsWith("\r\n")) { value = stripEOL(value); } if (value.length() == 0) { extract = readPart(input, thisPage, part.getTransferEncoding()); if (thisPage.getTerminateRequest()) { return; } part.setContents(extract); thisPage.addElement(part); break; } else { thisPage.addMessage("service method - Parsing line: " + value); part.parseLine(value); } } } if (thisPage.getEndOfPacket()) { break; } } if (thisPage.getTerminateRequest()) { return; } starter(thisPage); if (thisPage.getTerminateRequest()) { return; } processor(thisPage); if (thisPage.getTerminateRequest()) { return; } ender(thisPage); if (thisPage.getTerminateRequest()) { return; } if (thisPage.getRedirectAddress() != null) { thisPage .getResponse() .sendRedirect(thisPage.getResponse().encodeRedirectURL(thisPage.getRedirectAddress())); } }
/** * Obtain the byte array for this part of the request. * * <p>It may be necessary to modify this code to handle additional encoding types such as Base64. * * @param input Object from which data is read * @param thisPage Object containing information for this request * @param encoding type of character encoding to be used * @return Byte array for this part of request * @throws IOException if io errors */ protected byte[] readPart(ServletInputStream input, ThisPage thisPage, String encoding) throws IOException { HttpServletRequest req = thisPage.getRequest(); String boundary = extractBoundary(req); byte buffer[] = new byte[4096]; int bytesRead = -1; ByteArrayOutputStream working = null; boolean pendingRN = false; working = new ByteArrayOutputStream(); /* * Read body of part */ while (true) { bytesRead = input.readLine(buffer, 0, buffer.length); if (bytesRead < 0) { thisPage.addMessage("readPart method - Section of form not properly ended"); thisPage.errorMessage(); return null; } else if (bytesRead == 0) { thisPage.addMessage("readPart method - Read yielded 0 characters"); thisPage.errorMessage(); return null; } else if (bytesRead == 1 && buffer[0] == '\n') { if (pendingRN) { working.write('\r'); working.write('\n'); pendingRN = false; } working.write(buffer[0]); } else if (new String(buffer, 0, bytesRead).equals("--" + boundary + "\r\n")) { if (!pendingRN) { thisPage.addMessage("readPart method - Boundary reached without preceding end of line"); thisPage.errorMessage(); return null; } if (working.size() == 0) { return null; } return working.toByteArray(); } else if (new String(buffer, 0, bytesRead).equals("--" + boundary + "--\r\n")) { thisPage.setEndOfPacket(true); if (!pendingRN) { thisPage.addMessage( "readPart method - Final boundary reached with preceding end of line"); thisPage.errorMessage(); return null; } if (working.size() == 0) { return null; } return working.toByteArray(); } else if (buffer[bytesRead - 2] == '\r' && buffer[bytesRead - 1] == '\n') { if (pendingRN) { working.write('\r'); working.write('\n'); } if (bytesRead > 2) { working.write(buffer, 0, bytesRead - 2); } pendingRN = true; } else if (buffer[bytesRead - 1] == '\r') { if (pendingRN) { working.write('\r'); working.write('\n'); pendingRN = false; } if (bytesRead > 1) { working.write(buffer, 0, bytesRead - 1); } int nextChar = input.read(); if (nextChar == '\n') { pendingRN = true; } else { working.write('\r'); working.write(nextChar); } } else { if (pendingRN) { working.write('\r'); working.write('\n'); pendingRN = false; } working.write(buffer, 0, bytesRead); } } }
/** * Processing after calling processor method. * * <p>This method can be overridden in subclasses to provide a class that carries out the desired * operation for a group of classes. * * @see #processor(ThisPage) * @param thisPage Information on this HTTP transaction * @throws IOException */ public void ender(ThisPage thisPage) throws IOException { if (thisPage != null) { thisPage.addMessage("Running Servlet.ender"); thisPage.addMessage("This is a dummy stub that doesn't do any work"); } }