Rob Mason - 2009-09-22

Hi,
Don't know if the project is still active but I was using it recently and added handling of some additional message types. Patch set is included below.

<pre><code>diff -upr python-mms-0.2-rm/examples/encode.py python-mms-0.2/examples/encode.py
-- python-mms-0.2-rm/examples/encode.py 2009-09-22 17:45:40.000000000 +0100
+++ python-mms-0.2/examples/encode.py 2007-06-11 23:16:08.000000000 +0100
@@ -31,11 +31,6 @@ if __name__ == '__main__':    
     # …then create the message and add the pages…
     message = mms.MMSMessage()
     message.headers = 'Test MMS'
-    message.headers = 'application/vnd.wap.multipart.related'
-    message.headers = 'm-send-req'
-    message.headers = 'insert_sender/TYPE=PLMN'
-    message.headers = 'insert_recip/TYPE=PLMN'
-   
     message.addPage(slide1)
     message.addPage(slide2)
     message.addPage(slide3)
Only in python-mms-0.2-rm/examples: mine.mms
Only in python-mms-0.2-rm/examples: rmencoder.py
Only in python-mms-0.2-rm/examples: sample.mms
diff -upr python-mms-0.2-rm/mms/message.py python-mms-0.2/mms/message.py
-- python-mms-0.2-rm/mms/message.py 2009-09-22 17:45:40.000000000 +0100
+++ python-mms-0.2/mms/message.py 2007-07-13 10:17:25.000000000 +0100
@@ -23,11 +23,10 @@ class MMSMessage:
         self._pages =
         self._dataParts =
         self._metaTags = {}
-        self.headers = {}
-        #{'Message-Type' : 'm-send-req',
-        #                'Transaction-Id' : '1234',
-        #                'MMS-Version' : '1.0',
-        #                'Content-Type' : ('application/vnd.wap.multipart.mixed'        #, {})}
+        self.headers = {'Message-Type' : 'm-send-req',
+                        'Transaction-Id' : '1234',
+                        'MMS-Version' : '1.0',
+                        'Content-Type' : ('application/vnd.wap.multipart.mixed', {})}
         self.width = 176
         self.height = 220
         self.transactionID = '12345'
@@ -124,7 +123,7 @@ class MMSMessage:
         # Add pages to body
         for page in self._pages:
             parNode = smilDoc.createElement('par')
-            parNode.setAttribute('dur', str(page.duration)+'ms')
+            parNode.setAttribute('duration', str(page.duration))
             # Add the page content information
             if page.image != None:
                 #TODO: catch unpack exception
diff -upr python-mms-0.2-rm/mms/mms_pdu.py python-mms-0.2/mms/mms_pdu.py
-- python-mms-0.2-rm/mms/mms_pdu.py 2009-09-22 17:45:40.000000000 +0100
+++ python-mms-0.2/mms/mms_pdu.py 2007-07-21 16:57:50.000000000 +0100
@@ -82,8 +82,7 @@ class MMSDecoder(wsp_pdu.Decoder):
         self._mmsMessage = message.MMSMessage()
         self._mmsData = data
         bodyIter = self.decodeMessageHeader()
-        if bodyIter:
-            self.decodeMessageBody(bodyIter)
+        self.decodeMessageBody(bodyIter)
         return self._mmsMessage
    
     def decodeMessageHeader(self):
@@ -108,40 +107,22 @@ class MMSDecoder(wsp_pdu.Decoder):
         # The next few headers will not be in a specific order, except for
         # "Content-Type", which should be the last header
         # According to , MMS header field names will be short integers
-        lastHeaderFound = False
-        header, value = self.decodeHeader(dataIter)
-        self._mmsMessage.headers = value
-               
-        message_type = value
-        print "processing: %s" % message_type
-       
-        if message_type == 'm-send-conf':
-            last_header = MMSEncodingAssignments.fieldNames
-        elif message_type == 'm-notification-ind':
-            last_header = MMSEncodingAssignments.fieldNames
-        else:
-            last_header= MMSEncodingAssignments.fieldNames
-        while lastHeaderFound == False:
+        contentTypeFound = False
+        while contentTypeFound == False:
             header, value = self.decodeHeader(dataIter)
