App-zipdetails

 view release on metacpan or  search on metacpan

bin/zipdetails  view on Meta::CPAN

        my $diskNumber         = unpack("v", substr($buffer, 34, 2));
        my $locHeaderOffset    = unpack("V", substr($buffer, 42, 4));

        my $cdZip64 = 0;
        my $zip64Sizes = 0;

        if (! full32 $locHeaderOffset)
        {
            # Check for corrupt offset
            # 1. pointing paset EOF
            # 2. offset points forward in the file
            # 3. value at offset is not a CD record signature

            my $commonMessage = "'Local Header Offset' field in '" . Signatures::name(ZIP_CENTRAL_HDR_SIG) . "' is invalid";
            checkOffsetValue($locHeaderOffset, $startHeader, 0, $commonMessage,
                $startHeader + CentralDirectoryEntry::Offset_RelativeOffsetToLocal(),
                ZIP_LOCAL_HDR_SIG, 1) ;
        }

        $fh->read(my $filename, $filename_length) ;

        my $cdEntry = CentralDirectoryEntry->new();

        $cdEntry->centralHeaderOffset($startHeader) ;
        $cdEntry->localHeaderOffset($locHeaderOffset) ;
        $cdEntry->compressedSize($compressedSize) ;
        $cdEntry->uncompressedSize($uncompressedSize) ;
        $cdEntry->extractVersion($extractVer);
        $cdEntry->generalPurposeFlags($gpFlag);
        $cdEntry->filename($filename) ;
        $cdEntry->lastModDateTime($lastMod);
        $cdEntry->languageEncodingFlag($gpFlag & ZIP_GP_FLAG_LANGUAGE_ENCODING) ;
        $cdEntry->diskNumber($diskNumber) ;
        $cdEntry->crc32($crc) ;
        $cdEntry->zip64ExtraPresent($cdZip64) ;

        $cdEntry->std_localHeaderOffset($locHeaderOffset) ;
        $cdEntry->std_compressedSize($compressedSize) ;
        $cdEntry->std_uncompressedSize($uncompressedSize) ;
        $cdEntry->std_diskNumber($diskNumber) ;


        if ($extra_length)
        {
            $fh->read(my $extraField, $extra_length) ;

            # Check for Zip64
            my $zip64Extended = findID(0x0001, $extraField);

            if ($zip64Extended)
            {
                $cdZip64 = 1;
                walk_Zip64_in_CD(1, $zip64Extended, $cdEntry, 0);
            }
        }

        $cdEntry->offsetStart($startHeader) ;
        $cdEntry->offsetEnd($FH->tell() - 1);

        # don't call addEntry until after the extra fields have been scanned
        # the localheader offset value may be updated in th ezip64 extra field.
        $CentralDirectory->addEntry($cdEntry);
        $HeaderOffsetIndex->addOffset($cdEntry->localHeaderOffset, ZIP_LOCAL_HDR_SIG) ;

        skip($fh, $comment_length ) ;
    }

    $FH->seek($fh->tell() - ZIP_CD_FILENAME_OFFSET, SEEK_SET);

    # Check for Digital Signature
    $HeaderOffsetIndex->addOffset($fh->tell() - 4, ZIP_DIGITAL_SIGNATURE_SIG)
        if $fh->read($buffer, 4) == 4  &&
            unpack("V", $buffer) == ZIP_DIGITAL_SIGNATURE_SIG ;

    $CentralDirectory->sortByLocalOffset();
    $HeaderOffsetIndex->sortOffsets();

    $fh->seek($here, SEEK_SET) ;

}

use constant ZIP64_END_CENTRAL_LOC_HDR_SIZE     => 20;
use constant ZIP64_END_CENTRAL_REC_HDR_MIN_SIZE => 56;

sub offsetFromZip64
{
    my $fh = shift ;
    my $here = shift;
    my $eocdSize = shift;

    #### Zip64 end of central directory locator

    # check enough bytes available for zip64 locator record
    fatal_tryWalk undef, "Cannot find signature for " .  Signatures::nameAndHex(ZIP64_END_CENTRAL_LOC_HDR_SIG), # 'Zip64 end of central directory locator': 0x07064b50"
                         "Possible truncated or corrupt zip file"
        if $here < ZIP64_END_CENTRAL_LOC_HDR_SIZE ;

    $fh->seek($here - ZIP64_END_CENTRAL_LOC_HDR_SIZE, SEEK_SET) ;
    $here = $FH->tell();

    my $buffer;
    my $got = 0;
    $fh->read($buffer, ZIP64_END_CENTRAL_LOC_HDR_SIZE);

    my $gotSig = unpack("V", $buffer);
    fatal_tryWalk $here - 4, sprintf("Expected signature for " . Signatures::nameAndHex(ZIP64_END_CENTRAL_LOC_HDR_SIG) . " not found, got 0x%X", $gotSig)
        if $gotSig != ZIP64_END_CENTRAL_LOC_HDR_SIG ;

    $HeaderOffsetIndex->addOffset($fh->tell() - ZIP64_END_CENTRAL_LOC_HDR_SIZE, ZIP64_END_CENTRAL_LOC_HDR_SIG) ;


    my $cd64 = unpack "Q<", substr($buffer,  8, 8);
    my $totalDisks = unpack "V", substr($buffer,  16, 4);

    testPossiblePrefix($cd64, ZIP64_END_CENTRAL_REC_HDR_SIG);

    if ($totalDisks > 0)
    {
        my $commonMessage = "'Offset to Zip64 End of Central Directory Record' field in '" . Signatures::name(ZIP64_END_CENTRAL_LOC_HDR_SIG) . "' is invalid";
        $cd64 = checkOffsetValue($cd64, $here, 0, $commonMessage, $here + 8, ZIP64_END_CENTRAL_REC_HDR_SIG, 1) ;
    }



( run in 0.927 second using v1.01-cache-2.11-cpan-5a3173703d6 )