Skip to content

Commit

Permalink
Adding file validator
Browse files Browse the repository at this point in the history
  • Loading branch information
SeqLaz committed Oct 19, 2024
1 parent 7901b65 commit b9a8243
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
23 changes: 19 additions & 4 deletions libqfieldsync/project_checker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import re
import sys
from enum import Enum
from pathlib import Path
Expand All @@ -9,7 +8,7 @@

from libqfieldsync.layer import LayerSource, SyncAction, UnsupportedPrimaryKeyError
from libqfieldsync.project import ProjectConfiguration, ProjectProperties
from libqfieldsync.utils.file_utils import isascii
from libqfieldsync.utils.file_utils import isascii, is_valid_filepath

from .offline_converter import ExportType

Expand Down Expand Up @@ -236,7 +235,6 @@ def check_basemap_configuration(self) -> Optional[FeedbackResult]:

def check_files_have_unsupported_characters(self) -> Optional[FeedbackResult]:
problematic_paths = []
regexp = re.compile(r'[<>:"\\|?*]')
home_path = Path(self.project.fileName()).parent
try:
for path in home_path.rglob("*"):
Expand All @@ -245,8 +243,9 @@ def check_files_have_unsupported_characters(self) -> Optional[FeedbackResult]:
if str(relative_path).startswith(".qfieldsync"):
continue

if regexp.search(str(relative_path.as_posix())) is not None:
if not is_valid_filepath(str(relative_path.as_posix())):
problematic_paths.append(relative_path)

except FileNotFoundError:
# long paths on windows will raise a FileNotFoundError in rglob, so we have to handle
# that gracefully
Expand All @@ -257,8 +256,10 @@ def check_files_have_unsupported_characters(self) -> Optional[FeedbackResult]:
self.tr(
'Forbidden characters in filesystem path(s) "{}". '
'Please make sure there are no files and directories with "<", ">", ":", "/", "\\", "|", "?", "*" or double quotes (") characters in their path.'
"and must not be reserved names like CON, PRN, AUX, NUL, etc."
).format(", ".join([f'"{path}"' for path in problematic_paths]))
)

else:
return None

Expand Down Expand Up @@ -309,6 +310,20 @@ def check_layer_has_ascii_filename(
else:
return None

# def check_layer_has_invalid_filename(
# self, layer_source: LayerSource
# ) -> Optional[FeedbackResult]:
# if layer_source.is_file and not is_valid_filename(layer_source.filename):
# return FeedbackResult(
# self.tr(
# 'The layer "{}" has an invalid filename or path and was therefore removed from the cloud project.'
# 'Please make sure there are no files and directories their path.'
# "It is highly recommended to rename them to ASCII encoded paths. "
# ).format(layer_source.filename),
# )
# else:
# return None

def check_layer_primary_key(
self, layer_source: LayerSource
) -> Optional[FeedbackResult]:
Expand Down
22 changes: 22 additions & 0 deletions libqfieldsync/utils/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,25 @@ def isascii(filename: str) -> bool:
return True
except UnicodeEncodeError:
return False

def is_valid_filename(filename: str) -> bool:
"""
Check if the filename is valid.
"""
pattern = re.compile(
r'^(?!.*[<>:"/\\|?*])'
r"(?!(?:COM[0-9]|CON|LPT[0-9]|NUL|PRN|AUX|com[0-9]|con|lpt[0-9]|nul|prn|aux)$)"
r'[^\\\/:*"?<>|]{1,254}'
r"(?<![\s\.])$"
)
return bool(pattern.match(filename))

def is_valid_filepath(path: str) -> bool:
"""
Check if the entire path is valid by validating each part of the path.
"""
path_obj = Path(path)
for part in path_obj.parts:
if not is_valid_filename(part):
return False
return True

0 comments on commit b9a8243

Please sign in to comment.