Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,23 @@ sealed class ContainerNotificationType {

data object CadesFile : ContainerNotificationType()

data object DdocFile : ContainerNotificationType()

data object EmptyFile : ContainerNotificationType()

data class UnknownSignatures(
val count: Int,
) : ContainerNotificationType()

data class InvalidSignatures(
val count: Int,
) : ContainerNotificationType()

data class UnknownTimestamps(
val count: Int,
) : ContainerNotificationType()

data class InvalidTimestamps(
val count: Int,
) : ContainerNotificationType()
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,17 @@ fun SigningNavigation(
val isNestedContainer = sharedContainerViewModel.isNestedContainer(signedContainer)
val isXadesContainer = signedContainer?.isXades() == true
val isCadesContainer = signedContainer?.isCades() == true
val isDdocContainer = signedContainer?.isDdoc() == true
var isEmptyFileInContainer by remember { mutableStateOf(false) }

var validSignaturesCount by remember { mutableIntStateOf(0) }
var unknownSignaturesCount by remember { mutableIntStateOf(0) }
var invalidSignaturesCount by remember { mutableIntStateOf(0) }

var validTimestampsCount by remember { mutableIntStateOf(0) }
var unknownTimestampsCount by remember { mutableIntStateOf(0) }
var invalidTimestampsCount by remember { mutableIntStateOf(0) }

var isSignaturesCountLoaded by remember { mutableStateOf(false) }

val isParentContainerSivaConfirmed = sharedContainerViewModel.isSivaConfirmed.value == true
Expand Down Expand Up @@ -571,10 +577,26 @@ fun SigningNavigation(
invalidSignaturesCount =
signatureCounts?.get(ValidatorInterface.Status.Invalid) ?: 0

if (signedContainer?.containerMimetype() != ASICS_MIMETYPE) {
val timestampCounts = signedContainer?.getTimestampStatusCount()
validTimestampsCount = timestampCounts?.get(ValidatorInterface.Status.Valid) ?: 0
unknownTimestampsCount =
timestampCounts?.get(ValidatorInterface.Status.Unknown) ?: 0
invalidTimestampsCount =
timestampCounts?.get(ValidatorInterface.Status.Invalid) ?: 0
}

isEmptyFileInContainer =
signingViewModel.isEmptyFileInList(
signedContainer?.getDataFiles() ?: listOf(),
)

sharedContainerViewModel.setContainerNotifications(
listOfNotNull(
ContainerNotificationType.XadesFile.takeIf { isXadesContainer },
ContainerNotificationType.CadesFile.takeIf { isCadesContainer },
ContainerNotificationType.DdocFile.takeIf { isDdocContainer },
ContainerNotificationType.EmptyFile.takeIf { isEmptyFileInContainer },
ContainerNotificationType
.UnknownSignatures(
unknownSignaturesCount,
Expand All @@ -583,6 +605,14 @@ fun SigningNavigation(
.InvalidSignatures(
invalidSignaturesCount,
).takeIf { invalidSignaturesCount > 0 },
ContainerNotificationType
.UnknownTimestamps(
unknownTimestampsCount,
).takeIf { unknownTimestampsCount > 0 },
ContainerNotificationType
.InvalidTimestamps(
invalidTimestampsCount,
).takeIf { invalidTimestampsCount > 0 },
),
)
}
Expand Down Expand Up @@ -948,7 +978,7 @@ fun SigningNavigation(
signedContainer?.let { container ->
container
.getTimestamps()
?.let { timestamps ->
.let { timestamps ->
Row {
SignatureComponent(
modifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ fun ContainerNotificationsScreen(
when (type) {
ContainerNotificationType.XadesFile -> stringResource(R.string.xades_file_message)
ContainerNotificationType.CadesFile -> stringResource(R.string.cades_file_message)
ContainerNotificationType.DdocFile -> stringResource(R.string.ddoc_file_message)
ContainerNotificationType.EmptyFile -> stringResource(R.string.empty_file_message)
is ContainerNotificationType.UnknownSignatures ->
pluralStringResource(
id = R.plurals.signatures_unknown,
Expand All @@ -202,6 +204,18 @@ fun ContainerNotificationsScreen(
count = type.count,
type.count,
)
is ContainerNotificationType.UnknownTimestamps ->
pluralStringResource(
id = R.plurals.timestamps_unknown,
count = type.count,
type.count,
)
is ContainerNotificationType.InvalidTimestamps ->
pluralStringResource(
id = R.plurals.timestamps_invalid,
count = type.count,
type.count,
)
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import ee.ria.DigiDoc.common.Constant.UNSIGNABLE_CONTAINER_MIMETYPES
import ee.ria.DigiDoc.domain.repository.fileopening.FileOpeningRepository
import ee.ria.DigiDoc.domain.repository.siva.SivaRepository
import ee.ria.DigiDoc.libdigidoclib.SignedContainer
import ee.ria.DigiDoc.libdigidoclib.domain.model.DataFileInterface
import ee.ria.DigiDoc.libdigidoclib.domain.model.SignatureInterface
import ee.ria.DigiDoc.utilsLib.container.ContainerUtil
import ee.ria.DigiDoc.utilsLib.container.ContainerUtil.createContainerAction
Expand All @@ -45,6 +46,8 @@ import ee.ria.DigiDoc.utilsLib.logging.LoggingUtil.Companion.errorLog
import ee.ria.DigiDoc.utilsLib.mimetype.MimeTypeResolver
import ee.ria.DigiDoc.viewmodel.shared.SharedContainerViewModel
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.withContext
import org.apache.commons.io.FilenameUtils
import java.io.File
Expand All @@ -65,6 +68,9 @@ class SigningViewModel
private val _shouldResetSignedContainer = MutableLiveData(false)
val shouldResetSignedContainer: LiveData<Boolean?> = _shouldResetSignedContainer

private val _hasEmptyFiles = MutableStateFlow(false)
val hasEmptyFiles: StateFlow<Boolean> = _hasEmptyFiles

fun handleBackButton() {
_shouldResetSignedContainer.postValue(true)
}
Expand Down Expand Up @@ -137,6 +143,9 @@ class SigningViewModel
signature.countryName.isEmpty() &&
signature.postalCode.isEmpty()

fun isEmptyFileInList(dataFiles: List<DataFileInterface>): Boolean =
dataFiles.any { dataFile -> dataFile.fileSize == 0L }

@Throws(Exception::class)
suspend fun openCryptoContainer(
context: Context,
Expand Down
25 changes: 14 additions & 11 deletions app/src/main/res/values-et/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,28 @@
<string name="container_open_file_error">Failide laadimine ebaõnnestus</string>
<string name="container_load_error">Ümbriku laadimine ebaõnnestus</string>
<string name="empty_file_message">Ümbrikule on lisatud tühi fail. Allkirjastamiseks eemalda ümbrikust tühi fail.</string>
<string name="xades_file_message">Tegemist on XADES allkirja sisalduva ASICS ümbrikuga. Sellele ümbrikule ei saa allkirja lisada ega eemaldada.</string>
<string name="xades_file_message">Tegemist on XADES allkirja sisaldava ASICS ümbrikuga. Sellele ümbrikule ei saa allkirja lisada ega eemaldada.</string>
<string name="cades_file_message">Tegemist on CAdES allkirja sisaldava ümbrikuga. Sellele ümbrikule ei saa allkirja lisada ega eemaldada.</string>
<string name="ddoc_file_message">Tegemist on vanas formaadis DigiDoc ümbrikuga. Sellele ümbrikule ei saa allkirja lisada ega eemaldada.</string>
<plurals name="signatures_unknown">
<item quantity="one">%1$d ALLKIRI ON TEADMATA</item>
<item quantity="other">%1$d ALLKIRJA ON TEADMATA</item>
<!-- placeholder to keep line numbers same in different locales -->
<!-- placeholder to keep line numbers same in different locales -->
<item quantity="one">%1$d allkiri on teadmata</item>
<item quantity="other">%1$d allkirja on teadmata</item>
</plurals>
<plurals name="signatures_invalid">
<item quantity="one">%1$d ALLKIRI EI KEHTI</item>
<item quantity="other">%1$d ALLKIRJA EI KEHTI</item>
<!-- placeholder to keep line numbers same in different locales -->
<!-- placeholder to keep line numbers same in different locales -->
<item quantity="one">%1$d allkiri ei kehti</item>
<item quantity="other">%1$d allkirja ei kehti</item>
</plurals>
<plurals name="signatures_valid">
<item quantity="one">%1$d kehtiv allkiri</item>
<item quantity="other">%1$d kehtivat allkirja</item>
<!-- placeholder to keep line numbers same in different locales -->
<!-- placeholder to keep line numbers same in different locales -->
</plurals>
<plurals name="timestamps_unknown">
<item quantity="one">%1$d ajatempel on teadmata</item>
<item quantity="other">%1$d ajatemplit on teadmata</item>
</plurals>
<plurals name="timestamps_invalid">
<item quantity="one">%1$d ajatempel ei kehti</item>
<item quantity="other">%1$d ajatemplit ei kehti</item>
</plurals>

<string name="challenge_code_text">Kontrollkood:</string>
Expand Down
23 changes: 13 additions & 10 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,26 @@
<string name="empty_file_message">An empty file is attached to the envelope. Remove the empty file from the container to sign.</string>
<string name="xades_file_message">This ASICS container contains XADES signature. You are not allowed to add or remove signatures to this container.</string>
<string name="cades_file_message">This container contains CAdES signature. You are not allowed to add or remove signatures to this container.</string>
<string name="ddoc_file_message">The current file is a DigiDoc container that is not supported officially any longer. You are not allowed to add or remove signatures to this container.</string>
<plurals name="signatures_unknown">
<item quantity="one">%1$d UNKNOWN SIGNATURE</item>
<item quantity="other">%1$d UNKNOWN SIGNATURES</item>
<!-- placeholder to keep line numbers same in different locales -->
<!-- placeholder to keep line numbers same in different locales -->
<item quantity="one">%1$d unknown signature</item>
<item quantity="other">%1$d unknown signatures</item>
</plurals>
<plurals name="signatures_invalid">
<item quantity="one">%1$d INVALID SIGNATURE</item>
<item quantity="other">%1$d INVALID SIGNATURES</item>
<!-- placeholder to keep line numbers same in different locales -->
<!-- placeholder to keep line numbers same in different locales -->
<item quantity="one">%1$d invalid signature</item>
<item quantity="other">%1$d invalid signature</item>
</plurals>
<plurals name="signatures_valid">
<item quantity="one">%1$d valid signature</item>
<item quantity="other">%1$d valid signatures</item>
<!-- placeholder to keep line numbers same in different locales -->
<!-- placeholder to keep line numbers same in different locales -->
</plurals>
<plurals name="timestamps_unknown">
<item quantity="one">%1$d unknown timestamp</item>
<item quantity="other">%1$d unknown timestamps</item>
</plurals>
<plurals name="timestamps_invalid">
<item quantity="one">%1$d invalid timestamp</item>
<item quantity="other">%1$d invalid timestamps</item>
</plurals>

<string name="challenge_code_text">Control code:</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,26 @@ class SignedContainerTest {
assertEquals(0, signaturesStatuses[ValidatorInterface.Status.Invalid])
}

@Test
fun signedContainer_getTimestampStatusCount_successWithNoTimestamps() =
runTest {
val noSignaturesContainer =
getResourceFileAsFile(
context,
"example_no_signatures.asice",
ee.ria.DigiDoc.common.R.raw.example_no_signatures,
)

val signedContainer = openOrCreate(context, noSignaturesContainer, listOf(noSignaturesContainer), true)

val signaturesStatuses = signedContainer.getTimestampStatusCount()

assertNotNull(signaturesStatuses)
assertEquals(0, signaturesStatuses[ValidatorInterface.Status.Valid])
assertEquals(0, signaturesStatuses[ValidatorInterface.Status.Unknown])
assertEquals(0, signaturesStatuses[ValidatorInterface.Status.Invalid])
}

// Requires internet access, emulator should be running with internet access and RIA VPN on.
@Test
fun signedContainer_openOrCreate_successCreatingNewContainerWithPDFSignatures() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ package ee.ria.DigiDoc.libdigidoclib
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import ee.ria.DigiDoc.common.Constant.ASICS_MIMETYPE
import ee.ria.DigiDoc.common.Constant.DDOC_EXTENSION
import ee.ria.DigiDoc.common.Constant.DDOC_MIMETYPE
import ee.ria.DigiDoc.common.Constant.DEFAULT_CONTAINER_EXTENSION
import ee.ria.DigiDoc.common.Constant.DEFAULT_FILENAME
import ee.ria.DigiDoc.common.Constant.NON_LEGACY_CONTAINER_EXTENSIONS
Expand Down Expand Up @@ -68,7 +70,7 @@ class SignedContainer
private val container: Container? = null,
private var containerFile: File? = null,
private val isExistingContainer: Boolean = false,
private val timestamps: List<SignatureInterface>? = emptyList(),
private val timestamps: List<SignatureInterface> = emptyList(),
) : ee.ria.DigiDoc.common.container.Container {
suspend fun getDataFiles(): List<DataFileInterface> {
return CoroutineScope(IO)
Expand Down Expand Up @@ -108,7 +110,7 @@ class SignedContainer
return null
}

fun getTimestamps(): List<SignatureInterface>? = timestamps
fun getTimestamps(): List<SignatureInterface> = timestamps

suspend fun getSignatures(thread: CoroutineContext = IO): List<SignatureInterface> =
withContext(thread) {
Expand Down Expand Up @@ -237,27 +239,41 @@ class SignedContainer
signature?.profile()?.lowercase()?.contains("cades") ?: false
} ?: false

fun isDdoc(): Boolean =
containerMimetype().equals(DDOC_MIMETYPE, true) &&
containerFile?.extension == DDOC_EXTENSION

suspend fun getSignaturesStatusCount(): Map<ValidatorInterface.Status, Int> {
val signatures = getSignatures(Main)
return countStatuses(signatures) { it.validator.status }
}

fun getTimestampStatusCount(): Map<ValidatorInterface.Status, Int> {
val timestamps = getTimestamps()
return countStatuses(timestamps) { it.validator.status }
}

fun isSignedPDF(): Boolean = containerFile?.isSignedPDF(context) ?: false

private fun <T> countStatuses(
items: List<T>,
getStatus: (T) -> ValidatorInterface.Status,
): Map<ValidatorInterface.Status, Int> {
val counts =
mutableMapOf(
ValidatorInterface.Status.Valid to 0,
ValidatorInterface.Status.Unknown to 0,
ValidatorInterface.Status.Invalid to 0,
)

val signatures = getSignatures(Main)

for (signature in signatures) {
signature.validator.status.let { status ->
counts[status] = counts[status]?.plus(1) ?: 1
}
for (item in items) {
val status = getStatus(item)
counts[status] = counts[status]?.plus(1) ?: 1
}

return counts.toMap()
return counts
}

fun isSignedPDF(): Boolean = containerFile?.isSignedPDF(context) ?: false

companion object {
@Throws(Exception::class)
fun addDataFiles(
Expand Down
Loading