graciously handle GCM data length limit
[python-delta-tar] / deltatar / tarfile.py
index b63b593..ff4b239 100644 (file)
@@ -585,6 +585,7 @@ class _Stream:
             if getattr (self, "cmp", None) is not None:
                 self._finalize_write_gz ()
         if self.arcmode & ARCMODE_ENCRYPT:
+            self.__sync ()
             self._finalize_write_encrypt ()
             self._init_write_encrypt (name, set_last_block_offset=True)
         if self.arcmode & ARCMODE_COMPRESS:
@@ -633,7 +634,6 @@ class _Stream:
         Returns the list of IV fixed parts as used during encryption.
         """
         if self.lasthdr is not None:
-            self.__sync ()
             pos0 = self.fileobj.tell ()
             self.fileobj.seek_set (self.lasthdr)
             dummy = self.fileobj.read (crypto.PDTCRYPT_HDR_SIZE)
@@ -696,7 +696,7 @@ class _Stream:
         self.__write(s)
 
     def __sync(self):
-        """Write what’s self in the buffer to the stream."""
+        """Write what’s left in the buffer to the stream."""
         self.__write (b"") # → len (buf) <= bufsiz
         self.__enc_write (self.buf)
         self.buf = b""
@@ -715,7 +715,7 @@ class _Stream:
     def __write_to_file(self, s, pos=None):
         '''
         Writes directly to the fileobj; updates self.bytes_written. If “pos” is
-        given, the streem will seek to that position first and back afterwards,
+        given, the stream will seek to that position first and back afterwards,
         and the total of bytes written is not updated.
         '''
         self.fileobj.write(s, pos)
@@ -724,14 +724,27 @@ class _Stream:
 
 
     def __enc_write(self, s):
-        '''
-        If there's encryption, the string s is encrypted before write it to
-        the file
-        '''
-        tow = s
+        """
+        If encryption is active, the string s is encrypted before being written
+        to the file.
+        """
+        if len (s) == 0:
+            return
         if self.arcmode & ARCMODE_ENCRYPT:
-            tow = self.encryption.process(s)
-        self.__write_to_file(tow)
+            buf = s
+            while len (buf) > 0:
+                n, ct = self.encryption.process(buf)
+                self.__write_to_file(ct)
+                buf = buf [n:]
+                if len (buf) > 0:
+                    # The entire plaintext was not consumed: The size limit
+                    # for encrypted objects was reached. Transparently create
+                    # a new encrypted object and continue processing the input.
+                    self._finalize_write_encrypt ()
+                    self._init_write_encrypt ()
+        else:
+            self.__write_to_file(s)
+
 
     def estim_file_size(self):
         """ estimates size of file if closing it now
@@ -771,9 +784,9 @@ class _Stream:
                 if self.arcmode & ARCMODE_COMPRESS:
                     self._finalize_write_gz ()
                 # end of Tar archive marker (two empty blocks) was written
-                self.__sync()
                 # finalize encryption last; no writes may be performed after
                 # this point
+                self.__sync ()
                 if self.arcmode & ARCMODE_ENCRYPT:
                     self._finalize_write_encrypt ()