DecodeServlet.java (zxing-zxing-3.4.1) | : | DecodeServlet.java (zxing-zxing-3.5.0) | ||
---|---|---|---|---|
skipping to change at line 94 | skipping to change at line 94 | |||
* @author Sean Owen | * @author Sean Owen | |||
*/ | */ | |||
@MultipartConfig( | @MultipartConfig( | |||
maxFileSize = 1L << 26, // ~64MB | maxFileSize = 1L << 26, // ~64MB | |||
maxRequestSize = 1L << 26, // ~64MB | maxRequestSize = 1L << 26, // ~64MB | |||
fileSizeThreshold = 1 << 23, // ~8MB | fileSizeThreshold = 1 << 23, // ~8MB | |||
location = "/tmp") | location = "/tmp") | |||
@WebServlet(value = "/w/decode", loadOnStartup = 1, initParams = { | @WebServlet(value = "/w/decode", loadOnStartup = 1, initParams = { | |||
@WebInitParam(name = "maxAccessPerTime", value = "120"), | @WebInitParam(name = "maxAccessPerTime", value = "120"), | |||
@WebInitParam(name = "accessTimeSec", value = "120"), | @WebInitParam(name = "accessTimeSec", value = "120"), | |||
@WebInitParam(name = "maxEntries", value = "10000") | @WebInitParam(name = "maxEntries", value = "100000") | |||
}) | }) | |||
public final class DecodeServlet extends HttpServlet { | public final class DecodeServlet extends HttpServlet { | |||
private static final Logger log = Logger.getLogger(DecodeServlet.class.getName ()); | private static final Logger log = Logger.getLogger(DecodeServlet.class.getName ()); | |||
private static final Pattern WHITESPACE = Pattern.compile("\\s+"); | private static final Pattern WHITESPACE = Pattern.compile("\\s+"); | |||
// No real reason to let people upload more than ~64MB | // No real reason to let people upload more than ~64MB | |||
private static final long MAX_IMAGE_SIZE = 1L << 26; | private static final long MAX_IMAGE_SIZE = 1L << 26; | |||
// No real reason to deal with more than ~32 megapixels | // No real reason to deal with more than ~32 megapixels | |||
private static final int MAX_PIXELS = 1 << 25; | private static final int MAX_PIXELS = 1 << 25; | |||
skipping to change at line 173 | skipping to change at line 173 | |||
return; | return; | |||
} | } | |||
// Remove any whitespace to sanitize; none is valid anyway | // Remove any whitespace to sanitize; none is valid anyway | |||
imageURIString = WHITESPACE.matcher(imageURIString).replaceAll(""); | imageURIString = WHITESPACE.matcher(imageURIString).replaceAll(""); | |||
if (!blockedURLSubstrings.isEmpty()) { | if (!blockedURLSubstrings.isEmpty()) { | |||
for (CharSequence substring : blockedURLSubstrings) { | for (CharSequence substring : blockedURLSubstrings) { | |||
if (imageURIString.contains(substring)) { | if (imageURIString.contains(substring)) { | |||
log.info("Disallowed URI " + imageURIString); | log.info("Disallowed URI " + imageURIString); | |||
errorResponse(request, response, "badurl"); | errorResponse(request, response, HttpServletResponse.SC_FORBIDDEN, "ba durl"); | |||
return; | return; | |||
} | } | |||
} | } | |||
} | } | |||
URI imageURI; | URI imageURI; | |||
try { | try { | |||
imageURI = new URI(imageURIString); | imageURI = new URI(imageURIString); | |||
// Assume http: if not specified | // Assume http: if not specified | |||
if (imageURI.getScheme() == null) { | if (imageURI.getScheme() == null) { | |||
skipping to change at line 215 | skipping to change at line 215 | |||
return; | return; | |||
} | } | |||
try { | try { | |||
processImage(image, request, response); | processImage(image, request, response); | |||
} finally { | } finally { | |||
image.flush(); | image.flush(); | |||
} | } | |||
return; | return; | |||
} | } | |||
if (destHostTracker.isBanned(imageURI.getHost())) { | String host = imageURI.getHost(); | |||
errorResponse(request, response, "badurl"); | // Also should parse for 172.x subnets | |||
if (host == null || host.startsWith("10.") || host.startsWith("192.168.") || | ||||
"127.0.0.1".equals(host) || "localhost".equals(host) || | ||||
destHostTracker.isBanned(host)) { | ||||
errorResponse(request, response, HttpServletResponse.SC_FORBIDDEN, "badurl | ||||
"); | ||||
return; | return; | |||
} | } | |||
URL imageURL; | URL imageURL; | |||
try { | try { | |||
imageURL = imageURI.toURL(); | imageURL = imageURI.toURL(); | |||
} catch (MalformedURLException ignored) { | } catch (MalformedURLException ignored) { | |||
log.info("URI is not a URL: " + imageURIString); | log.info("URI is not a URL: " + imageURIString); | |||
errorResponse(request, response, "badurl"); | errorResponse(request, response, "badurl"); | |||
return; | return; | |||
skipping to change at line 271 | skipping to change at line 275 | |||
errorResponse(request, response, "badurl"); | errorResponse(request, response, "badurl"); | |||
return; | return; | |||
} | } | |||
try (InputStream is = connection.getInputStream()) { | try (InputStream is = connection.getInputStream()) { | |||
if (connection.getResponseCode() != HttpServletResponse.SC_OK) { | if (connection.getResponseCode() != HttpServletResponse.SC_OK) { | |||
log.info("Unsuccessful return code " + connection.getResponseCode() + " from " + imageURIString); | log.info("Unsuccessful return code " + connection.getResponseCode() + " from " + imageURIString); | |||
errorResponse(request, response, "badurl"); | errorResponse(request, response, "badurl"); | |||
return; | return; | |||
} | } | |||
if (connection.getHeaderFieldInt(HttpHeaders.CONTENT_LENGTH, 0) > MAX_IMAG | int contentLength = connection.getHeaderFieldInt(HttpHeaders.CONTENT_LENGT | |||
E_SIZE) { | H, -1); | |||
if (contentLength <= 0) { | ||||
log.info("Bad content length: " + imageURIString); | ||||
errorResponse(request, response, HttpServletResponse.SC_LENGTH_REQUIRED, | ||||
"badimage"); | ||||
return; | ||||
} | ||||
if (contentLength > MAX_IMAGE_SIZE) { | ||||
log.info("Too large: " + imageURIString); | log.info("Too large: " + imageURIString); | |||
errorResponse(request, response, "badimage"); | errorResponse(request, response, HttpServletResponse.SC_REQUEST_ENTITY_T OO_LARGE, "badimage"); | |||
return; | return; | |||
} | } | |||
// Assume we'll only handle image/* content types | // Assume we'll only handle image/* content types | |||
String contentType = connection.getContentType(); | String contentType = connection.getContentType(); | |||
if (contentType != null && !contentType.startsWith("image/")) { | if (contentType != null && !contentType.startsWith("image/")) { | |||
log.info("Wrong content type " + contentType + ": " + imageURIString); | log.info("Wrong content type " + contentType + ": " + imageURIString); | |||
errorResponse(request, response, "badimage"); | errorResponse(request, response, HttpServletResponse.SC_UNSUPPORTED_MEDI A_TYPE, "badimage"); | |||
return; | return; | |||
} | } | |||
log.info("Decoding " + imageURIString); | log.info("Decoding " + imageURIString); | |||
processStream(is, request, response); | processStream(is, request, response); | |||
} catch (IOException ioe) { | } catch (IOException ioe) { | |||
log.info("Error " + ioe + " processing " + imageURIString); | log.info("Error " + ioe + " processing " + imageURIString); | |||
errorResponse(request, response, "badurl"); | errorResponse(request, response, "badurl"); | |||
} finally { | } finally { | |||
connection.disconnect(); | connection.disconnect(); | |||
skipping to change at line 345 | skipping to change at line 355 | |||
errorResponse(request, response, "badimage"); | errorResponse(request, response, "badimage"); | |||
return; | return; | |||
} | } | |||
if (image == null) { | if (image == null) { | |||
errorResponse(request, response, "badimage"); | errorResponse(request, response, "badimage"); | |||
return; | return; | |||
} | } | |||
try { | try { | |||
int height = image.getHeight(); | int height = image.getHeight(); | |||
int width = image.getWidth(); | int width = image.getWidth(); | |||
if (height <= 1 || width <= 1 || height * width > MAX_PIXELS) { | if (height <= 1 || width <= 1) { | |||
log.info("Dimensions out of bounds: " + width + 'x' + height); | log.info("Dimensions too small: " + width + 'x' + height); | |||
errorResponse(request, response, "badimage"); | errorResponse(request, response, "badimage"); | |||
return; | return; | |||
} else if (height * width > MAX_PIXELS) { | ||||
log.info("Dimensions too large: " + width + 'x' + height); | ||||
errorResponse(request, response, HttpServletResponse.SC_REQUEST_ENTITY_T | ||||
OO_LARGE, "badimage"); | ||||
return; | ||||
} | } | |||
processImage(image, request, response); | processImage(image, request, response); | |||
} finally { | } finally { | |||
image.flush(); | image.flush(); | |||
} | } | |||
} | } | |||
private static void processImage(BufferedImage image, | private static void processImage(BufferedImage image, | |||
HttpServletRequest request, | HttpServletRequest request, | |||
skipping to change at line 450 | skipping to change at line 464 | |||
for (Result result : results) { | for (Result result : results) { | |||
out.write(result.getText()); | out.write(result.getText()); | |||
out.write('\n'); | out.write('\n'); | |||
} | } | |||
} | } | |||
} else { | } else { | |||
request.setAttribute("results", results); | request.setAttribute("results", results); | |||
request.getRequestDispatcher("decoderesult.jspx").forward(request, respons e); | request.getRequestDispatcher("decoderesult.jspx").forward(request, respons e); | |||
} | } | |||
} | } | |||
private static void errorResponse(HttpServletRequest request, | ||||
HttpServletResponse response, | ||||
String key) throws ServletException, IOExcep | ||||
tion { | ||||
errorResponse(request, response, HttpServletResponse.SC_BAD_REQUEST, key); | ||||
} | ||||
private static void errorResponse(HttpServletRequest request, | private static void errorResponse(HttpServletRequest request, | |||
HttpServletResponse response, | HttpServletResponse response, | |||
int httpStatus, | ||||
String key) throws ServletException, IOExcep tion { | String key) throws ServletException, IOExcep tion { | |||
Locale locale = request.getLocale(); | Locale locale = request.getLocale(); | |||
if (locale == null) { | if (locale == null) { | |||
locale = Locale.ENGLISH; | locale = Locale.ENGLISH; | |||
} | } | |||
ResourceBundle bundle = ResourceBundle.getBundle("Strings", locale); | ResourceBundle bundle = ResourceBundle.getBundle("Strings", locale); | |||
String title = bundle.getString("response.error." + key + ".title"); | String title = bundle.getString("response.error." + key + ".title"); | |||
String text = bundle.getString("response.error." + key + ".text"); | String text = bundle.getString("response.error." + key + ".text"); | |||
request.setAttribute("title", title); | request.setAttribute("title", title); | |||
request.setAttribute("text", text); | request.setAttribute("text", text); | |||
RequestDispatcher dispatcher = request.getRequestDispatcher("response.jspx") ; | RequestDispatcher dispatcher = request.getRequestDispatcher("response.jspx") ; | |||
if (dispatcher == null) { | if (dispatcher == null) { | |||
log.warning("Can't obtain RequestDispatcher"); | log.warning("Can't obtain RequestDispatcher"); | |||
} else { | } else { | |||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); | response.setStatus(httpStatus); | |||
dispatcher.forward(request, response); | dispatcher.forward(request, response); | |||
} | } | |||
} | } | |||
} | } | |||
End of changes. 11 change blocks. | ||||
11 lines changed or deleted | 35 lines changed or added |