citadel

My dotfiles, scripts and nix configs
git clone git://jb55.com/citadel
Log | Files | Refs | README | LICENSE

clearmime (2631B)


      1 #!/usr/bin/env python
      2 
      3 # Copyright 2008 Lenny Domnitser <http://domnit.org/>
      4 #
      5 # This program is free software; you can redistribute it and/or modify
      6 # it under the terms of the GNU General Public License as published by
      7 # the Free Software Foundation; either version 3 of the License, or (at
      8 # your option) any later version.
      9 #
     10 # This program is distributed in the hope that it will be useful, but
     11 # WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13 # General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU General Public License
     16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 __all__ = 'clarify',
     19 __author__ = 'Lenny Domnitser'
     20 __version__ = '0.1'
     21 
     22 import email
     23 import re
     24 
     25 TEMPLATE = '''-----BEGIN PGP SIGNED MESSAGE-----
     26 Hash: %(hashname)s
     27 NotDashEscaped: You need GnuPG to verify this message
     28 
     29 %(text)s%(sig)s'''
     30 
     31 
     32 def _clarify(message, messagetext):
     33     if message.get_content_type() == 'multipart/signed':
     34         if message.get_param('protocol') == 'application/pgp-signature':
     35             hashname = message.get_param('micalg').upper()
     36             assert hashname.startswith('PGP-')
     37             hashname = hashname.replace('PGP-', '', 1)
     38             textmess, sigmess = message.get_payload()
     39             assert sigmess.get_content_type() == 'application/pgp-signature'
     40             #text = textmess.as_string() - not byte-for-byte accurate
     41             text = messagetext.split('\n--%s\n' % message.get_boundary(), 2)[1]
     42             sig = sigmess.get_payload()
     43             assert isinstance(sig, str)
     44             # Setting content-type to application/octet instead of text/plain
     45             # to maintain CRLF endings. Using replace_header instead of
     46             # set_type because replace_header clears parameters.
     47             message.replace_header('Content-Type', 'application/octet')
     48             clearsign = TEMPLATE % locals()
     49             clearsign = clearsign.replace(
     50                 '\r\n', '\n').replace('\r', '\n').replace('\n', '\r\n')
     51             message.set_payload(clearsign)
     52     elif message.is_multipart():
     53         for message in message.get_payload():
     54             _clarify(message, messagetext)
     55 
     56 
     57 def clarify(messagetext):
     58     '''given a string containing a MIME message, returns a string
     59     where PGP/MIME messages are replaced with clearsigned messages.'''
     60 
     61     message = email.message_from_string(messagetext)
     62     _clarify(message, messagetext)
     63     return message.as_string()
     64 
     65 
     66 if __name__ == '__main__':
     67     import sys
     68     sys.stdout.write(clarify(sys.stdin.read()))