python-multipart 0.0.21__tar.gz → 0.0.22__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_multipart-0.0.21 → python_multipart-0.0.22}/CHANGELOG.md +4 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/PKG-INFO +1 -1
- {python_multipart-0.0.21 → python_multipart-0.0.22}/python_multipart/__init__.py +1 -1
- {python_multipart-0.0.21 → python_multipart-0.0.22}/python_multipart/multipart.py +3 -1
- python_multipart-0.0.22/tests/test_file.py +26 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/.gitignore +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/LICENSE.txt +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/README.md +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/multipart/__init__.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/multipart/decoders.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/multipart/exceptions.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/multipart/multipart.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/pyproject.toml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/python_multipart/decoders.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/python_multipart/exceptions.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/python_multipart/py.typed +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/__init__.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/compat.py +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CRLF_in_header.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CRLF_in_header.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CR_in_header.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CR_in_header.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CR_in_header_value.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CR_in_header_value.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary_without_CR.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary_without_CR.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary_without_LF.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary_without_LF.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary_without_final_hyphen.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary_without_final_hyphen.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_end_of_headers.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_end_of_headers.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_header_char.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_header_char.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_initial_boundary.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_initial_boundary.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/base64_encoding.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/base64_encoding.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/empty_header.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/empty_header.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/empty_message.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/empty_message.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/empty_message_with_bad_end.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/empty_message_with_bad_end.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/header_with_number.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/header_with_number.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/mixed_plain_and_base64_encoding.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/mixed_plain_and_base64_encoding.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_fields.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_fields.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_files.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_files.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/quoted_printable_encoding.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/quoted_printable_encoding.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_blocks.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_blocks.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_longer.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_longer.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_single_file.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_single_file.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_with_leading_newlines.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_with_leading_newlines.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_file.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_file.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/utf8_filename.http +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/utf8_filename.yaml +0 -0
- {python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_multipart.py +0 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.0.22 (2026-01-25)
|
|
4
|
+
|
|
5
|
+
* Drop directory path from filename in `File` [9433f4b](https://github.com/Kludex/python-multipart/commit/9433f4bbc9652bdde82bbe380984e32f8cfc89c4).
|
|
6
|
+
|
|
3
7
|
## 0.0.21 (2025-12-17)
|
|
4
8
|
|
|
5
9
|
* Add support for Python 3.14 and drop EOL 3.8 and 3.9 [#216](https://github.com/Kludex/python-multipart/pull/216).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-multipart
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.22
|
|
4
4
|
Summary: A streaming multipart parser for Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/Kludex/python-multipart
|
|
6
6
|
Project-URL: Documentation, https://kludex.github.io/python-multipart/
|
|
@@ -375,7 +375,9 @@ class File:
|
|
|
375
375
|
|
|
376
376
|
# Split the extension from the filename.
|
|
377
377
|
if file_name is not None:
|
|
378
|
-
|
|
378
|
+
# Extract just the basename to avoid directory traversal
|
|
379
|
+
basename = os.path.basename(file_name)
|
|
380
|
+
base, ext = os.path.splitext(basename)
|
|
379
381
|
self._file_base = base
|
|
380
382
|
self._ext = ext
|
|
381
383
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from python_multipart.multipart import File
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_upload_dir_with_leading_slash_in_filename(tmp_path: Path) -> None:
|
|
7
|
+
upload_dir = tmp_path / "upload"
|
|
8
|
+
upload_dir.mkdir()
|
|
9
|
+
|
|
10
|
+
# When the file_name provided has a leading slash, we should only use the basename.
|
|
11
|
+
# This is to avoid directory traversal.
|
|
12
|
+
to_upload = tmp_path / "foo.txt"
|
|
13
|
+
|
|
14
|
+
file = File(
|
|
15
|
+
bytes(to_upload),
|
|
16
|
+
config={
|
|
17
|
+
"UPLOAD_DIR": bytes(upload_dir),
|
|
18
|
+
"UPLOAD_KEEP_FILENAME": True,
|
|
19
|
+
"UPLOAD_KEEP_EXTENSIONS": True,
|
|
20
|
+
"MAX_MEMORY_FILE_SIZE": 10,
|
|
21
|
+
},
|
|
22
|
+
)
|
|
23
|
+
file.write(b"123456789012")
|
|
24
|
+
assert not file.in_memory
|
|
25
|
+
assert Path(upload_dir / "foo.txt").exists()
|
|
26
|
+
assert Path(upload_dir / "foo.txt").read_bytes() == b"123456789012"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CRLF_in_header.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CRLF_in_header.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CR_in_header_value.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/CR_in_header_value.yaml
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/almost_match_boundary.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_end_of_headers.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_end_of_headers.yaml
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_header_char.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_header_char.yaml
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_initial_boundary.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/bad_initial_boundary.yaml
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/base64_encoding.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/base64_encoding.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/header_with_number.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/header_with_number.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_fields.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_fields.yaml
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_files.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/multiple_files.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_blocks.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_blocks.yaml
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_longer.http
RENAMED
|
File without changes
|
{python_multipart-0.0.21 → python_multipart-0.0.22}/tests/test_data/http/single_field_longer.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|