Improvements and refinements to web site

git-svn-id: https://zxing.googlecode.com/svn/trunk@397 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-05-11 18:01:23 +00:00
parent 37559bac63
commit 5c705313bb
15 changed files with 235 additions and 171 deletions

View file

@ -67,14 +67,16 @@
<classes dir="web/WEB-INF/classes"/>
<fileset dir="web">
<include name="*.jspx"/>
<include name="*.png"/>
</fileset>
</war>
</target>
<target name="clean">
<delete dir="web/WEB-INF/classes"/>
<delete file="../core/core.jar"/>
<delete file="../javase/javase.jar"/>
<delete file="web/WEB-INF/lib/core.jar"/>
<delete file="web/WEB-INF/lib/javase.jar"/>
<delete file="zxingorg.war"/>
</target>
</project>

View file

@ -38,13 +38,18 @@ import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.awt.image.BufferedImage;
import java.io.UnsupportedEncodingException;
import java.io.IOException;
import java.util.Properties;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Sean Owen
* A {@link TimerTask} which repeatedly checks an e-mail account for messages with an attached
* image. When one is found it attempts to decode the image and replies with the decoded messages
* by e-mail.
*
* @author Sean Owen (srowen@google.com)
*/
final class DecodeEmailTask extends TimerTask {
@ -89,75 +94,85 @@ final class DecodeEmailTask extends TimerTask {
@Override
public void run() {
log.info("Checking email...");
Session session = Session.getInstance(sessionProperties, emailAuthenticator);
Store store = null;
Folder inbox = null;
try {
Session session = Session.getInstance(sessionProperties, emailAuthenticator);
Store store = null;
Folder inbox = null;
try {
store = session.getStore("pop3");
store.connect();
inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
int count = inbox.getMessageCount();
if (count > 0) {
log.info("Found " + count + " messages");
}
for (int i = 1; i <= count; i++) {
log.info("Processing message " + i);
Message message = inbox.getMessage(i);
Object content = message.getContent();
if (content instanceof MimeMultipart) {
MimeMultipart mimeContent = (MimeMultipart) content;
int numParts = mimeContent.getCount();
for (int j = 0; j < numParts; j++) {
MimeBodyPart part = (MimeBodyPart) mimeContent.getBodyPart(j);
String contentType = part.getContentType();
if (!contentType.startsWith("image/")) {
continue;
}
BufferedImage image = ImageIO.read(part.getInputStream());
if (image != null) {
Reader reader = new MultiFormatReader();
Result result = null;
try {
result = reader.decode(new BufferedImageMonochromeBitmapSource(image), DecodeServlet.HINTS);
} catch (ReaderException re) {
log.info("Decoding FAILED");
}
Message reply = new MimeMessage(session);
Address sender = message.getFrom()[0];
reply.setRecipient(Message.RecipientType.TO, sender);
reply.setFrom(fromAddress);
if (result == null) {
reply.setSubject("Decode failed");
reply.setContent("Sorry, we could not decode that image.", "text/plain");
} else {
String text = result.getText();
reply.setSubject("Decode succeeded");
reply.setContent(text, "text/plain");
}
log.info("Sending reply");
Transport.send(reply);
}
}
}
message.setFlag(Flags.Flag.DELETED, true);
}
} finally {
try {
if (inbox != null) {
inbox.close(true);
}
if (store != null) {
store.close();
}
} catch (MessagingException me) {
// continue
}
store = session.getStore("pop3");
store.connect();
inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE);
int count = inbox.getMessageCount();
if (count > 0) {
log.info("Found " + count + " messages");
}
for (int i = 1; i <= count; i++) {
log.info("Processing message " + i);
Message message = inbox.getMessage(i);
processMessage(session, message);
}
} catch (Throwable t) {
log.log(Level.WARNING, "Unexpected error", t);
} finally {
closeResources(store, inbox);
}
}
private void processMessage(Session session, Message message) throws MessagingException, IOException {
Object content = message.getContent();
if (content instanceof MimeMultipart) {
MimeMultipart mimeContent = (MimeMultipart) content;
int numParts = mimeContent.getCount();
for (int j = 0; j < numParts; j++) {
MimeBodyPart part = (MimeBodyPart) mimeContent.getBodyPart(j);
processMessagePart(session, message, part);
}
}
message.setFlag(Flags.Flag.DELETED, true);
}
private void processMessagePart(Session session, Message message, MimeBodyPart part)
throws MessagingException, IOException {
String contentType = part.getContentType();
if (contentType.startsWith("image/")) {
BufferedImage image = ImageIO.read(part.getInputStream());
if (image != null) {
Reader reader = new MultiFormatReader();
Result result = null;
try {
result = reader.decode(new BufferedImageMonochromeBitmapSource(image), DecodeServlet.HINTS);
} catch (ReaderException re) {
log.info("Decoding FAILED");
}
Message reply = new MimeMessage(session);
Address sender = message.getFrom()[0];
reply.setRecipient(Message.RecipientType.TO, sender);
reply.setFrom(fromAddress);
if (result == null) {
reply.setSubject("Decode failed");
reply.setContent("Sorry, we could not decode that image.", "text/plain");
} else {
String text = result.getText();
reply.setSubject("Decode succeeded");
reply.setContent(text, "text/plain");
}
log.info("Sending reply");
Transport.send(reply);
}
}
}
private void closeResources(Store store, Folder inbox) {
try {
if (inbox != null) {
inbox.close(true);
}
if (store != null) {
store.close();
}
} catch (MessagingException me) {
// continue
}
}

View file

@ -22,6 +22,7 @@ import com.google.zxing.Reader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageMonochromeBitmapSource;
import com.google.zxing.client.result.ParsedReaderResult;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
@ -63,7 +64,10 @@ import java.util.Timer;
import java.util.logging.Logger;
/**
* @author Sean Owen
* {@link HttpServlet} which decodes images containing barcodes. Given a URL, it will
* retrieve the image and decode it. It can also process image files uploaded via POST.
*
* @author Sean Owen (srowen@google.com)
*/
public final class DecodeServlet extends HttpServlet {
@ -114,7 +118,7 @@ public final class DecodeServlet extends HttpServlet {
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String imageURIString = request.getParameter("u");
if (imageURIString == null || imageURIString.length() == 0) {
@ -149,7 +153,7 @@ public final class DecodeServlet extends HttpServlet {
log.info("Decoding " + imageURI);
InputStream is = getResponse.getEntity().getContent();
try {
processStream(is, response);
processStream(is, request, response);
} finally {
is.close();
}
@ -183,12 +187,12 @@ public final class DecodeServlet extends HttpServlet {
log.info("Decoding uploaded file");
InputStream is = item.getInputStream();
try {
processStream(is, response);
processStream(is, request, response);
} finally {
is.close();
}
} else {
throw new ServletException("File is too large: " + item.getSize());
response.sendRedirect("badimage.jspx");
}
break;
}
@ -199,7 +203,8 @@ public final class DecodeServlet extends HttpServlet {
}
private static void processStream(InputStream is, HttpServletResponse response) throws IOException {
private static void processStream(InputStream is, HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
BufferedImage image = ImageIO.read(is);
if (image == null) {
response.sendRedirect("badimage.jspx");
@ -216,13 +221,20 @@ public final class DecodeServlet extends HttpServlet {
return;
}
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
try {
out.write(result.getText());
} finally {
out.close();
if (request.getParameter("full") == null) {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
try {
out.write(result.getText());
} finally {
out.close();
}
} else {
request.setAttribute("result", result);
ParsedReaderResult parsedReaderResult = ParsedReaderResult.parseReaderResult(result);
request.setAttribute("parsedReaderResult", parsedReaderResult);
request.getRequestDispatcher("decoderesult.jspx").forward(request, response);
}
}

View file

@ -35,7 +35,10 @@ import java.util.Timer;
import java.util.TimerTask;
/**
* @author Sean Owen
* A {@link Filter} that rejects requests from hosts that are sending too many
* requests in too short a time.
*
* @author Sean Owen (srowen@google.com)
*/
public final class DoSFilter implements Filter {

View file

@ -19,6 +19,11 @@ package com.google.zxing.web;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
/**
* A simple {@link Authenticator} which replies with a fixed username and password.
*
* @author Sean Owen (srowen@google.com)
*/
final class EmailAuthenticator extends Authenticator {
private final String emailUsername;

View file

@ -20,7 +20,9 @@ import java.net.InetAddress;
import java.util.Arrays;
/**
* @author Sean Owen
* A trie data structure for storing a set of IP addresses efficiently.
*
* @author Sean Owen (srowen@google.com)
*/
final class IPTrie {

View file

@ -22,7 +22,9 @@ import java.util.logging.Handler;
import java.util.logging.LogRecord;
/**
* @author Sean Owen
* A {@link Handler} that redirects log messages to the servlet container log.
*
* @author Sean Owen (srowen@google.com)
*/
final class ServletContextLogHandler extends Handler {

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2008 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Author: Sean Owen (srowen@google.com) -->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.1">
<jsp:output omit-xml-declaration="true"/>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-788492-5");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</jsp:root>

View file

@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Author: Sean Owen (srowen@google.com) -->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.1">
<jsp:output
omit-xml-declaration="false" doctype-root-element="html"
@ -23,27 +24,14 @@
<jsp:scriptlet>response.setHeader("Cache-Control", "public");</jsp:scriptlet>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>No Barcode Found</title>
<title>Bad Image</title>
</head>
<body>
<p>
<b>Bad URL</b>
</p>
<h1><img src="zxing-icon.png" height="32" width="32" alt=""/> Bad Image</h1>
<p>The image you uploaded could not be decoded, or was too large. Go "Back" in your browser and try another
image.
</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ?
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost +
"google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-788492-5");
pageTracker._initData();
pageTracker._trackPageview();
</script>
<jsp:include page="analytics.jspx"/>
</body>
</html>
</jsp:root>

View file

@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Author: Sean Owen (srowen@google.com) -->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.1">
<jsp:output
omit-xml-declaration="false" doctype-root-element="html"
@ -23,27 +24,14 @@
<jsp:scriptlet>response.setHeader("Cache-Control", "public");</jsp:scriptlet>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>No Barcode Found</title>
<title>Bad URL</title>
</head>
<body>
<p>
<b>Bad URL</b>
</p>
<h1><img src="zxing-icon.png" height="32" width="32" alt=""/> Bad URL</h1>
<p>You didn't specify a URL, or the URL was not valid, or did not return an image. Go "Back" in your browser and
try again.
</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ?
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost +
"google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-788492-5");
pageTracker._initData();
pageTracker._trackPageview();
</script>
<jsp:include page="analytics.jspx"/>
</body>
</html>
</jsp:root>

View file

@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Author: Sean Owen (srowen@google.com) -->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.1">
<jsp:output
omit-xml-declaration="false" doctype-root-element="html"
@ -26,47 +27,29 @@
<title>ZXing Decoder Online</title>
</head>
<body>
<h1>ZXing Decoder Online</h1>
<h1><img src="zxing-icon.png" height="32" width="32" alt=""/> ZXing Decoder Online</h1>
<p><b>Under Construction</b>: This is a simple page that will let you decode a 1D or 2D barcode found
in an image online. Enter a URL below.
</p>
<form action="decode" method="get">
<p>
<input type="text" size="50" name="u"/>
<input type="submit"/>
<input type="text" size="50" name="u"/>&amp;nbsp;<input type="submit"/>
<input type="hidden" name="full" value="true"/>
</p>
</form>
<p>Or try uploading a file:</p>
<form action="decode" method="post" enctype="multipart/form-data">
<p>
<input type="file" size="50" name="f"/>
<input type="submit"/>
<input type="file" size="50" name="f"/>&amp;nbsp;<input type="submit"/>
<input type="hidden" name="full" value="true"/>
</p>
</form>
<p>See the
<a href="http://code.google.com/p/zxing">project page</a>
for details.
</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ?
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost +
"google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-788492-5");
pageTracker._initData();
pageTracker._trackPageview();
</script>
<p>Copyright (C) 2008 Google Inc.</p>
<jsp:include page="analytics.jspx"/>
</body>
</html>
</jsp:root>

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2008 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Author: Sean Owen (srowen@google.com) -->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.1">
<jsp:output
omit-xml-declaration="false" doctype-root-element="html"
doctype-public="-//WAPFORUM//DTD XHTML Mobile 1.1//EN"
doctype-system="http://www.openmobilealliance.org/tech/DTD/xhtml-mobile11.dtd"/>
<jsp:directive.page contentType="application/xhtml+xml" session="false"/>
<jsp:scriptlet>response.setHeader("Cache-Control", "no-cache");</jsp:scriptlet>
<jsp:useBean id="result" scope="request" type="com.google.zxing.Result"/>
<jsp:useBean id="parsedReaderResult" scope="request" type="com.google.zxing.client.result.ParsedReaderResult"/>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Decode Succeeded</title>
<style type="text/css">
td { vertical-align: top; padding: 0.1in; background-color: #EEEEEE; font-family: monospace; }
</style>
</head>
<body>
<h1><img src="zxing-icon.png" height="32" width="32" alt=""/> Decode Succeeded</h1>
<table>
<tr>
<td>Raw text</td>
<td>${result.text}</td>
</tr>
<tr>
<td>Barcode format</td>
<td>${result.barcodeFormat}</td>
</tr>
<tr>
<td>Parsed Result Type</td>
<td>${parsedReaderResult.type}</td>
</tr>
<tr>
<td>Parsed Result</td>
<td>${parsedReaderResult.displayResult}</td>
</tr>
</table>
<p>Copyright (C) 2008 Google Inc.</p>
<jsp:include page="analytics.jspx"/>
</body>
</html>
</jsp:root>

View file

@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Author: Sean Owen (srowen@google.com) -->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.1">
<jsp:output
omit-xml-declaration="false" doctype-root-element="html"
@ -26,9 +27,7 @@
<title>Download ZXing Reader</title>
</head>
<body>
<p>
<strong>Welcome to zxing!</strong>
</p>
<h1><img src="zxing-icon.png" height="32" width="32" alt=""/> Download ZXing Reader</h1>
<p>
<a href="BarcodeReader.jad">Download</a>
the ZXing Barcode Reader.
@ -47,18 +46,8 @@
<a href="BarcodeReader.apk">Download</a>
the Android client.
</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ?
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost +
"google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-788492-5");
pageTracker._initData();
pageTracker._trackPageview();
</script>
<p>Copyright (C) 2008 Google Inc.</p>
<jsp:include page="analytics.jspx"/>
</body>
</html>
</jsp:root>

View file

@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Author: Sean Owen (srowen@google.com) -->
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.1">
<jsp:output
omit-xml-declaration="false" doctype-root-element="html"
@ -26,24 +27,11 @@
<title>No Barcode Found</title>
</head>
<body>
<p>
<b>No Barcode Found</b>
</p>
<h1><img src="zxing-icon.png" height="32" width="32" alt=""/> No Barcode Found</h1>
<p>No barcode was found in this image. Either it did not contain a barcode, or did not contain one in a
supported format, or the software was simply unable to find it. Go "Back" in your browser and try another image.
</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ?
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost +
"google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-788492-5");
pageTracker._initData();
pageTracker._trackPageview();
</script>
<jsp:include page="analytics.jspx"/>
</body>
</html>
</jsp:root>

BIN
zxingorg/web/zxing-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB