diff --git a/.idea/sonarIssues.xml b/.idea/sonarIssues.xml
index 1b3e5c29..90092077 100644
--- a/.idea/sonarIssues.xml
+++ b/.idea/sonarIssues.xml
@@ -108,6 +108,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -158,6 +168,11 @@
+
+
+
+
+
@@ -603,11 +618,21 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/DefaultGreenCertificateFetcher.kt b/app/src/main/java/dgca/wallet/app/android/certificate/DefaultGreenCertificateFetcher.kt
new file mode 100644
index 00000000..a909d726
--- /dev/null
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/DefaultGreenCertificateFetcher.kt
@@ -0,0 +1,66 @@
+/*
+ * ---license-start
+ * eu-digital-green-certificates / dgca-wallet-app-android
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ *
+ * Created by osarapulov on 8/26/21 10:36 AM
+ */
+
+package dgca.wallet.app.android.certificate
+
+import dgca.verifier.app.decoder.base45.Base45Service
+import dgca.verifier.app.decoder.cbor.CborService
+import dgca.verifier.app.decoder.compression.CompressorService
+import dgca.verifier.app.decoder.cose.CoseService
+import dgca.verifier.app.decoder.model.GreenCertificate
+import dgca.verifier.app.decoder.model.VerificationResult
+import dgca.verifier.app.decoder.prefixvalidation.PrefixValidationService
+import dgca.verifier.app.decoder.schema.SchemaValidator
+import timber.log.Timber
+
+class DefaultGreenCertificateFetcher(
+ private val prefixValidationService: PrefixValidationService,
+ private val base45Service: Base45Service,
+ private val compressorService: CompressorService,
+ private val coseService: CoseService,
+ private val schemaValidator: SchemaValidator,
+ private val cborService: CborService,
+) : GreenCertificateFetcher {
+ override fun fetchDataFromQrString(qrString: String): Pair {
+ val verificationResult = VerificationResult()
+ val plainInput = prefixValidationService.decode(qrString, verificationResult)
+ val compressedCose = base45Service.decode(plainInput, verificationResult)
+ val coseResult: ByteArray? = compressorService.decode(compressedCose, verificationResult)
+
+ if (coseResult == null) {
+ Timber.d("Verification failed: Too many bytes read")
+ return Pair(null, null)
+ }
+ val cose: ByteArray = coseResult
+
+ val coseData = coseService.decode(cose, verificationResult)
+ if (coseData == null) {
+ Timber.d("Verification failed: COSE not decoded")
+ return Pair(cose, null)
+ }
+
+ schemaValidator.validate(coseData.cbor, verificationResult)
+ return Pair(cose, cborService.decode(coseData.cbor, verificationResult))
+ }
+
+ override fun fetchGreenCertificateFromQrString(qrString: String): GreenCertificate? = fetchDataFromQrString(qrString).second
+}
\ No newline at end of file
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/GreenCertificateFetcher.kt b/app/src/main/java/dgca/wallet/app/android/certificate/GreenCertificateFetcher.kt
new file mode 100644
index 00000000..30b79e9c
--- /dev/null
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/GreenCertificateFetcher.kt
@@ -0,0 +1,31 @@
+/*
+ * ---license-start
+ * eu-digital-green-certificates / dgca-wallet-app-android
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ *
+ * Created by osarapulov on 8/26/21 10:35 AM
+ */
+
+package dgca.wallet.app.android.certificate
+
+import dgca.verifier.app.decoder.model.GreenCertificate
+
+interface GreenCertificateFetcher {
+ fun fetchDataFromQrString(qrString: String): Pair
+
+ fun fetchGreenCertificateFromQrString(qrString: String): GreenCertificate?
+}
\ No newline at end of file
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/add/BitmapFetcher.kt b/app/src/main/java/dgca/wallet/app/android/certificate/add/BitmapFetcher.kt
index c5a3a2b9..b0d5679c 100644
--- a/app/src/main/java/dgca/wallet/app/android/certificate/add/BitmapFetcher.kt
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/add/BitmapFetcher.kt
@@ -28,5 +28,6 @@ import android.net.Uri
interface BitmapFetcher {
fun loadBitmapByImageUri(uri: Uri): Bitmap
- fun loadBitmapByPdfUri(uri: Uri): Bitmap
+ @Throws(Exception::class)
+ fun loadBitmapByPdfUri(uri: Uri): List
}
\ No newline at end of file
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/add/DefaultBitmapFetcher.kt b/app/src/main/java/dgca/wallet/app/android/certificate/add/DefaultBitmapFetcher.kt
index fc639718..1504f485 100644
--- a/app/src/main/java/dgca/wallet/app/android/certificate/add/DefaultBitmapFetcher.kt
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/add/DefaultBitmapFetcher.kt
@@ -41,14 +41,19 @@ class DefaultBitmapFetcher(context: Context) : BitmapFetcher {
}.copy(Bitmap.Config.ARGB_8888, true)
}
- override fun loadBitmapByPdfUri(uri: Uri): Bitmap =
+ @Throws(Exception::class)
+ override fun loadBitmapByPdfUri(uri: Uri): List =
appContext.contentResolver.openFileDescriptor(uri, "r")!!.use { fileDescriptor ->
PdfRenderer(fileDescriptor).use { pdfRenderer ->
- pdfRenderer.openPage(0).use { page ->
- val bitmap = Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
- page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
- bitmap
+ val bitmaps = mutableListOf()
+ for (i in 0 until pdfRenderer.pageCount) {
+ pdfRenderer.openPage(i).use { page ->
+ val bitmap = Bitmap.createBitmap(page.width, page.height, Bitmap.Config.ARGB_8888)
+ page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
+ bitmaps.add(bitmap)
+ }
}
+ bitmaps.toList()
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/add/pdf/ImportPdfViewModel.kt b/app/src/main/java/dgca/wallet/app/android/certificate/add/pdf/ImportPdfViewModel.kt
index 79c9e401..76cfedae 100644
--- a/app/src/main/java/dgca/wallet/app/android/certificate/add/pdf/ImportPdfViewModel.kt
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/add/pdf/ImportPdfViewModel.kt
@@ -22,18 +22,22 @@
package dgca.wallet.app.android.certificate.add.pdf
+import android.graphics.Bitmap
import android.net.Uri
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
+import dgca.verifier.app.decoder.model.GreenCertificate
+import dgca.wallet.app.android.certificate.GreenCertificateFetcher
import dgca.wallet.app.android.certificate.add.BitmapFetcher
import dgca.wallet.app.android.certificate.add.FileSaver
import dgca.wallet.app.android.certificate.add.QrCodeFetcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import timber.log.Timber
import javax.inject.Inject
sealed class ImportPdfResult {
@@ -46,7 +50,8 @@ sealed class ImportPdfResult {
class ImportPdfViewModel @Inject constructor(
private val bitmapFetcher: BitmapFetcher,
private val qrCodeFetcher: QrCodeFetcher,
- private val fileSaver: FileSaver
+ private val fileSaver: FileSaver,
+ private val greenCertificateFetcher: GreenCertificateFetcher
) : ViewModel() {
private val _result = MutableLiveData()
val result: LiveData = _result
@@ -60,15 +65,34 @@ class ImportPdfViewModel @Inject constructor(
}
private fun Uri.handle(): ImportPdfResult {
- val qrCodeString: String? = try {
- bitmapFetcher.loadBitmapByPdfUri(this)
- .let { bitmap -> qrCodeFetcher.fetchQrCodeString(bitmap) }
+ val qrStrings = mutableListOf()
+ var bitmaps: List? = null
+ try {
+ bitmaps = bitmapFetcher.loadBitmapByPdfUri(this)
+ bitmaps.forEach { bitmap ->
+ qrStrings.add(qrCodeFetcher.fetchQrCodeString(bitmap))
+ bitmap.recycle()
+ }
} catch (exception: Exception) {
- null
+ Timber.d(exception, "Error fetching qr strings from bitmaps")
+ } finally {
+ bitmaps?.forEach { bitmap -> bitmap.recycle() }
+ }
+
+ var qrString = ""
+ var greenCertificate: GreenCertificate? = null
+
+ qrStrings.forEach { curQrString ->
+ val curGreenCertificate = greenCertificateFetcher.fetchGreenCertificateFromQrString(curQrString)
+ if (curGreenCertificate != null) {
+ qrString = curQrString
+ greenCertificate = curGreenCertificate
+ return@forEach
+ }
}
- return if (qrCodeString?.isNotBlank() == true) {
- ImportPdfResult.QrRecognised(qrCodeString)
+ return if (greenCertificate != null) {
+ ImportPdfResult.QrRecognised(qrString)
} else {
val file = try {
fileSaver.saveFileFromUri(this, "images", "${System.currentTimeMillis()}.pdf")
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/add/pick/image/PickImageViewModel.kt b/app/src/main/java/dgca/wallet/app/android/certificate/add/pick/image/PickImageViewModel.kt
index 610d4274..36d4ac84 100644
--- a/app/src/main/java/dgca/wallet/app/android/certificate/add/pick/image/PickImageViewModel.kt
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/add/pick/image/PickImageViewModel.kt
@@ -28,6 +28,8 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
+import dgca.verifier.app.decoder.model.GreenCertificate
+import dgca.wallet.app.android.certificate.GreenCertificateFetcher
import dgca.wallet.app.android.certificate.add.BitmapFetcher
import dgca.wallet.app.android.certificate.add.FileSaver
import dgca.wallet.app.android.certificate.add.QrCodeFetcher
@@ -46,7 +48,8 @@ sealed class PickImageResult {
class PickImageViewModel @Inject constructor(
private val qrCodeFetcher: QrCodeFetcher,
private val bitmapFetcher: BitmapFetcher,
- private val fileSaver: FileSaver
+ private val fileSaver: FileSaver,
+ private val greenCertificateFetcher: GreenCertificateFetcher
) : ViewModel() {
private val _result = MutableLiveData()
val result: LiveData = _result
@@ -66,7 +69,10 @@ class PickImageViewModel @Inject constructor(
null
}
- return if (qrCodeString?.isNotBlank() == true) {
+ val greenCertificate: GreenCertificate? =
+ qrCodeString?.let { qrString -> greenCertificateFetcher.fetchGreenCertificateFromQrString(qrString) }
+
+ return if (greenCertificate != null) {
PickImageResult.QrRecognised(qrCodeString)
} else {
val file = try {
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/add/take/photo/TakePhotoViewModel.kt b/app/src/main/java/dgca/wallet/app/android/certificate/add/take/photo/TakePhotoViewModel.kt
index d1c4f1d4..c3971a73 100644
--- a/app/src/main/java/dgca/wallet/app/android/certificate/add/take/photo/TakePhotoViewModel.kt
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/add/take/photo/TakePhotoViewModel.kt
@@ -28,6 +28,8 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
+import dgca.verifier.app.decoder.model.GreenCertificate
+import dgca.wallet.app.android.certificate.GreenCertificateFetcher
import dgca.wallet.app.android.certificate.add.BitmapFetcher
import dgca.wallet.app.android.certificate.add.FileSaver
import dgca.wallet.app.android.certificate.add.QrCodeFetcher
@@ -48,7 +50,8 @@ class TakePhotoViewModel @Inject constructor(
private val qrCodeFetcher: QrCodeFetcher,
private val bitmapFetcher: BitmapFetcher,
private val uriProvider: UriProvider,
- private val fileSaver: FileSaver
+ private val fileSaver: FileSaver,
+ private val greenCertificateFetcher: GreenCertificateFetcher
) : ViewModel() {
val uriLiveData: LiveData = MutableLiveData(uriProvider.getUriFor("temp", "temp.jpeg"))
private val _result = MutableLiveData()
@@ -70,9 +73,13 @@ class TakePhotoViewModel @Inject constructor(
} catch (exception: Exception) {
null
}
+ val greenCertificate: GreenCertificate? =
+ qrCodeString?.let { qrString -> greenCertificateFetcher.fetchGreenCertificateFromQrString(qrString) }
return when {
- qrCodeString?.isNotBlank() == true && uriProvider.deleteFileByUri(this) -> {
+ greenCertificate != null && uriProvider.deleteFileByUri(
+ this
+ ) -> {
TakePhotoResult.QrRecognised(qrCodeString)
}
else -> {
diff --git a/app/src/main/java/dgca/wallet/app/android/certificate/claim/ClaimCertificateViewModel.kt b/app/src/main/java/dgca/wallet/app/android/certificate/claim/ClaimCertificateViewModel.kt
index fcb543ca..d5c2f8b7 100644
--- a/app/src/main/java/dgca/wallet/app/android/certificate/claim/ClaimCertificateViewModel.kt
+++ b/app/src/main/java/dgca/wallet/app/android/certificate/claim/ClaimCertificateViewModel.kt
@@ -28,16 +28,11 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dgca.verifier.app.decoder.*
-import dgca.verifier.app.decoder.base45.Base45Service
-import dgca.verifier.app.decoder.cbor.CborService
-import dgca.verifier.app.decoder.compression.CompressorService
-import dgca.verifier.app.decoder.cose.CoseService
import dgca.verifier.app.decoder.model.GreenCertificate
-import dgca.verifier.app.decoder.model.VerificationResult
import dgca.verifier.app.decoder.prefixvalidation.PrefixValidationService
-import dgca.verifier.app.decoder.schema.SchemaValidator
import dgca.wallet.app.android.BuildConfig
import dgca.wallet.app.android.Event
+import dgca.wallet.app.android.certificate.GreenCertificateFetcher
import dgca.wallet.app.android.data.CertificateModel
import dgca.wallet.app.android.data.ConfigRepository
import dgca.wallet.app.android.data.WalletRepository
@@ -56,12 +51,8 @@ import javax.inject.Inject
@HiltViewModel
class ClaimCertificateViewModel @Inject constructor(
+ private val greenCertificateFetcher: GreenCertificateFetcher,
private val prefixValidationService: PrefixValidationService,
- private val base45Service: Base45Service,
- private val compressorService: CompressorService,
- private val coseService: CoseService,
- private val schemaValidator: SchemaValidator,
- private val cborService: CborService,
private val configRepository: ConfigRepository,
private val walletRepository: WalletRepository
) : ViewModel() {
@@ -81,26 +72,9 @@ class ClaimCertificateViewModel @Inject constructor(
fun init(qrCodeText: String) {
viewModelScope.launch {
_inProgress.value = true
- withContext(Dispatchers.IO) {
- val verificationResult = VerificationResult()
- val plainInput = prefixValidationService.decode(qrCodeText, verificationResult)
- val compressedCose = base45Service.decode(plainInput, verificationResult)
- val coseResult: ByteArray? = compressorService.decode(compressedCose, verificationResult)
-
- if (coseResult == null) {
- Timber.d("Verification failed: Too many bytes read")
- return@withContext
- }
- cose = coseResult
-
- val coseData = coseService.decode(cose, verificationResult)
- if (coseData == null) {
- Timber.d("Verification failed: COSE not decoded")
- return@withContext
- }
-
- schemaValidator.validate(coseData.cbor, verificationResult)
- greenCertificate = cborService.decode(coseData.cbor, verificationResult)
+ withContext(Dispatchers.IO) { greenCertificateFetcher.fetchDataFromQrString(qrCodeText) }.apply {
+ cose = first ?: cose
+ greenCertificate = second
}
_inProgress.value = false
_certificate.value = greenCertificate?.toCertificateModel()
diff --git a/app/src/main/java/dgca/wallet/app/android/di/DecoderModule.kt b/app/src/main/java/dgca/wallet/app/android/di/DecoderModule.kt
index 3ba2fb16..1fe850e2 100644
--- a/app/src/main/java/dgca/wallet/app/android/di/DecoderModule.kt
+++ b/app/src/main/java/dgca/wallet/app/android/di/DecoderModule.kt
@@ -44,6 +44,8 @@ import dgca.verifier.app.decoder.prefixvalidation.PrefixValidationService
import dgca.verifier.app.decoder.schema.DefaultSchemaValidator
import dgca.verifier.app.decoder.schema.SchemaValidator
import dgca.verifier.app.decoder.services.X509
+import dgca.wallet.app.android.certificate.DefaultGreenCertificateFetcher
+import dgca.wallet.app.android.certificate.GreenCertificateFetcher
import javax.inject.Singleton
/**
@@ -93,4 +95,22 @@ object DecoderModule {
@Singleton
@Provides
fun provideCryptoService(x509: X509): CryptoService = VerificationCryptoService(x509)
+
+ @Singleton
+ @Provides
+ fun provide(
+ prefixValidationService: PrefixValidationService,
+ base45Service: Base45Service,
+ compressorService: CompressorService,
+ coseService: CoseService,
+ schemaValidator: SchemaValidator,
+ cborService: CborService,
+ ): GreenCertificateFetcher = DefaultGreenCertificateFetcher(
+ prefixValidationService,
+ base45Service,
+ compressorService,
+ coseService,
+ schemaValidator,
+ cborService
+ )
}
\ No newline at end of file