mirror of
https://github.com/nextcloud/android.git
synced 2024-12-18 06:51:55 +03:00
Add checks for move or copy
Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
parent
7e85d80d8e
commit
b6a732cdfd
5 changed files with 121 additions and 1 deletions
|
@ -84,4 +84,76 @@ class FileNameValidatorTests : AbstractIT() {
|
||||||
assertTrue(FileNameValidator.isFileNameAlreadyExist("existingFile", existingFiles))
|
assertTrue(FileNameValidator.isFileNameAlreadyExist("existingFile", existingFiles))
|
||||||
assertFalse(FileNameValidator.isFileNameAlreadyExist("newFile", existingFiles))
|
assertFalse(FileNameValidator.isFileNameAlreadyExist("newFile", existingFiles))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testValidFolderAndFilePaths() {
|
||||||
|
val folderPath = "validFolder"
|
||||||
|
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertTrue(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFolderPathWithReservedName() {
|
||||||
|
val folderPath = "CON"
|
||||||
|
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFilePathWithReservedName() {
|
||||||
|
val folderPath = "validFolder"
|
||||||
|
val filePaths = listOf("file1.txt", "PRN.doc", "file3.jpg")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFolderPathWithInvalidCharacter() {
|
||||||
|
val folderPath = "invalid<Folder"
|
||||||
|
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFilePathWithInvalidCharacter() {
|
||||||
|
val folderPath = "validFolder"
|
||||||
|
val filePaths = listOf("file1.txt", "file|2.doc", "file3.jpg")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFolderPathEndingWithSpace() {
|
||||||
|
val folderPath = "folderWithSpace "
|
||||||
|
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFilePathEndingWithPeriod() {
|
||||||
|
val folderPath = "validFolder"
|
||||||
|
val filePaths = listOf("file1.txt", "file2.doc", "file3.")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFilePathWithNestedFolder() {
|
||||||
|
val folderPath = "validFolder\\secondValidFolder\\CON"
|
||||||
|
val filePaths = listOf("file1.txt", "file2.doc", "file3.")
|
||||||
|
|
||||||
|
val result = FileNameValidator.checkPath(folderPath, filePaths, capability, targetContext)
|
||||||
|
assertFalse(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,3 +15,12 @@ fun String.getRandomString(length: Int): String {
|
||||||
|
|
||||||
return this + result
|
return this + result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun String.removeFileExtension(): String {
|
||||||
|
val dotIndex = lastIndexOf('.')
|
||||||
|
return if (dotIndex != -1) {
|
||||||
|
substring(0, dotIndex)
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ package com.nextcloud.utils.fileNameValidator
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import com.nextcloud.utils.extensions.removeFileExtension
|
||||||
import com.owncloud.android.R
|
import com.owncloud.android.R
|
||||||
import com.owncloud.android.lib.resources.status.OCCapability
|
import com.owncloud.android.lib.resources.status.OCCapability
|
||||||
|
|
||||||
|
@ -46,7 +47,9 @@ object FileNameValidator {
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
if (capability.forbiddenFilenames.isTrue && reservedWindowsNames.contains(name.uppercase())) {
|
if (capability.forbiddenFilenames.isTrue &&
|
||||||
|
(reservedWindowsNames.contains(name.uppercase()) || reservedWindowsNames.contains(name.removeFileExtension().uppercase()))
|
||||||
|
) {
|
||||||
return context.getString(R.string.file_name_validator_error_reserved_names)
|
return context.getString(R.string.file_name_validator_error_reserved_names)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +60,24 @@ object FileNameValidator {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun checkPath(folderPath: String, filePaths: List<String>, capability: OCCapability, context: Context): Boolean {
|
||||||
|
val folderPaths = folderPath.split("/", "\\")
|
||||||
|
|
||||||
|
for (item in folderPaths) {
|
||||||
|
if (isValid(item, capability, context) != null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (item in filePaths) {
|
||||||
|
if (isValid(item, capability, context) != null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkInvalidCharacters(name: String, capability: OCCapability, context: Context): String? {
|
private fun checkInvalidCharacters(name: String, capability: OCCapability, context: Context): String? {
|
||||||
if (capability.forbiddenFilenameCharacters.isFalse) return null
|
if (capability.forbiddenFilenameCharacters.isFalse) return null
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.view.ActionMode
|
import android.view.ActionMode
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
@ -23,6 +25,7 @@ import android.view.View
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import com.nextcloud.client.di.Injectable
|
import com.nextcloud.client.di.Injectable
|
||||||
|
import com.nextcloud.utils.fileNameValidator.FileNameValidator
|
||||||
import com.owncloud.android.R
|
import com.owncloud.android.R
|
||||||
import com.owncloud.android.databinding.FilesFolderPickerBinding
|
import com.owncloud.android.databinding.FilesFolderPickerBinding
|
||||||
import com.owncloud.android.databinding.FilesPickerBinding
|
import com.owncloud.android.databinding.FilesPickerBinding
|
||||||
|
@ -441,6 +444,7 @@ open class FolderPickerActivity :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
private fun processOperation(action: String?) {
|
private fun processOperation(action: String?) {
|
||||||
val i = intent
|
val i = intent
|
||||||
val resultData = Intent()
|
val resultData = Intent()
|
||||||
|
@ -451,6 +455,18 @@ open class FolderPickerActivity :
|
||||||
}
|
}
|
||||||
|
|
||||||
targetFilePaths?.let { filePaths ->
|
targetFilePaths?.let { filePaths ->
|
||||||
|
|
||||||
|
val isPathValid = FileNameValidator.checkPath(file.remotePath, filePaths, capabilities, this)
|
||||||
|
if (!isPathValid) {
|
||||||
|
DisplayUtils.showSnackMessage(this, R.string.file_name_validator_error_copy_or_move)
|
||||||
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
|
setResult(RESULT_CANCELED, resultData)
|
||||||
|
finish()
|
||||||
|
|
||||||
|
}, 1000L)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
action?.let { action ->
|
action?.let { action ->
|
||||||
fileOperationsHelper.moveOrCopyFiles(action, filePaths, file)
|
fileOperationsHelper.moveOrCopyFiles(action, filePaths, file)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1219,6 +1219,8 @@
|
||||||
<string name="unified_search_fragment_contact_not_found">Contact not found, you can always sync to update. Redirecting to web…</string>
|
<string name="unified_search_fragment_contact_not_found">Contact not found, you can always sync to update. Redirecting to web…</string>
|
||||||
<string name="unified_search_fragment_permission_needed">Permissions are required to open search result otherwise it will redirected to web…</string>
|
<string name="unified_search_fragment_permission_needed">Permissions are required to open search result otherwise it will redirected to web…</string>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="file_name_validator_error_copy_or_move">Folder path contains reserved names or invalid character</string>
|
||||||
<string name="file_name_validator_error_invalid_character">File name contains invalid characters: %s</string>
|
<string name="file_name_validator_error_invalid_character">File name contains invalid characters: %s</string>
|
||||||
<string name="file_name_validator_error_reserved_names">File name is a reserved name</string>
|
<string name="file_name_validator_error_reserved_names">File name is a reserved name</string>
|
||||||
<string name="file_name_validator_error_ends_with_space_period">File name ends with a space or a period</string>
|
<string name="file_name_validator_error_ends_with_space_period">File name ends with a space or a period</string>
|
||||||
|
|
Loading…
Reference in a new issue