This commit is contained in:
+23
-13
@@ -223,24 +223,34 @@ class Handler(BaseHTTPRequestHandler):
|
||||
raw = self.rfile.read(length)
|
||||
ctype = self.headers.get("Content-Type", "")
|
||||
|
||||
# Простой multipart приём (как в upload.py)
|
||||
import cgi, io as io_mod
|
||||
# Простой multipart приём
|
||||
import cgi, re, io as io_mod
|
||||
_, params = cgi.parse_header(ctype)
|
||||
fs = cgi.FieldStorage(
|
||||
fp=io_mod.BytesIO(raw),
|
||||
environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': ctype},
|
||||
keep_blank_values=True
|
||||
)
|
||||
items = fs.getlist("files") if hasattr(fs, 'getlist') else ([fs["files"]] if "files" in fs else [])
|
||||
boundary = params.get("boundary", "")
|
||||
if not boundary:
|
||||
self._json({"ok": False, "error": "No boundary"}, 400)
|
||||
return
|
||||
# Ручной разбор multipart (надёжнее чем cgi.FieldStorage)
|
||||
parts = raw.split(b"--" + boundary.encode())
|
||||
files = []
|
||||
for item in items:
|
||||
if not getattr(item, 'filename', None):
|
||||
for part in parts:
|
||||
if b"Content-Disposition" not in part:
|
||||
continue
|
||||
name = os.path.basename(item.filename)
|
||||
try:
|
||||
hdr_end = part.index(b"\r\n\r\n")
|
||||
except ValueError:
|
||||
continue
|
||||
hdrs = part[:hdr_end].decode("latin-1", errors="replace")
|
||||
body = part[hdr_end + 4:]
|
||||
if body.endswith(b"\r\n"):
|
||||
body = body[:-2]
|
||||
m = re.search(r'filename="([^"]*)"', hdrs)
|
||||
if not m:
|
||||
continue
|
||||
name = os.path.basename(m.group(1))
|
||||
if not name or ".." in name or "/" in name or "\\" in name:
|
||||
continue
|
||||
data = item.file.read()
|
||||
files.append((name, data, ""))
|
||||
files.append((name, body, ""))
|
||||
|
||||
if not files:
|
||||
self._json({"ok": False, "error": "Нет файлов"}, 400)
|
||||
|
||||
Reference in New Issue
Block a user