@@ -17,6 +17,10 @@ class Zip extends Archive
1717{
1818 const LOCAL_FILE_HEADER_CRC_OFFSET = 14 ;
1919
20+ const SIG_LOCAL_FILE_HEADER = "\x50\x4b\x03\x04" ;
21+ const SIG_CENTRAL_FILE_HEADER = "\x50\x4b\x01\x02" ;
22+ const SIG_END_OF_CENTRAL_DIR = "\x50\x4b\x05\x06" ;
23+
2024 protected $ file = '' ;
2125 protected $ fh ;
2226 protected $ memory = '' ;
@@ -89,6 +93,7 @@ public function contents()
8993 *
9094 * @see contents()
9195 * @throws ArchiveIOException
96+ * @throws ArchiveCorruptedException
9297 * @return FileInfo[]
9398 */
9499 public function yieldContents ()
@@ -129,6 +134,7 @@ public function yieldContents()
129134 * @param string $exclude a regular expression of files to exclude
130135 * @param string $include a regular expression of files to include
131136 * @throws ArchiveIOException
137+ * @throws ArchiveCorruptedException
132138 * @return FileInfo[]
133139 */
134140 public function extract ($ outdir , $ strip = '' , $ exclude = '' , $ include = '' )
@@ -478,7 +484,7 @@ public function close()
478484 $ this ->writebytes ($ ctrldir );
479485
480486 // write end of central directory record
481- $ this ->writebytes ("\x50\x4b\x05\x06" ); // end of central dir signature
487+ $ this ->writebytes (self :: SIG_END_OF_CENTRAL_DIR );
482488 $ this ->writebytes (pack ('v ' , 0 )); // number of this disk
483489 $ this ->writebytes (pack ('v ' , 0 )); // number of the disk with the start of the central directory
484490 $ this ->writebytes (pack ('v ' ,
@@ -538,6 +544,7 @@ public function save($file)
538544 * This key-value list contains general information about the ZIP file
539545 *
540546 * @return array
547+ * @throws ArchiveCorruptedException when the file is not a valid ZIP archive
541548 */
542549 protected function readCentralDir ()
543550 {
@@ -550,21 +557,31 @@ protected function readCentralDir()
550557
551558 @fseek ($ this ->fh , $ size - $ maximum_size );
552559 $ pos = ftell ($ this ->fh );
553- $ bytes = 0x00000000 ;
560+ $ bytes = '' ;
554561
555562 while ($ pos < $ size ) {
556- $ byte = @fread ($ this ->fh , 1 );
557- $ bytes = (($ bytes << 8 ) & 0xFFFFFFFF ) | ord ($ byte );
558- if ($ bytes == 0x504b0506 ) {
563+ $ bytes = substr ($ bytes . (string )@fread ($ this ->fh , 1 ), -4 );
564+ if ($ bytes === self ::SIG_END_OF_CENTRAL_DIR ) {
559565 break ;
560566 }
561567 $ pos ++;
562568 }
563569
570+ if ($ bytes !== self ::SIG_END_OF_CENTRAL_DIR ) {
571+ throw new ArchiveCorruptedException (
572+ 'End of central directory signature not found - not a valid ZIP file '
573+ );
574+ }
575+
564576 $ data = unpack (
565577 'vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size ' ,
566578 fread ($ this ->fh , 18 )
567579 );
580+ if ($ data === false ) {
581+ throw new ArchiveCorruptedException (
582+ 'Could not read end of central directory record '
583+ );
584+ }
568585
569586 if ($ data ['comment_size ' ] != 0 ) {
570587 $ centd ['comment ' ] = fread ($ this ->fh , $ data ['comment_size ' ]);
@@ -912,7 +929,7 @@ protected function makeCentralFileRecord($offset, $ts, $crc, $len, $clen, $name,
912929
913930 list ($ name , $ extra ) = $ this ->encodeFilename ($ name );
914931
915- $ header = "\x50\x4b\x01\x02" ; // central file header signature
932+ $ header = self :: SIG_CENTRAL_FILE_HEADER ;
916933 $ header .= pack ('v ' , 14 ); // version made by - VFAT
917934 $ header .= pack ('v ' , 20 ); // version needed to extract - 2.0
918935 $ header .= pack ('v ' , 0 ); // general purpose flag - no flags set
@@ -959,7 +976,7 @@ protected function makeLocalFileHeader($ts, $crc, $len, $clen, $name, $comp = nu
959976
960977 list ($ name , $ extra ) = $ this ->encodeFilename ($ name );
961978
962- $ header = "\x50\x4b\x03\x04" ; // local file header signature
979+ $ header = self :: SIG_LOCAL_FILE_HEADER ;
963980 $ header .= pack ('v ' , 20 ); // version needed to extract - 2.0
964981 $ header .= pack ('v ' , 0 ); // general purpose flag - no flags set
965982 $ header .= pack ('v ' , $ comp ); // compression method - deflate|none
0 commit comments