#include "archivelib.h"
#include "zlibstream.h"
-class DeflatedArchiveFile : public ArchiveFile {
- CopiedString m_name;
- FileInputStream m_istream;
- SubFileInputStream m_substream;
- DeflatedInputStream m_zipstream;
- FileInputStream::size_type m_size;
+class DeflatedArchiveFile : public ArchiveFile
+{
+CopiedString m_name;
+FileInputStream m_istream;
+SubFileInputStream m_substream;
+DeflatedInputStream m_zipstream;
+FileInputStream::size_type m_size;
public:
- typedef FileInputStream::size_type size_type;
- typedef FileInputStream::position_type position_type;
-
- DeflatedArchiveFile(const char *name, const char *archiveName, position_type position, size_type stream_size,
- size_type file_size)
- : m_name(name), m_istream(archiveName), m_substream(m_istream, position, stream_size),
- m_zipstream(m_substream), m_size(file_size)
- {
- }
-
- void release()
- {
- delete this;
- }
-
- size_type size() const
- {
- return m_size;
- }
-
- const char *getName() const
- {
- return m_name.c_str();
- }
-
- InputStream &getInputStream()
- {
- return m_zipstream;
- }
+typedef FileInputStream::size_type size_type;
+typedef FileInputStream::position_type position_type;
+
+DeflatedArchiveFile( const char* name, const char* archiveName, position_type position, size_type stream_size, size_type file_size )
+ : m_name( name ), m_istream( archiveName ), m_substream( m_istream, position, stream_size ), m_zipstream( m_substream ), m_size( file_size ){
+}
+
+void release(){
+ delete this;
+}
+size_type size() const {
+ return m_size;
+}
+const char* getName() const {
+ return m_name.c_str();
+}
+InputStream& getInputStream(){
+ return m_zipstream;
+}
};
-class DeflatedArchiveTextFile : public ArchiveTextFile {
- CopiedString m_name;
- FileInputStream m_istream;
- SubFileInputStream m_substream;
- DeflatedInputStream m_zipstream;
- BinaryToTextInputStream<DeflatedInputStream> m_textStream;
+class DeflatedArchiveTextFile : public ArchiveTextFile
+{
+CopiedString m_name;
+FileInputStream m_istream;
+SubFileInputStream m_substream;
+DeflatedInputStream m_zipstream;
+BinaryToTextInputStream<DeflatedInputStream> m_textStream;
public:
- typedef FileInputStream::size_type size_type;
- typedef FileInputStream::position_type position_type;
-
- DeflatedArchiveTextFile(const char *name, const char *archiveName, position_type position, size_type stream_size)
- : m_name(name), m_istream(archiveName), m_substream(m_istream, position, stream_size),
- m_zipstream(m_substream), m_textStream(m_zipstream)
- {
- }
-
- void release()
- {
- delete this;
- }
-
- TextInputStream &getInputStream()
- {
- return m_textStream;
- }
+typedef FileInputStream::size_type size_type;
+typedef FileInputStream::position_type position_type;
+
+DeflatedArchiveTextFile( const char* name, const char* archiveName, position_type position, size_type stream_size )
+ : m_name( name ), m_istream( archiveName ), m_substream( m_istream, position, stream_size ), m_zipstream( m_substream ), m_textStream( m_zipstream ){
+}
+
+void release(){
+ delete this;
+}
+TextInputStream& getInputStream(){
+ return m_textStream;
+}
};
#include "pkzip.h"
#include "fs_filesystem.h"
-class ZipArchive : public Archive {
- class ZipRecord {
- public:
- enum ECompressionMode {
- eStored,
- eDeflated,
- };
-
- ZipRecord(unsigned int position, unsigned int compressed_size, unsigned int uncompressed_size,
- ECompressionMode mode)
- : m_position(position), m_stream_size(compressed_size), m_file_size(uncompressed_size), m_mode(mode)
- {
- }
-
- unsigned int m_position;
- unsigned int m_stream_size;
- unsigned int m_file_size;
- ECompressionMode m_mode;
- };
-
- typedef GenericFileSystem<ZipRecord> ZipFileSystem;
- ZipFileSystem m_filesystem;
- CopiedString m_name;
- FileInputStream m_istream;
-
- bool read_record()
- {
- zip_magic magic;
- istream_read_zip_magic(m_istream, magic);
- if (!(magic == zip_root_dirent_magic)) {
- return false;
- }
- zip_version version_encoder;
- istream_read_zip_version(m_istream, version_encoder);
- zip_version version_extract;
- istream_read_zip_version(m_istream, version_extract);
- //unsigned short flags =
- istream_read_int16_le(m_istream);
- unsigned short compression_mode = istream_read_int16_le(m_istream);
- if (compression_mode != Z_DEFLATED && compression_mode != 0) {
- return false;
- }
- zip_dostime dostime;
- istream_read_zip_dostime(m_istream, dostime);
- //unsigned int crc32 =
- istream_read_int32_le(m_istream);
- unsigned int compressed_size = istream_read_uint32_le(m_istream);
- unsigned int uncompressed_size = istream_read_uint32_le(m_istream);
- unsigned int namelength = istream_read_uint16_le(m_istream);
- unsigned short extras = istream_read_uint16_le(m_istream);
- unsigned short comment = istream_read_uint16_le(m_istream);
- //unsigned short diskstart =
- istream_read_int16_le(m_istream);
- //unsigned short filetype =
- istream_read_int16_le(m_istream);
- //unsigned int filemode =
- istream_read_int32_le(m_istream);
- unsigned int position = istream_read_int32_le(m_istream);
-
- Array<char> filename(namelength + 1);
- m_istream.read(reinterpret_cast<FileInputStream::byte_type *>( filename.data()), namelength);
- filename[namelength] = '\0';
-
- m_istream.seek(extras + comment, FileInputStream::cur);
-
- if (path_is_directory(filename.data())) {
- m_filesystem[filename.data()] = 0;
- } else {
- ZipFileSystem::entry_type &file = m_filesystem[filename.data()];
- if (!file.is_directory()) {
- globalOutputStream() << "Warning: zip archive " << makeQuoted(m_name.c_str())
- << " contains duplicated file: " << makeQuoted(filename.data()) << "\n";
- } else {
- file = new ZipRecord(position, compressed_size, uncompressed_size,
- (compression_mode == Z_DEFLATED) ? ZipRecord::eDeflated : ZipRecord::eStored);
- }
- }
-
- return true;
- }
-
- bool read_pkzip()
- {
- SeekableStream::position_type pos = pkzip_find_disk_trailer(m_istream);
- if (pos != 0) {
- zip_disk_trailer disk_trailer;
- m_istream.seek(pos);
- istream_read_zip_disk_trailer(m_istream, disk_trailer);
- if (!(disk_trailer.z_magic == zip_disk_trailer_magic)) {
- return false;
- }
-
- m_istream.seek(disk_trailer.z_rootseek);
- for (unsigned int i = 0; i < disk_trailer.z_entries; ++i) {
- if (!read_record()) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
+class ZipArchive : public Archive
+{
+class ZipRecord
+{
+public:
+enum ECompressionMode
+{
+ eStored,
+ eDeflated,
+};
+ZipRecord( unsigned int position, unsigned int compressed_size, unsigned int uncompressed_size, ECompressionMode mode )
+ : m_position( position ), m_stream_size( compressed_size ), m_file_size( uncompressed_size ), m_mode( mode ){
+}
+unsigned int m_position;
+unsigned int m_stream_size;
+unsigned int m_file_size;
+ECompressionMode m_mode;
+};
+
+typedef GenericFileSystem<ZipRecord> ZipFileSystem;
+ZipFileSystem m_filesystem;
+CopiedString m_name;
+FileInputStream m_istream;
+
+bool read_record(){
+ zip_magic magic;
+ istream_read_zip_magic( m_istream, magic );
+ if ( !( magic == zip_root_dirent_magic ) ) {
+ return false;
+ }
+ zip_version version_encoder;
+ istream_read_zip_version( m_istream, version_encoder );
+ zip_version version_extract;
+ istream_read_zip_version( m_istream, version_extract );
+ //unsigned short flags =
+ istream_read_int16_le( m_istream );
+ unsigned short compression_mode = istream_read_int16_le( m_istream );
+ if ( compression_mode != Z_DEFLATED && compression_mode != 0 ) {
+ return false;
+ }
+ zip_dostime dostime;
+ istream_read_zip_dostime( m_istream, dostime );
+ //unsigned int crc32 =
+ istream_read_int32_le( m_istream );
+ unsigned int compressed_size = istream_read_uint32_le( m_istream );
+ unsigned int uncompressed_size = istream_read_uint32_le( m_istream );
+ unsigned int namelength = istream_read_uint16_le( m_istream );
+ unsigned short extras = istream_read_uint16_le( m_istream );
+ unsigned short comment = istream_read_uint16_le( m_istream );
+ //unsigned short diskstart =
+ istream_read_int16_le( m_istream );
+ //unsigned short filetype =
+ istream_read_int16_le( m_istream );
+ //unsigned int filemode =
+ istream_read_int32_le( m_istream );
+ unsigned int position = istream_read_int32_le( m_istream );
+
+ Array<char> filename( namelength + 1 );
+ m_istream.read( reinterpret_cast<FileInputStream::byte_type*>( filename.data() ), namelength );
+ filename[namelength] = '\0';
+
+ m_istream.seek( extras + comment, FileInputStream::cur );
+
+ if ( path_is_directory( filename.data() ) ) {
+ m_filesystem[filename.data()] = 0;
+ }
+ else
+ {
+ ZipFileSystem::entry_type& file = m_filesystem[filename.data()];
+ if ( !file.is_directory() ) {
+ globalOutputStream() << "Warning: zip archive " << makeQuoted( m_name.c_str() ) << " contains duplicated file: " << makeQuoted( filename.data() ) << "\n";
+ }
+ else
+ {
+ file = new ZipRecord( position, compressed_size, uncompressed_size, ( compression_mode == Z_DEFLATED ) ? ZipRecord::eDeflated : ZipRecord::eStored );
+ }
+ }
+
+ return true;
+}
+bool read_pkzip(){
+ SeekableStream::position_type pos = pkzip_find_disk_trailer( m_istream );
+ if ( pos != 0 ) {
+ zip_disk_trailer disk_trailer;
+ m_istream.seek( pos );
+ istream_read_zip_disk_trailer( m_istream, disk_trailer );
+ if ( !( disk_trailer.z_magic == zip_disk_trailer_magic ) ) {
+ return false;
+ }
+
+ m_istream.seek( disk_trailer.z_rootseek );
+ for ( unsigned int i = 0; i < disk_trailer.z_entries; ++i )
+ {
+ if ( !read_record() ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
public:
- ZipArchive(const char *name)
- : m_name(name), m_istream(name)
- {
- if (!m_istream.failed()) {
- if (!read_pkzip()) {
- globalErrorStream() << "ERROR: invalid zip-file " << makeQuoted(name) << '\n';
- }
- }
- }
-
- ~ZipArchive()
- {
- for (ZipFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i) {
- delete i->second.file();
- }
- }
-
- bool failed()
- {
- return m_istream.failed();
- }
-
- void release()
- {
- delete this;
- }
-
- ArchiveFile *openFile(const char *name)
- {
- ZipFileSystem::iterator i = m_filesystem.find(name);
- if (i != m_filesystem.end() && !i->second.is_directory()) {
- ZipRecord *file = i->second.file();
-
- m_istream.seek(file->m_position);
- zip_file_header file_header;
- istream_read_zip_file_header(m_istream, file_header);
- if (file_header.z_magic != zip_file_header_magic) {
- globalErrorStream() << "error reading zip file " << makeQuoted(m_name.c_str());
- return 0;
- }
-
- switch (file->m_mode) {
- case ZipRecord::eStored:
- return StoredArchiveFile::create(name, m_name.c_str(), m_istream.tell(), file->m_stream_size,
- file->m_file_size);
- case ZipRecord::eDeflated:
- return new DeflatedArchiveFile(name, m_name.c_str(), m_istream.tell(), file->m_stream_size,
- file->m_file_size);
- }
- }
- return 0;
- }
-
- ArchiveTextFile *openTextFile(const char *name)
- {
- ZipFileSystem::iterator i = m_filesystem.find(name);
- if (i != m_filesystem.end() && !i->second.is_directory()) {
- ZipRecord *file = i->second.file();
-
- m_istream.seek(file->m_position);
- zip_file_header file_header;
- istream_read_zip_file_header(m_istream, file_header);
- if (file_header.z_magic != zip_file_header_magic) {
- globalErrorStream() << "error reading zip file " << makeQuoted(m_name.c_str());
- return 0;
- }
-
- switch (file->m_mode) {
- case ZipRecord::eStored:
- return StoredArchiveTextFile::create(name, m_name.c_str(), m_istream.tell(), file->m_stream_size);
- case ZipRecord::eDeflated:
- return new DeflatedArchiveTextFile(name, m_name.c_str(), m_istream.tell(), file->m_stream_size);
- }
- }
- return 0;
- }
-
- bool containsFile(const char *name)
- {
- ZipFileSystem::iterator i = m_filesystem.find(name);
- return i != m_filesystem.end() && !i->second.is_directory();
- }
-
- void forEachFile(VisitorFunc visitor, const char *root)
- {
- m_filesystem.traverse(visitor, root);
- }
+ZipArchive( const char* name )
+ : m_name( name ), m_istream( name ){
+ if ( !m_istream.failed() ) {
+ if ( !read_pkzip() ) {
+ globalErrorStream() << "ERROR: invalid zip-file " << makeQuoted( name ) << '\n';
+ }
+ }
+}
+~ZipArchive(){
+ for ( ZipFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i )
+ {
+ delete i->second.file();
+ }
+}
+
+bool failed(){
+ return m_istream.failed();
+}
+
+void release(){
+ delete this;
+}
+ArchiveFile* openFile( const char* name ){
+ ZipFileSystem::iterator i = m_filesystem.find( name );
+ if ( i != m_filesystem.end() && !i->second.is_directory() ) {
+ ZipRecord* file = i->second.file();
+
+ m_istream.seek( file->m_position );
+ zip_file_header file_header;
+ istream_read_zip_file_header( m_istream, file_header );
+ if ( file_header.z_magic != zip_file_header_magic ) {
+ globalErrorStream() << "error reading zip file " << makeQuoted( m_name.c_str() );
+ return 0;
+ }
+
+ switch ( file->m_mode )
+ {
+ case ZipRecord::eStored:
+ return StoredArchiveFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size );
+ case ZipRecord::eDeflated:
+ return new DeflatedArchiveFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size );
+ }
+ }
+ return 0;
+}
+ArchiveTextFile* openTextFile( const char* name ){
+ ZipFileSystem::iterator i = m_filesystem.find( name );
+ if ( i != m_filesystem.end() && !i->second.is_directory() ) {
+ ZipRecord* file = i->second.file();
+
+ m_istream.seek( file->m_position );
+ zip_file_header file_header;
+ istream_read_zip_file_header( m_istream, file_header );
+ if ( file_header.z_magic != zip_file_header_magic ) {
+ globalErrorStream() << "error reading zip file " << makeQuoted( m_name.c_str() );
+ return 0;
+ }
+
+ switch ( file->m_mode )
+ {
+ case ZipRecord::eStored:
+ return StoredArchiveTextFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size );
+ case ZipRecord::eDeflated:
+ return new DeflatedArchiveTextFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size );
+ }
+ }
+ return 0;
+}
+bool containsFile( const char* name ){
+ ZipFileSystem::iterator i = m_filesystem.find( name );
+ return i != m_filesystem.end() && !i->second.is_directory();
+}
+void forEachFile( VisitorFunc visitor, const char* root ){
+ m_filesystem.traverse( visitor, root );
+}
};
-Archive *OpenArchive(const char *name)
-{
- return new ZipArchive(name);
+Archive* OpenArchive( const char* name ){
+ return new ZipArchive( name );
}
#if 0
{
public:
void visit( const char* name ){
- int bleh = 0;
+ int bleh = 0;
}
};
public:
TestZip(){
- testzip( "c:/quake3/baseq3/mapmedia.pk3", "textures/radiant/notex.tga" );
+ testzip( "c:/quake3/baseq3/mapmedia.pk3", "textures/radiant/notex.tga" );
}
void testzip( const char* name, const char* filename ){
- Archive* archive = OpenArchive( name );
- ArchiveFile* file = archive->openFile( filename );
- if ( file != 0 ) {
- unsigned char buffer[4096];
- std::size_t count = file->getInputStream().read( (InputStream::byte_type*)buffer, 4096 );
- file->release();
- }
- TestVisitor visitor;
- archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" );
- archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" );
- archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "" );
- archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "" );
- archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures" );
- archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" );
- archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" );
- archive->release();
+ Archive* archive = OpenArchive( name );
+ ArchiveFile* file = archive->openFile( filename );
+ if ( file != 0 ) {
+ unsigned char buffer[4096];
+ std::size_t count = file->getInputStream().read( (InputStream::byte_type*)buffer, 4096 );
+ file->release();
+ }
+ TestVisitor visitor;
+ archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 0 ), "" );
+ archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "" );
+ archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFiles, 1 ), "" );
+ archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eDirectories, 1 ), "" );
+ archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures" );
+ archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 1 ), "textures/" );
+ archive->forEachFile( Archive::VisitorFunc( &visitor, Archive::eFilesAndDirectories, 2 ), "" );
+ archive->release();
}
};