Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mulipart fixes #53

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions sippy/MultipartMixBody.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
class MultipartMixBody():
parts = None
boundary = None

def __init__(self, body = None, ctype = None):
if body is None:
return
Expand All @@ -39,11 +39,22 @@ def __init__(self, body = None, ctype = None):
assert bparts[-1].strip() == '--'
parts = [p.lstrip() for p in bparts[1:-1]]
self.parts = []
self.part_headers = []
for sect in parts:
ct, sect = sect.split('\r\n', 1)
ct = SipHeader(ct).getBody()
headers = []
ct = None
headersect, sect = sect.split('\r\n\r\n', 1)
# parse sub headers
for hl in headersect.split('\r\n'):
h = SipHeader(hl)
if h.name == "content-type":
ct = h.getBody()
else:
headers.append(h)
# add part
sect = MsgBody(sect, ct)
self.parts.append(sect)
self.part_headers.append(headers)
self.boundary = ctype.params["boundary"]

def __str__(self):
Expand Down
45 changes: 45 additions & 0 deletions tests/test_Multipart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import unittest
from sippy.MsgBody import MsgBody
from sippy.MultipartMixBody import MultipartMixBody
from sippy.SipContentType import SipContentType

# body from RFC 8147 https://datatracker.ietf.org/doc/html/rfc8147
ecall_body1 = (
"--boundaryZZZ\r\n"
"Content-Disposition: by-reference\r\n"
"Content-Type: application/EmergencyCallData.Control+xml\r\n"
"Content-ID: <[email protected]>\r\n"
"\r\n"
'<?xml version="1.0" encoding="UTF-8"?>\r\n'
'<EmergencyCallData.Control xmlns="urn:ietf:params:xml:ns:EmergencyCallData:control">\r\n'
'<request action="send-data" datatype="eCall.MSD"/>\r\n'
"</EmergencyCallData.Control>\r\n"
"--boundaryZZZ--\r\n"
)
ecall_part0 = (
'<?xml version="1.0" encoding="UTF-8"?>\r\n'
'<EmergencyCallData.Control xmlns="urn:ietf:params:xml:ns:EmergencyCallData:control">\r\n'
'<request action="send-data" datatype="eCall.MSD"/>\r\n'
"</EmergencyCallData.Control>\r\n"
)


class TestMultipart(unittest.TestCase):
def test_multipart_unsorted_headers(self):
ct = SipContentType("multipart/mixed;boundary=boundaryZZZ")
ct.parse()
got = MsgBody(ecall_body1, mtype=ct)
got.parse()
mp = got.content
self.assertEqual(MultipartMixBody, type(mp))
self.assertEqual(1, len(mp.parts))
p0 = mp.parts[0]
self.assertEqual(MsgBody, type(p0))
#print(p0.mtype)
self.assertEqual(
"application/EmergencyCallData.Control+xml", p0.mtype.localStr())
h0 = mp.part_headers[0]
self.assertEqual("content-disposition", h0[0].name)
self.assertEqual("content-id", h0[1].name)
# check that part body is without headers
self.assertEqual(ecall_part0, p0.content)