mirror of
https://github.com/zxing/zxing.git
synced 2025-02-02 05:41:08 -08:00
- Fixed a crash when parsing a particular VCard with a blank entry.
- Trimmed whitespace around many fields to sanitize the results (this is very useful upstream, for example we hyphenate phone numbers on Android but can't tolerate extra whitespace). - Fixed a bug with 1D result points when scanning upside down - they needed to be mirrored to draw correctly. git-svn-id: https://zxing.googlecode.com/svn/trunk@592 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
1040c3188c
commit
bacd1469af
|
@ -28,12 +28,12 @@ package com.google.zxing.client.result;
|
||||||
*/
|
*/
|
||||||
abstract class AbstractDoCoMoResultParser extends ResultParser {
|
abstract class AbstractDoCoMoResultParser extends ResultParser {
|
||||||
|
|
||||||
static String[] matchDoCoMoPrefixedField(String prefix, String rawText) {
|
static String[] matchDoCoMoPrefixedField(String prefix, String rawText, boolean trim) {
|
||||||
return matchPrefixedField(prefix, rawText, ';');
|
return matchPrefixedField(prefix, rawText, ';', trim);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String matchSingleDoCoMoPrefixedField(String prefix, String rawText) {
|
static String matchSingleDoCoMoPrefixedField(String prefix, String rawText, boolean trim) {
|
||||||
return matchSinglePrefixedField(prefix, rawText, ';');
|
return matchSinglePrefixedField(prefix, rawText, ';', trim);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String[] maybeWrap(String value) {
|
static String[] maybeWrap(String value) {
|
||||||
|
|
|
@ -36,18 +36,18 @@ final class AddressBookAUResultParser extends ResultParser {
|
||||||
if (rawText == null || rawText.indexOf("MEMORY") < 0 || rawText.indexOf("\r\n") < 0) {
|
if (rawText == null || rawText.indexOf("MEMORY") < 0 || rawText.indexOf("\r\n") < 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String[] names = matchMultipleValuePrefix("NAME", 2, rawText);
|
String[] names = matchMultipleValuePrefix("NAME", 2, rawText, true);
|
||||||
String[] phoneNumbers = matchMultipleValuePrefix("TEL", 3, rawText);
|
String[] phoneNumbers = matchMultipleValuePrefix("TEL", 3, rawText, true);
|
||||||
String[] emails = matchMultipleValuePrefix("MAIL", 3, rawText);
|
String[] emails = matchMultipleValuePrefix("MAIL", 3, rawText, true);
|
||||||
String note = matchSinglePrefixedField("MEMORY:", rawText, '\r');
|
String note = matchSinglePrefixedField("MEMORY:", rawText, '\r', false);
|
||||||
String address = matchSinglePrefixedField("ADD:", rawText, '\r');
|
String address = matchSinglePrefixedField("ADD:", rawText, '\r', true);
|
||||||
return new AddressBookParsedResult(names, phoneNumbers, emails, note, address, null, null, null);
|
return new AddressBookParsedResult(names, phoneNumbers, emails, note, address, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] matchMultipleValuePrefix(String prefix, int max, String rawText) {
|
private static String[] matchMultipleValuePrefix(String prefix, int max, String rawText, boolean trim) {
|
||||||
Vector values = null;
|
Vector values = null;
|
||||||
for (int i = 1; i <= max; i++) {
|
for (int i = 1; i <= max; i++) {
|
||||||
String value = matchSinglePrefixedField(prefix + i + ':', rawText, '\r');
|
String value = matchSinglePrefixedField(prefix + i + ':', rawText, '\r', trim);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,16 +35,16 @@ final class AddressBookDoCoMoResultParser extends AbstractDoCoMoResultParser {
|
||||||
if (rawText == null || !rawText.startsWith("MECARD:")) {
|
if (rawText == null || !rawText.startsWith("MECARD:")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String[] rawName = matchDoCoMoPrefixedField("N:", rawText);
|
String[] rawName = matchDoCoMoPrefixedField("N:", rawText, true);
|
||||||
if (rawName == null) {
|
if (rawName == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String name = parseName(rawName[0]);
|
String name = parseName(rawName[0]);
|
||||||
String[] phoneNumbers = matchDoCoMoPrefixedField("TEL:", rawText);
|
String[] phoneNumbers = matchDoCoMoPrefixedField("TEL:", rawText, true);
|
||||||
String email = matchSingleDoCoMoPrefixedField("EMAIL:", rawText);
|
String email = matchSingleDoCoMoPrefixedField("EMAIL:", rawText, true);
|
||||||
String note = matchSingleDoCoMoPrefixedField("NOTE:", rawText);
|
String note = matchSingleDoCoMoPrefixedField("NOTE:", rawText, false);
|
||||||
String address = matchSingleDoCoMoPrefixedField("ADR:", rawText);
|
String address = matchSingleDoCoMoPrefixedField("ADR:", rawText, true);
|
||||||
String birthday = matchSingleDoCoMoPrefixedField("BDAY:", rawText);
|
String birthday = matchSingleDoCoMoPrefixedField("BDAY:", rawText, true);
|
||||||
if (birthday != null && !isStringOfDigits(birthday, 8)) {
|
if (birthday != null && !isStringOfDigits(birthday, 8)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,16 +38,16 @@ final class BizcardResultParser extends AbstractDoCoMoResultParser {
|
||||||
if (rawText == null || !rawText.startsWith("BIZCARD:")) {
|
if (rawText == null || !rawText.startsWith("BIZCARD:")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String firstName = matchSingleDoCoMoPrefixedField("N:", rawText);
|
String firstName = matchSingleDoCoMoPrefixedField("N:", rawText, true);
|
||||||
String lastName = matchSingleDoCoMoPrefixedField("X:", rawText);
|
String lastName = matchSingleDoCoMoPrefixedField("X:", rawText, true);
|
||||||
String fullName = buildName(firstName, lastName);
|
String fullName = buildName(firstName, lastName);
|
||||||
String title = matchSingleDoCoMoPrefixedField("T:", rawText);
|
String title = matchSingleDoCoMoPrefixedField("T:", rawText, true);
|
||||||
String org = matchSingleDoCoMoPrefixedField("C:", rawText);
|
String org = matchSingleDoCoMoPrefixedField("C:", rawText, true);
|
||||||
String address = matchSingleDoCoMoPrefixedField("A:", rawText);
|
String address = matchSingleDoCoMoPrefixedField("A:", rawText, true);
|
||||||
String phoneNumber1 = matchSingleDoCoMoPrefixedField("B:", rawText);
|
String phoneNumber1 = matchSingleDoCoMoPrefixedField("B:", rawText, true);
|
||||||
String phoneNumber2 = matchSingleDoCoMoPrefixedField("M:", rawText);
|
String phoneNumber2 = matchSingleDoCoMoPrefixedField("M:", rawText, true);
|
||||||
String phoneNumber3 = matchSingleDoCoMoPrefixedField("F:", rawText);
|
String phoneNumber3 = matchSingleDoCoMoPrefixedField("F:", rawText, true);
|
||||||
String email = matchSingleDoCoMoPrefixedField("E:", rawText);
|
String email = matchSingleDoCoMoPrefixedField("E:", rawText, true);
|
||||||
|
|
||||||
return new AddressBookParsedResult(maybeWrap(fullName),
|
return new AddressBookParsedResult(maybeWrap(fullName),
|
||||||
buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
|
buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
|
||||||
|
|
|
@ -31,8 +31,8 @@ final class BookmarkDoCoMoResultParser extends AbstractDoCoMoResultParser {
|
||||||
if (rawText == null || !rawText.startsWith("MEBKM:")) {
|
if (rawText == null || !rawText.startsWith("MEBKM:")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String title = matchSingleDoCoMoPrefixedField("TITLE:", rawText);
|
String title = matchSingleDoCoMoPrefixedField("TITLE:", rawText, true);
|
||||||
String[] rawUri = matchDoCoMoPrefixedField("URL:", rawText);
|
String[] rawUri = matchDoCoMoPrefixedField("URL:", rawText, true);
|
||||||
if (rawUri == null) {
|
if (rawUri == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ final class EmailDoCoMoResultParser extends AbstractDoCoMoResultParser {
|
||||||
if (rawText == null || !rawText.startsWith("MATMSG:")) {
|
if (rawText == null || !rawText.startsWith("MATMSG:")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String[] rawTo = matchDoCoMoPrefixedField("TO:", rawText);
|
String[] rawTo = matchDoCoMoPrefixedField("TO:", rawText, true);
|
||||||
if (rawTo == null) {
|
if (rawTo == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ final class EmailDoCoMoResultParser extends AbstractDoCoMoResultParser {
|
||||||
if (!isBasicallyValidEmailAddress(to)) {
|
if (!isBasicallyValidEmailAddress(to)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String subject = matchSingleDoCoMoPrefixedField("SUB:", rawText);
|
String subject = matchSingleDoCoMoPrefixedField("SUB:", rawText, false);
|
||||||
String body = matchSingleDoCoMoPrefixedField("BODY:", rawText);
|
String body = matchSingleDoCoMoPrefixedField("BODY:", rawText, false);
|
||||||
return new EmailAddressParsedResult(to, subject, body, "mailto:" + to);
|
return new EmailAddressParsedResult(to, subject, body, "mailto:" + to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ public abstract class ResultParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String[] matchPrefixedField(String prefix, String rawText, char endChar) {
|
static String[] matchPrefixedField(String prefix, String rawText, char endChar, boolean trim) {
|
||||||
Vector matches = null;
|
Vector matches = null;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int max = rawText.length();
|
int max = rawText.length();
|
||||||
|
@ -260,7 +260,11 @@ public abstract class ResultParser {
|
||||||
if (matches == null) {
|
if (matches == null) {
|
||||||
matches = new Vector(3); // lazy init
|
matches = new Vector(3); // lazy init
|
||||||
}
|
}
|
||||||
matches.addElement(unescapeBackslash(rawText.substring(start, i)));
|
String element = unescapeBackslash(rawText.substring(start, i));
|
||||||
|
if (trim) {
|
||||||
|
element = element.trim();
|
||||||
|
}
|
||||||
|
matches.addElement(element);
|
||||||
i++;
|
i++;
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
@ -272,8 +276,8 @@ public abstract class ResultParser {
|
||||||
return toStringArray(matches);
|
return toStringArray(matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String matchSinglePrefixedField(String prefix, String rawText, char endChar) {
|
static String matchSinglePrefixedField(String prefix, String rawText, char endChar, boolean trim) {
|
||||||
String[] matches = matchPrefixedField(prefix, rawText, endChar);
|
String[] matches = matchPrefixedField(prefix, rawText, endChar, trim);
|
||||||
return matches == null ? null : matches[0];
|
return matches == null ? null : matches[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,30 +36,30 @@ final class VCardResultParser extends ResultParser {
|
||||||
if (rawText == null || !rawText.startsWith("BEGIN:VCARD") || !rawText.endsWith("END:VCARD")) {
|
if (rawText == null || !rawText.startsWith("BEGIN:VCARD") || !rawText.endsWith("END:VCARD")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String[] names = matchVCardPrefixedField("FN", rawText);
|
String[] names = matchVCardPrefixedField("FN", rawText, true);
|
||||||
if (names == null) {
|
if (names == null) {
|
||||||
// If no display names found, look for regular name fields and format them
|
// If no display names found, look for regular name fields and format them
|
||||||
names = matchVCardPrefixedField("N", rawText);
|
names = matchVCardPrefixedField("N", rawText, true);
|
||||||
formatNames(names);
|
formatNames(names);
|
||||||
}
|
}
|
||||||
String[] phoneNumbers = matchVCardPrefixedField("TEL", rawText);
|
String[] phoneNumbers = matchVCardPrefixedField("TEL", rawText, true);
|
||||||
String[] emails = matchVCardPrefixedField("EMAIL", rawText);
|
String[] emails = matchVCardPrefixedField("EMAIL", rawText, true);
|
||||||
String note = matchSingleVCardPrefixedField("NOTE", rawText);
|
String note = matchSingleVCardPrefixedField("NOTE", rawText, false);
|
||||||
String address = matchSingleVCardPrefixedField("ADR", rawText);
|
String address = matchSingleVCardPrefixedField("ADR", rawText, true);
|
||||||
address = formatAddress(address);
|
address = formatAddress(address);
|
||||||
String org = matchSingleVCardPrefixedField("ORG", rawText);
|
String org = matchSingleVCardPrefixedField("ORG", rawText, true);
|
||||||
String birthday = matchSingleVCardPrefixedField("BDAY", rawText);
|
String birthday = matchSingleVCardPrefixedField("BDAY", rawText, true);
|
||||||
if (birthday != null && !isStringOfDigits(birthday, 8)) {
|
if (birthday != null && !isStringOfDigits(birthday, 8)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String title = matchSingleVCardPrefixedField("TITLE", rawText);
|
String title = matchSingleVCardPrefixedField("TITLE", rawText, true);
|
||||||
return new AddressBookParsedResult(names, phoneNumbers, emails, note, address, org, birthday, title);
|
return new AddressBookParsedResult(names, phoneNumbers, emails, note, address, org, birthday, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] matchVCardPrefixedField(String prefix, String rawText) {
|
private static String[] matchVCardPrefixedField(String prefix, String rawText, boolean trim) {
|
||||||
Vector matches = null;
|
Vector matches = null;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int max = rawText.length();
|
final int max = rawText.length();
|
||||||
while (i < max) {
|
while (i < max) {
|
||||||
i = rawText.indexOf(prefix, i);
|
i = rawText.indexOf(prefix, i);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
|
@ -79,22 +79,23 @@ final class VCardResultParser extends ResultParser {
|
||||||
}
|
}
|
||||||
i++; // skip colon
|
i++; // skip colon
|
||||||
int start = i; // Found the start of a match here
|
int start = i; // Found the start of a match here
|
||||||
boolean done = false;
|
|
||||||
while (!done) {
|
|
||||||
i = rawText.indexOf((int) '\n', i); // Really, ends in \r\n
|
i = rawText.indexOf((int) '\n', i); // Really, ends in \r\n
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||||
i = rawText.length();
|
i = max;
|
||||||
done = true;
|
} else if (i > start) {
|
||||||
} else {
|
|
||||||
// found a match
|
// found a match
|
||||||
if (matches == null) {
|
if (matches == null) {
|
||||||
matches = new Vector(3); // lazy init
|
matches = new Vector(3); // lazy init
|
||||||
}
|
}
|
||||||
matches.addElement(rawText.substring(start, i - 1)); // i - 1 to strip off the \r too
|
String element = rawText.substring(start, i);
|
||||||
i++;
|
if (trim) {
|
||||||
done = true;
|
element = element.trim();
|
||||||
}
|
}
|
||||||
|
matches.addElement(element);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (matches == null || matches.isEmpty()) {
|
if (matches == null || matches.isEmpty()) {
|
||||||
|
@ -103,8 +104,8 @@ final class VCardResultParser extends ResultParser {
|
||||||
return toStringArray(matches);
|
return toStringArray(matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String matchSingleVCardPrefixedField(String prefix, String rawText) {
|
static String matchSingleVCardPrefixedField(String prefix, String rawText, boolean trim) {
|
||||||
String[] values = matchVCardPrefixedField(prefix, rawText);
|
String[] values = matchVCardPrefixedField(prefix, rawText, trim);
|
||||||
return values == null ? null : values[0];
|
return values == null ? null : values[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ final class VEventResultParser extends ResultParser {
|
||||||
}
|
}
|
||||||
rawText = rawText.substring(vEventStart + 14, vEventEnd); // skip over BEGIN:VEVENT\r\n at start
|
rawText = rawText.substring(vEventStart + 14, vEventEnd); // skip over BEGIN:VEVENT\r\n at start
|
||||||
|
|
||||||
String summary = VCardResultParser.matchSingleVCardPrefixedField("SUMMARY", rawText);
|
String summary = VCardResultParser.matchSingleVCardPrefixedField("SUMMARY", rawText, true);
|
||||||
String start = VCardResultParser.matchSingleVCardPrefixedField("DTSTART", rawText);
|
String start = VCardResultParser.matchSingleVCardPrefixedField("DTSTART", rawText, true);
|
||||||
String end = VCardResultParser.matchSingleVCardPrefixedField("DTEND", rawText);
|
String end = VCardResultParser.matchSingleVCardPrefixedField("DTEND", rawText, true);
|
||||||
try {
|
try {
|
||||||
return new CalendarParsedResult(summary, start, end, null, null, null);
|
return new CalendarParsedResult(summary, start, end, null, null, null);
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
|
|
|
@ -22,7 +22,9 @@ import com.google.zxing.MonochromeBitmapSource;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.google.zxing.ResultMetadataType;
|
import com.google.zxing.ResultMetadataType;
|
||||||
|
import com.google.zxing.ResultPoint;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
|
import com.google.zxing.common.GenericResultPoint;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
@ -126,6 +128,10 @@ public abstract class AbstractOneDReader implements OneDReader {
|
||||||
if (attempt == 1) {
|
if (attempt == 1) {
|
||||||
// But it was upside down, so note that
|
// But it was upside down, so note that
|
||||||
result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
|
result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180));
|
||||||
|
// And remember to flip the result points horizontally.
|
||||||
|
ResultPoint[] points = result.getResultPoints();
|
||||||
|
points[0] = new GenericResultPoint(width - points[0].getX() - 1, points[0].getY());
|
||||||
|
points[1] = new GenericResultPoint(width - points[1].getX() - 1, points[1].getY());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (ReaderException re) {
|
} catch (ReaderException re) {
|
||||||
|
|
|
@ -97,8 +97,8 @@ public final class CommandLineRunner {
|
||||||
try {
|
try {
|
||||||
MonochromeBitmapSource source = new BufferedImageMonochromeBitmapSource(image);
|
MonochromeBitmapSource source = new BufferedImageMonochromeBitmapSource(image);
|
||||||
Result result = new MultiFormatReader().decode(source, hints);
|
Result result = new MultiFormatReader().decode(source, hints);
|
||||||
System.out.println(uri.toString() + ": " + result.getText() + " format: " +
|
System.out.println(uri.toString() + " (format: " + result.getBarcodeFormat() + "):\n" +
|
||||||
result.getBarcodeFormat());
|
result.getText());
|
||||||
return true;
|
return true;
|
||||||
} catch (ReaderException e) {
|
} catch (ReaderException e) {
|
||||||
System.out.println(uri.toString() + ": No barcode found");
|
System.out.println(uri.toString() + ": No barcode found");
|
||||||
|
|
Loading…
Reference in a new issue