-            #print "%s: %s" %(header,value)
-            if header == last_header: #MMSEncodingAssignments.fieldNames:
-                lastHeaderFound = True
-               
+            if header == MMSEncodingAssignments.fieldNames:
+                contentTypeFound = True
             else:
                 self._mmsMessage.headers = value
                 #print '%s: %s' % (header, str(value))
-        if message_type in :
-            self._mmsMessage.headers = value
-            dataIter = None
-        else:
-            cType = value
-            #print '%s: %s' % (header, cType)
-            params = value
-            #for parameter in params:
-            #    cType += ' ; %s' %parameter
-            #    if len(params) > 0:
-            #        cType +='=%s' % params
-            self._mmsMessage.headers = (cType , params)
+       
+        cType = value
+        #print '%s: %s' % (header, cType)
+        params = value
+        #for parameter in params:
+        #    print '    %s: %s' % (parameter, str(params))

  • +        self._mmsMessage.headers = (cType, params)
             return dataIter
        
                
    @@ -156,7 +137,7 @@ class MMSDecoder(wsp_pdu.Decoder):
             # Get the number of data parts in the MMS body
             nEntries = self.decodeUintvar(dataIter)
             #print 'Number of data entries (parts) in MMS body:', nEntries
    -           
    +       
             ########## MMS body: entries ##########
             # For every data "part", we have to read the following sequence:
             # <length of content-type + other possible headers>,
    @@ -167,10 +148,10 @@ class MMSDecoder(wsp_pdu.Decoder):
                 #print '\nPart %d:\n----' % partNum
                 headersLen = self.decodeUintvar(dataIter)
                 dataLen = self.decodeUintvar(dataIter)
    +           
                 # Prepare to read content-type + other possible headers
                 ctFieldBytes =
                 for i in range(headersLen):
    -                #print "ctFieldBytes now: %s" % ctFieldBytes
                     ctFieldBytes.append(dataIter.next())
    #            ctIter = iter(ctFieldBytes)
                 ctIter = PreviewIterator(ctFieldBytes)
    @@ -201,6 +182,7 @@ class MMSDecoder(wsp_pdu.Decoder):
                 part.contentTypeParameters = ctParameters
                 part.headers = headers
                 self._mmsMessage.addDataPart(part)
    +           
                 #extension = 'dump'
                 #if contentType == 'image/jpeg':
                 #    extension = 'jpg'
    @@ -577,13 +559,9 @@ class MMSEncoder(wsp_pdu.Encoder):
             @return: The binary-encoded MMS data, as a sequence of bytes
             @rtype: array.array('B')
             """
    -        doEncodeBody = False
             self._mmsMessage = mmsMessage
    -        if  ('m-send-req' or 'm-retrieve-conf')  in mmsMessage.headers.values():
    -            doEncodeBody = True
             msgData = self.encodeMessageHeader()
    -        if  doEncodeBody:
    -            msgData.extend(self.encodeMessageBody())
    +        msgData.extend(self.encodeMessageBody())
             return msgData
        
         def encodeMessageHeader(self):
    @@ -601,7 +579,7 @@ class MMSEncoder(wsp_pdu.Encoder):
                          'Insert-address-token'  : 0x81}
                
             contentTypes = {'application/vnd.wap.multipart.related' : 0xb3}
    -        addCtype = False
    +       
             # Create an array of 8-bit values
             messageHeader = array.array('B')
        
    @@ -622,6 +600,7 @@ class MMSEncoder(wsp_pdu.Encoder):
             # - X-Mms-Message-Type
             # - X-Mms-Transaction-ID
             # - X-Mms-Version
    +       
             ### Start of Message-Type verification
             if 'Message-Type' not in headersToEncode:
                 # Default to 'm-retrieve-conf'; we don't need a To/CC field for this
    @@ -652,15 +631,12 @@ class MMSEncoder(wsp_pdu.Encoder):
             ### Start of MMS-Version verification
             if 'MMS-Version' not in headersToEncode:
                 headersToEncode = '1.0'
  • -        if  headersToEncode in :
    -            addCtype = True
            
             # Encode the first three headers, in correct order
             for hdr in ('Message-Type', 'Transaction-Id', 'MMS-Version'):
                 messageHeader.extend(MMSEncoder.encodeHeader(hdr, headersToEncode))
                 del headersToEncode
    -           
    +   
             # Encode all remaining MMS message headers, except "Content-Type"
             # - this needs to be added last, according  and
             for hdr in headersToEncode:
    @@ -669,11 +645,10 @@ class MMSEncoder(wsp_pdu.Encoder):
                 messageHeader.extend(MMSEncoder.encodeHeader(hdr, headersToEncode))
            
             # Ok, now only "Content-type" should be left
    -        if addCtype:
    -            ctType = headersToEncode
    -            ctParameters = headersToEncode
    -            messageHeader.extend(MMSEncoder.encodeMMSFieldName('Content-Type'))
    -            messageHeader.extend(MMSEncoder.encodeContentTypeValue(ctType, ctParameters))
    +        ctType = headersToEncode
    +        ctParameters = headersToEncode
    +        messageHeader.extend(MMSEncoder.encodeMMSFieldName('Content-Type'))
    +        messageHeader.extend(MMSEncoder.encodeContentTypeValue(ctType, ctParameters))

         return messageHeader
    
@@ -721,11 +696,12 @@ class MMSEncoder(wsp_pdu.Encoder):
         #TODO: enable encoding of MMSs without SMIL file
         ########## MMS body: header ##########
         # Parts: SMIL file + <number of data elements in each slide>
-        nEntries = 0 # original code said 1
+        nEntries = 1
         for page in self._mmsMessage._pages:
             nEntries += page.numberOfParts()
         for dataPart in self._mmsMessage._dataParts:
             nEntries += 1
+           
         messageBody.extend(self.encodeUintvar(nEntries))
        
         ########## MMS body: entries ##########
@@ -735,24 +711,19 @@ class MMSEncoder(wsp_pdu.Encoder):
         # <content-type + other possible headers>,
         # <data>.

-        ###################################################################
-        # The below is commented out as processing smil is not part of core
-        # encoding and breaks round trip use of the library. If SMIL is
-        # add this processing into the app level encoding function
-        ###################################################################
         # Gather the data parts, adding the MMS message's SMIL file
-        # smilPart = message.DataPart()
-        # smil = self._mmsMessage.smil()
-        # smilPart.setData(smil, 'application/smil')
-        # #TODO: make this dynamic….
-        # smilPart.headers = '<0000>'
-        # parts =
-        # for slide in self._mmsMessage._pages:
-        #     for partTuple in (slide.image, slide.audio, slide.text):
-        #         if partTuple != None:
-        #             parts.append(partTuple)
-        # print "Found %d parts" % len(parts)
-        for part in self._mmsMessage.dataParts:
+        smilPart = message.DataPart()
+        smil = self._mmsMessage.smil()
+        smilPart.setData(smil, 'application/smil')
+        #TODO: make this dynamic….
+        smilPart.headers = '<0000>'
+        parts =
+        for slide in self._mmsMessage._pages:
+            for partTuple in (slide.image, slide.audio, slide.text):
+                if partTuple != None:
+                    parts.append(partTuple)
+   
+        for part in parts:
             partContentType = self.encodeContentTypeValue(part.headers, part.headers)
            
             encodedPartHeaders =
@@ -773,7 +744,6 @@ class MMSEncoder(wsp_pdu.Encoder):
             # Data (note: we do not null-terminate this)
             for char in part.data:
                 messageBody.append(ord(char))
-           
         return messageBody

    
diff -upr python-mms-0.2-rm/mms/wsp_pdu.py python-mms-0.2/mms/wsp_pdu.py
-- python-mms-0.2-rm/mms/wsp_pdu.py 2009-09-22 17:45:40.000000000 +0100
+++ python-mms-0.2/mms/wsp_pdu.py 2007-07-21 14:13:29.000000000 +0100
@@ -664,10 +664,6 @@ class Decoder:
         return integer
    
     @staticmethod
-    def decodeBooleanValue(byteIter):
-        return bool(Decoder.decodeIntegerValue(byteIter))
-                   
-    @staticmethod
     def decodeContentTypeValue(byteIter):
         """ Decodes an encoded content type value.

@@ -1616,10 +1612,6 @@ class Encoder:
         return encodedInteger

     @staticmethod
-    def encodeBooleanValue(boolean):
-        return Encoder.encodeIntegerValue(int(boolean))
-   
-    @staticmethod
     def encodeTextValue(text):
         """ Stub for encoding Text-values; this is equivalent to
         C{encodeTextString} """
    </code></pre>