fixed error in assertion text
[p2pool.git] / wstools / MIMEAttachment.py
1 #TODO add the license
2 #I had to rewrite this class because the python MIME email.mime (version 2.5)
3 #are buggy, they use \n instead \r\n for new line which is not compliant
4 #to standard!
5 # http://bugs.python.org/issue5525
6
7 #TODO do not load all the message in memory stream it from the disk
8
9 import re
10 import random
11 import sys
12
13
14 #new line
15 NL='\r\n'
16
17 _width = len(repr(sys.maxint-1))
18 _fmt = '%%0%dd' % _width
19
20 class MIMEMessage:
21
22     def __init__(self):
23         self._files = []
24         self._xmlMessage = ""
25         self._startCID = ""
26         self._boundary = ""
27
28     def makeBoundary(self):
29         #create the boundary 
30         msgparts = []
31         msgparts.append(self._xmlMessage)
32         for i in self._files:
33             msgparts.append(i.read())
34         #this sucks, all in memory
35         alltext = NL.join(msgparts)
36         self._boundary  = _make_boundary(alltext)
37         #maybe I can save some memory
38         del alltext
39         del msgparts
40         self._startCID =  "<" + (_fmt % random.randrange(sys.maxint)) + (_fmt % random.randrange(sys.maxint)) + ">"
41
42
43     def toString(self):
44         '''it return a string with the MIME message'''
45         if len(self._boundary) == 0:
46             #the makeBoundary hasn't been called yet
47             self.makeBoundary()
48         #ok we have everything let's start to spit the message out
49         #first the XML
50         returnstr = NL + "--" + self._boundary + NL
51         returnstr += "Content-Type: text/xml; charset=\"us-ascii\"" + NL
52         returnstr += "Content-Transfer-Encoding: 7bit" + NL
53         returnstr += "Content-Id: " + self._startCID + NL + NL
54         returnstr += self._xmlMessage + NL
55         #then the files
56         for file in self._files:
57             returnstr += "--" + self._boundary + NL
58             returnstr += "Content-Type: application/octet-stream" + NL
59             returnstr += "Content-Transfer-Encoding: binary" + NL
60             returnstr += "Content-Id: <" + str(id(file)) + ">" + NL + NL
61             file.seek(0)
62             returnstr += file.read() + NL
63         #closing boundary
64         returnstr += "--" + self._boundary + "--" + NL 
65         return returnstr
66
67     def attachFile(self, file):
68         '''
69         it adds a file to this attachment
70         '''
71         self._files.append(file)
72
73     def addXMLMessage(self, xmlMessage):
74         '''
75         it adds the XML message. we can have only one XML SOAP message
76         '''
77         self._xmlMessage = xmlMessage
78
79     def getBoundary(self):
80         '''
81         this function returns the string used in the mime message as a 
82         boundary. First the write method as to be called
83         '''
84         return self._boundary
85
86     def getStartCID(self):
87         '''
88         This function returns the CID of the XML message
89         '''
90         return self._startCID
91
92
93 def _make_boundary(text=None):
94     #some code taken from python stdlib
95     # Craft a random boundary.  If text is given, ensure that the chosen
96     # boundary doesn't appear in the text.
97     token = random.randrange(sys.maxint)
98     boundary = ('=' * 10) + (_fmt % token) + '=='
99     if text is None:
100         return boundary
101     b = boundary
102     counter = 0
103     while True:
104         cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
105         if not cre.search(text):
106             break
107         b = boundary + '.' + str(counter)
108         counter += 1
109     return b
110