Use backend response for validation

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-07-17 16:56:56 +02:00 committed by Alper Öztürk
parent 436f0de8d1
commit 15bf9d4f31
4 changed files with 74 additions and 42 deletions

View file

@ -10,7 +10,6 @@ package com.nextcloud.utils
import com.nextcloud.utils.fileNameValidator.FileNameValidator
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
import com.owncloud.android.lib.resources.status.CapabilityBooleanType
import com.owncloud.android.lib.resources.status.OCCapability
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@ -26,9 +25,13 @@ class FileNameValidatorTests : AbstractIT() {
@Before
fun setup() {
capability = capability.apply {
forbiddenFilenames = CapabilityBooleanType.TRUE
forbiddenFilenameExtension = CapabilityBooleanType.TRUE
forbiddenFilenameCharacters = CapabilityBooleanType.TRUE
forbiddenFilenamesJson =
"""["CON", "PRN", "AUX", "NUL", "COM0", "COM1", "COM2", "COM3", "COM4",
"COM5", "COM6", "COM7", "COM8", "COM9", "COM¹", "COM²", "COM³",
"LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7",
"LPT8", "LPT9", "LPT¹", "LPT²", "LPT³"]"""
forbiddenFilenameExtensionJson = """"[".filepart",".part"]"""
forbiddenFilenameCharactersJson = """["\\[<>:\"/\\\\|?*\\]","\\[/<>|:&\\]"]"""
}
}

View file

@ -0,0 +1,30 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.utils.extensions
import com.google.gson.Gson
import com.owncloud.android.lib.resources.status.OCCapability
import org.json.JSONException
private val gson = Gson()
fun OCCapability.forbiddenFilenames(): List<String> = jsonToList(forbiddenFilenamesJson)
fun OCCapability.forbiddenFilenameCharacters(): List<String> = jsonToList(forbiddenFilenameCharactersJson)
fun OCCapability.forbiddenFilenameExtension(): List<String> = jsonToList(forbiddenFilenameExtensionJson)
private fun jsonToList(json: String?): List<String> {
if (json == null) return emptyList()
return try {
return gson.fromJson(json, Array<String>::class.java).toList()
} catch (e: JSONException) {
emptyList()
}
}

View file

@ -10,22 +10,15 @@ package com.nextcloud.utils.fileNameValidator
import android.content.Context
import android.text.TextUtils
import com.nextcloud.utils.extensions.dot
import com.nextcloud.utils.extensions.forbiddenFilenameCharacters
import com.nextcloud.utils.extensions.forbiddenFilenameExtension
import com.nextcloud.utils.extensions.forbiddenFilenames
import com.nextcloud.utils.extensions.removeFileExtension
import com.nextcloud.utils.extensions.space
import com.owncloud.android.R
import com.owncloud.android.lib.resources.status.OCCapability
object FileNameValidator {
private val reservedWindowsChars = "[<>:\"/\\\\|?*]".toRegex()
private val reservedUnixChars = "[/<>|:&]".toRegex()
private val reservedWindowsNames = listOf(
"CON", "PRN", "AUX", "NUL",
"COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
"COM¹", "COM²", "COM³",
"LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
"LPT¹", "LPT²", "LPT³"
)
private val forbiddenFileExtensions = listOf(".filepart", ".part")
/**
* Checks the validity of a file name.
@ -61,25 +54,28 @@ object FileNameValidator {
return it
}
if (capability.forbiddenFilenames.isTrue &&
(
reservedWindowsNames.contains(filename.uppercase()) ||
reservedWindowsNames.contains(filename.removeFileExtension().uppercase())
capability.forbiddenFilenamesJson?.let {
val forbiddenFilenames = capability.forbiddenFilenames()
if (forbiddenFilenames.contains(filename.uppercase()) || forbiddenFilenames.contains(
filename.removeFileExtension().uppercase()
)
) {
return context.getString(R.string.file_name_validator_error_reserved_names, filename.substringBefore(dot()))
) {
return context.getString(
R.string.file_name_validator_error_reserved_names,
filename.substringBefore(dot())
)
}
}
if (capability.forbiddenFilenameExtension.isTrue && forbiddenFileExtensions.any {
filename.endsWith(
it,
ignoreCase = true
capability.forbiddenFilenameExtensionJson?.let {
val forbiddenFilenameExtension = capability.forbiddenFilenameExtension()
if (forbiddenFilenameExtension.any { filename.endsWith(it, ignoreCase = true) }) {
return context.getString(
R.string.file_name_validator_error_forbidden_file_extensions,
filename.substringAfter(dot())
)
}) {
return context.getString(
R.string.file_name_validator_error_forbidden_file_extensions,
filename.substringAfter(dot())
)
}
}
return null
@ -114,16 +110,19 @@ object FileNameValidator {
@Suppress("ReturnCount")
private fun checkInvalidCharacters(name: String, capability: OCCapability, context: Context): String? {
if (capability.forbiddenFilenameCharacters.isFalse) return null
capability.forbiddenFilenameCharactersJson?.let {
val forbiddenFilenameCharacters = capability.forbiddenFilenameCharacters()
val invalidCharacter = name.find {
val input = it.toString()
input.matches(reservedWindowsChars) || input.matches(reservedUnixChars)
val invalidCharacter = forbiddenFilenameCharacters.find { forbiddenSuffix ->
name.endsWith(forbiddenSuffix, ignoreCase = true)
}
if (invalidCharacter == null) return null
return context.getString(R.string.file_name_validator_error_invalid_character, invalidCharacter)
}
if (invalidCharacter == null) return null
return context.getString(R.string.file_name_validator_error_invalid_character, invalidCharacter)
return null
}
fun isFileHidden(name: String): Boolean = !TextUtils.isEmpty(name) && name[0] == '.'

View file

@ -2053,9 +2053,9 @@ public class FileDataStorageManager {
contentValues.put(ProviderTableMeta.CAPABILITIES_DROP_ACCOUNT, capability.getDropAccount().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_SECURITY_GUARD, capability.getSecurityGuard().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAME_CHARACTERS, capability.getForbiddenFilenameCharacters().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAMES, capability.getForbiddenFilenames().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_EXTENSIONS, capability.getForbiddenFilenameExtension().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAME_CHARACTERS, capability.getForbiddenFilenameCharactersJson());
contentValues.put(ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAMES, capability.getForbiddenFilenamesJson());
contentValues.put(ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_EXTENSIONS, capability.getForbiddenFilenameExtensionJson());
return contentValues;
}
@ -2226,9 +2226,9 @@ public class FileDataStorageManager {
capability.setDropAccount(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_DROP_ACCOUNT));
capability.setSecurityGuard(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_SECURITY_GUARD));
capability.setForbiddenFilenameCharacters(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAME_CHARACTERS));
capability.setForbiddenFilenames(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAMES));
capability.setForbiddenFilenameExtension(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_EXTENSIONS));
capability.setForbiddenFilenameCharactersJson(getString(cursor, ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAME_CHARACTERS));
capability.setForbiddenFilenamesJson(getString(cursor, ProviderTableMeta.CAPABILITIES_FORBIDDEN_FILENAMES));
capability.setForbiddenFilenameExtensionJson(getString(cursor, ProviderTableMeta.CAPABILITIES_FORBIDDEN_FORBIDDEN_FILENAME_EXTENSIONS));
}
return capability;