Skip to content

Commit aa3364a

Browse files
committed
#553 - File type validation on upload through web browser
1 parent d277098 commit aa3364a

File tree

2 files changed

+17
-13
lines changed

2 files changed

+17
-13
lines changed

atr/detection.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,32 +65,32 @@ def validate_directory(directory: pathlib.Path) -> list[str]:
6565
errors.append(f"{path.name}: Symbolic links are not allowed")
6666
continue
6767
if path.is_file():
68-
if error := _validate_file(path):
68+
if error := validate_file(path):
6969
errors.append(error)
7070
return errors
7171

7272

73-
def _suffix(filename: str) -> str:
74-
name = filename.lower()
75-
for compound in _COMPOUND_SUFFIXES:
76-
if name.endswith(compound):
77-
return compound
78-
return pathlib.Path(name).suffix
79-
80-
81-
def _validate_file(path: pathlib.Path) -> str | None:
73+
def validate_file(path: pathlib.Path) -> str | None:
8274
# TODO: Report errors using the whole relative path, not just the filename
8375
suffix = _suffix(path.name)
8476
if suffix not in _EXPECTED:
85-
return None
77+
return f"{path.name}: Unsupported file format ({suffix})"
8678
if path.stat().st_size == 0:
8779
return f"{path.name}: Empty file"
8880
try:
8981
results = puremagic.magic_file(path)
9082
except puremagic.PureError:
9183
return f"{path.name}: Unidentified file format (expected {suffix})"
92-
detected_types = {r.mime_type for r in results}
84+
detected_types = {r.mime_type for r in results if r.mime_type != ""}
9385
if not (detected_types & _EXPECTED[suffix]):
94-
primary = results[0].mime_type if results else "unknown"
86+
primary = next(iter(detected_types)) if len(detected_types) > 0 else "unknown"
9587
return f"{path.name}: Content mismatch (expected {suffix}, detected {primary})"
9688
return None
89+
90+
91+
def _suffix(filename: str) -> str:
92+
name = filename.lower()
93+
for compound in _COMPOUND_SUFFIXES:
94+
if name.endswith(compound):
95+
return compound
96+
return pathlib.Path(name).suffix

atr/post/upload.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import atr.blueprints.post as post
3030
import atr.db as db
31+
import atr.detection as detection
3132
import atr.form as form
3233
import atr.get as get
3334
import atr.log as log
@@ -136,6 +137,9 @@ async def stage(
136137
# 1 MiB chunks
137138
while chunk := await asyncio.to_thread(file.stream.read, 1024 * 1024):
138139
await f.write(chunk)
140+
content_error = detection.validate_file(path=target_path)
141+
if content_error:
142+
raise ValueError(content_error)
139143
except Exception as e:
140144
log.exception("Error staging file:")
141145
if await aiofiles.os.path.exists(target_path):

0 commit comments

Comments
 (0)