(filename: Optional[str])
| 159 | _walk(doc) |
| 160 | |
| 161 | def _parse_upload_filename(filename: Optional[str]) -> tuple[str, str]: |
| 162 | if not filename: |
| 163 | raise ValueError("Upload filename is missing.") |
| 164 | filename = _normalize_relative_path(filename) |
| 165 | if "/" not in filename: |
| 166 | raise ValueError(f"Invalid upload filename: {filename!r}") |
| 167 | app_name, rel_path = filename.split("/", 1) |
| 168 | if not app_name or not rel_path: |
| 169 | raise ValueError(f"Invalid upload filename: {filename!r}") |
| 170 | if rel_path.startswith("/"): |
| 171 | raise ValueError(f"Absolute upload path rejected: {filename!r}") |
| 172 | if _has_parent_reference(rel_path): |
| 173 | raise ValueError(f"Path traversal rejected: {filename!r}") |
| 174 | ext = os.path.splitext(rel_path)[1].lower() |
| 175 | if ext not in _ALLOWED_EXTENSIONS: |
| 176 | raise ValueError( |
| 177 | f"File type not allowed: {rel_path!r}" |
| 178 | f" (allowed: {', '.join(sorted(_ALLOWED_EXTENSIONS))})" |
| 179 | ) |
| 180 | return app_name, rel_path |
| 181 | |
| 182 | def _parse_file_path(file_path: str) -> str: |
| 183 | file_path = _normalize_relative_path(file_path) |
no test coverage detected