From 5cf41ed664cd53e294b949f6924bea2585c440c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Apr 2023 16:44:16 +0000 Subject: [PATCH 1/2] Bump com.github.spotbugs from 4.7.5 to 5.0.14 Bumps com.github.spotbugs from 4.7.5 to 5.0.14. --- updated-dependencies: - dependency-name: com.github.spotbugs dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 894beab48..32ba76dd3 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'com.android.application' version '7.4.2' apply false - id 'com.github.spotbugs' version "4.7.5" apply false + id 'com.github.spotbugs' version "5.0.14" apply false } allprojects { From 6653a940edc9fbf1d1fc6e3c1f815a3b23e001e9 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Sun, 9 Apr 2023 17:18:19 +0200 Subject: [PATCH 2/2] Make spotbugs happy --- .../CardsOnPowerScreenService.java | 10 +-- .../protect/card_locker/ImportURIHelper.java | 2 +- .../protect/card_locker/MainActivity.java | 83 +++++++++++-------- .../protect/card_locker/ScanActivity.java | 27 +++--- .../main/java/protect/card_locker/Utils.java | 19 ++++- .../card_locker/importexport/CSVHelpers.java | 32 +++---- .../importexport/CatimaImporter.java | 71 ++++++++++------ .../protect/card_locker/ImportURITest.java | 3 +- 8 files changed, 142 insertions(+), 105 deletions(-) diff --git a/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java b/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java index 9cce5a1e2..55b6fa917 100644 --- a/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java +++ b/app/src/main/java/protect/card_locker/CardsOnPowerScreenService.java @@ -1,6 +1,5 @@ package protect.card_locker; -import android.annotation.SuppressLint; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; @@ -69,10 +68,9 @@ public class CardsOnPowerScreenService extends ControlsProviderService { subscriber.onSubscribe(new NoOpSubscription()); for (String controlId : controlIds) { Control control; - - try { - Integer cardId = this.controlIdToCardId(controlId); - LoyaltyCard card = DBHelper.getLoyaltyCard(mDatabase, cardId); + Integer cardId = this.controlIdToCardId(controlId); + LoyaltyCard card = DBHelper.getLoyaltyCard(mDatabase, cardId); + if (card != null) { Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .putExtra("id", card.id); @@ -85,7 +83,7 @@ public class CardsOnPowerScreenService extends ControlsProviderService { .setControlTemplate(new StatelessTemplate(controlId)) .setCustomIcon(Icon.createWithBitmap(getIcon(this, card))) .build(); - } catch (NullPointerException ignored) { + } else { Intent mainScreenIntent = new Intent(this, MainActivity.class) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), -1, mainScreenIntent, PendingIntent.FLAG_IMMUTABLE); diff --git a/app/src/main/java/protect/card_locker/ImportURIHelper.java b/app/src/main/java/protect/card_locker/ImportURIHelper.java index e01cd1b6d..d110cc24f 100644 --- a/app/src/main/java/protect/card_locker/ImportURIHelper.java +++ b/app/src/main/java/protect/card_locker/ImportURIHelper.java @@ -123,7 +123,7 @@ public class ImportURIHelper { } return new LoyaltyCard(-1, store, note, validFrom, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, 0, Utils.getUnixTime(), 100, 0); - } catch (NullPointerException | NumberFormatException | UnsupportedEncodingException | ArrayIndexOutOfBoundsException ex) { + } catch (NumberFormatException | UnsupportedEncodingException | ArrayIndexOutOfBoundsException ex) { throw new InvalidObjectException("Not a valid import URI"); } } diff --git a/app/src/main/java/protect/card_locker/MainActivity.java b/app/src/main/java/protect/card_locker/MainActivity.java index 2546d2ae1..083817518 100644 --- a/app/src/main/java/protect/card_locker/MainActivity.java +++ b/app/src/main/java/protect/card_locker/MainActivity.java @@ -375,18 +375,28 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard // Start of active tab logic updateTabGroups(groupsTabLayout); - // Restore settings from Shared Preference + // Restore selected tab from Shared Preference SharedPreferences activeTabPref = getApplicationContext().getSharedPreferences( getString(R.string.sharedpreference_active_tab), Context.MODE_PRIVATE); selectedTab = activeTabPref.getInt(getString(R.string.sharedpreference_active_tab), 0); + + // Restore sort preferences from Shared Preferences + // If one of the sorting prefererences has never been set or is set to an invalid value, + // stick to the defaults. SharedPreferences sortPref = getApplicationContext().getSharedPreferences( getString(R.string.sharedpreference_sort), Context.MODE_PRIVATE); - try { - mOrder = DBHelper.LoyaltyCardOrder.valueOf(sortPref.getString(getString(R.string.sharedpreference_sort_order), null)); - mOrderDirection = DBHelper.LoyaltyCardOrderDirection.valueOf(sortPref.getString(getString(R.string.sharedpreference_sort_direction), null)); - } catch (IllegalArgumentException | NullPointerException ignored) { + + String orderString = sortPref.getString(getString(R.string.sharedpreference_sort_order), null); + String orderDirectionString = sortPref.getString(getString(R.string.sharedpreference_sort_direction), null); + + if (orderString != null && orderDirectionString != null) { + try { + mOrder = DBHelper.LoyaltyCardOrder.valueOf(orderString); + mOrderDirection = DBHelper.LoyaltyCardOrderDirection.valueOf(orderDirectionString); + } catch (IllegalArgumentException ignored) { + } } mGroup = null; @@ -520,38 +530,41 @@ public class MainActivity extends CatimaAppCompatActivity implements LoyaltyCard // Check if an image was shared to us if (Intent.ACTION_SEND.equals(receivedAction)) { - if (receivedType.startsWith("image/")) { - BarcodeValues barcodeValues; - try { - Bitmap bitmap; - try { - Uri data = intent.getParcelableExtra(Intent.EXTRA_STREAM); - bitmap = Utils.retrieveImageFromUri(this, data); - } catch (IOException e) { - Log.e(TAG, "Error getting data from image file"); - e.printStackTrace(); - Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show(); - finish(); - return; - } - - barcodeValues = Utils.getBarcodeFromBitmap(bitmap); - - if (barcodeValues.isEmpty()) { - Log.i(TAG, "No barcode found in image file"); - Toast.makeText(this, R.string.noBarcodeFound, Toast.LENGTH_LONG).show(); - finish(); - return; - } - } catch (NullPointerException e) { - Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show(); - finish(); - return; - } - processBarcodeValues(barcodeValues, null); - } else { + if (!receivedType.startsWith("image/")) { Log.e(TAG, "Wrong mime-type"); + return; } + + BarcodeValues barcodeValues; + Bitmap bitmap; + + Uri data = intent.getParcelableExtra(Intent.EXTRA_STREAM); + if (data == null) { + Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show(); + finish(); + return; + } + + try { + bitmap = Utils.retrieveImageFromUri(this, data); + } catch (IOException e) { + Log.e(TAG, "Error getting data from image file"); + e.printStackTrace(); + Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show(); + finish(); + return; + } + + barcodeValues = Utils.getBarcodeFromBitmap(bitmap); + + if (barcodeValues.isEmpty()) { + Log.i(TAG, "No barcode found in image file"); + Toast.makeText(this, R.string.noBarcodeFound, Toast.LENGTH_LONG).show(); + finish(); + return; + } + + processBarcodeValues(barcodeValues, null); } } diff --git a/app/src/main/java/protect/card_locker/ScanActivity.java b/app/src/main/java/protect/card_locker/ScanActivity.java index 4e6f17762..7825bfd8f 100644 --- a/app/src/main/java/protect/card_locker/ScanActivity.java +++ b/app/src/main/java/protect/card_locker/ScanActivity.java @@ -194,27 +194,22 @@ public class ScanActivity extends CatimaAppCompatActivity { private void handleActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); - BarcodeValues barcodeValues; + BarcodeValues barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this); - try { - barcodeValues = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this); - } catch (NullPointerException e) { - Toast.makeText(this, R.string.errorReadingImage, Toast.LENGTH_LONG).show(); + if (barcodeValues.isEmpty()) { return; } - if (!barcodeValues.isEmpty()) { - Intent manualResult = new Intent(); - Bundle manualResultBundle = new Bundle(); - manualResultBundle.putString(BarcodeSelectorActivity.BARCODE_CONTENTS, barcodeValues.content()); - manualResultBundle.putString(BarcodeSelectorActivity.BARCODE_FORMAT, barcodeValues.format()); - if (addGroup != null) { - manualResultBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, addGroup); - } - manualResult.putExtras(manualResultBundle); - ScanActivity.this.setResult(RESULT_OK, manualResult); - finish(); + Intent manualResult = new Intent(); + Bundle manualResultBundle = new Bundle(); + manualResultBundle.putString(BarcodeSelectorActivity.BARCODE_CONTENTS, barcodeValues.content()); + manualResultBundle.putString(BarcodeSelectorActivity.BARCODE_FORMAT, barcodeValues.format()); + if (addGroup != null) { + manualResultBundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, addGroup); } + manualResult.putExtras(manualResultBundle); + ScanActivity.this.setResult(RESULT_OK, manualResult); + finish(); } public void addManually(View view) { diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index 1aa154ae6..160b0f874 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -114,6 +114,17 @@ public class Utils { return ColorUtils.calculateLuminance(backgroundColor) > LUMINANCE_MIDPOINT; } + /** + * Returns the Barcode format and content based on the result of an activity. + * It shows toasts to notify the end-user as needed itself and will return an empty + * BarcodeValues object if the activity was cancelled or nothing could be found. + * + * @param requestCode + * @param resultCode + * @param intent + * @param context + * @return BarcodeValues + */ static public BarcodeValues parseSetBarcodeActivityResult(int requestCode, int resultCode, Intent intent, Context context) { String contents; String format; @@ -125,9 +136,15 @@ public class Utils { if (requestCode == Utils.BARCODE_IMPORT_FROM_IMAGE_FILE) { Log.i(TAG, "Received image file with possible barcode"); + Uri data = intent.getData(); + if (data == null) { + Log.e(TAG, "Intent did not contain any data"); + Toast.makeText(context, R.string.errorReadingImage, Toast.LENGTH_LONG).show(); + return new BarcodeValues(null, null); + } + Bitmap bitmap; try { - Uri data = intent.getData(); bitmap = retrieveImageFromUri(context, data); } catch (IOException e) { Log.e(TAG, "Error getting data from image file"); diff --git a/app/src/main/java/protect/card_locker/importexport/CSVHelpers.java b/app/src/main/java/protect/card_locker/importexport/CSVHelpers.java index d21b0f11a..9c46e0c83 100644 --- a/app/src/main/java/protect/card_locker/importexport/CSVHelpers.java +++ b/app/src/main/java/protect/card_locker/importexport/CSVHelpers.java @@ -8,22 +8,14 @@ public class CSVHelpers { /** * Extract a string from the items array. The index into the array * is determined by looking up the index in the fields map using the - * "key" as the key. If no such key exists, defaultValue is returned - * if it is not null. Otherwise, a FormatException is thrown. + * "key" as the key. If no such key exists, defaultValue is returned. */ - static String extractString(String key, CSVRecord record, String defaultValue) - throws FormatException { - String toReturn = defaultValue; - + static String extractString(String key, CSVRecord record, String defaultValue) { if (record.isMapped(key)) { - toReturn = record.get(key); - } else { - if (defaultValue == null) { - throw new FormatException("Field not used but expected: " + key); - } + return record.get(key); } - return toReturn; + return defaultValue; } /** @@ -32,15 +24,15 @@ public class CSVHelpers { * "key" as the key. If no such key exists, or the data is not a valid * int, a FormatException is thrown. */ - static Integer extractInt(String key, CSVRecord record, boolean nullIsOk) + static Integer extractInt(String key, CSVRecord record) throws FormatException { - if (record.isMapped(key) == false) { + if (!record.isMapped(key)) { throw new FormatException("Field not used but expected: " + key); } String value = record.get(key); - if (value.isEmpty() && nullIsOk) { - return null; + if (value.isEmpty()) { + throw new FormatException("Field is empty: " + key); } try { @@ -56,15 +48,15 @@ public class CSVHelpers { * "key" as the key. If no such key exists, or the data is not a valid * int, a FormatException is thrown. */ - static Long extractLong(String key, CSVRecord record, boolean nullIsOk) + static Long extractLong(String key, CSVRecord record) throws FormatException { - if (record.isMapped(key) == false) { + if (!record.isMapped(key)) { throw new FormatException("Field not used but expected: " + key); } String value = record.get(key); - if (value.isEmpty() && nullIsOk) { - return null; + if (value.isEmpty()) { + throw new FormatException("Field is empty: " + key); } try { 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 dbd35162c..52d521781 100644 --- a/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java +++ b/app/src/main/java/protect/card_locker/importexport/CatimaImporter.java @@ -77,7 +77,7 @@ public class CatimaImporter implements Importer { int version = parseVersion(bufferedReader); switch (version) { case 1: - parseV1(context, database, bufferedReader); + parseV1(database, bufferedReader); break; case 2: parseV2(context, database, bufferedReader); @@ -87,12 +87,12 @@ public class CatimaImporter implements Importer { } } - public void parseV1(Context context, SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException { + public void parseV1(SQLiteDatabase database, BufferedReader input) throws IOException, FormatException, InterruptedException { final CSVParser parser = new CSVParser(input, CSVFormat.RFC4180.builder().setHeader().build()); try { for (CSVRecord record : parser) { - importLoyaltyCard(context, database, record); + importLoyaltyCard(database, record); if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -214,7 +214,7 @@ public class CatimaImporter implements Importer { } for (CSVRecord record : records) { - importLoyaltyCard(context, database, record); + importLoyaltyCard(database, record); } } @@ -276,9 +276,9 @@ public class CatimaImporter implements Importer { * Import a single loyalty card into the database using the given * session. */ - private void importLoyaltyCard(Context context, SQLiteDatabase database, CSVRecord record) - throws IOException, FormatException { - int id = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ID, record, false); + private void importLoyaltyCard(SQLiteDatabase database, CSVRecord record) + throws FormatException { + int id = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ID, record); String store = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.STORE, record, ""); if (store.isEmpty()) { @@ -286,25 +286,38 @@ public class CatimaImporter implements Importer { } String note = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.NOTE, record, ""); + Date validFrom = null; + Long validFromLong; try { - validFrom = new Date(CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.VALID_FROM, record, true)); - } catch (NullPointerException | FormatException e) { + validFromLong = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.VALID_FROM, record); + } catch (FormatException ignored) { + validFromLong = null; + } + if (validFromLong != null) { + validFrom = new Date(validFromLong); } Date expiry = null; + Long expiryLong; try { - expiry = new Date(CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.EXPIRY, record, true)); - } catch (NullPointerException | FormatException e) { + expiryLong = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.EXPIRY, record); + } catch (FormatException ignored) { + expiryLong = null; + } + if (expiryLong != null) { + expiry = new Date(expiryLong); } - BigDecimal balance; - try { - balance = new BigDecimal(CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null)); - } catch (FormatException _e) { - // These fields did not exist in versions 1.8.1 and before - // We catch this exception so we can still import old backups - balance = new BigDecimal("0"); + // These fields did not exist in versions 1.8.1 and before + // We default to 0 so we can still import old backups + BigDecimal balance = new BigDecimal("0"); + String balanceString = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null); + if (balanceString != null) { + try { + balance = new BigDecimal(CSVHelpers.extractString(DBHelper.LoyaltyCardDbIds.BALANCE, record, null)); + } catch (NumberFormatException ignored) { + } } Currency balanceType = null; @@ -330,14 +343,14 @@ public class CatimaImporter implements Importer { } Integer headerColor = null; - - if (record.isMapped(DBHelper.LoyaltyCardDbIds.HEADER_COLOR)) { - headerColor = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record, true); + try { + headerColor = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.HEADER_COLOR, record); + } catch (FormatException ignored) { } int starStatus = 0; try { - starStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.STAR_STATUS, record, false); + starStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.STAR_STATUS, record); } catch (FormatException _e) { // This field did not exist in versions 0.28 and before // We catch this exception so we can still import old backups @@ -346,7 +359,7 @@ public class CatimaImporter implements Importer { int archiveStatus = 0; try { - archiveStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ARCHIVE_STATUS, record, false); + archiveStatus = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIds.ARCHIVE_STATUS, record); } catch (FormatException _e) { // This field did not exist in versions 2.16.3 and before // We catch this exception so we can still import old backups @@ -355,7 +368,7 @@ public class CatimaImporter implements Importer { Long lastUsed = 0L; try { - lastUsed = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.LAST_USED, record, false); + lastUsed = CSVHelpers.extractLong(DBHelper.LoyaltyCardDbIds.LAST_USED, record); } catch (FormatException _e) { // This field did not exist in versions 2.5.0 and before // We catch this exception so we can still import old backups @@ -371,6 +384,10 @@ public class CatimaImporter implements Importer { private void importGroup(SQLiteDatabase database, CSVRecord record) throws FormatException { String id = CSVHelpers.extractString(DBHelper.LoyaltyCardDbGroups.ID, record, null); + if (id == null) { + throw new FormatException("Group has no ID: " + record); + } + DBHelper.insertGroup(database, id); } @@ -379,9 +396,13 @@ public class CatimaImporter implements Importer { * session. */ private void importCardGroupMapping(SQLiteDatabase database, CSVRecord record) throws FormatException { - Integer cardId = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIdsGroups.cardID, record, false); + int cardId = CSVHelpers.extractInt(DBHelper.LoyaltyCardDbIdsGroups.cardID, record); String groupId = CSVHelpers.extractString(DBHelper.LoyaltyCardDbIdsGroups.groupID, record, null); + if (groupId == null) { + throw new FormatException("Group has no ID: " + record); + } + List cardGroups = DBHelper.getLoyaltyCardGroups(database, cardId); cardGroups.add(DBHelper.getGroup(database, groupId)); DBHelper.setLoyaltyCardGroups(database, cardId, cardGroups); diff --git a/app/src/test/java/protect/card_locker/ImportURITest.java b/app/src/test/java/protect/card_locker/ImportURITest.java index c43515319..408799db5 100644 --- a/app/src/test/java/protect/card_locker/ImportURITest.java +++ b/app/src/test/java/protect/card_locker/ImportURITest.java @@ -111,10 +111,11 @@ public class ImportURITest { @Test public void failToParseBadData() { - String[] urls = new String[3]; + String[] urls = new String[4]; urls[0] = "https://brarcher.github.io/loyalty-card-locker/share?stare=store¬e=note&cardid=12345&barcodetype=ITF&headercolor=-416706"; urls[1] = "https://thelastproject.github.io/Catima/share#stare%3Dstore%26note%3Dnote%26balance%3D0%26cardid%3D12345%26barcodetype%3DITF%26headercolor%3D-416706"; urls[2] = "https://catima.app/share#stare%3Dstore%26note%3Dnote%26balance%3D0%26cardid%3D12345%26barcodetype%3DITF%26headercolor%3D-416706"; + urls[3] = "https://catima.app/share#"; for (String url : urls) { try {