Skip to content

Commit

Permalink
Filename validator (#92)
Browse files Browse the repository at this point in the history
* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* cleanup

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* Make singleton

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

* WIP

Signed-off-by: Milen Pivchev <[email protected]>

---------

Signed-off-by: Milen Pivchev <[email protected]>
Co-authored-by: Milen Pivchev <[email protected]>
Signed-off-by: Milen Pivchev <[email protected]>
# Conflicts:
#	Sources/NextcloudKit/Utils/FileNameValidator.swift
#	Tests/NextcloudKitUnitTests/FileNameValidatorTests.swift
  • Loading branch information
marinofaggiana authored and mpivchev committed Aug 26, 2024
1 parent a2f4cb3 commit 7c17db8
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 8 deletions.
17 changes: 9 additions & 8 deletions Sources/NextcloudKit/Utils/FileNameValidator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,27 @@ public class FileNameValidator {
return instance
}()

public var forbiddenFileNames: [String] = [] {
public private(set) var forbiddenFileNames: [String] = [] {
didSet {
forbiddenFileNames = forbiddenFileNames.map({$0.uppercased()})
}
}
public var forbiddenFileNameBasenames: [String] = [] {

public private(set) var forbiddenFileNameBasenames: [String] = [] {
didSet {
forbiddenFileNameBasenames = forbiddenFileNameBasenames.map({$0.uppercased()})
}
}

private var forbiddenFileNameCharactersRegex: NSRegularExpression?

public var forbiddenFileNameCharacters: [String] = [] {
public private(set) var forbiddenFileNameCharacters: [String] = [] {
didSet {
forbiddenFileNameCharactersRegex = try? NSRegularExpression(pattern: "[\(forbiddenFileNameCharacters.joined())]")
}
}

public var forbiddenFileNameExtensions: [String] = [] {
public private(set) var forbiddenFileNameExtensions: [String] = [] {
didSet {
forbiddenFileNameExtensions = forbiddenFileNameExtensions.map({$0.uppercased()})
}
Expand All @@ -56,19 +57,19 @@ public class FileNameValidator {
public let fileEndsWithSpacePeriodError = NKError(errorCode: NSURLErrorCannotCreateFile, errorDescription: NSLocalizedString("_file_name_validator_error_ends_with_space_period_", value: "File name ends with a space or a period.", comment: ""))

public var fileReservedNameError: NKError {
let errorMessageTemplate = NSLocalizedString("_file_name_validator_error_reserved_name_", value: "%@ is a forbidden name.", comment: "")
let errorMessageTemplate = NSLocalizedString("_file_name_validator_error_reserved_name_", value: "\"%@\" is a forbidden name.", comment: "")
let errorMessage = String(format: errorMessageTemplate, templateString)
return NKError(errorCode: NSURLErrorCannotCreateFile, errorDescription: errorMessage)
}

public var fileForbiddenFileExtensionError: NKError {
let errorMessageTemplate = NSLocalizedString("_file_name_validator_error_forbidden_file_extension_", value: ".%@ is a forbidden file extension.", comment: "")
let errorMessageTemplate = NSLocalizedString("_file_name_validator_error_forbidden_file_extension_", value: ".\"%@\" is a forbidden file extension.", comment: "")
let errorMessage = String(format: errorMessageTemplate, templateString)
return NKError(errorCode: NSURLErrorCannotCreateFile, errorDescription: errorMessage)
}

public var fileInvalidCharacterError: NKError {
let errorMessageTemplate = NSLocalizedString("file_name_validator_error_invalid_character_", value: "Name contains an invalid character: %@.", comment: "")
let errorMessageTemplate = NSLocalizedString("_file_name_validator_error_invalid_character_", value: "Name contains an invalid character: \"%@\".", comment: "")
let errorMessage = String(format: errorMessageTemplate, templateString)
return NKError(errorCode: NSURLErrorCannotCreateFile, errorDescription: errorMessage)
}
Expand All @@ -84,7 +85,7 @@ public class FileNameValidator {
self.forbiddenFileNameExtensions = forbiddenFileNameExtensions
}

public func checkFileName(_ filename: String, existedFileNames: Set<String>? = nil) -> NKError? {
public func checkFileName(_ filename: String) -> NKError? {
if filename.hasSuffix(" ") || filename.hasSuffix(".") {
return fileEndsWithSpacePeriodError
}
Expand Down
111 changes: 111 additions & 0 deletions Tests/NextcloudKitUnitTests/FileNameValidatorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//
// fileNameValidatorTests.swift
//
//
// Created by Milen Pivchev on 12.07.24.
// Copyright © 2024 Milen Pivchev. All rights reserved.
//
// Author: Milen Pivchev <[email protected]>
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

import XCTest
@testable import NextcloudKit

class FileNameValidatorTests: XCTestCase {
let fileNameValidator = FileNameValidator.shared

override func setUp() {
fileNameValidator.setup(
forbiddenFileNames: [".htaccess",".htaccess"],
forbiddenFileNameBasenames: ["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³"],
forbiddenFileNameCharacters: ["<", ">", ":", "\\\\", "/", "|", "?", "*", "&"],
forbiddenFileNameExtensions: [".filepart",".part"]
)
super.setUp()
}

func testInvalidCharacter() {
let result = fileNameValidator.checkFileName("file<name")
XCTAssertEqual(result?.errorDescription, fileNameValidator.fileInvalidCharacterError.errorDescription)
}

func testReservedName() {
let result = fileNameValidator.checkFileName("CON")
XCTAssertEqual(result?.errorDescription, fileNameValidator.fileReservedNameError.errorDescription)
}

func testForbiddenFilenameExtension() {
let result = fileNameValidator.checkFileName("my_fav_file.filepart")
XCTAssertEqual(result?.errorDescription, fileNameValidator.fileForbiddenFileExtensionError.errorDescription)
}

func testEndsWithSpaceOrPeriod() {
let result = fileNameValidator.checkFileName("filename ")
XCTAssertEqual(result?.errorDescription, fileNameValidator.fileEndsWithSpacePeriodError.errorDescription)

let result2 = fileNameValidator.checkFileName("filename.")
XCTAssertEqual(result2?.errorDescription, fileNameValidator.fileEndsWithSpacePeriodError.errorDescription)
}

func testValidFileName() {
let result = fileNameValidator.checkFileName("validFileName")
XCTAssertNil(result?.errorDescription)
}

func testValidFolderAndFilePaths() {
let folderPath = "validFolder"

let result = fileNameValidator.checkFolderPath(folderPath: folderPath)
XCTAssertTrue(result)
}

func testFolderPathWithReservedName() {
let folderPath = "CON"

let result = fileNameValidator.checkFolderPath(folderPath: folderPath)
XCTAssertFalse(result)
}

func testFolderPathWithInvalidCharacter() {
let folderPath = "invalid<Folder"

let result = fileNameValidator.checkFolderPath(folderPath: folderPath)
XCTAssertFalse(result)
}

func testFolderPathEndingWithSpace() {
let folderPath = "folderWithSpace "

let result = fileNameValidator.checkFolderPath(folderPath: folderPath)
XCTAssertFalse(result)
}

func testFolderPathEndingWithPeriod() {
let folderPath = "validFolder."

let result = fileNameValidator.checkFolderPath(folderPath: folderPath)
XCTAssertFalse(result)
}

func testFilePathWithNestedFolder() {
let folderPath = "validFolder/secondValidFolder/CON"

let result = fileNameValidator.checkFolderPath(folderPath: folderPath)
XCTAssertFalse(result)
}
}

0 comments on commit 7c17db8

Please sign in to comment.