uu_codec.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. """Python 'uu_codec' Codec - UU content transfer encoding.
  2. This codec de/encodes from bytes to bytes.
  3. Written by Marc-Andre Lemburg (mal@lemburg.com). Some details were
  4. adapted from uu.py which was written by Lance Ellinghouse and
  5. modified by Jack Jansen and Fredrik Lundh.
  6. """
  7. import codecs
  8. import binascii
  9. from io import BytesIO
  10. ### Codec APIs
  11. def uu_encode(input, errors='strict', filename='<data>', mode=0o666):
  12. assert errors == 'strict'
  13. infile = BytesIO(input)
  14. outfile = BytesIO()
  15. read = infile.read
  16. write = outfile.write
  17. # Encode
  18. write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii'))
  19. chunk = read(45)
  20. while chunk:
  21. write(binascii.b2a_uu(chunk))
  22. chunk = read(45)
  23. write(b' \nend\n')
  24. return (outfile.getvalue(), len(input))
  25. def uu_decode(input, errors='strict'):
  26. assert errors == 'strict'
  27. infile = BytesIO(input)
  28. outfile = BytesIO()
  29. readline = infile.readline
  30. write = outfile.write
  31. # Find start of encoded data
  32. while 1:
  33. s = readline()
  34. if not s:
  35. raise ValueError('Missing "begin" line in input data')
  36. if s[:5] == b'begin':
  37. break
  38. # Decode
  39. while True:
  40. s = readline()
  41. if not s or s == b'end\n':
  42. break
  43. try:
  44. data = binascii.a2b_uu(s)
  45. except binascii.Error as v:
  46. # Workaround for broken uuencoders by /Fredrik Lundh
  47. nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
  48. data = binascii.a2b_uu(s[:nbytes])
  49. #sys.stderr.write("Warning: %s\n" % str(v))
  50. write(data)
  51. if not s:
  52. raise ValueError('Truncated input data')
  53. return (outfile.getvalue(), len(input))
  54. class Codec(codecs.Codec):
  55. def encode(self, input, errors='strict'):
  56. return uu_encode(input, errors)
  57. def decode(self, input, errors='strict'):
  58. return uu_decode(input, errors)
  59. class IncrementalEncoder(codecs.IncrementalEncoder):
  60. def encode(self, input, final=False):
  61. return uu_encode(input, self.errors)[0]
  62. class IncrementalDecoder(codecs.IncrementalDecoder):
  63. def decode(self, input, final=False):
  64. return uu_decode(input, self.errors)[0]
  65. class StreamWriter(Codec, codecs.StreamWriter):
  66. charbuffertype = bytes
  67. class StreamReader(Codec, codecs.StreamReader):
  68. charbuffertype = bytes
  69. ### encodings module API
  70. def getregentry():
  71. return codecs.CodecInfo(
  72. name='uu',
  73. encode=uu_encode,
  74. decode=uu_decode,
  75. incrementalencoder=IncrementalEncoder,
  76. incrementaldecoder=IncrementalDecoder,
  77. streamreader=StreamReader,
  78. streamwriter=StreamWriter,
  79. _is_text_encoding=False,
  80. )