Archive-Zip-SimpleZip

 view release on metacpan or  search on metacpan

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

        }

        $fh = IO::File->new("<$inValue")
            or return _setError(undef, undef, "cannot open file '$inValue': $!");
    }
    elsif( $inType eq 'buffer' || $inType eq 'handle')
    {
        $fh = $inValue;
    }
    else
    {
        return _illegalFilename
    }

    my %obj ;

    my $got = _ckParams(@_);
    my $filesOnly = $got->getValue('filesonly');

    my $inner = IO::Compress::Base::Common::createSelfTiedObject($class, \$SimpleUnzipError);

    *$inner->{Pause} = 1;
    $inner->_create(undef, 0, $fh)
        or return undef;

    my ($CD, $Members, $comment) = $inner->scanCentralDirectory($filesOnly);
    $obj{CD} = $CD;
    $obj{Members} = $Members ;
    $obj{Comment} = $comment;
    $obj{Cursor} = 0;
    $obj{Inner} = $inner;
    $obj{Open} = 1 ;

    bless \%obj, $class;
}

sub close
{
    my $self = shift;
    # TODO - fix me
#    $self->{Inner}->close();
    return 1;
}

sub DESTROY
{
    my $self = shift;
}

sub resetter
{
    my $inner = shift;
    my $member = shift;


    *$inner->{NewStream} = 0 ;
    *$inner->{EndStream} = 0 ;
    *$inner->{TotalInflatedBytesRead} = 0;
    *$inner->{Info}{TrailerLength} = 0;

    # disable streaming if present & set sizes from central dir
    # TODO - this will only allow a single file to be read at a time.
    #        police it or fix it.
    *$inner->{ZipData}{Streaming} = 0;
    *$inner->{ZipData}{Crc32} = $member->{CRC32};
    *$inner->{ZipData}{CompressedLen} = $member->{CompressedLength};
    *$inner->{ZipData}{UnCompressedLen} = $member->{UncompressedLength};
    *$inner->{CompressedInputLengthRemaining} =
            *$inner->{CompressedInputLength} = $member->{CompressedLength};
}

sub _readLocalHeader
{
    my $self = shift;
    my $member = shift;

    my $inner = $self->{Inner};

    resetter($inner, $member);

    my $status = $inner->smartSeek($member->{LocalHeaderOffset}, 0, SEEK_SET);
    $inner->_readFullZipHeader() ;
    $member->{DataOffset} = $inner->smartTell();
}

sub comment
{
    my $self = shift;

    return $self->{Comment} ;
}

sub _mkMember
{
    my $self = shift;
    my $member = shift;

    $self->_readLocalHeader($member);

    my %member ;
    $member{Inner}  = $self->{Inner};
    $member{Info} = $member;
    #Scalar::Util::weaken $member{Inner}; # for 5.8


    return bless \%member, 'Archive::Zip::SimpleUnzip::Member';
}

sub member
{
    my $self = shift;
    my $name = shift;

    return _setError(undef, undef, "Member '$name' not in zip")
        if ! defined $name ;

    my $member = $self->{Members}{$name};

    return _setError(undef, undef, "Member '$name' not in zip")
        if ! defined $member ;

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

        my $uncompressedLength = unpack("V", substr($buffer, 24, 4));
        my $filename_length    = unpack("v", substr($buffer, 28, 2));
        my $extra_length       = unpack("v", substr($buffer, 30, 2));
        my $comment_length     = unpack("v", substr($buffer, 32, 2));
        my $locHeaderOffset    = unpack("V", substr($buffer, 42, 4));

        my $filename;
        my $extraField;
        my $comment = '';
        if ($filename_length)
        {
            $self->smartReadExact(\$filename, $filename_length)
                or return $self->TruncatedTrailer("filename");
#            print "Filename [$filename]\n";
        }

        if ($extra_length)
        {
            $self->smartReadExact(\$extraField, $extra_length)
                or return $self->TruncatedTrailer("extra");

            # Check for Zip64
            my $zip64Extended = IO::Compress::Zlib::Extra::findID("\x01\x00", $extraField);
            if ($zip64Extended)
            {
                if ($uncompressedLength == 0xFFFFFFFF)
                {
                    $uncompressedLength = U64::Value_VV64  substr($zip64Extended, 0, 8, "");
                    # $uncompressedLength = unpack "Q<", substr($zip64Extended, 0, 8, "");
                }
                if ($compressedLength == 0xFFFFFFFF)
                {
                    $compressedLength = U64::Value_VV64  substr($zip64Extended, 0, 8, "");
                    # $compressedLength = unpack "Q<", substr($zip64Extended, 0, 8, "");
                }
                if ($locHeaderOffset == 0xFFFFFFFF)
                {
                    $locHeaderOffset = U64::Value_VV64  substr($zip64Extended, 0, 8, "");
                    # $locHeaderOffset = unpack "Q<", substr($zip64Extended, 0, 8, "");
                }
            }
        }

        next
            if $filesOnly && substr($filename, -1, 1) eq '/' && $uncompressedLength == 0;

        if ($comment_length)
        {
            $self->smartReadExact(\$comment, $comment_length)
                or return $self->TruncatedTrailer("comment");
        }

        my %data = (
                    'Name'               => $filename,
                    'Comment'            => $comment,
                    'LocalHeaderOffset'  => $locHeaderOffset,
                    'CompressedLength'   => $compressedLength ,
                    'UncompressedLength' => $uncompressedLength ,
                    'CRC32'              => $crc32 ,
                    #'Time'               => _dosToUnixTime($lastModTime),
                    #'Stream'             => $streamingMode,
                    #'Zip64'              => $zip64,
                    #
                    #'MethodID'           => $compressedMethod,
                    );
        push @CD, \%data;
        $Members{$filename} = \%data ;

        ++ $index;
    }

    $self->seekOrDie($here, 0, SEEK_SET) ;

    return (\@CD, \%Members, $zipcomment) ;
}

sub offsetFromZip64
{
#    print "offsetFromZip64\n";

    my $self = shift ;
    my $here = shift;

    $self->seekOrDie($here - 20, 0, SEEK_SET) ;

    my $buffer;
    my $got = 0;
    $self->readOrDie(\$buffer, 20) ;
        # or die "xxx $here $got $!" ;

    if ( unpack("V", $buffer) == ZIP64_END_CENTRAL_LOC_HDR_SIG ) {
        my $cd64 = U64::Value_VV64 substr($buffer,  8, 8);
        # my $cd64 = unpack "Q<", substr($buffer,  8, 8);

        $self->seekOrDie($cd64, 0, SEEK_SET) ;

        $self->readOrDie(\$buffer, 4) ;

        if ( unpack("V", $buffer) == ZIP64_END_CENTRAL_REC_HDR_SIG ) {

            $self->readOrDie(\$buffer, 8);
                # or die "xxx" ;
            my $size  = U64::Value_VV64($buffer);
            # my $size  = unpack "Q<", $buffer;

            $self->readOrDie(\$buffer, $size);
                # or die "xxx" ;

            my $cd64 =  U64::Value_VV64 substr($buffer,  36, 8);
            # my $cd64 = unpack "Q<", substr($buffer,  36, 8);

            return $cd64 ;
        }

        die "zzz1";
    }

    die "zzz2";
}

use constant Pack_ZIP_END_CENTRAL_HDR_SIG => pack("V", ZIP_END_CENTRAL_HDR_SIG);



( run in 0.632 second using v1.01-cache-2.11-cpan-140bd7fdf52 )