Exemplo n.º 1
0
    def decode_message_body(self, data_iter):
        """
        Decodes the MMS message body

        :param data_iter: an iterator over the sequence of bytes of the MMS
                          body
        :type data_iter: iter
        """
        ######### MMS body: headers ###########
        # Get the number of data parts in the MMS body
        try:
            num_entries = self.decode_uint_var(data_iter)
        except StopIteration:
            return

        #print 'Number of data entries (parts) in MMS body:', num_entries

        ########## MMS body: entries ##########
        # For every data "part", we have to read the following sequence:
        # <length of content-type + other possible headers>,
        # <length of data>,
        # <content-type + other possible headers>,
        # <data>
        for part_num in xrange(num_entries):
            #print '\nPart %d:\n------' % part_num
            headers_len = self.decode_uint_var(data_iter)
            data_len = self.decode_uint_var(data_iter)

            # Prepare to read content-type + other possible headers
            ct_field_bytes = []
            for i in xrange(headers_len):
                ct_field_bytes.append(data_iter.next())

            ct_iter = PreviewIterator(ct_field_bytes)
            # Get content type
            ctype, ct_parameters = self.decode_content_type_value(ct_iter)
            headers = {'Content-Type': (ctype, ct_parameters)}

            # Now read other possible headers until <headers_len> bytes
            # have been read
            while True:
                try:
                    hdr, value = self.decode_header(ct_iter)
                    headers[hdr] = value
                except StopIteration:
                    break

            # Data (note: this is not null-terminated)
            data = array.array('B')
            for i in xrange(data_len):
                data.append(data_iter.next())

            part = message.DataPart()
            part.set_data(data, ctype)
            part.content_type_parameters = ct_parameters
            part.headers = headers
            self._mms_message.add_data_part(part)
Exemplo n.º 2
0
    def encode_message_body(self):
        """
        Binary-encodes the MMS body data

        The MMS body's header should not be confused with the actual
        MMS header, as returned by :func:`encode_header`.

        The encoding used for the MMS body is specified in [5],
        section 8.5. It is only referenced in [4], however [2]
        provides a good example of how this ties in with the MMS
        header encoding.

        The MMS body is of type `application/vnd.wap.multipart` ``mixed``
        or ``related``. As such, its structure is divided into a header, and
        the data entries/parts::

            [ header ][ entries ]
            ^^^^^^^^^^^^^^^^^^^^^
                  MMS Body

        The MMS Body header consists of one entry[5]::

            name             type           purpose
            -------          -------        -----------
            num_entries      uint_var        num of entries in the multipart entity

        The MMS body's multipart entries structure::

            name             type                   purpose
            -------          -----                  -----------
            HeadersLen       uint_var                length of the ContentType and
                                                    Headers fields combined
            DataLen          uint_var                length of the Data field
            ContentType      Multiple octets        the content type of the data
            Headers          (<HeadersLen>
                              - length of
                             <ContentType>) octets  the part's headers
            Data             <DataLen> octets       the part's data

        :return: The binary-encoded MMS PDU body, as an array of bytes
        :rtype: array.array('B')
        """
        message_body = array.array('B')

        #TODO: enable encoding of MMSs without SMIL file
        ########## MMS body: header ##########
        # Parts: SMIL file + <number of data elements in each slide>
        num_entries = 1
        for page in self._mms_message._pages:
            num_entries += page.number_of_parts()

        for data_part in self._mms_message._data_parts:
            num_entries += 1

        message_body.extend(self.encode_uint_var(num_entries))

        ########## MMS body: entries ##########
        # For every data "part", we have to add the following sequence:
        # <length of content-type + other possible headers>,
        # <length of data>,
        # <content-type + other possible headers>,
        # <data>.

        # Gather the data parts, adding the MMS message's SMIL file
        smil_part = message.DataPart()
        smil = self._mms_message.smil()
        smil_part.set_data(smil, 'application/smil')
        #TODO: make this dynamic....
        smil_part.headers['Content-ID'] = '<0000>'
        parts = [smil_part]
        for slide in self._mms_message._pages:
            for part_tuple in (slide.image, slide.audio, slide.text):
                if part_tuple is not None:
                    parts.append(part_tuple[0])

        for part in parts:
            name, val_type = part.headers['Content-Type']
            part_content_type = self.encode_content_type_value(name, val_type)

            encoded_part_headers = []
            for hdr in part.headers:
                if hdr == 'Content-Type':
                    continue
                encoded_part_headers.extend(
                        wsp_pdu.Encoder.encode_header(hdr, part.headers[hdr]))

            # HeadersLen entry (length of the ContentType and
            #  Headers fields combined)
            headers_len = len(part_content_type) + len(encoded_part_headers)
            message_body.extend(self.encode_uint_var(headers_len))
            # DataLen entry (length of the Data field)
            message_body.extend(self.encode_uint_var(len(part)))
            # ContentType entry
            message_body.extend(part_content_type)
            # Headers
            message_body.extend(encoded_part_headers)
            # Data (note: we do not null-terminate this)
            for char in part.data:
                message_body.append(ord(char))

        return message_body