uu_codec.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. # Remove newline chars from filename
  18. filename = filename.replace('\n','\\n')
  19. filename = filename.replace('\r','\\r')
  20. # Encode
  21. write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii'))
  22. chunk = read(45)
  23. while chunk:
  24. write(binascii.b2a_uu(chunk))
  25. chunk = read(45)
  26. write(b' \nend\n')
  27. return (outfile.getvalue(), len(input))
  28. def uu_decode(input, errors='strict'):
  29. assert errors == 'strict'
  30. infile = BytesIO(input)
  31. outfile = BytesIO()
  32. readline = infile.readline
  33. write = outfile.write
  34. # Find start of encoded data
  35. while 1:
  36. s = readline()
  37. if not s:
  38. raise ValueError('Missing "begin" line in input data')
  39. if s[:5] == b'begin':
  40. break
  41. # Decode
  42. while True:
  43. s = readline()
  44. if not s or s == b'end\n':
  45. break
  46. try:
  47. data = binascii.a2b_uu(s)
  48. except binascii.Error as v:
  49. # Workaround for broken uuencoders by /Fredrik Lundh
  50. nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
  51. data = binascii.a2b_uu(s[:nbytes])
  52. #sys.stderr.write("Warning: %s\n" % str(v))
  53. write(data)
  54. if not s:
  55. raise ValueError('Truncated input data')
  56. return (outfile.getvalue(), len(input))
  57. class Codec(codecs.Codec):
  58. def encode(self, input, errors='strict'):
  59. return uu_encode(input, errors)
  60. def decode(self, input, errors='strict'):
  61. return uu_decode(input, errors)
  62. class IncrementalEncoder(codecs.IncrementalEncoder):
  63. def encode(self, input, final=False):
  64. return uu_encode(input, self.errors)[0]
  65. class IncrementalDecoder(codecs.IncrementalDecoder):
  66. def decode(self, input, final=False):
  67. return uu_decode(input, self.errors)[0]
  68. class StreamWriter(Codec, codecs.StreamWriter):
  69. charbuffertype = bytes
  70. class StreamReader(Codec, codecs.StreamReader):
  71. charbuffertype = bytes
  72. ### encodings module API
  73. def getregentry():
  74. return codecs.CodecInfo(
  75. name='uu',
  76. encode=uu_encode,
  77. decode=uu_decode,
  78. incrementalencoder=IncrementalEncoder,
  79. incrementaldecoder=IncrementalDecoder,
  80. streamreader=StreamReader,
  81. streamwriter=StreamWriter,
  82. _is_text_encoding=False,
  83. )