Files
Athena-Deck/image_upload.py
T

35 lines
2.0 KiB
Python

"""Bounded multipart reader for image edit requests."""
import base64
from email import policy
from email.parser import BytesParser
MAX_IMAGE=10*1024*1024
MAX_BODY=4*MAX_IMAGE+65536
def read_image_upload(handler,profile_field='model'):
handler.connection.settimeout(45)
if handler.headers.get('Transfer-Encoding'):raise ValueError('Chunked Upload wird nicht unterstützt.')
try:length=int(handler.headers.get('Content-Length','0'))
except ValueError:raise ValueError('Ungültige Upload-Länge.') from None
content_type=handler.headers.get('Content-Type','')
if not 0<length<=MAX_BODY or not content_type.lower().startswith('multipart/form-data;'):raise ValueError('Multipart-Upload mit höchstens vier Bildern zu je 10 MiB erforderlich.')
raw=handler.rfile.read(length)
if len(raw)!=length:raise ValueError('Upload unvollständig.')
message=BytesParser(policy=policy.default).parsebytes(b'Content-Type: '+content_type.encode()+b'\r\nMIME-Version: 1.0\r\n\r\n'+raw)
if not message.is_multipart() or message.defects:raise ValueError('Ungültiger Multipart-Upload.')
fields={};images=[]
for part in message.iter_parts():
name=part.get_param('name',header='content-disposition');data=part.get_payload(decode=True)
if not isinstance(data,bytes):raise ValueError('Ungültiges Upload-Feld.')
if name in ('image','image[]'):
if len(images)>=4 or not 0<len(data)<=MAX_IMAGE:raise ValueError('Höchstens vier Referenzbilder bis je 10 MiB erlaubt.')
mime=part.get_content_type().lower()
if mime not in ('image/png','image/jpeg','image/webp'):raise ValueError('Nur PNG, JPEG oder WebP erlaubt.')
images.append('data:'+mime+';base64,'+base64.b64encode(data).decode('ascii'))
else:
if name not in (profile_field,'prompt','size','n','response_format') or name in fields or len(data)>4096:raise ValueError('Ungültiges oder doppeltes Formularfeld.')
try:fields[name]=data.decode('utf-8')
except UnicodeError:raise ValueError('Ungültiges Textfeld.') from None
if profile_field not in fields:raise ValueError('Bildprofil fehlt.')
return fields,images