diff --git a/app/src/main/java/protect/card_locker/DBHelper.java b/app/src/main/java/protect/card_locker/DBHelper.java index 23b59d56b..493e6f329 100644 --- a/app/src/main/java/protect/card_locker/DBHelper.java +++ b/app/src/main/java/protect/card_locker/DBHelper.java @@ -26,7 +26,7 @@ import java.util.Set; public class DBHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "Catima.db"; public static final int ORIGINAL_DATABASE_VERSION = 1; - public static final int DATABASE_VERSION = 18; + public static final int DATABASE_VERSION = 19; // NB: changing these values requires a migration public static final int DEFAULT_ZOOM_LEVEL = 100; @@ -345,6 +345,17 @@ public class DBHelper extends SQLiteOpenHelper { db.execSQL("ALTER TABLE " + LoyaltyCardDbIds.TABLE + " ADD COLUMN " + LoyaltyCardDbIds.BARCODE_ENCODING + " TEXT"); } + + // On upgrade to 2.41.3, force all existing "Automatic" cards to ISO-8859-1. + // UTF-8 support was only added in 2.42.0, before that, all barcodes were saved without + // any encoding info. As many scanners deal badly with ECI info, automatically guessing + // UTF-8 for old barcodes may break them. + // + // New cards will be saved using either "Automatic" encoding to guess or, for pkpass files, + // whatever encoding is specified. + if (oldVersion < 19 && newVersion >= 19) { + db.execSQL("UPDATE " + LoyaltyCardDbIds.TABLE + " SET " + LoyaltyCardDbIds.BARCODE_ENCODING + " = 'ISO-8859-1' WHERE " + LoyaltyCardDbIds.BARCODE_ENCODING + " IS NULL"); + } } public static Set imageFiles(Context context, final SQLiteDatabase database) { diff --git a/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java b/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java index a6567dd44..b819ab858 100644 --- a/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java @@ -459,8 +459,11 @@ public class CatimaImporter implements Importer { barcodeType = CatimaBarcode.fromName(unparsedBarcodeType); } + // Barcode encoding information is only supported since Catima 2.41.0, so old exports will lack this field + // Database migration 19 forcing ISO-8859-1 on all cards, so we should treat imports from old Catima versions the same and force ISO-8859-1 there too + // This limits the risk of breaking cards when importing an old database backup Charset barcodeEncoding = null; - String unparsedBarcodeEncoding = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_ENCODING, record, ""); + String unparsedBarcodeEncoding = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BARCODE_ENCODING, record, "ISO-8859-1"); if (!unparsedBarcodeEncoding.isEmpty()) { barcodeEncoding = Charset.forName(unparsedBarcodeEncoding); } diff --git a/app/src/test/java/protect/card_locker/DatabaseTest.java b/app/src/test/java/protect/card_locker/DatabaseTest.java index c84ac1567..5314cccef 100644 --- a/app/src/test/java/protect/card_locker/DatabaseTest.java +++ b/app/src/test/java/protect/card_locker/DatabaseTest.java @@ -497,7 +497,7 @@ public class DatabaseTest { assertEquals("cardId", card.cardId); assertEquals(null, card.barcodeId); assertEquals(BarcodeFormat.UPC_A, card.barcodeType.format()); - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertEquals(null, card.headerColor); assertEquals(0, card.starStatus); assertEquals(0, card.lastUsed); @@ -515,7 +515,7 @@ public class DatabaseTest { assertEquals("cardId", card2.cardId); assertEquals(null, card2.barcodeId); assertEquals(null, card2.barcodeType); // Empty string should've become null - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertEquals(null, card2.headerColor); assertEquals(0, card2.starStatus); assertEquals(0, card2.lastUsed); diff --git a/app/src/test/java/protect/card_locker/ImportExportTest.java b/app/src/test/java/protect/card_locker/ImportExportTest.java index e10d10d85..9f01f517b 100644 --- a/app/src/test/java/protect/card_locker/ImportExportTest.java +++ b/app/src/test/java/protect/card_locker/ImportExportTest.java @@ -669,7 +669,7 @@ public class ImportExportTest { assertEquals("12345", card.cardId); assertEquals(null, card.barcodeId); assertEquals(BarcodeFormat.AZTEC, card.barcodeType.format()); - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertNull(card.headerColor); assertEquals(0, card.starStatus); @@ -696,7 +696,7 @@ public class ImportExportTest { assertEquals("12345", card.cardId); assertEquals(null, card.barcodeId); assertEquals(BarcodeFormat.AZTEC, card.barcodeType.format()); - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertNull(card.headerColor); assertEquals(0, card.starStatus); @@ -735,7 +735,7 @@ public class ImportExportTest { assertEquals("12345", card.cardId); assertEquals(null, card.barcodeId); assertEquals(null, card.barcodeType); - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertEquals(1, (long) card.headerColor); assertEquals(0, card.starStatus); @@ -762,7 +762,7 @@ public class ImportExportTest { assertEquals("12345", card.cardId); assertEquals(null, card.barcodeId); assertEquals(BarcodeFormat.AZTEC, card.barcodeType.format()); - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertEquals(1, (long) card.headerColor); assertEquals(1, card.starStatus); @@ -789,7 +789,7 @@ public class ImportExportTest { assertEquals("12345", card.cardId); assertEquals(null, card.barcodeId); assertEquals(BarcodeFormat.AZTEC, card.barcodeType.format()); - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertEquals(1, (long) card.headerColor); assertEquals(0, card.starStatus); @@ -823,7 +823,7 @@ public class ImportExportTest { assertEquals("12345", card.cardId); assertEquals(null, card.barcodeId); assertEquals(BarcodeFormat.AZTEC, card.barcodeType.format()); - assertEquals(null, card.barcodeEncoding); + assertEquals(StandardCharsets.ISO_8859_1, card.barcodeEncoding); // Old cards are assumed to be ISO-8859-1 assertEquals(1, (long) card.headerColor); assertEquals(0, card.starStatus);