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

📄 filesystemzip.cpp

📁 rcssserver3d Robocup 3D比赛官方指定平台
💻 CPP
字号:
/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*-   this file is part of rcssserver3D   Fri May 9 2003   Copyright (C) 2002,2003 Koblenz University   Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group   $Id: filesystemzip.cpp,v 1.5 2008/02/24 10:18:09 rollmark Exp $   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; version 2 of the License.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "filesystemzip.h"#include <salt/fileclasses.h>#include <zeitgeist/logserver/logserver.h>#include <string.h>#include <zlib.h>#include <boost/regex.hpp>#ifndef HAVE_STRUPR#include <ctype.h>char*strupr( char* s1 ){    int i;    for (i=0; i<strlen(s1); ++i)        {            s1[i] = toupper(s1[i]);        }    return s1;}#endif//ZIP Format Definitions#define SIG_LOCAL_HEADER          0x04034b50#define SIG_FILE_HEADER           0x02014b50#define SIG_CENTRAL_DIRECTORY_END 0x06054b50#define ZIP_STORE   0#define ZIP_DEFLATE 8using namespace salt;using namespace std;using namespace boost;FileSystemZIP::FileSystemZIP()    : FileSystem(){}FileSystemZIP::~FileSystemZIP(){    Clear();}int FileSystemZIP::ForEachFile(const string& expression, TCallback callback, void* param){    if (!callback)        {            return 0;        }    int count = 0;    boost::regex regExpression(expression);    for (TEntryMap::iterator i = mEntryMap.begin(); i != mEntryMap.end(); ++i)        {            TArchiveEntry *cur = (*i).second;            // check if we have a file            if (!(cur->attr&16))                {                    if (boost::regex_match(cur->filename, regExpression))                        {                            callback(cur->filename,param);                            ++count;                        }                }        }    return count;}//// This sets the path to the archive this object will be associated with.// The behavior is quite simple. First it will try 'inName' then 'inName.zip'//bool FileSystemZIP::SetPath(const string& inName){    if(mHandle.get() != 0)        {            //Already selected an archive so unselect it            Clear();        }    // get a stdio file    mHandle = shared_ptr<StdFile>(new StdFile());    // try inName directly    if(! mHandle->Open(inName.c_str()))        {            // ok, let's try it with a '.zip' extension            string tryName = inName + ".zip";            if(! mHandle->Open(tryName.c_str()))                {                    GetLog()->Error() << "(FileSystemZIP) ERROR: unable to open '"                                      << inName << "'\n";                    return false;                }        }    //The open operation succeeded, so we can store the name of the    //archive file    mArchiveName = inName;    //Read Central Directory End    TCentralDirectoryEnd    cde;    ZIPGetCentralDirectoryEndFirst(&cde);    //Move to beginning of the Central Directory    mHandle->Seek(cde.offset_start_cd, SEEK_SET);    //Free memory    delete[] cde.zipfile_comment;    //Start reading data    TLocalHeader lh;    TFileHeader fh;    TArchiveEntry* ae;    int sig = mHandle->Igetl();    while(! mHandle->Eof())        {            switch(sig){            case SIG_LOCAL_HEADER:                //We should actually never get here, but this is left in for completeness                ZIPGetLocalHeader(&lh);                ZIPSkipData(&lh);                delete[] lh.filename;                delete[] lh.extra_field;                break;            case SIG_FILE_HEADER:                //The data for this block is added to our internal database                ZIPGetFileHeader(&fh);                ae = new TArchiveEntry;                ae->filename    = strupr(fh.filename);                ae->data                = fh.relative_offset+4;                ae->attr                = (fh.external_file_attributes)&0xff;                AddArchiveEntry(ae);                delete[] fh.extra_field;                delete[] fh.file_comment;                break;            case SIG_CENTRAL_DIRECTORY_END:                //Again useless reading of data, but we need to eat up the stuff, so here goes                ZIPGetCentralDirectoryEnd(&cde);                delete[] cde.zipfile_comment;                break;            default:                // an error has occured                return false;        }        //Get next signature and update EOF flag        sig = mHandle->Igetl();    }    return true;}shared_ptr<salt::RFile> FileSystemZIP::Open(const string& inName){    char            *fileName;    TArchiveEntry   *cur;    TLocalHeader    lh;    unsigned int    bytes_left=0;    size_t                  size;    unsigned int    buf_size=4096;    unsigned char   *compr, *uncompr;    unsigned int    err;    z_stream        d_stream; /* decompression stream */    // if no file is open, return 0    if(mHandle.get() == 0)        {            return shared_ptr<salt::RFile>();        }    // we have an archive, now get a local copy of inName    fileName = new char[inName.size()+1];    strcpy(fileName, inName.c_str());    // search for file    TEntryMap::iterator i = mEntryMap.find(std::string(strupr(fileName)));    delete[]fileName;    if (i == mEntryMap.end())        {            return shared_ptr<salt::RFile>();        }    // we have found a file    cur = (*i).second;    //Move to beginning of data    mHandle->Seek(cur->data,SEEK_SET);    //Get the local header    ZIPGetLocalHeader(&lh);    //Allocate memory for file    uncompr = new unsigned char[lh.uncompressed_size];    //Get data based on compression method used    switch(lh.compression_method)        {        case ZIP_STORE:            //Data is not compressed, so just read it from the file            mHandle->Read(uncompr, lh.uncompressed_size);            break;        case ZIP_DEFLATE:            //Data is compressed, so decompress it            bytes_left                      = lh.uncompressed_size;            d_stream.zalloc         = (alloc_func)0;            d_stream.zfree          = (free_func)0;            d_stream.opaque         = (voidpf)0;            d_stream.avail_out      = lh.uncompressed_size;            d_stream.next_out       = uncompr;            // get memory for buffer            compr                   = new unsigned char[buf_size];            //This makes ZLIB able to decompress ZIP File streams            inflateInit2(&d_stream, -15);            while(bytes_left)                {                    d_stream.next_in = compr;                    if(bytes_left > buf_size)                        size = buf_size;                    else                        size = bytes_left;                    d_stream.avail_in = mHandle->Read(compr, size);                    err = inflate(&d_stream,bytes_left>size ? Z_PARTIAL_FLUSH : Z_FINISH);                    bytes_left -= size;                }            //Finished decompression            inflateEnd(&d_stream);            //Free decompression buffer            delete[]compr;            break;        default:            //Mode not supported            delete []uncompr;            uncompr=0;            break;        }    shared_ptr<salt::RFile> f;    if(uncompr != 0)        {            MemFile* mf = new MemFile();            mf->Open(uncompr, lh.uncompressed_size);            f.reset(mf);        }    delete[] lh.filename;    delete[] lh.extra_field;    return f;}void FileSystemZIP::Clear(){    mArchiveName = "";    mHandle.reset();    for (TEntryMap::iterator i = mEntryMap.begin(); i != mEntryMap.end(); ++i)        {            TArchiveEntry *cur = (*i).second;            delete[] cur->filename;            delete cur;        }    mEntryMap.clear();}void FileSystemZIP::ZIPGetLocalHeader(TLocalHeader *lh){    int i;    lh->signature                   = SIG_LOCAL_HEADER;    lh->version_needed              = mHandle->Igetw();    lh->general_purpose             = mHandle->Igetw();    lh->compression_method  = mHandle->Igetw();    lh->last_mod_time               = mHandle->Igetw();    lh->last_mod_date               = mHandle->Igetw();    lh->crc32                               = mHandle->Igetl();    lh->compressed_size             = mHandle->Igetl();    lh->uncompressed_size   = mHandle->Igetl();    lh->filename_length             = mHandle->Igetw();    lh->extra_field_length  = mHandle->Igetw();    lh->filename = new char[lh->filename_length+1];    for(i=0;i<lh->filename_length;i++)        lh->filename[i]=mHandle->Getc();    lh->filename[i] = 0;    lh->extra_field = new char[lh->extra_field_length+1];    for(i=0;i<lh->extra_field_length;i++)        lh->extra_field[i]=mHandle->Getc();    lh->extra_field[i] = 0;}void FileSystemZIP::ZIPSkipData(TLocalHeader *lh){    mHandle->Seek(lh->compressed_size,SEEK_CUR);}void FileSystemZIP::ZIPGetFileHeader(TFileHeader *fh){    int i;    fh->signature              = SIG_FILE_HEADER;    fh->version_made           = mHandle->Igetw();    fh->version_needed         = mHandle->Igetw();    fh->general_purpose        = mHandle->Igetw();    fh->compression_method     = mHandle->Igetw();    fh->last_mod_time          = mHandle->Igetw();    fh->last_mod_date          = mHandle->Igetw();    fh->crc32                  = mHandle->Igetl();    fh->compressed_size        = mHandle->Igetl();    fh->uncompressed_size      = mHandle->Igetl();    fh->filename_length        = mHandle->Igetw();    fh->extra_field_length     = mHandle->Igetw();    fh->file_comment_length    = mHandle->Igetw();    fh->disk_number_start      = mHandle->Igetw();    fh->internal_file_attributes = mHandle->Igetw();    fh->external_file_attributes = mHandle->Igetl();    fh->relative_offset           = mHandle->Igetl();    fh->filename = new char[fh->filename_length+1];    for(i=0;i<fh->filename_length;i++)        fh->filename[i]=mHandle->Getc();    fh->filename[i] = 0;    fh->extra_field = new char[fh->extra_field_length+1];    for(i=0;i<fh->extra_field_length;i++)        fh->extra_field[i]=mHandle->Getc();    fh->extra_field[i] = 0;    fh->file_comment = new char[fh->file_comment_length+1];    for(i=0;i<fh->file_comment_length;i++)        fh->file_comment[i]=mHandle->Getc();    fh->file_comment[i] = 0;}void FileSystemZIP::ZIPGetCentralDirectoryEnd(TCentralDirectoryEnd *cde){    int i;    cde->signature                  = SIG_CENTRAL_DIRECTORY_END;    cde->this_disk_no               = mHandle->Igetw();    cde->cds_disk_no                = mHandle->Igetw();    cde->num_entries_this_disk      = mHandle->Igetw();    cde->num_entries_total          = mHandle->Igetw();    cde->cd_size                    = mHandle->Igetl();    cde->offset_start_cd            = mHandle->Igetl();    cde->zipfile_comment_length     = mHandle->Igetw();    cde->zipfile_comment = new char[cde->zipfile_comment_length+1];    for(i=0;i<cde->zipfile_comment_length;i++)        cde->zipfile_comment[i]=mHandle->Getc();    cde->zipfile_comment[i] = 0;}void FileSystemZIP::ZIPGetCentralDirectoryEndFirst(TCentralDirectoryEnd *cde){    int save_pos = mHandle->Tell();    long sig = 0;    //position fpointer to end of file    //fseek(f,0,SEEK_END) did not work!    if(mHandle->Seek(mHandle->Size()-21,SEEK_SET)) return;    sig = mHandle->Igetl();    while(sig!=SIG_CENTRAL_DIRECTORY_END)        {            if(mHandle->Seek(-5,SEEK_CUR)) return;            sig = mHandle->Igetl();        }    ZIPGetCentralDirectoryEnd(cde);    mHandle->Seek(save_pos, SEEK_SET);}void FileSystemZIP::AddArchiveEntry(TArchiveEntry *ae){    mEntryMap[std::string(ae->filename)] = ae;}

⌨️ 快捷键说明

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