Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
mimetools.py
Go to the documentation of this file.
1 """Various tools used by MIME-reading or MIME-writing programs."""
2 
3 
4 import os
5 import rfc822
6 import tempfile
7 
8 __all__ = ["Message","choose_boundary","encode","decode","copyliteral",
9  "copybinary"]
10 
12  """A derived class of rfc822.Message that knows about MIME headers and
13  contains some hooks for decoding encoded and multipart messages."""
14 
15  def __init__(self, fp, seekable = 1):
16  rfc822.Message.__init__(self, fp, seekable)
17  self.encodingheader = \
18  self.getheader('content-transfer-encoding')
19  self.typeheader = \
20  self.getheader('content-type')
21  self.parsetype()
22  self.parseplist()
23 
24  def parsetype(self):
25  str = self.typeheader
26  if str is None:
27  str = 'text/plain'
28  if ';' in str:
29  i = str.index(';')
30  self.plisttext = str[i:]
31  str = str[:i]
32  else:
33  self.plisttext = ''
34  fields = str.split('/')
35  for i in range(len(fields)):
36  fields[i] = fields[i].strip().lower()
37  self.type = '/'.join(fields)
38  self.maintype = fields[0]
39  self.subtype = '/'.join(fields[1:])
40 
41  def parseplist(self):
42  str = self.plisttext
43  self.plist = []
44  while str[:1] == ';':
45  str = str[1:]
46  if ';' in str:
47  # XXX Should parse quotes!
48  end = str.index(';')
49  else:
50  end = len(str)
51  f = str[:end]
52  if '=' in f:
53  i = f.index('=')
54  f = f[:i].strip().lower() + \
55  '=' + f[i+1:].strip()
56  self.plist.append(f.strip())
57  str = str[end:]
58 
59  def getplist(self):
60  return self.plist
61 
62  def getparam(self, name):
63  name = name.lower() + '='
64  n = len(name)
65  for p in self.plist:
66  if p[:n] == name:
67  return rfc822.unquote(p[n:])
68  return None
69 
70  def getparamnames(self):
71  result = []
72  for p in self.plist:
73  i = p.find('=')
74  if i >= 0:
75  result.append(p[:i].lower())
76  return result
77 
78  def getencoding(self):
79  if self.encodingheader is None:
80  return '7bit'
81  return self.encodingheader.lower()
82 
83  def gettype(self):
84  return self.type
85 
86  def getmaintype(self):
87  return self.maintype
88 
89  def getsubtype(self):
90  return self.subtype
91 
92 
93 
94 
95 # Utility functions
96 # -----------------
97 
98 
99 _prefix = None
100 
102  """Return a random string usable as a multipart boundary.
103  The method used is so that it is *very* unlikely that the same
104  string of characters will every occur again in the Universe,
105  so the caller needn't check the data it is packing for the
106  occurrence of the boundary.
107 
108  The boundary contains dots so you have to quote it in the header."""
109 
110  global _prefix
111  import time
112  import random
113  if _prefix is None:
114  import socket
115  import os
116  hostid = socket.gethostbyname(socket.gethostname())
117  try:
118  uid = `os.getuid()`
119  except:
120  uid = '1'
121  try:
122  pid = `os.getpid()`
123  except:
124  pid = '1'
125  _prefix = hostid + '.' + uid + '.' + pid
126  timestamp = '%.3f' % time.time()
127  seed = `random.randint(0, 32767)`
128  return _prefix + '.' + timestamp + '.' + seed
129 
130 
131 # Subroutines for decoding some common content-transfer-types
132 
133 def decode(input, output, encoding):
134  """Decode common content-transfer-encodings (base64, quopri, uuencode)."""
135  if encoding == 'base64':
136  import base64
137  return base64.decode(input, output)
138  if encoding == 'quoted-printable':
139  import quopri
140  return quopri.decode(input, output)
141  if encoding in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
142  import uu
143  return uu.decode(input, output)
144  if encoding in ('7bit', '8bit'):
145  return output.write(input.read())
146  if decodetab.has_key(encoding):
147  pipethrough(input, decodetab[encoding], output)
148  else:
149  raise ValueError, \
150  'unknown Content-Transfer-Encoding: %s' % encoding
151 
152 def encode(input, output, encoding):
153  """Encode common content-transfer-encodings (base64, quopri, uuencode)."""
154  if encoding == 'base64':
155  import base64
156  return base64.encode(input, output)
157  if encoding == 'quoted-printable':
158  import quopri
159  return quopri.encode(input, output, 0)
160  if encoding in ('uuencode', 'x-uuencode', 'uue', 'x-uue'):
161  import uu
162  return uu.encode(input, output)
163  if encoding in ('7bit', '8bit'):
164  return output.write(input.read())
165  if encodetab.has_key(encoding):
166  pipethrough(input, encodetab[encoding], output)
167  else:
168  raise ValueError, \
169  'unknown Content-Transfer-Encoding: %s' % encoding
170 
171 # The following is no longer used for standard encodings
172 
173 # XXX This requires that uudecode and mmencode are in $PATH
174 
175 uudecode_pipe = '''(
176 TEMP=/tmp/@uu.$$
177 sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
178 cat $TEMP
179 rm $TEMP
180 )'''
181 
182 decodetab = {
183  'uuencode': uudecode_pipe,
184  'x-uuencode': uudecode_pipe,
185  'uue': uudecode_pipe,
186  'x-uue': uudecode_pipe,
187  'quoted-printable': 'mmencode -u -q',
188  'base64': 'mmencode -u -b',
189 }
190 
191 encodetab = {
192  'x-uuencode': 'uuencode tempfile',
193  'uuencode': 'uuencode tempfile',
194  'x-uue': 'uuencode tempfile',
195  'uue': 'uuencode tempfile',
196  'quoted-printable': 'mmencode -q',
197  'base64': 'mmencode -b',
198 }
199 
200 def pipeto(input, command):
201  pipe = os.popen(command, 'w')
202  copyliteral(input, pipe)
203  pipe.close()
204 
205 def pipethrough(input, command, output):
206  tempname = tempfile.mktemp()
207  temp = open(tempname, 'w')
208  copyliteral(input, temp)
209  temp.close()
210  pipe = os.popen(command + ' <' + tempname, 'r')
211  copybinary(pipe, output)
212  pipe.close()
213  os.unlink(tempname)
214 
215 def copyliteral(input, output):
216  while 1:
217  line = input.readline()
218  if not line: break
219  output.write(line)
220 
221 def copybinary(input, output):
222  BUFSIZE = 8192
223  while 1:
224  line = input.read(BUFSIZE)
225  if not line: break
226  output.write(line)