Archive-Zip

 view release on metacpan or  search on metacpan

lib/Archive/Zip/Member.pm  view on Meta::CPAN

    my $compressedSize            = $self->_writeOffset();
    my $uncompressedSize          = $self->uncompressedSize();
    my $localHeaderRelativeOffset = $self->writeLocalHeaderRelativeOffset();
    my $cdExtraField              = $self->cdExtraField();

    if (!$zip64) {
        # no-op
    }
    else {
        return _zip64NotSupported() unless ZIP64_SUPPORTED;

        $versionNeededToExtract = 45 if ($versionNeededToExtract < 45);

        my $extraFieldFormat = '';
        my @extraFieldValues = ();
        my $extraFieldSize   = 0;
        if ($uncompressedSize > 0xffffffff) {
            $extraFieldFormat .= 'Q< ';
            push(@extraFieldValues, $uncompressedSize);
            $extraFieldSize += 8;
            $uncompressedSize = 0xffffffff;
        }
        if ($compressedSize > 0xffffffff) {
            $extraFieldFormat .= 'Q< ';
            push(@extraFieldValues, $compressedSize);
            $extraFieldSize += 8;
            $compressedSize = 0xffffffff;
        }
        # Avoid empty zip64 extended information extra fields
        if (   $localHeaderRelativeOffset > 0xffffffff
            || @extraFieldValues == 0) {
            $extraFieldFormat .= 'Q< ';
            push(@extraFieldValues, $localHeaderRelativeOffset);
            $extraFieldSize += 8;
            $localHeaderRelativeOffset = 0xffffffff;
        }

        $cdExtraField .=
          pack("S< S< $extraFieldFormat",
               0x0001, $extraFieldSize,
               @extraFieldValues);
    }

    my $fileNameLength    = length($self->fileNameAsBytes());
    my $extraFieldLength  = length($cdExtraField);
    my $fileCommentLength = length($self->fileComment());

    my $sigData =
      pack(SIGNATURE_FORMAT, CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE);
    $self->_print($fh, $sigData)
      or return _ioError("writing central directory header signature");

    my $header = pack(
        CENTRAL_DIRECTORY_FILE_HEADER_FORMAT,
        $versionMadeBy,
        $self->fileAttributeFormat(),
        $versionNeededToExtract,
        $self->bitFlag(),
        $self->desiredCompressionMethod(),
        $self->lastModFileDateTime(),
        $self->crc32(),            # these three fields should have been updated
        $compressedSize,           # by writing the data stream out
        $uncompressedSize,         #
        $fileNameLength,
        $extraFieldLength,
        $fileCommentLength,
        0,                         # {'diskNumberStart'},
        $self->internalFileAttributes(),
        $self->externalFileAttributes(),
        $localHeaderRelativeOffset);

    $self->_print($fh, $header)
      or return _ioError("writing central directory header");

    if ($fileNameLength) {
        $self->_print($fh, $self->fileNameAsBytes())
          or return _ioError("writing central directory header signature");
    }
    if ($extraFieldLength) {
        $self->_print($fh, $cdExtraField)
          or return _ioError("writing central directory extra field");
    }
    if ($fileCommentLength) {
        $self->_print($fh, $self->fileComment())
          or return _ioError("writing central directory file comment");
    }

    # Update object members with information which might have
    # changed while writing this member.  We already did the
    # zip64 flag.  We must not update the extra fields with any
    # zip64 information, since we consider that internal.
    $self->{'versionNeededToExtract'} = $versionNeededToExtract;
    $self->{'compressedSize'}         = $self->_writeOffset();

    return
      (AZ_OK,
       CENTRAL_DIRECTORY_FILE_HEADER_LENGTH +
       SIGNATURE_LENGTH +
       $fileNameLength +
       $extraFieldLength +
       $fileCommentLength)
}

# This writes a data descriptor to the given file handle.
# Assumes that crc32, writeOffset, and uncompressedSize are
# set correctly (they should be after a write).
# Returns a pair (AZ_OK, $dataDescriptorSize) on success.
# Further, the local file header should have the
# GPBF_HAS_DATA_DESCRIPTOR_MASK bit set.
sub _writeDataDescriptor {
    my $self   = shift;
    my $fh     = shift;

    my $descriptor;
    if (! $self->zip64()) {
        $descriptor =
          pack(SIGNATURE_FORMAT . DATA_DESCRIPTOR_FORMAT,
               DATA_DESCRIPTOR_SIGNATURE,
               $self->crc32(),
               $self->_writeOffset(),   # compressed size
               $self->uncompressedSize());



( run in 0.620 second using v1.01-cache-2.11-cpan-99c4e6809bf )