python-hserver/hserver/mime.py

112 lines
2.6 KiB
Python

import io
import traceback
from hserver.mimeheaders import MIMEHeaders
class MIMEException(Exception):
pass
class ContentSizeLimitException(MIMEException):
pass
class MIME:
def __init__(self,fp=None,source=None,limit=10485760,defaultlength=-1,parent=None):
if (not fp is None):
self.__fp = fp
elif (not source is None):
self.__fp = io.BytesIO(source)
self.__parent = parent
self.__limit = limit
self.__defaultlength = defaultlength
self.__body = None
self.__headers = None
self.__multipart = False
self.__parts = []
self.__parse()
def __getitem__(self,name):
if self.__multipart:
for p in self.__parts:
if not p.name() is None:
return p.name()
raise KeyError()
def __contains__(self, name):
return name in self.__headers
def headers(self):
return self.__headers
def multipart(self):
return self.__multipart
def parts(self):
return self.__parts
def name(self):
pp = self.__headers.parameters("CONTENT-DISPOSITION")
if (not pp is None) and ("name" in pp.keys()):
return pp["name"]
return None
def body(self):
return self.__body
def __parse(self):
self.__headers = MIMEHeaders( fp=self.__fp )
l = int(self.__headers.value("CONTENT-LENGTH",self.__defaultlength))
if (l > self.__limit):
raise ContentSizeLimitException(size=l,limit=self.__limit)
self.__body = self.__fp.read(l)
if (not "filename" in self.__headers.parameters("CONTENT-DISPOSITION")) and (self.__headers.value("CONTENT-TYPE").upper() == "TEXT/PLAIN"):
if ("charset" in self.__headers.parameters("CONTENT-TYPE")):
charset = self.__headers.parameters("CONTENT-TYPE")["charset"]
else:
# charset = "us-ascii"
charset = "utf-8"
self.__body = str(self.__body,charset)
type = self.__headers.value("CONTENT-TYPE","/").split("/")[0].upper()
if (type == "MULTIPART"):
try:
self.__parsemultipart()
except Exception as ex:
traceback.print_exception(type(ex),ex,ex.__traceback__)
def __parsemultipart(self):
"""
p = start of preceeding boundary
c = end of preceeding boundary
e = start of following boundary
"""
self.__multipart = True
boundary = b'--' + bytes(self.__headers.get("CONTENT-TYPE").parameters()["boundary"],"iso-8859-1")
p = self.__body.find(boundary)
c = p + len(boundary) + 2
boundary = b'\r\n' + boundary
while (True):
e = self.__body.find(boundary,c)
if (e < 0):
return
else:
self.__parts.append(MIME(source=self.__body[c : e],parent=self))
p = e
c = p + len(boundary) + 2
if (self.__body[c - 2 : c] == b"--"):
return