@@ -859,6 +859,8 @@ def make_zip64_file(
859859        self , file_size_64_set = False , file_size_extra = False ,
860860        compress_size_64_set = False , compress_size_extra = False ,
861861        header_offset_64_set = False , header_offset_extra = False ,
862+         extensible_data = b'' ,
863+         end_of_central_dir_size = None , offset_to_end_of_central_dir = None ,
862864    ):
863865        """Generate bytes sequence for a zip with (incomplete) zip64 data. 
864866
@@ -912,6 +914,12 @@ def make_zip64_file(
912914
913915        central_dir_size  =  struct .pack ('<Q' , 58  +  8  *  len (central_zip64_fields ))
914916        offset_to_central_dir  =  struct .pack ('<Q' , 50  +  8  *  len (local_zip64_fields ))
917+         if  end_of_central_dir_size  is  None :
918+             end_of_central_dir_size  =  44  +  len (extensible_data )
919+         if  offset_to_end_of_central_dir  is  None :
920+             offset_to_end_of_central_dir  =  (108 
921+                                             +  8  *  len (local_zip64_fields )
922+                                             +  8  *  len (central_zip64_fields ))
915923
916924        local_extra_length  =  struct .pack ("<H" , 4  +  8  *  len (local_zip64_fields ))
917925        central_extra_length  =  struct .pack ("<H" , 4  +  8  *  len (central_zip64_fields ))
@@ -940,14 +948,17 @@ def make_zip64_file(
940948            +  filename 
941949            +  central_extra 
942950            # Zip64 end of central directory 
943-             +  b"PK\x06 \x06 ,\x00 \x00 \x00 \x00 \x00 \x00 \x00 -\x00 -" 
944-             +  b"\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 " 
951+             +  b"PK\x06 \x06 " 
952+             +  struct .pack ('<Q' , end_of_central_dir_size )
953+             +  b"-\x00 -\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 " 
945954            +  b"\x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " 
946955            +  central_dir_size 
947956            +  offset_to_central_dir 
957+             +  extensible_data 
948958            # Zip64 end of central directory locator 
949-             +  b"PK\x06 \x07 \x00 \x00 \x00 \x00 l\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 " 
950-             +  b"\x00 \x00 \x00 " 
959+             +  b"PK\x06 \x07 \x00 \x00 \x00 \x00 " 
960+             +  struct .pack ('<Q' , offset_to_end_of_central_dir )
961+             +  b"\x01 \x00 \x00 \x00 " 
951962            # end of central directory 
952963            +  b"PK\x05 \x06 \x00 \x00 \x00 \x00 \x01 \x00 \x01 \x00 :\x00 \x00 \x00 2\x00 " 
953964            +  b"\x00 \x00 \x00 \x00 " 
@@ -978,6 +989,7 @@ def test_bad_zip64_extra(self):
978989        with  self .assertRaises (zipfile .BadZipFile ) as  e :
979990            zipfile .ZipFile (io .BytesIO (missing_file_size_extra ))
980991        self .assertIn ('file size' , str (e .exception ).lower ())
992+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_file_size_extra )))
981993
982994        # zip64 file size present, zip64 compress size present, one field in 
983995        # extra, expecting two, equals missing compress size. 
@@ -989,6 +1001,7 @@ def test_bad_zip64_extra(self):
9891001        with  self .assertRaises (zipfile .BadZipFile ) as  e :
9901002            zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
9911003        self .assertIn ('compress size' , str (e .exception ).lower ())
1004+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
9921005
9931006        # zip64 compress size present, no fields in extra, expecting one, 
9941007        # equals missing compress size. 
@@ -998,6 +1011,7 @@ def test_bad_zip64_extra(self):
9981011        with  self .assertRaises (zipfile .BadZipFile ) as  e :
9991012            zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
10001013        self .assertIn ('compress size' , str (e .exception ).lower ())
1014+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
10011015
10021016        # zip64 file size present, zip64 compress size present, zip64 header 
10031017        # offset present, two fields in extra, expecting three, equals missing 
@@ -1012,6 +1026,7 @@ def test_bad_zip64_extra(self):
10121026        with  self .assertRaises (zipfile .BadZipFile ) as  e :
10131027            zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
10141028        self .assertIn ('header offset' , str (e .exception ).lower ())
1029+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
10151030
10161031        # zip64 compress size present, zip64 header offset present, one field 
10171032        # in extra, expecting two, equals missing header offset 
@@ -1024,6 +1039,7 @@ def test_bad_zip64_extra(self):
10241039        with  self .assertRaises (zipfile .BadZipFile ) as  e :
10251040            zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
10261041        self .assertIn ('header offset' , str (e .exception ).lower ())
1042+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
10271043
10281044        # zip64 file size present, zip64 header offset present, one field in 
10291045        # extra, expecting two, equals missing header offset 
@@ -1036,6 +1052,7 @@ def test_bad_zip64_extra(self):
10361052        with  self .assertRaises (zipfile .BadZipFile ) as  e :
10371053            zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
10381054        self .assertIn ('header offset' , str (e .exception ).lower ())
1055+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
10391056
10401057        # zip64 header offset present, no fields in extra, expecting one, 
10411058        # equals missing header offset 
@@ -1047,6 +1064,63 @@ def test_bad_zip64_extra(self):
10471064        with  self .assertRaises (zipfile .BadZipFile ) as  e :
10481065            zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
10491066        self .assertIn ('header offset' , str (e .exception ).lower ())
1067+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1068+ 
1069+     def  test_bad_zip64_end_of_central_dir (self ):
1070+         zipdata  =  self .make_zip64_file (end_of_central_dir_size = 0 )
1071+         with  self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1072+             zipfile .ZipFile (io .BytesIO (zipdata ))
1073+         self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1074+ 
1075+         zipdata  =  self .make_zip64_file (end_of_central_dir_size = 100 )
1076+         with  self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1077+             zipfile .ZipFile (io .BytesIO (zipdata ))
1078+         self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1079+ 
1080+         zipdata  =  self .make_zip64_file (offset_to_end_of_central_dir = 0 )
1081+         with  self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1082+             zipfile .ZipFile (io .BytesIO (zipdata ))
1083+         self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1084+ 
1085+         zipdata  =  self .make_zip64_file (offset_to_end_of_central_dir = 1000 )
1086+         with  self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*locator' ):
1087+             zipfile .ZipFile (io .BytesIO (zipdata ))
1088+         self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1089+ 
1090+     def  test_zip64_end_of_central_dir_record_not_found (self ):
1091+         zipdata  =  self .make_zip64_file ()
1092+         zipdata  =  zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1093+         with  self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1094+             zipfile .ZipFile (io .BytesIO (zipdata ))
1095+         self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1096+ 
1097+         zipdata  =  self .make_zip64_file (
1098+             extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1099+         zipdata  =  zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1100+         with  self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1101+             zipfile .ZipFile (io .BytesIO (zipdata ))
1102+         self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1103+ 
1104+     def  test_zip64_extensible_data (self ):
1105+         # These values are what is set in the make_zip64_file method. 
1106+         expected_file_size  =  8 
1107+         expected_compress_size  =  8 
1108+         expected_header_offset  =  0 
1109+         expected_content  =  b"test1234" 
1110+ 
1111+         zipdata  =  self .make_zip64_file (
1112+             extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1113+         with  zipfile .ZipFile (io .BytesIO (zipdata )) as  zf :
1114+             zinfo  =  zf .infolist ()[0 ]
1115+             self .assertEqual (zinfo .file_size , expected_file_size )
1116+             self .assertEqual (zinfo .compress_size , expected_compress_size )
1117+             self .assertEqual (zinfo .header_offset , expected_header_offset )
1118+             self .assertEqual (zf .read (zinfo ), expected_content )
1119+         self .assertTrue (zipfile .is_zipfile (io .BytesIO (zipdata )))
1120+ 
1121+         with  self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1122+             zipfile .ZipFile (io .BytesIO (b'prepended'  +  zipdata ))
1123+         self .assertFalse (zipfile .is_zipfile (io .BytesIO (b'prepended'  +  zipdata )))
10501124
10511125    def  test_generated_valid_zip64_extra (self ):
10521126        # These values are what is set in the make_zip64_file method. 
0 commit comments