⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 archive.pm

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 PM
📖 第 1 页 / 共 2 页
字号:
          or return _ioError('seeking to write central directory');    }    else {        $offset = $self->_writeCentralDirectoryOffset();    }    foreach my $member ( $self->members() ) {        my $status = $member->_writeCentralDirectoryFileHeader($fh);        return $status if $status != AZ_OK;        $offset += $member->_centralDirectoryHeaderSize();        $self->{'writeEOCDOffset'} = $offset;    }    return $self->_writeEndOfCentralDirectory($fh);}sub read {    my $self     = shift;    my $fileName = shift;    return _error('No filename given') unless $fileName;    my ( $status, $fh ) = _newFileHandle( $fileName, 'r' );    return _ioError("opening $fileName for read") unless $status;    $status = $self->readFromFileHandle( $fh, $fileName );    return $status if $status != AZ_OK;    $fh->close();    $self->{'fileName'} = $fileName;    return AZ_OK;}sub readFromFileHandle {    my $self     = shift;    my $fh       = shift;    my $fileName = shift;    $fileName = $fh unless defined($fileName);    return _error('No filehandle given')   unless $fh;    return _ioError('filehandle not open') unless $fh->opened();    _binmode($fh);    $self->{'fileName'} = "$fh";    # TODO: how to support non-seekable zips?    return _error('file not seekable')      unless _isSeekable($fh);    $fh->seek( 0, 0 );    # rewind the file    my $status = $self->_findEndOfCentralDirectory($fh);    return $status if $status != AZ_OK;    my $eocdPosition = $fh->tell();    $status = $self->_readEndOfCentralDirectory($fh);    return $status if $status != AZ_OK;    $fh->seek( $eocdPosition - $self->centralDirectorySize(),        IO::Seekable::SEEK_SET )      or return _ioError("Can't seek $fileName");    # Try to detect garbage at beginning of archives    # This should be 0    $self->{'eocdOffset'} = $eocdPosition - $self->centralDirectorySize() # here      - $self->centralDirectoryOffsetWRTStartingDiskNumber();    for ( ; ; ) {        my $newMember =          $self->ZIPMEMBERCLASS->_newFromZipFile( $fh, $fileName,            $self->eocdOffset() );        my $signature;        ( $status, $signature ) = _readSignature( $fh, $fileName );        return $status if $status != AZ_OK;        last           if $signature == END_OF_CENTRAL_DIRECTORY_SIGNATURE;        $status = $newMember->_readCentralDirectoryFileHeader();        return $status if $status != AZ_OK;        $status = $newMember->endRead();        return $status if $status != AZ_OK;        $newMember->_becomeDirectoryIfNecessary();        push( @{ $self->{'members'} }, $newMember );    }    return AZ_OK;}# Read EOCD, starting from position before signature.# Return AZ_OK on success.sub _readEndOfCentralDirectory {    my $self = shift;    my $fh   = shift;    # Skip past signature    $fh->seek( SIGNATURE_LENGTH, IO::Seekable::SEEK_CUR )      or return _ioError("Can't seek past EOCD signature");    my $header = '';    my $bytesRead = $fh->read( $header, END_OF_CENTRAL_DIRECTORY_LENGTH );    if ( $bytesRead != END_OF_CENTRAL_DIRECTORY_LENGTH ) {        return _ioError("reading end of central directory");    }    my $zipfileCommentLength;    (        $self->{'diskNumber'},        $self->{'diskNumberWithStartOfCentralDirectory'},        $self->{'numberOfCentralDirectoriesOnThisDisk'},        $self->{'numberOfCentralDirectories'},        $self->{'centralDirectorySize'},        $self->{'centralDirectoryOffsetWRTStartingDiskNumber'},        $zipfileCommentLength    ) = unpack( END_OF_CENTRAL_DIRECTORY_FORMAT, $header );    if ($zipfileCommentLength) {        my $zipfileComment = '';        $bytesRead = $fh->read( $zipfileComment, $zipfileCommentLength );        if ( $bytesRead != $zipfileCommentLength ) {            return _ioError("reading zipfile comment");        }        $self->{'zipfileComment'} = $zipfileComment;    }    return AZ_OK;}# Seek in my file to the end, then read backwards until we find the# signature of the central directory record. Leave the file positioned right# before the signature. Returns AZ_OK if success.sub _findEndOfCentralDirectory {    my $self = shift;    my $fh   = shift;    my $data = '';    $fh->seek( 0, IO::Seekable::SEEK_END )      or return _ioError("seeking to end");    my $fileLength = $fh->tell();    if ( $fileLength < END_OF_CENTRAL_DIRECTORY_LENGTH + 4 ) {        return _formatError("file is too short");    }    my $seekOffset = 0;    my $pos        = -1;    for ( ; ; ) {        $seekOffset += 512;        $seekOffset = $fileLength if ( $seekOffset > $fileLength );        $fh->seek( -$seekOffset, IO::Seekable::SEEK_END )          or return _ioError("seek failed");        my $bytesRead = $fh->read( $data, $seekOffset );        if ( $bytesRead != $seekOffset ) {            return _ioError("read failed");        }        $pos = rindex( $data, END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING );        last          if ( $pos >= 0            or $seekOffset == $fileLength            or $seekOffset >= $Archive::Zip::ChunkSize );    }    if ( $pos >= 0 ) {        $fh->seek( $pos - $seekOffset, IO::Seekable::SEEK_CUR )          or return _ioError("seeking to EOCD");        return AZ_OK;    }    else {        return _formatError("can't find EOCD signature");    }}# Used to avoid taint problems when chdir'ing.# Not intended to increase security in any way; just intended to shut up the -T# complaints.  If your Cwd module is giving you unreliable returns from cwd()# you have bigger problems than this.sub _untaintDir {    my $dir = shift;    $dir =~ m/\A(.+)\z/s;    return $1;}sub addTree {    my $self = shift;    my $root = shift or return _error("root arg missing in call to addTree()");    my $dest = shift;    $dest = '' unless defined($dest);    my $pred = shift || sub { -r };    my @files;    my $startDir = _untaintDir( cwd() );    return _error( 'undef returned by _untaintDir on cwd ', cwd() )      unless $startDir;    # This avoids chdir'ing in Find, in a way compatible with older    # versions of File::Find.    my $wanted = sub {        local $main::_ = $File::Find::name;        my $dir = _untaintDir($File::Find::dir);        chdir($startDir);        push( @files, $File::Find::name ) if (&$pred);        chdir($dir);    };    File::Find::find( $wanted, $root );    my $rootZipName = _asZipDirName( $root, 1 );    # with trailing slash    my $pattern = $rootZipName eq './' ? '^' : "^\Q$rootZipName\E";    $dest = _asZipDirName( $dest, 1 );              # with trailing slash    foreach my $fileName (@files) {        my $isDir = -d $fileName;        # normalize, remove leading ./        my $archiveName = _asZipDirName( $fileName, $isDir );        if ( $archiveName eq $rootZipName ) { $archiveName = $dest }        else { $archiveName =~ s{$pattern}{$dest} }        next if $archiveName =~ m{^\.?/?$};         # skip current dir        my $member = $isDir          ? $self->addDirectory( $fileName, $archiveName )          : $self->addFile( $fileName, $archiveName );        return _error("add $fileName failed in addTree()") if !$member;    }    return AZ_OK;}sub addTreeMatching {    my $self = shift;    my $root = shift      or return _error("root arg missing in call to addTreeMatching()");    my $dest = shift;    $dest = '' unless defined($dest);    my $pattern = shift      or return _error("pattern missing in call to addTreeMatching()");    my $pred = shift;    my $matcher =      $pred ? sub { m{$pattern} && &$pred } : sub { m{$pattern} && -r };    return $self->addTree( $root, $dest, $matcher );}# $zip->extractTree( $root, $dest [, $volume] );## $root and $dest are Unix-style.# $volume is in local FS format.#sub extractTree {    my $self = shift;    my $root = shift;    # Zip format    $root = '' unless defined($root);    my $dest = shift;    # Zip format    $dest = './' unless defined($dest);    my $volume  = shift;                              # optional    my $pattern = "^\Q$root";    my @members = $self->membersMatching($pattern);    foreach my $member (@members) {        my $fileName = $member->fileName();           # in Unix format        $fileName =~ s{$pattern}{$dest};    # in Unix format                                            # convert to platform format:        $fileName = Archive::Zip::_asLocalName( $fileName, $volume );        my $status = $member->extractToFileNamed($fileName);        return $status if $status != AZ_OK;    }    return AZ_OK;}# $zip->updateMember( $memberOrName, $fileName );# Returns (possibly updated) member, if any; undef on errors.sub updateMember {    my $self      = shift;    my $oldMember = shift;    my $fileName  = shift;    if ( !defined($fileName) ) {        _error("updateMember(): missing fileName argument");        return undef;    }    my @newStat = stat($fileName);    if ( !@newStat ) {        _ioError("Can't stat $fileName");        return undef;    }    my $isDir = -d _;    my $memberName;    if ( ref($oldMember) ) {        $memberName = $oldMember->fileName();    }    else {        $oldMember = $self->memberNamed( $memberName = $oldMember )          || $self->memberNamed( $memberName =              _asZipDirName( $oldMember, $isDir ) );    }    unless ( defined($oldMember)        && $oldMember->lastModTime() == $newStat[9]        && $oldMember->isDirectory() == $isDir        && ( $isDir || ( $oldMember->uncompressedSize() == $newStat[7] ) ) )    {        # create the new member        my $newMember = $isDir          ? $self->ZIPMEMBERCLASS->newDirectoryNamed( $fileName, $memberName )          : $self->ZIPMEMBERCLASS->newFromFile( $fileName, $memberName );        unless ( defined($newMember) ) {            _error("creation of member $fileName failed in updateMember()");            return undef;        }        # replace old member or append new one        if ( defined($oldMember) ) {            $self->replaceMember( $oldMember, $newMember );        }        else { $self->addMember($newMember); }        return $newMember;    }    return $oldMember;}# $zip->updateTree( $root, [ $dest, [ $pred [, $mirror]]] );## This takes the same arguments as addTree, but first checks to see# whether the file or directory already exists in the zip file.## If the fourth argument $mirror is true, then delete all my members# if corresponding files weren't found.sub updateTree {    my $self = shift;    my $root = shift      or return _error("root arg missing in call to updateTree()");    my $dest = shift;    $dest = '' unless defined($dest);    $dest = _asZipDirName( $dest, 1 );    my $pred = shift || sub { -r };    my $mirror = shift;    my $rootZipName = _asZipDirName( $root, 1 );    # with trailing slash    my $pattern = $rootZipName eq './' ? '^' : "^\Q$rootZipName\E";    my @files;    my $startDir = _untaintDir( cwd() );    return _error( 'undef returned by _untaintDir on cwd ', cwd() )      unless $startDir;    # This avoids chdir'ing in Find, in a way compatible with older    # versions of File::Find.    my $wanted = sub {        local $main::_ = $File::Find::name;        my $dir = _untaintDir($File::Find::dir);        chdir($startDir);        push( @files, $File::Find::name ) if (&$pred);        chdir($dir);    };    File::Find::find( $wanted, $root );    # Now @files has all the files that I could potentially be adding to    # the zip. Only add the ones that are necessary.    # For each file (updated or not), add its member name to @done.    my %done;    foreach my $fileName (@files) {        my @newStat = stat($fileName);        my $isDir   = -d _;        # normalize, remove leading ./        my $memberName = _asZipDirName( $fileName, $isDir );        if ( $memberName eq $rootZipName ) { $memberName = $dest }        else { $memberName =~ s{$pattern}{$dest} }        next if $memberName =~ m{^\.?/?$};    # skip current dir        $done{$memberName} = 1;        my $changedMember = $self->updateMember( $memberName, $fileName );        return _error("updateTree failed to update $fileName")          unless ref($changedMember);    }    # @done now has the archive names corresponding to all the found files.    # If we're mirroring, delete all those members that aren't in @done.    if ($mirror) {        foreach my $member ( $self->members() ) {            $self->removeMember($member)              unless $done{ $member->fileName() };        }    }    return AZ_OK;}1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -