-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidators.py
More file actions
130 lines (104 loc) · 3.07 KB
/
Copy pathvalidators.py
File metadata and controls
130 lines (104 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
====================================================
Universal File Converter
File Validation Module
====================================================
"""
from __future__ import annotations
from pathlib import Path
from typing import BinaryIO
from PIL import Image
from pypdf import PdfReader
from config import (
ALLOWED_EXTENSIONS,
MAX_FILE_SIZE_BYTES,
)
class FileValidator:
"""
Handles validation of uploaded files.
"""
@staticmethod
def sanitize_filename(filename: str) -> str:
"""
Return only the safe filename.
"""
return Path(filename).name
@staticmethod
def validate_extension(filename: str) -> bool:
"""
Check whether the file extension is supported.
"""
extension = Path(filename).suffix.lower()
return extension in ALLOWED_EXTENSIONS
@staticmethod
def validate_size(file: BinaryIO) -> bool:
"""
Validate uploaded file size.
"""
current_position = file.tell()
file.seek(0, 2)
size = file.tell()
file.seek(current_position)
return size <= MAX_FILE_SIZE_BYTES
@staticmethod
def validate_image(file: BinaryIO) -> bool:
"""
Validate image integrity.
"""
try:
file.seek(0)
img = Image.open(file)
img.verify()
file.seek(0)
return True
except Exception:
file.seek(0)
return False
@staticmethod
def validate_pdf(file: BinaryIO) -> bool:
"""
Validate PDF integrity.
"""
try:
file.seek(0)
PdfReader(file)
file.seek(0)
return True
except Exception:
file.seek(0)
return False
@staticmethod
def validate_text(file: BinaryIO) -> bool:
"""
Validate text file.
"""
try:
file.seek(0)
file.read().decode("utf-8")
file.seek(0)
return True
except Exception:
file.seek(0)
return False
@staticmethod
def validate(file: BinaryIO, filename: str) -> tuple[bool, str]:
"""
Perform complete validation.
Returns:
(success, message)
"""
if not FileValidator.validate_extension(filename):
return False, "Unsupported file format."
if not FileValidator.validate_size(file):
return False, "File exceeds the maximum allowed size."
extension = Path(filename).suffix.lower()
if extension in (".jpg", ".jpeg", ".png", ".webp", ".bmp", ".tiff"):
if not FileValidator.validate_image(file):
return False, "Corrupted image file."
elif extension == ".pdf":
if not FileValidator.validate_pdf(file):
return False, "Corrupted PDF file."
elif extension == ".txt":
if not FileValidator.validate_text(file):
return False, "Invalid text file."
return True, "Validation successful."