root/OpenSceneGraph/trunk/src/osgPlugins/zip/unzip.cpp @ 12597

Revision 12597, 148.1 kB (checked in by robert, 3 years ago)

Resolved warnings reported by g++ 4.6's -Wunused-but-set-variable.

Warnings were:

/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osg/ShapeDrawable.cpp: In member function ‘void PrimitiveShapeVisitor::createHalfSphere(unsigned int, unsigned int, float, int, float, const Matrix&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osg/ShapeDrawable.cpp:1409:11: warning: variable ‘nzBase’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osg/ShapeDrawable.cpp:1410:11: warning: variable ‘nRatioBase’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgUtil/DelaunayTriangulator.cpp: In function ‘osgUtil::Triangle_list osgUtil::fillHole(osg::Vec3Array*, std::vector<unsigned int, std::allocator<unsigned int> >)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgUtil/DelaunayTriangulator.cpp:569:27: warning: variable ‘ptest’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgUtil/DelaunayTriangulator.cpp: In member function ‘bool osgUtil::DelaunayTriangulator::triangulate()’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgUtil/DelaunayTriangulator.cpp:979:45: warning: variable ‘curp’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgUtil/RenderStage.cpp: In member function ‘void osgUtil::RenderStage::runCameraSetUp(osg::RenderInfo?&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgUtil/RenderStage.cpp:631:18: warning: variable ‘stencilAttached’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgText/FadeText.cpp: In member function ‘void FadeTextPolytopeData::buildPolytope()’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgText/FadeText.cpp:74:20: warning: variable ‘edge23’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgText/FadeText.cpp:75:20: warning: variable ‘edge30’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgText/Text.cpp: In member function ‘void osgText::Text::computeBackdropPositions(unsigned int) const’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgText/Text.cpp:747:10: warning: variable ‘is_valid_size’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgGA/NodeTrackerManipulator.cpp: In member function ‘virtual bool osgGA::NodeTrackerManipulator::performMovementLeftMouseButton(double, double, double)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgGA/NodeTrackerManipulator.cpp:257:21: warning: variable ‘lookVector’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgGA/NodeTrackerManipulator.cpp:259:21: warning: variable ‘upVector’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgGA/TerrainManipulator.cpp: In member function ‘virtual bool osgGA::TerrainManipulator::performMovementMiddleMouseButton(double, double, double)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgGA/TerrainManipulator.cpp:217:11: warning: variable ‘lookVector’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgGA/TerrainManipulator.cpp:219:11: warning: variable ‘upVector’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgVolume/FixedFunctionTechnique.cpp: In member function ‘virtual void osgVolume::FixedFunctionTechnique::init()’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgVolume/FixedFunctionTechnique.cpp:124:30: warning: variable ‘tf’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgParticle/FluidProgram.cpp: In member function ‘virtual void osgParticle::FluidProgram::execute(double)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgParticle/FluidProgram.cpp:38:23: warning: variable ‘velBefore’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgShadow/ParallelSplitShadowMap.cpp: In member function ‘virtual void osgShadow::ParallelSplitShadowMap::cull(osgUtil::CullVisitor?&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgShadow/ParallelSplitShadowMap.cpp:593:22: warning: variable ‘bb’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgTerrain/GeometryTechnique.cpp: In member function ‘virtual void osgTerrain::GeometryTechnique::generateGeometry(osgTerrain::GeometryTechnique::BufferData?&, osgTerrain::Locator*, const osg::Vec3d&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgTerrain/GeometryTechnique.cpp:777:12: warning: variable ‘i_sampleFactor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgTerrain/GeometryTechnique.cpp:778:12: warning: variable ‘j_sampleFactor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/dds/ReaderWriterDDS.cpp: In function ‘osg::Image* ReadDDSFile(std::istream&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/dds/ReaderWriterDDS.cpp:314:10: warning: variable ‘is3dImage’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/dds/ReaderWriterDDS.cpp: In function ‘bool WriteDDSFile(const osg::Image*, std::ostream&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/dds/ReaderWriterDDS.cpp:721:10: warning: variable ‘is3dImage’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/hdr/hdrloader.cpp: In static member function ‘static bool HDRLoader::load(const char*, bool, HDRLoaderResult&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/hdr/hdrloader.cpp:101:10: warning: variable ‘cmd’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/vtf/ReaderWriterVTF.cpp: In function ‘osg::Image* ReadVTFFile(std::istream&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/vtf/ReaderWriterVTF.cpp:360:23: warning: variable ‘base’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/jp2/ReaderWriterJP2.cpp: In function ‘int putdata(jas_stream_t*, jas_image_t*, int)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/jp2/ReaderWriterJP2.cpp:41:13: warning: variable ‘linelen’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/Inventor/ConvertToInventor.cpp: In member function ‘void ConvertToInventor::processGeometry(const osg::Geometry*, ConvertToInventor::InventorState?*)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/Inventor/ConvertToInventor.cpp:1639:10: warning: variable ‘ok’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/Inventor/ConvertFromInventor.cpp: In member function ‘virtual SbBool? SoVRMLImageTextureOsg::readInstance(SoInput?*, short unsigned int)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/Inventor/ConvertFromInventor.cpp:1264:16: warning: variable ‘retval’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/OpenFlight/GeometryRecords.cpp: In member function ‘virtual void flt::Face::readRecord(flt::RecordInputStream?&, flt::Document&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/OpenFlight/GeometryRecords.cpp:369:19: warning: variable ‘secondaryPackedColor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/OpenFlight/GeometryRecords.cpp: In member function ‘virtual void flt::Mesh::readRecord(flt::RecordInputStream?&, flt::Document&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/OpenFlight/GeometryRecords.cpp:942:19: warning: variable ‘secondaryPackedColor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp: In member function ‘virtual osgDB::ReaderWriter::ReadResult? FLTReaderWriter::readNode(std::istream&, const Options*) const’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp:427:40: warning: variable ‘pos’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ive/ShapeAttributeList.cpp: In member function ‘void ive::ShapeAttributeList::write(ive::DataOutputStream?*)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ive/ShapeAttributeList.cpp:31:48: warning: variable ‘it’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ac/Geode.cpp: In member function ‘void ac3d::Geode::ProcessGeometry?(std::ostream&, unsigned int)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ac/Geode.cpp:806:35: warning: variable ‘fRep_s’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ac/Geode.cpp:806:43: warning: variable ‘fRep_t’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ac/Geode.cpp:807:35: warning: variable ‘fOffset_s’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ac/Geode.cpp:807:46: warning: variable ‘fOffset_t’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/ac/Geode.cpp:932:38: warning: variable ‘primLength’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/txp/trpage_geom.cpp: In member function ‘virtual bool trpgGeometry::Write(trpgWriteBuffer&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/txp/trpage_geom.cpp:615:19: warning: variable ‘u’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/txp/trpage_material.cpp: In member function ‘int trpgMatTable::AddMaterial?(const trpgMaterial&, bool)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/txp/trpage_material.cpp:103:10: warning: variable ‘spaceInTable’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/txp/trpage_rarchive.cpp: In member function ‘virtual bool trpgr_Archive::ReadHeader?(bool)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/txp/trpage_rarchive.cpp:261:14: warning: variable ‘headerHasTexTable’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/zip/unzip.cpp: In member function ‘ZRESULT TUnzip::Get(int, ZIPENTRY*)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/zip/unzip.cpp:4055:8: warning: variable ‘hidden’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/zip/unzip.cpp:4055:22: warning: variable ‘system’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/zip/unzip.cpp:4055:36: warning: variable ‘archive’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/zip/ZipArchive.cpp: In member function ‘virtual bool ZipArchive::getFileNames(osgDB::Archive::FileNameList?&) const’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/zip/ZipArchive.cpp:91:37: warning: variable ‘iterEnd’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/pvr/ReaderWriterPVR.cpp: In member function ‘osgDB::ReaderWriter::ReadResult? ReaderWriterPVR::readPVRStream(std::istream&) const’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/pvr/ReaderWriterPVR.cpp:155:14: warning: variable ‘hasAlpha’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgViewer/View.cpp: In function ‘osg::Geometry* create3DSphericalDisplayDistortionMesh(const Vec3&, const Vec3&, const Vec3&, double, double, osg::Image*, const Matrix&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgViewer/View.cpp:737:15: warning: variable ‘cursor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgViewer/View.cpp: In function ‘osg::Geometry* createParoramicSphericalDisplayDistortionMesh(const Vec3&, const Vec3&, const Vec3&, double, double, osg::Image*, const Matrix&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgViewer/View.cpp:1130:19: warning: variable ‘cursor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgViewer/View.cpp:1118:15: warning: variable ‘dx’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgViewer/GraphicsWindowX11.cpp: In member function ‘virtual void osgViewer::GraphicsWindowX11::checkEvents()’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgViewer/GraphicsWindowX11.cpp:1181:10: warning: variable ‘destroyWindowRequested’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/cfg/ConfigParser.cpp: In member function ‘bool osgProducer::CameraConfig::parseFile(const string&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/cfg/ConfigParser.cpp:2247:13: warning: variable ‘result’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgQt/QGraphicsViewAdapter.cpp: In member function ‘bool osgQt::QGraphicsViewAdapter::handlePointerEvent(int, int, int)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgQt/QGraphicsViewAdapter.cpp:344:17: warning: variable ‘viewportGeometry’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgdistortion/osgdistortion.cpp: In function ‘osg::Node* createDistortionSubgraph(osg::Node*, const Vec4&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgdistortion/osgdistortion.cpp:125:19: warning: variable ‘cursor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgdistortion/osgdistortion.cpp:126:19: warning: variable ‘texcoord’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgdistortion/osgdistortion.cpp: In function ‘osg::Geometry* createDomeDistortionMesh(const Vec3&, const Vec3&, const Vec3&, osg::ArgumentParser?&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgdistortion/osgdistortion.cpp:358:15: warning: variable ‘cursor’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgposter/osgposter.cpp: In function ‘int main(int, char**)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgposter/osgposter.cpp:253:31: warning: variable ‘outputTiles’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgthreadedterrain/osgthreadedterrain.cpp: In function ‘int main(int, char**)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgthreadedterrain/osgthreadedterrain.cpp:669:10: warning: variable ‘readParameter’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgtext3D/TextNode.cpp: In member function ‘virtual void osgText::Layout::layout(osgText::TextNode?&) const’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgtext3D/TextNode.cpp:80:11: warning: variable ‘characterHeightScale’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgvolume/osgvolume.cpp: In function ‘int main(int, char**)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgvolume/osgvolume.cpp:678:38: warning: variable ‘internalFormatMode’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgwidgetcanvas/osgwidgetcanvas.cpp: In function ‘bool windowMouseOver(osgWidget::Event&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgwidgetcanvas/osgwidgetcanvas.cpp:27:24: warning: variable ‘xy’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgwidgetcanvas/osgwidgetcanvas.cpp: In function ‘bool widgetMouseOver(osgWidget::Event&)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/examples/osgwidgetcanvas/osgwidgetcanvas.cpp:35:24: warning: variable ‘xy’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/p3d/ReaderWriterP3D.cpp: In member function ‘osg::Node* ReaderWriterP3DXML::parseXmlGraph(osgDB::XmlNode?*, bool, osgDB::Options*) const’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/src/osgPlugins/p3d/ReaderWriterP3D.cpp:2121:10: warning: variable ‘readSlide’ set but not used [-Wunused-but-set-variable]
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/applications/present3D/present3D.cpp: In function ‘int main(int, char**)’:
/home/stephan/Dev/LibSources/OpenSceneGraph-3.0.0-rc2/applications/present3D/present3D.cpp:639:10: warning: variable ‘sizesSpecified’ set but not used [-Wunused-but-set-variable]

  • Property svn:eol-style set to native
Line 
1// THIS FILE is almost entirely based upon code by Jean-loup Gailly
2// and Mark Adler, and subsequent modifications by Lucian Wischik.
3// It has been modified further by Neil Hughes.
4// The modifications were: a minor reorganisation of the include files
5// referenced within the cpp files, moving them to the .h file to ease
6// compilation with OpenSceneGraph - found at http://www.openscenegraph.org/projects/osg
7// Providing alternative to _tcsncpy_s for ZIP_STD compilations.
8// Provided alternative to _tsprintf code for ZIP_STD compilations.
9// The original copyright text and comments as recorded in
10// Lucian Wischik's cpp follows.
11//
12// THIS FILE is almost entirely based upon code by Jean-loup Gailly
13// and Mark Adler. It has been modified by Lucian Wischik.
14// The modifications were: incorporate the bugfixes of 1.1.4, allow
15// unzipping to/from handles/pipes/files/memory, encryption, unicode,
16// a windowsish api, and putting everything into a single .cpp file.
17// The original code may be found at http://www.gzip.org/zlib/
18// The original copyright text follows.
19//
20//
21//
22// zlib.h -- interface of the 'zlib' general purpose compression library
23//  version 1.1.3, July 9th, 1998
24//
25//  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
26//
27//  This software is provided 'as-is', without any express or implied
28//  warranty.  In no event will the authors be held liable for any damages
29//  arising from the use of this software.
30//
31//  Permission is granted to anyone to use this software for any purpose,
32//  including commercial applications, and to alter it and redistribute it
33//  freely, subject to the following restrictions:
34//
35//  1. The origin of this software must not be misrepresented; you must not
36//     claim that you wrote the original software. If you use this software
37//     in a product, an acknowledgment in the product documentation would be
38//     appreciated but is not required.
39//  2. Altered source versions must be plainly marked as such, and must not be
40//     misrepresented as being the original software.
41//  3. This notice may not be removed or altered from any source distribution.
42//
43//  Jean-loup Gailly        Mark Adler
44//  jloup@gzip.org          madler@alumni.caltech.edu
45//
46//
47//  The data format used by the zlib library is described by RFCs (Request for
48//  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
49//  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
50//
51//
52//     The 'zlib' compression library provides in-memory compression and
53//  decompression functions, including integrity checks of the uncompressed
54//  data.  This version of the library supports only one compression method
55//  (deflation) but other algorithms will be added later and will have the same
56//  stream interface.
57//
58//     Compression can be done in a single step if the buffers are large
59//  enough (for example if an input file is mmap'ed), or can be done by
60//  repeated calls of the compression function.  In the latter case, the
61//  application must provide more input and/or consume the output
62//  (providing more output space) before each call.
63//
64//     The library also supports reading and writing files in gzip (.gz) format
65//  with an interface similar to that of stdio.
66//
67//     The library does not install any signal handler. The decoder checks
68//  the consistency of the compressed data, so the library should never
69//  crash even in case of corrupted input.
70//
71// for more info about .ZIP format, see ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
72//   PkWare has also a specification at ftp://ftp.pkware.com/probdesc.zip
73
74//#ifdef ZIP_STD
75//#include <stdio.h>
76//#include <string.h>
77//#include <malloc.h>
78//#include <time.h>
79//#ifdef _MSC_VER
80//#include <sys/utime.h> // microsoft puts it here
81//#else
82//#include <utime.h>
83//#endif
84//#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
85//#include <direct.h>
86//#define lumkdir(t) (mkdir(t))
87//#else
88//#include <unistd.h>
89//#define lumkdir(t) (mkdir(t,0755))
90//#endif
91//#include <sys/types.h>
92//#include <sys/stat.h>
93//#include "unzip.h"
94////
95//typedef unsigned short WORD;
96//#define _tcslen strlen
97//#define _tcsicmp stricmp
98//#define _tcsncpy strncpy
99//#define _tcsstr strstr
100//#define INVALID_HANDLE_VALUE 0
101//#ifndef _T
102//#define _T(s) s
103//#endif
104//#ifndef S_IWUSR
105//#define S_IWUSR 0000200
106//#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
107//#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
108//#endif
109////
110//#else
111//#include <windows.h>
112//#include <stdio.h>
113//#include <stdlib.h>
114//#include <string.h>
115//#include <tchar.h>
116//#include "unzip.h"
117//#endif
118////
119
120
121#include "unzip.h"
122
123#ifndef ZIP_STD
124#ifdef UNICODE
125#define _tsprintf swprintf
126#else
127#define _tsprintf sprintf_s
128#endif
129#endif
130
131// workaround for Windows warnings.
132#if defined(_MSC_VER)
133    #define FILENO _fileno
134    #define GETCWD _getcwd
135#else
136    #define FILENO fileno
137    #define GETCWD getcwd
138#endif
139
140
141
142#define ZIP_HANDLE   1
143#define ZIP_FILENAME 2
144#define ZIP_MEMORY   3
145
146
147#define zmalloc(len) malloc(len)
148
149#define zfree(p) free(p)
150
151typedef unsigned long lutime_t;       // define it ourselves since we don't include time.h
152
153/*
154void *zmalloc(unsigned int len)
155{ char *buf = new char[len+32];
156  for (int i=0; i<16; i++)
157  { buf[i]=i;
158    buf[len+31-i]=i;
159  }
160  *((unsigned int*)buf) = len;
161  char c[1000]; wsprintf(c,"malloc 0x%lx  - %lu",buf+16,len);
162  OutputDebugString(c);
163  return buf+16;
164}
165
166void zfree(void *buf)
167{ char c[1000]; wsprintf(c,"free   0x%lx",buf);
168  OutputDebugString(c);
169  char *p = ((char*)buf)-16;
170  unsigned int len = *((unsigned int*)p);
171  bool blown=false;
172  for (int i=0; i<16; i++)
173  { char lo = p[i];
174    char hi = p[len+31-i];
175    if (hi!=i || (lo!=i && i>4)) blown=true;
176  }
177  if (blown)
178  { OutputDebugString("BLOWN!!!");
179  }
180  delete[] p;
181}
182*/
183
184
185typedef struct tm_unz_s
186{ unsigned int tm_sec;            // seconds after the minute - [0,59]
187  unsigned int tm_min;            // minutes after the hour - [0,59]
188  unsigned int tm_hour;           // hours since midnight - [0,23]
189  unsigned int tm_mday;           // day of the month - [1,31]
190  unsigned int tm_mon;            // months since January - [0,11]
191  unsigned int tm_year;           // years - [1980..2044]
192} tm_unz;
193
194
195
196// ----------------------------------------------------------------------
197// some windows<->linux portability things
198#ifdef ZIP_STD
199DWORD GetFilePosU(HANDLE hfout)
200{ struct stat st; fstat(FILENO(hfout),&st);
201  if ((st.st_mode&S_IFREG)==0) return 0xFFFFFFFF;
202  return ftell(hfout);
203}
204
205bool FileExists(const TCHAR *fn)
206{ struct stat st;
207  int res=stat(fn,&st);
208  return (res==0);
209}
210
211FILETIME dosdatetime2filetime(WORD dosdate,WORD dostime)
212{ struct tm t;
213  t.tm_year = (WORD)(((dosdate>>9)&0x7f) + 1980 - 1900);
214  t.tm_isdst = -1;
215  t.tm_mon = (WORD)(((dosdate>>5)&0xf) - 1);
216  t.tm_mday = (WORD)(dosdate&0x1f);
217  t.tm_hour = (WORD)((dostime>>11)&0x1f);
218  t.tm_min = (WORD)((dostime>>5)&0x3f);
219  t.tm_sec = (WORD)((dostime&0x1f)*2);
220  time_t t2 = mktime(&t);
221  return t2;
222}
223
224void LocalFileTimeToFileTime(FILETIME *lft, FILETIME *ft)
225{ *ft = *lft;
226}
227
228FILETIME timet2filetime(const lutime_t t)
229{ return t;
230}
231
232#else
233// ----------------------------------------------------------------------
234DWORD GetFilePosU(HANDLE hfout)
235{ return SetFilePointer(hfout,0,0,FILE_CURRENT);
236}
237
238FILETIME timet2filetime(const lutime_t t)
239{ LONGLONG i = Int32x32To64(t,10000000) + 116444736000000000LL;
240  FILETIME ft;
241  ft.dwLowDateTime = (DWORD) i;
242  ft.dwHighDateTime = (DWORD)(i >>32);
243  return ft;
244}
245
246FILETIME dosdatetime2filetime(WORD dosdate,WORD dostime)
247{ // date: bits 0-4 are day of month 1-31. Bits 5-8 are month 1..12. Bits 9-15 are year-1980
248  // time: bits 0-4 are seconds/2, bits 5-10 are minute 0..59. Bits 11-15 are hour 0..23
249  SYSTEMTIME st;
250  st.wYear = (WORD)(((dosdate>>9)&0x7f) + 1980);
251  st.wMonth = (WORD)((dosdate>>5)&0xf);
252  st.wDay = (WORD)(dosdate&0x1f);
253  st.wHour = (WORD)((dostime>>11)&0x1f);
254  st.wMinute = (WORD)((dostime>>5)&0x3f);
255  st.wSecond = (WORD)((dostime&0x1f)*2);
256  st.wMilliseconds = 0;
257  FILETIME ft; SystemTimeToFileTime(&st,&ft);
258  return ft;
259}
260
261bool FileExists(const TCHAR *fn)
262{ return (GetFileAttributes(fn)!=0xFFFFFFFF);
263}
264#endif
265// ----------------------------------------------------------------------
266
267
268
269// unz_global_info structure contain global data about the ZIPfile
270typedef struct unz_global_info_s
271{ unsigned long number_entry;         // total number of entries in the central dir on this disk
272  unsigned long size_comment;         // size of the global comment of the zipfile
273} unz_global_info;
274
275// unz_file_info contain information about a file in the zipfile
276typedef struct unz_file_info_s
277{ unsigned long version;              // version made by                 2 bytes
278  unsigned long version_needed;       // version needed to extract       2 bytes
279  unsigned long flag;                 // general purpose bit flag        2 bytes
280  unsigned long compression_method;   // compression method              2 bytes
281  unsigned long dosDate;              // last mod file date in Dos fmt   4 bytes
282  unsigned long crc;                  // crc-32                          4 bytes
283  unsigned long compressed_size;      // compressed size                 4 bytes
284  unsigned long uncompressed_size;    // uncompressed size               4 bytes
285  unsigned long size_filename;        // filename length                 2 bytes
286  unsigned long size_file_extra;      // extra field length              2 bytes
287  unsigned long size_file_comment;    // file comment length             2 bytes
288  unsigned long disk_num_start;       // disk number start               2 bytes
289  unsigned long internal_fa;          // internal file attributes        2 bytes
290  unsigned long external_fa;          // external file attributes        4 bytes
291  tm_unz tmu_date;
292} unz_file_info;
293
294
295#define UNZ_OK                  (0)
296#define UNZ_END_OF_LIST_OF_FILE (-100)
297#define UNZ_ERRNO               (Z_ERRNO)
298#define UNZ_EOF                 (0)
299#define UNZ_PARAMERROR          (-102)
300#define UNZ_BADZIPFILE          (-103)
301#define UNZ_INTERNALERROR       (-104)
302#define UNZ_CRCERROR            (-105)
303#define UNZ_PASSWORD            (-106)
304
305
306
307
308
309
310
311#define ZLIB_VERSION "1.1.3"
312
313
314// Allowed flush values; see deflate() for details
315#define Z_NO_FLUSH      0
316#define Z_SYNC_FLUSH    2
317#define Z_FULL_FLUSH    3
318#define Z_FINISH        4
319
320
321// compression levels
322#define Z_NO_COMPRESSION         0
323#define Z_BEST_SPEED             1
324#define Z_BEST_COMPRESSION       9
325#define Z_DEFAULT_COMPRESSION  (-1)
326
327// compression strategy; see deflateInit2() for details
328#define Z_FILTERED            1
329#define Z_HUFFMAN_ONLY        2
330#define Z_DEFAULT_STRATEGY    0
331
332// Possible values of the data_type field
333#define Z_BINARY   0
334#define Z_ASCII    1
335#define Z_UNKNOWN  2
336
337// The deflate compression method (the only one supported in this version)
338#define Z_DEFLATED   8
339
340// for initializing zalloc, zfree, opaque
341#define Z_NULL  0
342
343// case sensitivity when searching for filenames
344#define CASE_SENSITIVE 1
345#define CASE_INSENSITIVE 2
346
347
348// Return codes for the compression/decompression functions. Negative
349// values are errors, positive values are used for special but normal events.
350#define Z_OK            0
351#define Z_STREAM_END    1
352#define Z_NEED_DICT     2
353#define Z_ERRNO        (-1)
354#define Z_STREAM_ERROR (-2)
355#define Z_DATA_ERROR   (-3)
356#define Z_MEM_ERROR    (-4)
357#define Z_BUF_ERROR    (-5)
358#define Z_VERSION_ERROR (-6)
359
360
361
362// Basic data types
363typedef unsigned char  Byte;  // 8 bits
364typedef unsigned int   uInt;  // 16 bits or more
365typedef unsigned long  uLong; // 32 bits or more
366typedef void *voidpf;
367typedef void     *voidp;
368typedef long z_off_t;
369
370
371
372
373
374
375
376
377
378
379
380
381typedef voidpf (*alloc_func) (voidpf opaque, uInt items, uInt size);
382typedef void   (*free_func)  (voidpf opaque, voidpf address);
383
384struct internal_state;
385
386typedef struct z_stream_s {
387    Byte    *next_in;  // next input byte
388    uInt     avail_in;  // number of bytes available at next_in
389    uLong    total_in;  // total nb of input bytes read so far
390
391    Byte    *next_out; // next output byte should be put there
392    uInt     avail_out; // remaining free space at next_out
393    uLong    total_out; // total nb of bytes output so far
394
395    char     *msg;      // last error message, NULL if no error
396    struct internal_state *state; // not visible by applications
397
398    alloc_func zalloc;  // used to allocate the internal state
399    free_func  zfree;   // used to free the internal state
400    voidpf     opaque;  // private data object passed to zalloc and zfree
401
402    int     data_type;  // best guess about the data type: ascii or binary
403    uLong   adler;      // adler32 value of the uncompressed data
404    uLong   reserved;   // reserved for future use
405} z_stream;
406
407typedef z_stream *z_streamp;
408
409
410//   The application must update next_in and avail_in when avail_in has
411//   dropped to zero. It must update next_out and avail_out when avail_out
412//   has dropped to zero. The application must initialize zalloc, zfree and
413//   opaque before calling the init function. All other fields are set by the
414//   compression library and must not be updated by the application.
415//
416//   The opaque value provided by the application will be passed as the first
417//   parameter for calls of zalloc and zfree. This can be useful for custom
418//   memory management. The compression library attaches no meaning to the
419//   opaque value.
420//
421//   zalloc must return Z_NULL if there is not enough memory for the object.
422//   If zlib is used in a multi-threaded application, zalloc and zfree must be
423//   thread safe.
424//
425//   The fields total_in and total_out can be used for statistics or
426//   progress reports. After compression, total_in holds the total size of
427//   the uncompressed data and may be saved for use in the decompressor
428//   (particularly if the decompressor wants to decompress everything in
429//   a single step).
430//
431
432
433// basic functions
434
435const char *zlibVersion ();
436// The application can compare zlibVersion and ZLIB_VERSION for consistency.
437// If the first character differs, the library code actually used is
438// not compatible with the zlib.h header file used by the application.
439// This check is automatically made by inflateInit.
440
441
442
443
444
445
446int inflate (z_streamp strm, int flush);
447//
448//    inflate decompresses as much data as possible, and stops when the input
449//  buffer becomes empty or the output buffer becomes full. It may some
450//  introduce some output latency (reading input without producing any output)
451//  except when forced to flush.
452//
453//  The detailed semantics are as follows. inflate performs one or both of the
454//  following actions:
455//
456//  - Decompress more input starting at next_in and update next_in and avail_in
457//    accordingly. If not all input can be processed (because there is not
458//    enough room in the output buffer), next_in is updated and processing
459//    will resume at this point for the next call of inflate().
460//
461//  - Provide more output starting at next_out and update next_out and avail_out
462//    accordingly.  inflate() provides as much output as possible, until there
463//    is no more input data or no more space in the output buffer (see below
464//    about the flush parameter).
465//
466//  Before the call of inflate(), the application should ensure that at least
467//  one of the actions is possible, by providing more input and/or consuming
468//  more output, and updating the next_* and avail_* values accordingly.
469//  The application can consume the uncompressed output when it wants, for
470//  example when the output buffer is full (avail_out == 0), or after each
471//  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
472//  must be called again after making room in the output buffer because there
473//  might be more output pending.
474//
475//    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
476//  output as possible to the output buffer. The flushing behavior of inflate is
477//  not specified for values of the flush parameter other than Z_SYNC_FLUSH
478//  and Z_FINISH, but the current implementation actually flushes as much output
479//  as possible anyway.
480//
481//    inflate() should normally be called until it returns Z_STREAM_END or an
482//  error. However if all decompression is to be performed in a single step
483//  (a single call of inflate), the parameter flush should be set to
484//  Z_FINISH. In this case all pending input is processed and all pending
485//  output is flushed; avail_out must be large enough to hold all the
486//  uncompressed data. (The size of the uncompressed data may have been saved
487//  by the compressor for this purpose.) The next operation on this stream must
488//  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
489//  is never required, but can be used to inform inflate that a faster routine
490//  may be used for the single inflate() call.
491//
492//     If a preset dictionary is needed at this point (see inflateSetDictionary
493//  below), inflate sets strm-adler to the adler32 checksum of the
494//  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
495//  it sets strm->adler to the adler32 checksum of all output produced
496//  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
497//  an error code as described below. At the end of the stream, inflate()
498//  checks that its computed adler32 checksum is equal to that saved by the
499//  compressor and returns Z_STREAM_END only if the checksum is correct.
500//
501//    inflate() returns Z_OK if some progress has been made (more input processed
502//  or more output produced), Z_STREAM_END if the end of the compressed data has
503//  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
504//  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
505//  corrupted (input stream not conforming to the zlib format or incorrect
506//  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
507//  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
508//  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
509//  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
510//  case, the application may then call inflateSync to look for a good
511//  compression block.
512//
513
514
515int inflateEnd (z_streamp strm);
516//
517//     All dynamically allocated data structures for this stream are freed.
518//   This function discards any unprocessed input and does not flush any
519//   pending output.
520//
521//     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
522//   was inconsistent. In the error case, msg may be set but then points to a
523//   static string (which must not be deallocated).
524
525                        // Advanced functions
526
527//  The following functions are needed only in some special applications.
528
529
530
531
532
533int inflateSetDictionary (z_streamp strm,
534                                             const Byte *dictionary,
535                                             uInt  dictLength);
536//
537//     Initializes the decompression dictionary from the given uncompressed byte
538//   sequence. This function must be called immediately after a call of inflate
539//   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
540//   can be determined from the Adler32 value returned by this call of
541//   inflate. The compressor and decompressor must use exactly the same
542//   dictionary.
543//
544//     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
545//   parameter is invalid (such as NULL dictionary) or the stream state is
546//   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
547//   expected one (incorrect Adler32 value). inflateSetDictionary does not
548//   perform any decompression: this will be done by subsequent calls of
549//   inflate().
550
551
552int inflateSync (z_streamp strm);
553//
554//    Skips invalid compressed data until a full flush point can be found, or until all
555//  available input is skipped. No output is provided.
556//
557//    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
558//  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
559//  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
560//  case, the application may save the current current value of total_in which
561//  indicates where valid compressed data was found. In the error case, the
562//  application may repeatedly call inflateSync, providing more input each time,
563//  until success or end of the input data.
564
565
566int inflateReset (z_streamp strm);
567//     This function is equivalent to inflateEnd followed by inflateInit,
568//   but does not free and reallocate all the internal decompression state.
569//   The stream will keep attributes that may have been set by inflateInit2.
570//
571//      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
572//   stream state was inconsistent (such as zalloc or state being NULL).
573//
574
575
576
577// checksum functions
578// These functions are not related to compression but are exported
579// anyway because they might be useful in applications using the
580// compression library.
581
582uLong adler32 (uLong adler, const Byte *buf, uInt len);
583//     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
584//   return the updated checksum. If buf is NULL, this function returns
585//   the required initial value for the checksum.
586//   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
587//   much faster. Usage example:
588//
589//     uLong adler = adler32(0L, Z_NULL, 0);
590//
591//     while (read_buffer(buffer, length) != EOF) {
592//       adler = adler32(adler, buffer, length);
593//     }
594//     if (adler != original_adler) error();
595
596uLong ucrc32   (uLong crc, const Byte *buf, uInt len);
597//     Update a running crc with the bytes buf[0..len-1] and return the updated
598//   crc. If buf is NULL, this function returns the required initial value
599//   for the crc. Pre- and post-conditioning (one's complement) is performed
600//   within this function so it shouldn't be done by the application.
601//   Usage example:
602//
603//     uLong crc = crc32(0L, Z_NULL, 0);
604//
605//     while (read_buffer(buffer, length) != EOF) {
606//       crc = crc32(crc, buffer, length);
607//     }
608//     if (crc != original_crc) error();
609
610
611
612
613const char   *zError           (int err);
614int           inflateSyncPoint (z_streamp z);
615const uLong *get_crc_table    (void);
616
617
618
619typedef unsigned char  uch;
620typedef uch uchf;
621typedef unsigned short ush;
622typedef ush ushf;
623typedef unsigned long  ulg;
624
625
626
627const char * const z_errmsg[10] = { // indexed by 2-zlib_error
628"need dictionary",     // Z_NEED_DICT       2
629"stream end",          // Z_STREAM_END      1
630"",                    // Z_OK              0
631"file error",          // Z_ERRNO         (-1)
632"stream error",        // Z_STREAM_ERROR  (-2)
633"data error",          // Z_DATA_ERROR    (-3)
634"insufficient memory", // Z_MEM_ERROR     (-4)
635"buffer error",        // Z_BUF_ERROR     (-5)
636"incompatible version",// Z_VERSION_ERROR (-6)
637""};
638
639
640#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
641
642#define ERR_RETURN(strm,err) \
643  return (strm->msg = (char*)ERR_MSG(err), (err))
644// To be used only when the state is known to be valid
645
646        // common constants
647
648
649#define STORED_BLOCK 0
650#define STATIC_TREES 1
651#define DYN_TREES    2
652// The three kinds of block type
653
654#define MIN_MATCH  3
655#define MAX_MATCH  258
656// The minimum and maximum match lengths
657
658#define PRESET_DICT 0x20 // preset dictionary flag in zlib header
659
660        // target dependencies
661
662#define OS_CODE  0x0b  // Window 95 & Windows NT
663
664
665
666         // functions
667
668#define zmemzero(dest, len) memset(dest, 0, len)
669
670// Diagnostic functions
671#define LuAssert(cond,msg)
672#define LuTrace(x)
673#define LuTracev(x)
674#define LuTracevv(x)
675#define LuTracec(c,x)
676#define LuTracecv(c,x)
677
678
679typedef uLong (*check_func) (uLong check, const Byte *buf, uInt len);
680voidpf zcalloc (voidpf opaque, unsigned items, unsigned size);
681void   zcfree  (voidpf opaque, voidpf ptr);
682
683#define ZALLOC(strm, items, size) \
684           (*((strm)->zalloc))((strm)->opaque, (items), (size))
685#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
686
687//void ZFREE(z_streamp strm,voidpf addr)
688//{ *((strm)->zfree))((strm)->opaque, addr);
689//}
690
691#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
692
693
694
695
696// Huffman code lookup table entry--this entry is four bytes for machines
697// that have 16-bit pointers (e.g. PC's in the small or medium model).
698
699
700typedef struct inflate_huft_s inflate_huft;
701
702struct inflate_huft_s {
703  union {
704    struct {
705      Byte Exop;        // number of extra bits or operation
706      Byte Bits;        // number of bits in this code or subcode
707    } what;
708    uInt pad;           // pad structure to a power of 2 (4 bytes for
709  } word;               //  16-bit, 8 bytes for 32-bit int's)
710  uInt base;            // literal, length base, distance base, or table offset
711};
712
713// Maximum size of dynamic tree.  The maximum found in a long but non-
714//   exhaustive search was 1004 huft structures (850 for length/literals
715//   and 154 for distances, the latter actually the result of an
716//   exhaustive search).  The actual maximum is not known, but the
717//   value below is more than safe.
718#define MANY 1440
719
720int inflate_trees_bits (
721    uInt *,                    // 19 code lengths
722    uInt *,                    // bits tree desired/actual depth
723    inflate_huft * *,       // bits tree result
724    inflate_huft *,             // space for trees
725    z_streamp);                // for messages
726
727int inflate_trees_dynamic (
728    uInt,                       // number of literal/length codes
729    uInt,                       // number of distance codes
730    uInt *,                    // that many (total) code lengths
731    uInt *,                    // literal desired/actual bit depth
732    uInt *,                    // distance desired/actual bit depth
733    inflate_huft * *,       // literal/length tree result
734    inflate_huft * *,       // distance tree result
735    inflate_huft *,             // space for trees
736    z_streamp);                // for messages
737
738int inflate_trees_fixed (
739    uInt *,                    // literal desired/actual bit depth
740    uInt *,                    // distance desired/actual bit depth
741    const inflate_huft * *,       // literal/length tree result
742    const inflate_huft * *,       // distance tree result
743    z_streamp);                // for memory allocation
744
745
746
747
748
749struct inflate_blocks_state;
750typedef struct inflate_blocks_state inflate_blocks_statef;
751
752inflate_blocks_statef * inflate_blocks_new (
753    z_streamp z,
754    check_func c,               // check function
755    uInt w);                   // window size
756
757int inflate_blocks (
758    inflate_blocks_statef *,
759    z_streamp ,
760    int);                      // initial return code
761
762void inflate_blocks_reset (
763    inflate_blocks_statef *,
764    z_streamp ,
765    uLong *);                  // check value on output
766
767int inflate_blocks_free (
768    inflate_blocks_statef *,
769    z_streamp);
770
771void inflate_set_dictionary (
772    inflate_blocks_statef *s,
773    const Byte *d,  // dictionary
774    uInt  n);       // dictionary length
775
776int inflate_blocks_sync_point (
777    inflate_blocks_statef *s);
778
779
780
781
782struct inflate_codes_state;
783typedef struct inflate_codes_state inflate_codes_statef;
784
785inflate_codes_statef *inflate_codes_new (
786    uInt, uInt,
787    const inflate_huft *, const inflate_huft *,
788    z_streamp );
789
790int inflate_codes (
791    inflate_blocks_statef *,
792    z_streamp ,
793    int);
794
795void inflate_codes_free (
796    inflate_codes_statef *,
797    z_streamp );
798
799
800
801
802typedef enum {
803      IBM_TYPE,     // get type bits (3, including end bit)
804      IBM_LENS,     // get lengths for stored
805      IBM_STORED,   // processing stored block
806      IBM_TABLE,    // get table lengths
807      IBM_BTREE,    // get bit lengths tree for a dynamic block
808      IBM_DTREE,    // get length, distance trees for a dynamic block
809      IBM_CODES,    // processing fixed or dynamic block
810      IBM_DRY,      // output remaining window bytes
811      IBM_DONE,     // finished last block, done
812      IBM_BAD}      // got a data error--stuck here
813inflate_block_mode;
814
815// inflate blocks semi-private state
816struct inflate_blocks_state {
817
818  // mode
819  inflate_block_mode  mode;     // current inflate_block mode
820
821  // mode dependent information
822  union {
823    uInt left;          // if STORED, bytes left to copy
824    struct {
825      uInt table;               // table lengths (14 bits)
826      uInt index;               // index into blens (or border)
827      uInt *blens;             // bit lengths of codes
828      uInt bb;                  // bit length tree depth
829      inflate_huft *tb;         // bit length decoding tree
830    } trees;            // if DTREE, decoding info for trees
831    struct {
832      inflate_codes_statef
833         *codes;
834    } decode;           // if CODES, current state
835  } sub;                // submode
836  uInt last;            // true if this block is the last block
837
838  // mode independent information
839  uInt bitk;            // bits in bit buffer
840  uLong bitb;           // bit buffer
841  inflate_huft *hufts;  // single malloc for tree space
842  Byte *window;        // sliding window
843  Byte *end;           // one byte after sliding window
844  Byte *read;          // window read pointer
845  Byte *write;         // window write pointer
846  check_func checkfn;   // check function
847  uLong check;          // check on output
848
849};
850
851
852// defines for inflate input/output
853//   update pointers and return
854#define UPDBITS {s->bitb=b;s->bitk=k;}
855#define UPDIN {z->avail_in=n;z->total_in+=(uLong)(p-z->next_in);z->next_in=p;}
856#define UPDOUT {s->write=q;}
857#define UPDATE {UPDBITS UPDIN UPDOUT}
858#define LEAVE {UPDATE return inflate_flush(s,z,r);}
859//   get bytes and bits
860#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
861#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
862#define NEXTBYTE (n--,*p++)
863#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
864#define DUMPBITS(j) {b>>=(j);k-=(j);}
865//   output bytes
866#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
867#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
868#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
869#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
870#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
871#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
872//   load local pointers
873#define LOAD {LOADIN LOADOUT}
874
875// masks for lower bits (size given to avoid silly warnings with Visual C++)
876// And'ing with mask[n] masks the lower n bits
877const uInt inflate_mask[17] = {
878    0x0000,
879    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
880    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
881};
882
883// copy as much as possible from the sliding window to the output area
884int inflate_flush (inflate_blocks_statef *, z_streamp, int);
885
886int inflate_fast (uInt, uInt, const inflate_huft *, const inflate_huft *, inflate_blocks_statef *, z_streamp );
887
888
889
890const uInt fixed_bl = 9;
891const uInt fixed_bd = 5;
892const inflate_huft fixed_tl[] = {
893    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
894    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
895    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
896    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
897    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
898    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
899    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
900    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
901    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
902    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
903    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
904    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
905    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
906    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
907    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
908    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
909    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
910    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
911    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
912    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
913    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
914    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
915    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
916    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
917    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
918    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
919    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
920    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
921    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
922    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
923    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
924    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
925    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
926    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
927    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
928    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
929    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
930    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
931    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
932    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
933    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
934    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
935    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
936    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
937    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
938    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
939    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
940    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
941    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
942    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
943    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
944    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
945    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
946    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
947    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
948    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
949    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
950    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
951    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
952    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
953    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
954    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
955    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
956    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
957    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
958    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
959    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
960    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
961    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
962    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
963    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
964    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
965    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
966    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
967    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
968    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
969    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
970    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
971    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
972    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
973    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
974    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
975    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
976    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
977    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
978    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
979    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
980    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
981    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
982    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
983    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
984    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
985    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
986    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
987    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
988    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
989    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
990    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
991    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
992    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
993    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
994    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
995    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
996    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
997    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
998    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
999    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
1000    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
1001    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
1002    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
1003    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
1004    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
1005    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
1006    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
1007    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
1008    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
1009    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
1010    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
1011    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
1012    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
1013    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
1014    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
1015    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
1016    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
1017    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
1018    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
1019    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
1020    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
1021  };
1022const inflate_huft fixed_td[] = {
1023    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
1024    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
1025    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
1026    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
1027    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
1028    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
1029    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
1030    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
1031  };
1032
1033
1034
1035
1036
1037
1038
1039// copy as much as possible from the sliding window to the output area
1040int inflate_flush(inflate_blocks_statef *s,z_streamp z,int r)
1041{
1042  uInt n;
1043  Byte *p;
1044  Byte *q;
1045
1046  // local copies of source and destination pointers
1047  p = z->next_out;
1048  q = s->read;
1049
1050  // compute number of bytes to copy as far as end of window
1051  n = (uInt)((q <= s->write ? s->write : s->end) - q);
1052  if (n > z->avail_out) n = z->avail_out;
1053  if (n && r == Z_BUF_ERROR) r = Z_OK;
1054
1055  // update counters
1056  z->avail_out -= n;
1057  z->total_out += n;
1058
1059  // update check information
1060  if (s->checkfn != Z_NULL)
1061    z->adler = s->check = (*s->checkfn)(s->check, q, n);
1062
1063  // copy as far as end of window
1064  if (n!=0)          // check for n!=0 to avoid waking up CodeGuard
1065  { memcpy(p, q, n);
1066    p += n;
1067    q += n;
1068  }
1069
1070  // see if more to copy at beginning of window
1071  if (q == s->end)
1072  {
1073    // wrap pointers
1074    q = s->window;
1075    if (s->write == s->end)
1076      s->write = s->window;
1077
1078    // compute bytes to copy
1079    n = (uInt)(s->write - q);
1080    if (n > z->avail_out) n = z->avail_out;
1081    if (n && r == Z_BUF_ERROR) r = Z_OK;
1082
1083    // update counters
1084    z->avail_out -= n;
1085    z->total_out += n;
1086
1087    // update check information
1088    if (s->checkfn != Z_NULL)
1089      z->adler = s->check = (*s->checkfn)(s->check, q, n);
1090
1091    // copy
1092    if (n!=0) {memcpy(p,q,n); p+=n; q+=n;}
1093  }
1094
1095  // update pointers
1096  z->next_out = p;
1097  s->read = q;
1098
1099  // done
1100  return r;
1101}
1102
1103
1104
1105
1106
1107
1108// simplify the use of the inflate_huft type with some defines
1109#define exop word.what.Exop
1110#define bits word.what.Bits
1111
1112typedef enum {        // waiting for "i:"=input, "o:"=output, "x:"=nothing
1113      START,    // x: set up for LEN
1114      LEN,      // i: get length/literal/eob next
1115      LENEXT,   // i: getting length extra (have base)
1116      DIST,     // i: get distance next
1117      DISTEXT,  // i: getting distance extra
1118      COPY,     // o: copying bytes in window, waiting for space
1119      LIT,      // o: got literal, waiting for output space
1120      WASH,     // o: got eob, possibly still output waiting
1121      END,      // x: got eob and all data flushed
1122      BADCODE}  // x: got error
1123inflate_codes_mode;
1124
1125// inflate codes private state
1126struct inflate_codes_state {
1127
1128  // mode
1129  inflate_codes_mode mode;      // current inflate_codes mode
1130
1131  // mode dependent information
1132  uInt len;
1133  union {
1134    struct {
1135      const inflate_huft *tree;       // pointer into tree
1136      uInt need;                // bits needed
1137    } code;             // if LEN or DIST, where in tree
1138    uInt lit;           // if LIT, literal
1139    struct {
1140      uInt get;                 // bits to get for extra
1141      uInt dist;                // distance back to copy from
1142    } copy;             // if EXT or COPY, where and how much
1143  } sub;                // submode
1144
1145  // mode independent information
1146  Byte lbits;           // ltree bits decoded per branch
1147  Byte dbits;           // dtree bits decoder per branch
1148  const inflate_huft *ltree;          // literal/length/eob tree
1149  const inflate_huft *dtree;          // distance tree
1150
1151};
1152
1153
1154inflate_codes_statef *inflate_codes_new(
1155uInt bl, uInt bd,
1156const inflate_huft *tl,
1157const inflate_huft *td, // need separate declaration for Borland C++
1158z_streamp z)
1159{
1160  inflate_codes_statef *c;
1161
1162  if ((c = (inflate_codes_statef *)
1163       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
1164  {
1165    c->mode = START;
1166    c->lbits = (Byte)bl;
1167    c->dbits = (Byte)bd;
1168    c->ltree = tl;
1169    c->dtree = td;
1170    LuTracev((stderr, "inflate:       codes new\n"));
1171  }
1172  return c;
1173}
1174
1175
1176int inflate_codes(inflate_blocks_statef *s, z_streamp z, int r)
1177{
1178  uInt j;               // temporary storage
1179  const inflate_huft *t;      // temporary pointer
1180  uInt e;               // extra bits or operation
1181  uLong b;              // bit buffer
1182  uInt k;               // bits in bit buffer
1183  Byte *p;             // input data pointer
1184  uInt n;               // bytes available there
1185  Byte *q;             // output window write pointer
1186  uInt m;               // bytes to end of window or read pointer
1187  Byte *f;             // pointer to copy strings from
1188  inflate_codes_statef *c = s->sub.decode.codes;  // codes state
1189
1190  // copy input/output information to locals (UPDATE macro restores)
1191  LOAD
1192
1193  // process input and output based on current state
1194  for(;;) switch (c->mode)
1195  {             // waiting for "i:"=input, "o:"=output, "x:"=nothing
1196    case START:         // x: set up for LEN
1197#ifndef SLOW
1198      if (m >= 258 && n >= 10)
1199      {
1200        UPDATE
1201        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
1202        LOAD
1203        if (r != Z_OK)
1204        {
1205          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
1206          break;
1207        }
1208      }
1209#endif // !SLOW
1210      c->sub.code.need = c->lbits;
1211      c->sub.code.tree = c->ltree;
1212      c->mode = LEN;
1213    case LEN:           // i: get length/literal/eob next
1214      j = c->sub.code.need;
1215      NEEDBITS(j)
1216      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
1217      DUMPBITS(t->bits)
1218      e = (uInt)(t->exop);
1219      if (e == 0)               // literal
1220      {
1221        c->sub.lit = t->base;
1222        LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
1223                 "inflate:         literal '%c'\n" :
1224                 "inflate:         literal 0x%02x\n", t->base));
1225        c->mode = LIT;
1226        break;
1227      }
1228      if (e & 16)               // length
1229      {
1230        c->sub.copy.get = e & 15;
1231        c->len = t->base;
1232        c->mode = LENEXT;
1233        break;
1234      }
1235      if ((e & 64) == 0)        // next table
1236      {
1237        c->sub.code.need = e;
1238        c->sub.code.tree = t + t->base;
1239        break;
1240      }
1241      if (e & 32)               // end of block
1242      {
1243        LuTracevv((stderr, "inflate:         end of block\n"));
1244        c->mode = WASH;
1245        break;
1246      }
1247      c->mode = BADCODE;        // invalid code
1248      z->msg = (char*)"invalid literal/length code";
1249      r = Z_DATA_ERROR;
1250      LEAVE
1251    case LENEXT:        // i: getting length extra (have base)
1252      j = c->sub.copy.get;
1253      NEEDBITS(j)
1254      c->len += (uInt)b & inflate_mask[j];
1255      DUMPBITS(j)
1256      c->sub.code.need = c->dbits;
1257      c->sub.code.tree = c->dtree;
1258      LuTracevv((stderr, "inflate:         length %u\n", c->len));
1259      c->mode = DIST;
1260    case DIST:          // i: get distance next
1261      j = c->sub.code.need;
1262      NEEDBITS(j)
1263      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
1264      DUMPBITS(t->bits)
1265      e = (uInt)(t->exop);
1266      if (e & 16)               // distance
1267      {
1268        c->sub.copy.get = e & 15;
1269        c->sub.copy.dist = t->base;
1270        c->mode = DISTEXT;
1271        break;
1272      }
1273      if ((e & 64) == 0)        // next table
1274      {
1275        c->sub.code.need = e;
1276        c->sub.code.tree = t + t->base;
1277        break;
1278      }
1279      c->mode = BADCODE;        // invalid code
1280      z->msg = (char*)"invalid distance code";
1281      r = Z_DATA_ERROR;
1282      LEAVE
1283    case DISTEXT:       // i: getting distance extra
1284      j = c->sub.copy.get;
1285      NEEDBITS(j)
1286      c->sub.copy.dist += (uInt)b & inflate_mask[j];
1287      DUMPBITS(j)
1288      LuTracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
1289      c->mode = COPY;
1290    case COPY:          // o: copying bytes in window, waiting for space
1291      f = q - c->sub.copy.dist;
1292      while (f < s->window)             // modulo window size-"while" instead
1293        f += s->end - s->window;        // of "if" handles invalid distances
1294      while (c->len)
1295      {
1296        NEEDOUT
1297        OUTBYTE(*f++)
1298        if (f == s->end)
1299          f = s->window;
1300        c->len--;
1301      }
1302      c->mode = START;
1303      break;
1304    case LIT:           // o: got literal, waiting for output space
1305      NEEDOUT
1306      OUTBYTE(c->sub.lit)
1307      c->mode = START;
1308      break;
1309    case WASH:          // o: got eob, possibly more output
1310      if (k > 7)        // return unused byte, if any
1311      {
1312        //Assert(k < 16, "inflate_codes grabbed too many bytes")
1313        k -= 8;
1314        n++;
1315        p--;            // can always return one
1316      }
1317      FLUSH
1318      if (s->read != s->write)
1319        LEAVE
1320      c->mode = END;
1321    case END:
1322      r = Z_STREAM_END;
1323      LEAVE
1324    case BADCODE:       // x: got error
1325      r = Z_DATA_ERROR;
1326      LEAVE
1327    default:
1328      r = Z_STREAM_ERROR;
1329      LEAVE
1330  }
1331}
1332
1333
1334void inflate_codes_free(inflate_codes_statef *c,z_streamp z)
1335{ ZFREE(z, c);
1336  LuTracev((stderr, "inflate:       codes free\n"));
1337}
1338
1339
1340
1341// infblock.c -- interpret and process block types to last block
1342// Copyright (C) 1995-1998 Mark Adler
1343// For conditions of distribution and use, see copyright notice in zlib.h
1344
1345//struct inflate_codes_state {int dummy;}; // for buggy compilers
1346
1347
1348
1349// Table for deflate from PKZIP's appnote.txt.
1350const uInt border[] = { // Order of the bit length code lengths
1351        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
1352
1353//
1354// Notes beyond the 1.93a appnote.txt:
1355//
1356// 1. Distance pointers never point before the beginning of the output stream.
1357// 2. Distance pointers can point back across blocks, up to 32k away.
1358// 3. There is an implied maximum of 7 bits for the bit length table and
1359//    15 bits for the actual data.
1360// 4. If only one code exists, then it is encoded using one bit.  (Zero
1361//    would be more efficient, but perhaps a little confusing.)  If two
1362//    codes exist, they are coded using one bit each (0 and 1).
1363// 5. There is no way of sending zero distance codes--a dummy must be
1364//    sent if there are none.  (History: a pre 2.0 version of PKZIP would
1365//    store blocks with no distance codes, but this was discovered to be
1366//    too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
1367//    zero distance codes, which is sent as one code of zero bits in
1368//    length.
1369// 6. There are up to 286 literal/length codes.  Code 256 represents the
1370//    end-of-block.  Note however that the static length tree defines
1371//    288 codes just to fill out the Huffman codes.  Codes 286 and 287
1372//    cannot be used though, since there is no length base or extra bits
1373//    defined for them.  Similarily, there are up to 30 distance codes.
1374//    However, static trees define 32 codes (all 5 bits) to fill out the
1375//    Huffman codes, but the last two had better not show up in the data.
1376// 7. Unzip can check dynamic Huffman blocks for complete code sets.
1377//    The exception is that a single code would not be complete (see #4).
1378// 8. The five bits following the block type is really the number of
1379//    literal codes sent minus 257.
1380// 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
1381//    (1+6+6).  Therefore, to output three times the length, you output
1382//    three codes (1+1+1), whereas to output four times the same length,
1383//    you only need two codes (1+3).  Hmm.
1384//10. In the tree reconstruction algorithm, Code = Code + Increment
1385//    only if BitLength(i) is not zero.  (Pretty obvious.)
1386//11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
1387//12. Note: length code 284 can represent 227-258, but length code 285
1388//    really is 258.  The last length deserves its own, short code
1389//    since it gets used a lot in very redundant files.  The length
1390//    258 is special since 258 - 3 (the min match length) is 255.
1391//13. The literal/length and distance code bit lengths are read as a
1392//    single stream of lengths.  It is possible (and advantageous) for
1393//    a repeat code (16, 17, or 18) to go across the boundary between
1394//    the two sets of lengths.
1395
1396
1397void inflate_blocks_reset(inflate_blocks_statef *s, z_streamp z, uLong *c)
1398{
1399  if (c != Z_NULL)
1400    *c = s->check;
1401  if (s->mode == IBM_BTREE || s->mode == IBM_DTREE)
1402    ZFREE(z, s->sub.trees.blens);
1403  if (s->mode == IBM_CODES)
1404    inflate_codes_free(s->sub.decode.codes, z);
1405  s->mode = IBM_TYPE;
1406  s->bitk = 0;
1407  s->bitb = 0;
1408  s->read = s->write = s->window;
1409  if (s->checkfn != Z_NULL)
1410    z->adler = s->check = (*s->checkfn)(0L, (const Byte *)Z_NULL, 0);
1411  LuTracev((stderr, "inflate:   blocks reset\n"));
1412}
1413
1414
1415inflate_blocks_statef *inflate_blocks_new(z_streamp z, check_func c, uInt w)
1416{
1417  inflate_blocks_statef *s;
1418
1419  if ((s = (inflate_blocks_statef *)ZALLOC
1420       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
1421    return s;
1422  if ((s->hufts =
1423       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
1424  {
1425    ZFREE(z, s);
1426    return Z_NULL;
1427  }
1428  if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL)
1429  {
1430    ZFREE(z, s->hufts);
1431    ZFREE(z, s);
1432    return Z_NULL;
1433  }
1434  s->end = s->window + w;
1435  s->checkfn = c;
1436  s->mode = IBM_TYPE;
1437  LuTracev((stderr, "inflate:   blocks allocated\n"));
1438  inflate_blocks_reset(s, z, Z_NULL);
1439  return s;
1440}
1441
1442
1443int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r)
1444{
1445  uInt t;               // temporary storage
1446  uLong b;              // bit buffer
1447  uInt k;               // bits in bit buffer
1448  Byte *p;             // input data pointer
1449  uInt n;               // bytes available there
1450  Byte *q;             // output window write pointer
1451  uInt m;               // bytes to end of window or read pointer
1452
1453  // copy input/output information to locals (UPDATE macro restores)
1454  LOAD
1455
1456  // process input based on current state
1457  for(;;) switch (s->mode)
1458  {
1459    case IBM_TYPE:
1460      NEEDBITS(3)
1461      t = (uInt)b & 7;
1462      s->last = t & 1;
1463      switch (t >> 1)
1464      {
1465        case 0:                         // stored
1466          LuTracev((stderr, "inflate:     stored block%s\n",
1467                 s->last ? " (last)" : ""));
1468          DUMPBITS(3)
1469          t = k & 7;                    // go to byte boundary
1470          DUMPBITS(t)
1471          s->mode = IBM_LENS;               // get length of stored block
1472          break;
1473        case 1:                         // fixed
1474          LuTracev((stderr, "inflate:     fixed codes block%s\n",
1475                 s->last ? " (last)" : ""));
1476          {
1477            uInt bl, bd;
1478            const inflate_huft *tl, *td;
1479
1480            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
1481            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
1482            if (s->sub.decode.codes == Z_NULL)
1483            {
1484              r = Z_MEM_ERROR;
1485              LEAVE
1486            }
1487          }
1488          DUMPBITS(3)
1489          s->mode = IBM_CODES;
1490          break;
1491        case 2:                         // dynamic
1492          LuTracev((stderr, "inflate:     dynamic codes block%s\n",
1493                 s->last ? " (last)" : ""));
1494          DUMPBITS(3)
1495          s->mode = IBM_TABLE;
1496          break;
1497        case 3:                         // illegal
1498          DUMPBITS(3)
1499          s->mode = IBM_BAD;
1500          z->msg = (char*)"invalid block type";
1501          r = Z_DATA_ERROR;
1502          LEAVE
1503      }
1504      break;
1505    case IBM_LENS:
1506      NEEDBITS(32)
1507      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
1508      {
1509        s->mode = IBM_BAD;
1510        z->msg = (char*)"invalid stored block lengths";
1511        r = Z_DATA_ERROR;
1512        LEAVE
1513      }
1514      s->sub.left = (uInt)b & 0xffff;
1515      b = k = 0;                      // dump bits
1516      LuTracev((stderr, "inflate:       stored length %u\n", s->sub.left));
1517      s->mode = s->sub.left ? IBM_STORED : (s->last ? IBM_DRY : IBM_TYPE);
1518      break;
1519    case IBM_STORED:
1520      if (n == 0)
1521        LEAVE
1522      NEEDOUT
1523      t = s->sub.left;
1524      if (t > n) t = n;
1525      if (t > m) t = m;
1526      memcpy(q, p, t);
1527      p += t;  n -= t;
1528      q += t;  m -= t;
1529      if ((s->sub.left -= t) != 0)
1530        break;
1531      LuTracev((stderr, "inflate:       stored end, %lu total out\n",
1532              z->total_out + (q >= s->read ? q - s->read :
1533              (s->end - s->read) + (q - s->window))));
1534      s->mode = s->last ? IBM_DRY : IBM_TYPE;
1535      break;
1536    case IBM_TABLE:
1537      NEEDBITS(14)
1538      s->sub.trees.table = t = (uInt)b & 0x3fff;
1539      // remove this section to workaround bug in pkzip
1540      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
1541      {
1542        s->mode = IBM_BAD;
1543        z->msg = (char*)"too many length or distance symbols";
1544        r = Z_DATA_ERROR;
1545        LEAVE
1546      }
1547      // end remove
1548      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
1549      if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
1550      {
1551        r = Z_MEM_ERROR;
1552        LEAVE
1553      }
1554      DUMPBITS(14)
1555      s->sub.trees.index = 0;
1556      LuTracev((stderr, "inflate:       table sizes ok\n"));
1557      s->mode = IBM_BTREE;
1558    case IBM_BTREE:
1559      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
1560      {
1561        NEEDBITS(3)
1562        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
1563        DUMPBITS(3)
1564      }
1565      while (s->sub.trees.index < 19)
1566        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
1567      s->sub.trees.bb = 7;
1568      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
1569                             &s->sub.trees.tb, s->hufts, z);
1570      if (t != Z_OK)
1571      {
1572        r = t;
1573        if (r == Z_DATA_ERROR)
1574        {
1575          ZFREE(z, s->sub.trees.blens);
1576          s->mode = IBM_BAD;
1577        }
1578        LEAVE
1579      }
1580      s->sub.trees.index = 0;
1581      LuTracev((stderr, "inflate:       bits tree ok\n"));
1582      s->mode = IBM_DTREE;
1583    case IBM_DTREE:
1584      while (t = s->sub.trees.table,
1585             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
1586      {
1587        inflate_huft *h;
1588        uInt i, j, c;
1589
1590        t = s->sub.trees.bb;
1591        NEEDBITS(t)
1592        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
1593        t = h->bits;
1594        c = h->base;
1595        if (c < 16)
1596        {
1597          DUMPBITS(t)
1598          s->sub.trees.blens[s->sub.trees.index++] = c;
1599        }
1600        else // c == 16..18
1601        {
1602          i = c == 18 ? 7 : c - 14;
1603          j = c == 18 ? 11 : 3;
1604          NEEDBITS(t + i)
1605          DUMPBITS(t)
1606          j += (uInt)b & inflate_mask[i];
1607          DUMPBITS(i)
1608          i = s->sub.trees.index;
1609          t = s->sub.trees.table;
1610          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
1611              (c == 16 && i < 1))
1612          {
1613            ZFREE(z, s->sub.trees.blens);
1614            s->mode = IBM_BAD;
1615            z->msg = (char*)"invalid bit length repeat";
1616            r = Z_DATA_ERROR;
1617            LEAVE
1618          }
1619          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
1620          do {
1621            s->sub.trees.blens[i++] = c;
1622          } while (--j);
1623          s->sub.trees.index = i;
1624        }
1625      }
1626      s->sub.trees.tb = Z_NULL;
1627      {
1628        uInt bl, bd;
1629        inflate_huft *tl, *td;
1630        inflate_codes_statef *c;
1631
1632        bl = 9;         // must be <= 9 for lookahead assumptions
1633        bd = 6;         // must be <= 9 for lookahead assumptions
1634        t = s->sub.trees.table;
1635        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
1636                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
1637                                  s->hufts, z);
1638        if (t != Z_OK)
1639        {
1640          if (t == (uInt)Z_DATA_ERROR)
1641          {
1642            ZFREE(z, s->sub.trees.blens);
1643            s->mode = IBM_BAD;
1644          }
1645          r = t;
1646          LEAVE
1647        }
1648        LuTracev((stderr, "inflate:       trees ok\n"));
1649        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
1650        {
1651          r = Z_MEM_ERROR;
1652          LEAVE
1653        }
1654        s->sub.decode.codes = c;
1655      }
1656      ZFREE(z, s->sub.trees.blens);
1657      s->mode = IBM_CODES;
1658    case IBM_CODES:
1659      UPDATE
1660      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
1661        return inflate_flush(s, z, r);
1662      r = Z_OK;
1663      inflate_codes_free(s->sub.decode.codes, z);
1664      LOAD
1665      LuTracev((stderr, "inflate:       codes end, %lu total out\n",
1666              z->total_out + (q >= s->read ? q - s->read :
1667              (s->end - s->read) + (q - s->window))));
1668      if (!s->last)
1669      {
1670        s->mode = IBM_TYPE;
1671        break;
1672      }
1673      s->mode = IBM_DRY;
1674    case IBM_DRY:
1675      FLUSH
1676      if (s->read != s->write)
1677        LEAVE
1678      s->mode = IBM_DONE;
1679    case IBM_DONE:
1680      r = Z_STREAM_END;
1681      LEAVE
1682    case IBM_BAD:
1683      r = Z_DATA_ERROR;
1684      LEAVE
1685    default:
1686      r = Z_STREAM_ERROR;
1687      LEAVE
1688  }
1689}
1690
1691
1692int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z)
1693{
1694  inflate_blocks_reset(s, z, Z_NULL);
1695  ZFREE(z, s->window);
1696  ZFREE(z, s->hufts);
1697  ZFREE(z, s);
1698  LuTracev((stderr, "inflate:   blocks freed\n"));
1699  return Z_OK;
1700}
1701
1702
1703
1704// inftrees.c -- generate Huffman trees for efficient decoding
1705// Copyright (C) 1995-1998 Mark Adler
1706// For conditions of distribution and use, see copyright notice in zlib.h
1707//
1708
1709
1710
1711extern const char inflate_copyright[] =
1712   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
1713// If you use the zlib library in a product, an acknowledgment is welcome
1714// in the documentation of your product. If for some reason you cannot
1715// include such an acknowledgment, I would appreciate that you keep this
1716// copyright string in the executable of your product.
1717
1718
1719
1720int huft_build (
1721    uInt *,            // code lengths in bits
1722    uInt,               // number of codes
1723    uInt,               // number of "simple" codes
1724    const uInt *,      // list of base values for non-simple codes
1725    const uInt *,      // list of extra bits for non-simple codes
1726    inflate_huft **,// result: starting table
1727    uInt *,            // maximum lookup bits (returns actual)
1728    inflate_huft *,     // space for trees
1729    uInt *,             // hufts used in space
1730    uInt * );         // space for values
1731
1732// Tables for deflate from PKZIP's appnote.txt.
1733const uInt cplens[31] = { // Copy lengths for literal codes 257..285
1734        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
1735        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
1736        // see note #13 above about 258
1737const uInt cplext[31] = { // Extra bits for literal codes 257..285
1738        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
1739        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; // 112==invalid
1740const uInt cpdist[30] = { // Copy offsets for distance codes 0..29
1741        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
1742        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
1743        8193, 12289, 16385, 24577};
1744const uInt cpdext[30] = { // Extra bits for distance codes
1745        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
1746        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
1747        12, 12, 13, 13};
1748
1749//
1750//   Huffman code decoding is performed using a multi-level table lookup.
1751//   The fastest way to decode is to simply build a lookup table whose
1752//   size is determined by the longest code.  However, the time it takes
1753//   to build this table can also be a factor if the data being decoded
1754//   is not very long.  The most common codes are necessarily the
1755//   shortest codes, so those codes dominate the decoding time, and hence
1756//   the speed.  The idea is you can have a shorter table that decodes the
1757//   shorter, more probable codes, and then point to subsidiary tables for
1758//   the longer codes.  The time it costs to decode the longer codes is
1759//   then traded against the time it takes to make longer tables.
1760//
1761//   This results of this trade are in the variables lbits and dbits
1762//   below.  lbits is the number of bits the first level table for literal/
1763//   length codes can decode in one step, and dbits is the same thing for
1764//   the distance codes.  Subsequent tables are also less than or equal to
1765//   those sizes.  These values may be adjusted either when all of the
1766//   codes are shorter than that, in which case the longest code length in
1767//   bits is used, or when the shortest code is *longer* than the requested
1768//   table size, in which case the length of the shortest code in bits is
1769//   used.
1770//
1771//   There are two different values for the two tables, since they code a
1772//   different number of possibilities each.  The literal/length table
1773//   codes 286 possible values, or in a flat code, a little over eight
1774//   bits.  The distance table codes 30 possible values, or a little less
1775//   than five bits, flat.  The optimum values for speed end up being
1776//   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
1777//   The optimum values may differ though from machine to machine, and
1778//   possibly even between compilers.  Your mileage may vary.
1779//
1780
1781
1782// If BMAX needs to be larger than 16, then h and x[] should be uLong.
1783#define BMAX 15         // maximum bit length of any code
1784
1785int huft_build(
1786uInt *b,               // code lengths in bits (all assumed <= BMAX)
1787uInt n,                 // number of codes (assumed <= 288)
1788uInt s,                 // number of simple-valued codes (0..s-1)
1789const uInt *d,         // list of base values for non-simple codes
1790const uInt *e,         // list of extra bits for non-simple codes
1791inflate_huft * *t,  // result: starting table
1792uInt *m,               // maximum lookup bits, returns actual
1793inflate_huft *hp,       // space for trees
1794uInt *hn,               // hufts used in space
1795uInt *v)               // working area: values in order of bit length
1796// Given a list of code lengths and a maximum table size, make a set of
1797// tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
1798// if the given code set is incomplete (the tables are still built in this
1799// case), or Z_DATA_ERROR if the input is invalid.
1800{
1801
1802  uInt a;                       // counter for codes of length k
1803  uInt c[BMAX+1];               // bit length count table
1804  uInt f;                       // i repeats in table every f entries
1805  int g;                        // maximum code length
1806  int h;                        // table level
1807  register uInt i;              // counter, current code
1808  register uInt j;              // counter
1809  register int k;               // number of bits in current code
1810  int l;                        // bits per table (returned in m)
1811  uInt mask;                    // (1 << w) - 1, to avoid cc -O bug on HP
1812  register uInt *p;            // pointer into c[], b[], or v[]
1813  inflate_huft *q;              // points to current table
1814  struct inflate_huft_s r;      // table entry for structure assignment
1815  inflate_huft *u[BMAX];        // table stack
1816  register int w;               // bits before this table == (l * h)
1817  uInt x[BMAX+1];               // bit offsets, then code stack
1818  uInt *xp;                    // pointer into x
1819  int y;                        // number of dummy codes added
1820  uInt z;                       // number of entries in current table
1821
1822  // provide a default value
1823  r.base = 0;
1824
1825  // Generate counts for each bit length
1826  p = c;
1827#define C0 *p++ = 0;
1828#define C2 C0 C0 C0 C0
1829#define C4 C2 C2 C2 C2
1830  C4;                           // clear c[]--assume BMAX+1 is 16
1831  p = b;  i = n;
1832  do {
1833    c[*p++]++;                  // assume all entries <= BMAX
1834  } while (--i);
1835  if (c[0] == n)                // null input--all zero length codes
1836  {
1837    *t = (inflate_huft *)Z_NULL;
1838    *m = 0;
1839    return Z_OK;
1840  }
1841
1842
1843  // Find minimum and maximum length, bound *m by those
1844  l = *m;
1845  for (j = 1; j <= BMAX; j++)
1846    if (c[j])
1847      break;
1848  k = j;                        // minimum code length
1849  if ((uInt)l < j)
1850    l = j;
1851  for (i = BMAX; i; i--)
1852    if (c[i])
1853      break;
1854  g = i;                        // maximum code length
1855  if ((uInt)l > i)
1856    l = i;
1857  *m = l;
1858
1859
1860  // Adjust last length count to fill out codes, if needed
1861  for (y = 1 << j; j < i; j++, y <<= 1)
1862    if ((y -= c[j]) < 0)
1863      return Z_DATA_ERROR;
1864  if ((y -= c[i]) < 0)
1865    return Z_DATA_ERROR;
1866  c[i] += y;
1867
1868
1869  // Generate starting offsets into the value table for each length
1870  x[1] = j = 0;
1871  p = c + 1;  xp = x + 2;
1872  while (--i) {                 // note that i == g from above
1873    *xp++ = (j += *p++);
1874  }
1875
1876
1877  // Make a table of values in order of bit lengths
1878  p = b;  i = 0;
1879  do {
1880    if ((j = *p++) != 0)
1881      v[x[j]++] = i;
1882  } while (++i < n);
1883  n = x[g];                     // set n to length of v
1884
1885
1886  // Generate the Huffman codes and for each, make the table entries
1887  x[0] = i = 0;                 // first Huffman code is zero
1888  p = v;                        // grab values in bit order
1889  h = -1;                       // no tables yet--level -1
1890  w = -l;                       // bits decoded == (l * h)
1891  u[0] = (inflate_huft *)Z_NULL;        // just to keep compilers happy
1892  q = (inflate_huft *)Z_NULL;   // ditto
1893  z = 0;                        // ditto
1894
1895  // go through the bit lengths (k already is bits in shortest code)
1896  for (; k <= g; k++)
1897  {
1898    a = c[k];
1899    while (a--)
1900    {
1901      // here i is the Huffman code of length k bits for value *p
1902      // make tables up to required level
1903      while (k > w + l)
1904      {
1905        h++;
1906        w += l;                 // previous table always l bits
1907
1908        // compute minimum size table less than or equal to l bits
1909        z = g - w;
1910        z = z > (uInt)l ? l : z;        // table size upper limit
1911        if ((f = 1 << (j = k - w)) > a + 1)     // try a k-w bit table
1912        {                       // too few codes for k-w bit table
1913          f -= a + 1;           // deduct codes from patterns left
1914          xp = c + k;
1915          if (j < z)
1916            while (++j < z)     // try smaller tables up to z bits
1917            {
1918              if ((f <<= 1) <= *++xp)
1919                break;          // enough codes to use up j bits
1920              f -= *xp;         // else deduct codes from patterns
1921            }
1922        }
1923        z = 1 << j;             // table entries for j-bit table
1924
1925        // allocate new table
1926        if (*hn + z > MANY)     // (note: doesn't matter for fixed)
1927          return Z_DATA_ERROR;  // overflow of MANY
1928        u[h] = q = hp + *hn;
1929        *hn += z;
1930
1931        // connect to last table, if there is one
1932        if (h)
1933        {
1934          x[h] = i;             // save pattern for backing up
1935          r.bits = (Byte)l;     // bits to dump before this table
1936          r.exop = (Byte)j;     // bits in this table
1937          j = i >> (w - l);
1938          r.base = (uInt)(q - u[h-1] - j);   // offset to this table
1939          u[h-1][j] = r;        // connect to last table
1940        }
1941        else
1942          *t = q;               // first table is returned result
1943      }
1944
1945      // set up table entry in r
1946      r.bits = (Byte)(k - w);
1947      if (p >= v + n)
1948        r.exop = 128 + 64;      // out of values--invalid code
1949      else if (*p < s)
1950      {
1951        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     // 256 is end-of-block
1952        r.base = *p++;          // simple code is just the value
1953      }
1954      else
1955      {
1956        r.exop = (Byte)(e[*p - s] + 16 + 64);// non-simple--look up in lists
1957        r.base = d[*p++ - s];
1958      }
1959
1960      // fill code-like entries with r
1961      f = 1 << (k - w);
1962      for (j = i >> w; j < z; j += f)
1963        q[j] = r;
1964
1965      // backwards increment the k-bit code i
1966      for (j = 1 << (k - 1); i & j; j >>= 1)
1967        i ^= j;
1968      i ^= j;
1969
1970      // backup over finished tables
1971      mask = (1 << w) - 1;      // needed on HP, cc -O bug
1972      while ((i & mask) != x[h])
1973      {
1974        h--;                    // don't need to update q
1975        w -= l;
1976        mask = (1 << w) - 1;
1977      }
1978    }
1979  }
1980
1981
1982  // Return Z_BUF_ERROR if we were given an incomplete table
1983  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
1984}
1985
1986
1987int inflate_trees_bits(
1988uInt *c,               // 19 code lengths
1989uInt *bb,              // bits tree desired/actual depth
1990inflate_huft * *tb, // bits tree result
1991inflate_huft *hp,       // space for trees
1992z_streamp z)            // for messages
1993{
1994  int r;
1995  uInt hn = 0;          // hufts used in space
1996  uInt *v;             // work area for huft_build
1997
1998  if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
1999    return Z_MEM_ERROR;
2000  r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL,
2001                 tb, bb, hp, &hn, v);
2002  if (r == Z_DATA_ERROR)
2003    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
2004  else if (r == Z_BUF_ERROR || *bb == 0)
2005  {
2006    z->msg = (char*)"incomplete dynamic bit lengths tree";
2007    r = Z_DATA_ERROR;
2008  }
2009  ZFREE(z, v);
2010  return r;
2011}
2012
2013
2014int inflate_trees_dynamic(
2015uInt nl,                // number of literal/length codes
2016uInt nd,                // number of distance codes
2017uInt *c,               // that many (total) code lengths
2018uInt *bl,              // literal desired/actual bit depth
2019uInt *bd,              // distance desired/actual bit depth
2020inflate_huft * *tl, // literal/length tree result
2021inflate_huft * *td, // distance tree result
2022inflate_huft *hp,       // space for trees
2023z_streamp z)            // for messages
2024{
2025  int r;
2026  uInt hn = 0;          // hufts used in space
2027  uInt *v;             // work area for huft_build
2028
2029  // allocate work area
2030  if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
2031    return Z_MEM_ERROR;
2032
2033  // build literal/length tree
2034  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
2035  if (r != Z_OK || *bl == 0)
2036  {
2037    if (r == Z_DATA_ERROR)
2038      z->msg = (char*)"oversubscribed literal/length tree";
2039    else if (r != Z_MEM_ERROR)
2040    {
2041      z->msg = (char*)"incomplete literal/length tree";
2042      r = Z_DATA_ERROR;
2043    }
2044    ZFREE(z, v);
2045    return r;
2046  }
2047
2048  // build distance tree
2049  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
2050  if (r != Z_OK || (*bd == 0 && nl > 257))
2051  {
2052    if (r == Z_DATA_ERROR)
2053      z->msg = (char*)"oversubscribed distance tree";
2054    else if (r == Z_BUF_ERROR) {
2055      z->msg = (char*)"incomplete distance tree";
2056      r = Z_DATA_ERROR;
2057    }
2058    else if (r != Z_MEM_ERROR)
2059    {
2060      z->msg = (char*)"empty distance tree with lengths";
2061      r = Z_DATA_ERROR;
2062    }
2063    ZFREE(z, v);
2064    return r;
2065  }
2066
2067  // done
2068  ZFREE(z, v);
2069  return Z_OK;
2070}
2071
2072
2073
2074
2075
2076int inflate_trees_fixed(
2077uInt *bl,               // literal desired/actual bit depth
2078uInt *bd,               // distance desired/actual bit depth
2079const inflate_huft * * tl,     // literal/length tree result
2080const inflate_huft * *td,     // distance tree result
2081z_streamp )             // for memory allocation
2082{
2083  *bl = fixed_bl;
2084  *bd = fixed_bd;
2085  *tl = fixed_tl;
2086  *td = fixed_td;
2087  return Z_OK;
2088}
2089
2090
2091// inffast.c -- process literals and length/distance pairs fast
2092// Copyright (C) 1995-1998 Mark Adler
2093// For conditions of distribution and use, see copyright notice in zlib.h
2094//
2095
2096
2097//struct inflate_codes_state {int dummy;}; // for buggy compilers
2098
2099
2100// macros for bit input with no checking and for returning unused bytes
2101#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
2102#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
2103
2104// Called with number of bytes left to write in window at least 258
2105// (the maximum string length) and number of input bytes available
2106// at least ten.  The ten bytes are six bytes for the longest length/
2107// distance pair plus four bytes for overloading the bit buffer.
2108
2109int inflate_fast(
2110uInt bl, uInt bd,
2111const inflate_huft *tl,
2112const inflate_huft *td, // need separate declaration for Borland C++
2113inflate_blocks_statef *s,
2114z_streamp z)
2115{
2116  const inflate_huft *t;      // temporary pointer
2117  uInt e;               // extra bits or operation
2118  uLong b;              // bit buffer
2119  uInt k;               // bits in bit buffer
2120  Byte *p;             // input data pointer
2121  uInt n;               // bytes available there
2122  Byte *q;             // output window write pointer
2123  uInt m;               // bytes to end of window or read pointer
2124  uInt ml;              // mask for literal/length tree
2125  uInt md;              // mask for distance tree
2126  uInt c;               // bytes to copy
2127  uInt d;               // distance back to copy from
2128  Byte *r;             // copy source pointer
2129
2130  // load input, output, bit values
2131  LOAD
2132
2133  // initialize masks
2134  ml = inflate_mask[bl];
2135  md = inflate_mask[bd];
2136
2137  // do until not enough input or output space for fast loop
2138  do {                          // assume called with m >= 258 && n >= 10
2139    // get literal/length code
2140    GRABBITS(20)                // max bits for literal/length code
2141    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
2142    {
2143      DUMPBITS(t->bits)
2144      LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
2145                "inflate:         * literal '%c'\n" :
2146                "inflate:         * literal 0x%02x\n", t->base));
2147      *q++ = (Byte)t->base;
2148      m--;
2149      continue;
2150    }
2151    for (;;) {
2152      DUMPBITS(t->bits)
2153      if (e & 16)
2154      {
2155        // get extra bits for length
2156        e &= 15;
2157        c = t->base + ((uInt)b & inflate_mask[e]);
2158        DUMPBITS(e)
2159        LuTracevv((stderr, "inflate:         * length %u\n", c));
2160
2161        // decode distance base of block to copy
2162        GRABBITS(15);           // max bits for distance code
2163        e = (t = td + ((uInt)b & md))->exop;
2164        for (;;) {
2165          DUMPBITS(t->bits)
2166          if (e & 16)
2167          {
2168            // get extra bits to add to distance base
2169            e &= 15;
2170            GRABBITS(e)         // get extra bits (up to 13)
2171            d = t->base + ((uInt)b & inflate_mask[e]);
2172            DUMPBITS(e)
2173            LuTracevv((stderr, "inflate:         * distance %u\n", d));
2174
2175            // do the copy
2176            m -= c;
2177            r = q - d;
2178            if (r < s->window)                  // wrap if needed
2179            {
2180              do {
2181                r += s->end - s->window;        // force pointer in window
2182              } while (r < s->window);          // covers invalid distances
2183              e = (uInt) (s->end - r);
2184              if (c > e)
2185              {
2186                c -= e;                         // wrapped copy
2187                do {
2188                    *q++ = *r++;
2189                } while (--e);
2190                r = s->window;
2191                do {
2192                    *q++ = *r++;
2193                } while (--c);
2194              }
2195              else                              // normal copy
2196              {
2197                *q++ = *r++;  c--;
2198                *q++ = *r++;  c--;
2199                do {
2200                    *q++ = *r++;
2201                } while (--c);
2202              }
2203            }
2204            else                                /* normal copy */
2205            {
2206              *q++ = *r++;  c--;
2207              *q++ = *r++;  c--;
2208              do {
2209                *q++ = *r++;
2210              } while (--c);
2211            }
2212            break;
2213          }
2214          else if ((e & 64) == 0)
2215          {
2216            t += t->base;
2217            e = (t += ((uInt)b & inflate_mask[e]))->exop;
2218          }
2219          else
2220          {
2221            z->msg = (char*)"invalid distance code";
2222            UNGRAB
2223            UPDATE
2224            return Z_DATA_ERROR;
2225          }
2226        };
2227        break;
2228      }
2229      if ((e & 64) == 0)
2230      {
2231        t += t->base;
2232        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
2233        {
2234          DUMPBITS(t->bits)
2235          LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
2236                    "inflate:         * literal '%c'\n" :
2237                    "inflate:         * literal 0x%02x\n", t->base));
2238          *q++ = (Byte)t->base;
2239          m--;
2240          break;
2241        }
2242      }
2243      else if (e & 32)
2244      {
2245        LuTracevv((stderr, "inflate:         * end of block\n"));
2246        UNGRAB
2247        UPDATE
2248        return Z_STREAM_END;
2249      }
2250      else
2251      {
2252        z->msg = (char*)"invalid literal/length code";
2253        UNGRAB
2254        UPDATE
2255        return Z_DATA_ERROR;
2256      }
2257    };
2258  } while (m >= 258 && n >= 10);
2259
2260  // not enough input or output--restore pointers and return
2261  UNGRAB
2262  UPDATE
2263  return Z_OK;
2264}
2265
2266
2267
2268
2269
2270
2271// crc32.c -- compute the CRC-32 of a data stream
2272// Copyright (C) 1995-1998 Mark Adler
2273// For conditions of distribution and use, see copyright notice in zlib.h
2274
2275// @(#) $Id$
2276
2277
2278
2279
2280
2281
2282// Table of CRC-32's of all single-byte values (made by make_crc_table)
2283const uLong crc_table[256] = {
2284  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
2285  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
2286  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
2287  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
2288  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
2289  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
2290  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
2291  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
2292  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
2293  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
2294  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
2295  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
2296  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
2297  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
2298  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
2299  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
2300  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
2301  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
2302  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
2303  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
2304  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
2305  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
2306  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
2307  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
2308  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
2309  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
2310  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
2311  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
2312  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
2313  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
2314  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
2315  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
2316  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
2317  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
2318  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
2319  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
2320  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
2321  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
2322  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
2323  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
2324  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
2325  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
2326  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
2327  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
2328  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
2329  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
2330  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
2331  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
2332  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
2333  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
2334  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
2335  0x2d02ef8dL
2336};
2337
2338const uLong * get_crc_table()
2339{ return (const uLong *)crc_table;
2340}
2341
2342#define CRC_DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
2343#define CRC_DO2(buf)  CRC_DO1(buf); CRC_DO1(buf);
2344#define CRC_DO4(buf)  CRC_DO2(buf); CRC_DO2(buf);
2345#define CRC_DO8(buf)  CRC_DO4(buf); CRC_DO4(buf);
2346
2347uLong ucrc32(uLong crc, const Byte *buf, uInt len)
2348{ if (buf == Z_NULL) return 0L;
2349  crc = crc ^ 0xffffffffL;
2350  while (len >= 8)  {CRC_DO8(buf); len -= 8;}
2351  if (len) do {CRC_DO1(buf);} while (--len);
2352  return crc ^ 0xffffffffL;
2353}
2354
2355
2356
2357// =============================================================
2358// some decryption routines
2359#define CRC32(c, b) (crc_table[((int)(c)^(b))&0xff]^((c)>>8))
2360void Uupdate_keys(unsigned long *keys, char c)
2361{ keys[0] = CRC32(keys[0],c);
2362  keys[1] += keys[0] & 0xFF;
2363  keys[1] = keys[1]*134775813L +1;
2364  keys[2] = CRC32(keys[2], keys[1] >> 24);
2365}
2366char Udecrypt_byte(unsigned long *keys)
2367{ unsigned temp = ((unsigned)keys[2] & 0xffff) | 2;
2368  return (char)(((temp * (temp ^ 1)) >> 8) & 0xff);
2369}
2370char zdecode(unsigned long *keys, char c)
2371{ c^=Udecrypt_byte(keys);
2372  Uupdate_keys(keys,c);
2373  return c;
2374}
2375
2376
2377
2378// adler32.c -- compute the Adler-32 checksum of a data stream
2379// Copyright (C) 1995-1998 Mark Adler
2380// For conditions of distribution and use, see copyright notice in zlib.h
2381
2382// @(#) $Id$
2383
2384
2385#define BASE 65521L // largest prime smaller than 65536
2386#define NMAX 5552
2387// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
2388
2389#define AD_DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
2390#define AD_DO2(buf,i)  AD_DO1(buf,i); AD_DO1(buf,i+1);
2391#define AD_DO4(buf,i)  AD_DO2(buf,i); AD_DO2(buf,i+2);
2392#define AD_DO8(buf,i)  AD_DO4(buf,i); AD_DO4(buf,i+4);
2393#define AD_DO16(buf)   AD_DO8(buf,0); AD_DO8(buf,8);
2394
2395// =========================================================================
2396uLong adler32(uLong adler, const Byte *buf, uInt len)
2397{
2398    unsigned long s1 = adler & 0xffff;
2399    unsigned long s2 = (adler >> 16) & 0xffff;
2400    int k;
2401
2402    if (buf == Z_NULL) return 1L;
2403
2404    while (len > 0) {
2405        k = len < NMAX ? len : NMAX;
2406        len -= k;
2407        while (k >= 16) {
2408            AD_DO16(buf);
2409            buf += 16;
2410            k -= 16;
2411        }
2412        if (k != 0) do {
2413            s1 += *buf++;
2414            s2 += s1;
2415        } while (--k);
2416        s1 %= BASE;
2417        s2 %= BASE;
2418    }
2419    return (s2 << 16) | s1;
2420}
2421
2422
2423
2424// zutil.c -- target dependent utility functions for the compression library
2425// Copyright (C) 1995-1998 Jean-loup Gailly.
2426// For conditions of distribution and use, see copyright notice in zlib.h
2427// @(#) $Id$
2428
2429
2430
2431
2432
2433
2434const char * zlibVersion()
2435{
2436    return ZLIB_VERSION;
2437}
2438
2439// exported to allow conversion of error code to string for compress() and
2440// uncompress()
2441const char * zError(int err)
2442{ return ERR_MSG(err);
2443}
2444
2445
2446
2447
2448voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
2449{
2450    if (opaque) items += size - size; // make compiler happy
2451    return (voidpf)calloc(items, size);
2452}
2453
2454void  zcfree (voidpf opaque, voidpf ptr)
2455{
2456    zfree(ptr);
2457    if (opaque) return; // make compiler happy
2458}
2459
2460
2461
2462// inflate.c -- zlib interface to inflate modules
2463// Copyright (C) 1995-1998 Mark Adler
2464// For conditions of distribution and use, see copyright notice in zlib.h
2465
2466//struct inflate_blocks_state {int dummy;}; // for buggy compilers
2467
2468typedef enum {
2469      IM_METHOD,   // waiting for method byte
2470      IM_FLAG,     // waiting for flag byte
2471      IM_DICT4,    // four dictionary check bytes to go
2472      IM_DICT3,    // three dictionary check bytes to go
2473      IM_DICT2,    // two dictionary check bytes to go
2474      IM_DICT1,    // one dictionary check byte to go
2475      IM_DICT0,    // waiting for inflateSetDictionary
2476      IM_BLOCKS,   // decompressing blocks
2477      IM_CHECK4,   // four check bytes to go
2478      IM_CHECK3,   // three check bytes to go
2479      IM_CHECK2,   // two check bytes to go
2480      IM_CHECK1,   // one check byte to go
2481      IM_DONE,     // finished check, done
2482      IM_BAD}      // got an error--stay here
2483inflate_mode;
2484
2485// inflate private state
2486struct internal_state {
2487
2488  // mode
2489  inflate_mode  mode;   // current inflate mode
2490
2491  // mode dependent information
2492  union {
2493    uInt method;        // if IM_FLAGS, method byte
2494    struct {
2495      uLong was;                // computed check value
2496      uLong need;               // stream check value
2497    } check;            // if CHECK, check values to compare
2498    uInt marker;        // if IM_BAD, inflateSync's marker bytes count
2499  } sub;        // submode
2500
2501  // mode independent information
2502  int  nowrap;          // flag for no wrapper
2503  uInt wbits;           // log2(window size)  (8..15, defaults to 15)
2504  inflate_blocks_statef
2505    *blocks;            // current inflate_blocks state
2506
2507};
2508
2509int inflateReset(z_streamp z)
2510{
2511  if (z == Z_NULL || z->state == Z_NULL)
2512    return Z_STREAM_ERROR;
2513  z->total_in = z->total_out = 0;
2514  z->msg = Z_NULL;
2515  z->state->mode = z->state->nowrap ? IM_BLOCKS : IM_METHOD;
2516  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
2517  LuTracev((stderr, "inflate: reset\n"));
2518  return Z_OK;
2519}
2520
2521int inflateEnd(z_streamp z)
2522{
2523  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
2524    return Z_STREAM_ERROR;
2525  if (z->state->blocks != Z_NULL)
2526    inflate_blocks_free(z->state->blocks, z);
2527  ZFREE(z, z->state);
2528  z->state = Z_NULL;
2529  LuTracev((stderr, "inflate: end\n"));
2530  return Z_OK;
2531}
2532
2533
2534int inflateInit2(z_streamp z)
2535{ const char *version = ZLIB_VERSION; int stream_size = sizeof(z_stream);
2536  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != sizeof(z_stream)) return Z_VERSION_ERROR;
2537
2538  int w = -15; // MAX_WBITS: 32K LZ77 window.
2539  // Warning: reducing MAX_WBITS makes minigzip unable to extract .gz files created by gzip.
2540  // The memory requirements for deflate are (in bytes):
2541  //            (1 << (windowBits+2)) +  (1 << (memLevel+9))
2542  // that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
2543  // plus a few kilobytes for small objects. For example, if you want to reduce
2544  // the default memory requirements from 256K to 128K, compile with
2545  //     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
2546  // Of course this will generally degrade compression (there's no free lunch).
2547  //
2548  //   The memory requirements for inflate are (in bytes) 1 << windowBits
2549  // that is, 32K for windowBits=15 (default value) plus a few kilobytes
2550  // for small objects.
2551
2552  // initialize state
2553  if (z == Z_NULL) return Z_STREAM_ERROR;
2554  z->msg = Z_NULL;
2555  if (z->zalloc == Z_NULL)
2556  {
2557    z->zalloc = zcalloc;
2558    z->opaque = (voidpf)0;
2559  }
2560  if (z->zfree == Z_NULL) z->zfree = zcfree;
2561  if ((z->state = (struct internal_state *)
2562       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
2563    return Z_MEM_ERROR;
2564  z->state->blocks = Z_NULL;
2565
2566  // handle undocumented nowrap option (no zlib header or check)
2567  z->state->nowrap = 0;
2568  if (w < 0)
2569  {
2570    w = - w;
2571    z->state->nowrap = 1;
2572  }
2573
2574  // set window size
2575  if (w < 8 || w > 15)
2576  {
2577    inflateEnd(z);
2578    return Z_STREAM_ERROR;
2579  }
2580  z->state->wbits = (uInt)w;
2581
2582  // create inflate_blocks state
2583  if ((z->state->blocks =
2584      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
2585      == Z_NULL)
2586  {
2587    inflateEnd(z);
2588    return Z_MEM_ERROR;
2589  }
2590  LuTracev((stderr, "inflate: allocated\n"));
2591
2592  // reset state
2593  inflateReset(z);
2594  return Z_OK;
2595}
2596
2597
2598
2599#define IM_NEEDBYTE {if(z->avail_in==0)return r;r=f;}
2600#define IM_NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
2601
2602int inflate(z_streamp z, int f)
2603{
2604  int r;
2605  uInt b;
2606
2607  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
2608    return Z_STREAM_ERROR;
2609  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
2610  r = Z_BUF_ERROR;
2611  for (;;) switch (z->state->mode)
2612  {
2613    case IM_METHOD:
2614      IM_NEEDBYTE
2615      if (((z->state->sub.method = IM_NEXTBYTE) & 0xf) != Z_DEFLATED)
2616      {
2617        z->state->mode = IM_BAD;
2618        z->msg = (char*)"unknown compression method";
2619        z->state->sub.marker = 5;       // can't try inflateSync
2620        break;
2621      }
2622      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
2623      {
2624        z->state->mode = IM_BAD;
2625        z->msg = (char*)"invalid window size";
2626        z->state->sub.marker = 5;       // can't try inflateSync
2627        break;
2628      }
2629      z->state->mode = IM_FLAG;
2630    case IM_FLAG:
2631      IM_NEEDBYTE
2632      b = IM_NEXTBYTE;
2633      if (((z->state->sub.method << 8) + b) % 31)
2634      {
2635        z->state->mode = IM_BAD;
2636        z->msg = (char*)"incorrect header check";
2637        z->state->sub.marker = 5;       // can't try inflateSync
2638        break;
2639      }
2640      LuTracev((stderr, "inflate: zlib header ok\n"));
2641      if (!(b & PRESET_DICT))
2642      {
2643        z->state->mode = IM_BLOCKS;
2644        break;
2645      }
2646      z->state->mode = IM_DICT4;
2647    case IM_DICT4:
2648      IM_NEEDBYTE
2649      z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24;
2650      z->state->mode = IM_DICT3;
2651    case IM_DICT3:
2652      IM_NEEDBYTE
2653      z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16;
2654      z->state->mode = IM_DICT2;
2655    case IM_DICT2:
2656      IM_NEEDBYTE
2657      z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8;
2658      z->state->mode = IM_DICT1;
2659    case IM_DICT1:
2660      IM_NEEDBYTE;
2661      z->state->sub.check.need += (uLong)IM_NEXTBYTE;
2662      z->adler = z->state->sub.check.need;
2663      z->state->mode = IM_DICT0;
2664      return Z_NEED_DICT;
2665    case IM_DICT0:
2666      z->state->mode = IM_BAD;
2667      z->msg = (char*)"need dictionary";
2668      z->state->sub.marker = 0;       // can try inflateSync
2669      return Z_STREAM_ERROR;
2670    case IM_BLOCKS:
2671      r = inflate_blocks(z->state->blocks, z, r);
2672      if (r == Z_DATA_ERROR)
2673      {
2674        z->state->mode = IM_BAD;
2675        z->state->sub.marker = 0;       // can try inflateSync
2676        break;
2677      }
2678      if (r == Z_OK)
2679        r = f;
2680      if (r != Z_STREAM_END)
2681        return r;
2682      r = f;
2683      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
2684      if (z->state->nowrap)
2685      {
2686        z->state->mode = IM_DONE;
2687        break;
2688      }
2689      z->state->mode = IM_CHECK4;
2690    case IM_CHECK4:
2691      IM_NEEDBYTE
2692      z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24;
2693      z->state->mode = IM_CHECK3;
2694    case IM_CHECK3:
2695      IM_NEEDBYTE
2696      z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16;
2697      z->state->mode = IM_CHECK2;
2698    case IM_CHECK2:
2699      IM_NEEDBYTE
2700      z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8;
2701      z->state->mode = IM_CHECK1;
2702    case IM_CHECK1:
2703      IM_NEEDBYTE
2704      z->state->sub.check.need += (uLong)IM_NEXTBYTE;
2705
2706      if (z->state->sub.check.was != z->state->sub.check.need)
2707      {
2708        z->state->mode = IM_BAD;
2709        z->msg = (char*)"incorrect data check";
2710        z->state->sub.marker = 5;       // can't try inflateSync
2711        break;
2712      }
2713      LuTracev((stderr, "inflate: zlib check ok\n"));
2714      z->state->mode = IM_DONE;
2715    case IM_DONE:
2716      return Z_STREAM_END;
2717    case IM_BAD:
2718      return Z_DATA_ERROR;
2719    default:
2720      return Z_STREAM_ERROR;
2721  }
2722}
2723
2724
2725
2726
2727
2728// unzip.c -- IO on .zip files using zlib
2729// Version 0.15 beta, Mar 19th, 1998,
2730// Read unzip.h for more info
2731
2732
2733
2734
2735#define UNZ_BUFSIZE (16384)
2736#define UNZ_MAXFILENAMEINZIP (256)
2737#define SIZECENTRALDIRITEM (0x2e)
2738#define SIZEZIPLOCALHEADER (0x1e)
2739
2740
2741
2742
2743const char unz_copyright[] = " unzip 0.15 Copyright 1998 Gilles Vollant ";
2744
2745// unz_file_info_interntal contain internal info about a file in zipfile
2746typedef struct unz_file_info_internal_s
2747{
2748    uLong offset_curfile;// relative offset of local header 4 bytes
2749} unz_file_info_internal;
2750
2751
2752typedef struct
2753{ bool is_handle; // either a handle or memory
2754  bool canseek;
2755  // for handles:
2756  HANDLE h; bool herr; unsigned long initial_offset; bool mustclosehandle;
2757  // for memory:
2758  void *buf; unsigned int len,pos; // if it's a memory block
2759} LUFILE;
2760
2761
2762LUFILE *lufopen(void *z,unsigned int len,DWORD flags,ZRESULT *err)
2763{ if (flags!=ZIP_HANDLE && flags!=ZIP_FILENAME && flags!=ZIP_MEMORY) {*err=ZR_ARGS; return NULL;}
2764  //
2765  HANDLE h=0; bool canseek=false; *err=ZR_OK;
2766  bool mustclosehandle=false;
2767  if (flags==ZIP_HANDLE||flags==ZIP_FILENAME)
2768  { if (flags==ZIP_HANDLE)
2769    { HANDLE hf = (HANDLE)z;
2770      h=hf; mustclosehandle=false;
2771#ifdef DuplicateHandle
2772      BOOL res = DuplicateHandle(GetCurrentProcess(),hf,GetCurrentProcess(),&h,0,FALSE,DUPLICATE_SAME_ACCESS);
2773      if (!res) mustclosehandle=true;
2774#endif
2775    }
2776    else
2777    {
2778#ifdef ZIP_STD
2779      h=fopen((const char*)z,"rb");
2780      if (h==0) {*err=ZR_NOFILE; return NULL;}
2781#else
2782      h=CreateFile((const TCHAR*)z,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
2783      if (h==INVALID_HANDLE_VALUE) {*err=ZR_NOFILE; return NULL;}
2784#endif
2785      mustclosehandle=true;
2786    }
2787    // test if we can seek on it. We can't use GetFileType(h)==FILE_TYPE_DISK since it's not on CE.
2788    DWORD res = GetFilePosU(h);
2789    canseek = (res!=0xFFFFFFFF);
2790  }
2791  LUFILE *lf = new LUFILE;
2792  if (flags==ZIP_HANDLE||flags==ZIP_FILENAME)
2793  { lf->is_handle=true; lf->mustclosehandle=mustclosehandle;
2794    lf->canseek=canseek;
2795    lf->h=h; lf->herr=false;
2796    lf->initial_offset=0;
2797    if (canseek) lf->initial_offset = GetFilePosU(h);
2798  }
2799  else
2800  { lf->is_handle=false;
2801    lf->canseek=true;
2802    lf->mustclosehandle=false;
2803    lf->buf=z; lf->len=len; lf->pos=0; lf->initial_offset=0;
2804  }
2805  *err=ZR_OK;
2806  return lf;
2807}
2808
2809
2810int lufclose(LUFILE *stream)
2811{ if (stream==NULL) return EOF;
2812#ifdef ZIP_STD
2813  if (stream->mustclosehandle) fclose(stream->h);
2814#else
2815  if (stream->mustclosehandle) CloseHandle(stream->h);
2816#endif
2817  delete stream;
2818  return 0;
2819}
2820
2821int luferror(LUFILE *stream)
2822{ if (stream->is_handle && stream->herr) return 1;
2823  else return 0;
2824}
2825
2826long int luftell(LUFILE *stream)
2827{ if (stream->is_handle && stream->canseek) return GetFilePosU(stream->h)-stream->initial_offset;
2828  else if (stream->is_handle) return 0;
2829  else return stream->pos;
2830}
2831
2832int lufseek(LUFILE *stream, long offset, int whence)
2833{ if (stream->is_handle && stream->canseek)
2834  {
2835#ifdef ZIP_STD
2836    return fseek(stream->h,stream->initial_offset+offset,whence);
2837#else
2838    if (whence==SEEK_SET) SetFilePointer(stream->h,stream->initial_offset+offset,0,FILE_BEGIN);
2839    else if (whence==SEEK_CUR) SetFilePointer(stream->h,offset,NULL,FILE_CURRENT);
2840    else if (whence==SEEK_END) SetFilePointer(stream->h,offset,NULL,FILE_END);
2841    else return 19; // EINVAL
2842    return 0;
2843#endif
2844  }
2845  else if (stream->is_handle) return 29; // ESPIPE
2846  else
2847  { if (whence==SEEK_SET) stream->pos=offset;
2848    else if (whence==SEEK_CUR) stream->pos+=offset;
2849    else if (whence==SEEK_END) stream->pos=stream->len+offset;
2850    return 0;
2851  }
2852}
2853
2854
2855size_t lufread(void *ptr,size_t size,size_t n,LUFILE *stream)
2856{ unsigned int toread = (unsigned int)(size*n);
2857  if (stream->is_handle)
2858  {
2859#ifdef ZIP_STD
2860    return fread(ptr,size,n,stream->h);
2861#else
2862    DWORD red; BOOL res = ReadFile(stream->h,ptr,toread,&red,NULL);
2863    if (!res) stream->herr=true;
2864    return red/size;
2865#endif
2866  }
2867  if (stream->pos+toread > stream->len) toread = stream->len-stream->pos;
2868  memcpy(ptr, (char*)stream->buf + stream->pos, toread); DWORD red = toread;
2869  stream->pos += red;
2870  return red/size;
2871}
2872
2873
2874
2875
2876// file_in_zip_read_info_s contain internal information about a file in zipfile,
2877//  when reading and decompress it
2878typedef struct
2879{
2880        char  *read_buffer;         // internal buffer for compressed data
2881        z_stream stream;            // zLib stream structure for inflate
2882
2883        uLong pos_in_zipfile;       // position in byte on the zipfile, for fseek
2884        uLong stream_initialised;   // flag set if stream structure is initialised
2885
2886        uLong offset_local_extrafield;// offset of the local extra field
2887        uInt  size_local_extrafield;// size of the local extra field
2888        uLong pos_local_extrafield;   // position in the local extra field in read
2889
2890        uLong crc32;                // crc32 of all data uncompressed
2891        uLong crc32_wait;           // crc32 we must obtain after decompress all
2892        uLong rest_read_compressed; // number of byte to be decompressed
2893        uLong rest_read_uncompressed;//number of byte to be obtained after decomp
2894        LUFILE* file;                 // io structore of the zipfile
2895        uLong compression_method;   // compression method (0==store)
2896        uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx)
2897  bool encrypted;               // is it encrypted?
2898  unsigned long keys[3];        // decryption keys, initialized by unzOpenCurrentFile
2899  int encheadleft;              // the first call(s) to unzReadCurrentFile will read this many encryption-header bytes first
2900  char crcenctest;              // if encrypted, we'll check the encryption buffer against this
2901} file_in_zip_read_info_s;
2902
2903
2904// unz_s contain internal information about the zipfile
2905typedef struct
2906{
2907        LUFILE* file;               // io structore of the zipfile
2908        unz_global_info gi;         // public global information
2909        uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx)
2910        uLong num_file;             // number of the current file in the zipfile
2911        uLong pos_in_central_dir;   // pos of the current file in the central dir
2912        uLong current_file_ok;      // flag about the usability of the current file
2913        uLong central_pos;          // position of the beginning of the central dir
2914
2915        uLong size_central_dir;     // size of the central directory
2916        uLong offset_central_dir;   // offset of start of central directory with respect to the starting disk number
2917
2918        unz_file_info cur_file_info; // public info about the current file in zip
2919        unz_file_info_internal cur_file_info_internal; // private info about it
2920    file_in_zip_read_info_s* pfile_in_zip_read; // structure about the current file if we are decompressing it
2921} unz_s, *unzFile;
2922
2923
2924int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity);
2925//   Compare two filename (fileName1,fileName2).
2926
2927z_off_t unztell (unzFile file);
2928//  Give the current position in uncompressed data
2929
2930int unzeof (unzFile file);
2931//  return 1 if the end of file was reached, 0 elsewhere
2932
2933int unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len);
2934//  Read extra field from the current file (opened by unzOpenCurrentFile)
2935//  This is the local-header version of the extra field (sometimes, there is
2936//    more info in the local-header version than in the central-header)
2937//
2938//  if buf==NULL, it return the size of the local extra field
2939//
2940//  if buf!=NULL, len is the size of the buffer, the extra header is copied in
2941//      buf.
2942//  the return value is the number of bytes copied in buf, or (if <0)
2943//      the error code
2944
2945
2946
2947// ===========================================================================
2948//   Read a byte from a gz_stream; update next_in and avail_in. Return EOF
2949// for end of file.
2950// IN assertion: the stream s has been sucessfully opened for reading.
2951
2952int unzlocal_getByte(LUFILE *fin,int *pi)
2953{ unsigned char c;
2954  int err = (int)lufread(&c, 1, 1, fin);
2955  if (err==1)
2956  { *pi = (int)c;
2957    return UNZ_OK;
2958  }
2959  else
2960  { if (luferror(fin)) return UNZ_ERRNO;
2961    else return UNZ_EOF;
2962  }
2963}
2964
2965
2966// ===========================================================================
2967// Reads a long in LSB order from the given gz_stream. Sets
2968int unzlocal_getShort (LUFILE *fin,uLong *pX)
2969{
2970    uLong x ;
2971    int i;
2972    int err;
2973
2974    err = unzlocal_getByte(fin,&i);
2975    x = (uLong)i;
2976
2977    if (err==UNZ_OK)
2978        err = unzlocal_getByte(fin,&i);
2979    x += ((uLong)i)<<8;
2980
2981    if (err==UNZ_OK)
2982        *pX = x;
2983    else
2984        *pX = 0;
2985    return err;
2986}
2987
2988int unzlocal_getLong (LUFILE *fin,uLong *pX)
2989{
2990    uLong x ;
2991    int i;
2992    int err;
2993
2994    err = unzlocal_getByte(fin,&i);
2995    x = (uLong)i;
2996   
2997    if (err==UNZ_OK)
2998        err = unzlocal_getByte(fin,&i);
2999    x += ((uLong)i)<<8;
3000
3001    if (err==UNZ_OK)
3002        err = unzlocal_getByte(fin,&i);
3003    x += ((uLong)i)<<16;
3004
3005    if (err==UNZ_OK)
3006        err = unzlocal_getByte(fin,&i);
3007    x += ((uLong)i)<<24;
3008   
3009    if (err==UNZ_OK)
3010        *pX = x;
3011    else
3012        *pX = 0;
3013    return err;
3014}
3015
3016
3017// My own strcmpi / strcasecmp
3018int strcmpcasenosensitive_internal (const char* fileName1,const char *fileName2)
3019{
3020        for (;;)
3021        {
3022                char c1=*(fileName1++);
3023                char c2=*(fileName2++);
3024                if ((c1>='a') && (c1<='z'))
3025                        c1 -= (char)0x20;
3026                if ((c2>='a') && (c2<='z'))
3027                        c2 -= (char)0x20;
3028                if (c1=='\0')
3029                        return ((c2=='\0') ? 0 : -1);
3030                if (c2=='\0')
3031                        return 1;
3032                if (c1<c2)
3033                        return -1;
3034                if (c1>c2)
3035                        return 1;
3036        }
3037}
3038
3039
3040
3041
3042//
3043// Compare two filename (fileName1,fileName2).
3044// If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
3045// If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp)
3046//
3047int unzStringFileNameCompare (const char*fileName1,const char*fileName2,int iCaseSensitivity)
3048{ if (iCaseSensitivity==1) return strcmp(fileName1,fileName2);
3049  else return strcmpcasenosensitive_internal(fileName1,fileName2);
3050}
3051
3052#define BUFREADCOMMENT (0x400)
3053
3054
3055//  Locate the Central directory of a zipfile (at the end, just before
3056// the global comment). Lu bugfix 2005.07.26 - returns 0xFFFFFFFF if not found,
3057// rather than 0, since 0 is a valid central-dir-location for an empty zipfile.
3058uLong unzlocal_SearchCentralDir(LUFILE *fin)
3059{ if (lufseek(fin,0,SEEK_END) != 0) return 0xFFFFFFFF;
3060  uLong uSizeFile = luftell(fin);
3061
3062  uLong uMaxBack=0xffff; // maximum size of global comment
3063  if (uMaxBack>uSizeFile) uMaxBack = uSizeFile;
3064
3065  unsigned char *buf = (unsigned char*)zmalloc(BUFREADCOMMENT+4);
3066  if (buf==NULL) return 0xFFFFFFFF;
3067  uLong uPosFound=0xFFFFFFFF;
3068
3069  uLong uBackRead = 4;
3070  while (uBackRead<uMaxBack)
3071  { uLong uReadSize,uReadPos ;
3072    int i;
3073    if (uBackRead+BUFREADCOMMENT>uMaxBack) uBackRead = uMaxBack;
3074    else uBackRead+=BUFREADCOMMENT;
3075    uReadPos = uSizeFile-uBackRead ;
3076    uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
3077    if (lufseek(fin,uReadPos,SEEK_SET)!=0) break;
3078    if (lufread(buf,(uInt)uReadSize,1,fin)!=1) break;
3079    for (i=(int)uReadSize-3; (i--)>=0;)
3080    { if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
3081      { uPosFound = uReadPos+i; break;
3082      }
3083    }
3084    if (uPosFound!=0) break;
3085  }
3086  if (buf) zfree(buf);
3087  return uPosFound;
3088}
3089
3090
3091int unzGoToFirstFile (unzFile file);
3092int unzCloseCurrentFile (unzFile file);
3093
3094// Open a Zip file.
3095// If the zipfile cannot be opened (file don't exist or in not valid), return NULL.
3096// Otherwise, the return value is a unzFile Handle, usable with other unzip functions
3097unzFile unzOpenInternal(LUFILE *fin)
3098{ if (fin==NULL) return NULL;
3099  if (unz_copyright[0]!=' ') {lufclose(fin); return NULL;}
3100
3101  int err=UNZ_OK;
3102  unz_s us={0};
3103  uLong central_pos=0,uL=0;
3104  central_pos = unzlocal_SearchCentralDir(fin);
3105  if (central_pos==0xFFFFFFFF) err=UNZ_ERRNO;
3106  if (err==UNZ_OK && lufseek(fin,central_pos,SEEK_SET)!=0) err=UNZ_ERRNO;
3107  // the signature, already checked
3108  if (err==UNZ_OK && unzlocal_getLong(fin,&uL)!=UNZ_OK) err=UNZ_ERRNO;
3109  // number of this disk
3110  uLong number_disk=0;          // number of the current dist, used for spanning ZIP, unsupported, always 0
3111  if (err==UNZ_OK && unzlocal_getShort(fin,&number_disk)!=UNZ_OK) err=UNZ_ERRNO;
3112  // number of the disk with the start of the central directory
3113  uLong number_disk_with_CD=0;  // number the the disk with central dir, used for spaning ZIP, unsupported, always 0
3114  if (err==UNZ_OK && unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO;
3115  // total number of entries in the central dir on this disk
3116  if (err==UNZ_OK && unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO;
3117  // total number of entries in the central dir
3118  uLong number_entry_CD=0;      // total number of entries in the central dir (same than number_entry on nospan)
3119  if (err==UNZ_OK && unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO;
3120  if (err==UNZ_OK && ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))) err=UNZ_BADZIPFILE;
3121  // size of the central directory
3122  if (err==UNZ_OK && unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO;
3123  // offset of start of central directory with respect to the starting disk number
3124  if (err==UNZ_OK && unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO;
3125  // zipfile comment length
3126  if (err==UNZ_OK && unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO;
3127  if (err==UNZ_OK && ((central_pos+fin->initial_offset<us.offset_central_dir+us.size_central_dir) && (err==UNZ_OK))) err=UNZ_BADZIPFILE;
3128  if (err!=UNZ_OK) {lufclose(fin);return NULL;}
3129
3130  us.file=fin;
3131  us.byte_before_the_zipfile = central_pos+fin->initial_offset - (us.offset_central_dir+us.size_central_dir);
3132  us.central_pos = central_pos;
3133  us.pfile_in_zip_read = NULL;
3134  fin->initial_offset = 0; // since the zipfile itself is expected to handle this
3135
3136  unz_s *s = (unz_s*)zmalloc(sizeof(unz_s));
3137  *s=us;
3138  unzGoToFirstFile((unzFile)s);
3139  return (unzFile)s;
3140}
3141
3142
3143
3144//  Close a ZipFile opened with unzipOpen.
3145//  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
3146//    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
3147//  return UNZ_OK if there is no problem.
3148int unzClose (unzFile file)
3149{
3150   
3151    if (file==NULL)
3152        return UNZ_PARAMERROR;
3153
3154    unz_s* s=(unz_s*)file;
3155
3156    if (s->pfile_in_zip_read!=NULL)
3157        unzCloseCurrentFile(file);
3158
3159    lufclose(s->file);
3160    zfree(s);
3161    return UNZ_OK;
3162}
3163
3164
3165//  Write info about the ZipFile in the *pglobal_info structure.
3166//  No preparation of the structure is needed
3167//  return UNZ_OK if there is no problem.
3168int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info)
3169{
3170        unz_s* s;
3171        if (file==NULL)
3172                return UNZ_PARAMERROR;
3173        s=(unz_s*)file;
3174        *pglobal_info=s->gi;
3175        return UNZ_OK;
3176}
3177
3178
3179//   Translate date/time from Dos format to tm_unz (readable more easilty)
3180void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
3181{
3182    uLong uDate;
3183    uDate = (uLong)(ulDosDate>>16);
3184    ptm->tm_mday = (uInt)(uDate&0x1f) ;
3185    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
3186    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
3187
3188    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
3189    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
3190    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
3191}
3192
3193//  Get Info about the current file in the zipfile, with internal only info
3194int unzlocal_GetCurrentFileInfoInternal (unzFile file,
3195                                                  unz_file_info *pfile_info,
3196                                                  unz_file_info_internal
3197                                                  *pfile_info_internal,
3198                                                  char *szFileName,
3199                                                                                                  uLong fileNameBufferSize,
3200                                                  void *extraField,
3201                                                                                                  uLong extraFieldBufferSize,
3202                                                  char *szComment,
3203                                                                                                  uLong commentBufferSize);
3204
3205int unzlocal_GetCurrentFileInfoInternal (unzFile file, unz_file_info *pfile_info,
3206   unz_file_info_internal *pfile_info_internal, char *szFileName,
3207   uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize,
3208   char *szComment, uLong commentBufferSize)
3209{
3210        unz_s* s;
3211        unz_file_info file_info;
3212        unz_file_info_internal file_info_internal;
3213        int err=UNZ_OK;
3214        uLong uMagic;
3215        long lSeek=0;
3216
3217        if (file==NULL)
3218                return UNZ_PARAMERROR;
3219        s=(unz_s*)file;
3220        if (lufseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
3221                err=UNZ_ERRNO;
3222
3223
3224        // we check the magic
3225        if (err==UNZ_OK)
3226        {
3227                if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
3228                        err=UNZ_ERRNO;
3229                else if (uMagic!=0x02014b50)
3230                        err=UNZ_BADZIPFILE;
3231        }
3232
3233        if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
3234                err=UNZ_ERRNO;
3235
3236        if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
3237                err=UNZ_ERRNO;
3238
3239        if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
3240                err=UNZ_ERRNO;
3241
3242        if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
3243                err=UNZ_ERRNO;
3244
3245        if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
3246                err=UNZ_ERRNO;
3247
3248    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
3249
3250        if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
3251                err=UNZ_ERRNO;
3252
3253        if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
3254                err=UNZ_ERRNO;
3255
3256        if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
3257                err=UNZ_ERRNO;
3258
3259        if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
3260                err=UNZ_ERRNO;
3261
3262        if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
3263                err=UNZ_ERRNO;
3264
3265        if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
3266                err=UNZ_ERRNO;
3267
3268        if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
3269                err=UNZ_ERRNO;
3270
3271        if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
3272                err=UNZ_ERRNO;
3273
3274        if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
3275                err=UNZ_ERRNO;
3276
3277        if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
3278                err=UNZ_ERRNO;
3279
3280        lSeek+=file_info.size_filename;
3281        if ((err==UNZ_OK) && (szFileName!=NULL))
3282        {
3283                uLong uSizeRead ;
3284                if (file_info.size_filename<fileNameBufferSize)
3285                {
3286                        *(szFileName+file_info.size_filename)='\0';
3287                        uSizeRead = file_info.size_filename;
3288                }
3289                else
3290                        uSizeRead = fileNameBufferSize;
3291
3292                if ((file_info.size_filename>0) && (fileNameBufferSize>0))
3293                        if (lufread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
3294                                err=UNZ_ERRNO;
3295                lSeek -= uSizeRead;
3296        }
3297
3298
3299        if ((err==UNZ_OK) && (extraField!=NULL))
3300        {
3301                uLong uSizeRead ;
3302                if (file_info.size_file_extra<extraFieldBufferSize)
3303                        uSizeRead = file_info.size_file_extra;
3304                else
3305                        uSizeRead = extraFieldBufferSize;
3306
3307                if (lSeek!=0)
3308                {
3309                        if (lufseek(s->file,lSeek,SEEK_CUR)==0)
3310                                lSeek=0;
3311                        else
3312                                err=UNZ_ERRNO;
3313                }
3314
3315                if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
3316                {
3317                        if (lufread(extraField,(uInt)uSizeRead,1,s->file)!=1)
3318                                err=UNZ_ERRNO;
3319                }
3320
3321                lSeek += file_info.size_file_extra - uSizeRead;
3322        }
3323        else
3324                lSeek+=file_info.size_file_extra;
3325
3326
3327        if ((err==UNZ_OK) && (szComment!=NULL))
3328        {
3329                uLong uSizeRead ;
3330                if (file_info.size_file_comment<commentBufferSize)
3331                {
3332                        *(szComment+file_info.size_file_comment)='\0';
3333                        uSizeRead = file_info.size_file_comment;
3334                }
3335                else
3336                        uSizeRead = commentBufferSize;
3337
3338                if (lSeek!=0)
3339                {
3340                        if (lufseek(s->file,lSeek,SEEK_CUR)==0)
3341                                {} // unused lSeek=0;
3342                        else
3343                                err=UNZ_ERRNO;
3344                }
3345
3346                if ((file_info.size_file_comment>0) && (commentBufferSize>0))
3347                        if (lufread(szComment,(uInt)uSizeRead,1,s->file)!=1)
3348                                err=UNZ_ERRNO;
3349                //unused lSeek+=file_info.size_file_comment - uSizeRead;
3350        }
3351        else {} //unused lSeek+=file_info.size_file_comment;
3352
3353        if ((err==UNZ_OK) && (pfile_info!=NULL))
3354                *pfile_info=file_info;
3355
3356        if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
3357                *pfile_info_internal=file_info_internal;
3358
3359        return err;
3360}
3361
3362
3363
3364//  Write info about the ZipFile in the *pglobal_info structure.
3365//  No preparation of the structure is needed
3366//  return UNZ_OK if there is no problem.
3367int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info,
3368  char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize,
3369  char *szComment, uLong commentBufferSize)
3370{ return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,szFileName,fileNameBufferSize,
3371      extraField,extraFieldBufferSize, szComment,commentBufferSize);
3372}
3373
3374
3375//  Set the current file of the zipfile to the first file.
3376//  return UNZ_OK if there is no problem
3377int unzGoToFirstFile (unzFile file)
3378{
3379        int err;
3380        unz_s* s;
3381        if (file==NULL) return UNZ_PARAMERROR;
3382        s=(unz_s*)file;
3383        s->pos_in_central_dir=s->offset_central_dir;
3384        s->num_file=0;
3385        err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
3386                                                                                         &s->cur_file_info_internal,
3387                                                                                         NULL,0,NULL,0,NULL,0);
3388        s->current_file_ok = (err == UNZ_OK);
3389        return err;
3390}
3391
3392
3393//  Set the current file of the zipfile to the next file.
3394//  return UNZ_OK if there is no problem
3395//  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
3396int unzGoToNextFile (unzFile file)
3397{
3398        unz_s* s;
3399        int err;
3400
3401        if (file==NULL)
3402                return UNZ_PARAMERROR;
3403        s=(unz_s*)file;
3404        if (!s->current_file_ok)
3405                return UNZ_END_OF_LIST_OF_FILE;
3406        if (s->num_file+1==s->gi.number_entry)
3407                return UNZ_END_OF_LIST_OF_FILE;
3408
3409        s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
3410                        s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
3411        s->num_file++;
3412        err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
3413                                                                                           &s->cur_file_info_internal,
3414                                                                                           NULL,0,NULL,0,NULL,0);
3415        s->current_file_ok = (err == UNZ_OK);
3416        return err;
3417}
3418
3419
3420//  Try locate the file szFileName in the zipfile.
3421//  For the iCaseSensitivity signification, see unzStringFileNameCompare
3422//  return value :
3423//  UNZ_OK if the file is found. It becomes the current file.
3424//  UNZ_END_OF_LIST_OF_FILE if the file is not found
3425int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
3426{
3427        unz_s* s;
3428        int err;
3429
3430
3431        uLong num_fileSaved;
3432        uLong pos_in_central_dirSaved;
3433
3434
3435        if (file==NULL)
3436                return UNZ_PARAMERROR;
3437
3438    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
3439        return UNZ_PARAMERROR;
3440
3441        s=(unz_s*)file;
3442        if (!s->current_file_ok)
3443                return UNZ_END_OF_LIST_OF_FILE;
3444
3445        num_fileSaved = s->num_file;
3446        pos_in_central_dirSaved = s->pos_in_central_dir;
3447
3448        err = unzGoToFirstFile(file);
3449
3450        while (err == UNZ_OK)
3451        {
3452                char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
3453                unzGetCurrentFileInfo(file,NULL,
3454                                                                szCurrentFileName,sizeof(szCurrentFileName)-1,
3455                                                                NULL,0,NULL,0);
3456                if (unzStringFileNameCompare(szCurrentFileName,szFileName,iCaseSensitivity)==0)
3457                        return UNZ_OK;
3458                err = unzGoToNextFile(file);
3459        }
3460
3461        s->num_file = num_fileSaved ;
3462        s->pos_in_central_dir = pos_in_central_dirSaved ;
3463        return err;
3464}
3465
3466
3467//  Read the local header of the current zipfile
3468//  Check the coherency of the local header and info in the end of central
3469//        directory about this file
3470//  store in *piSizeVar the size of extra info in local header
3471//        (filename and size of extra field data)
3472int unzlocal_CheckCurrentFileCoherencyHeader (unz_s *s,uInt *piSizeVar,
3473  uLong *poffset_local_extrafield, uInt  *psize_local_extrafield)
3474{
3475        uLong uMagic,uData,uFlags;
3476        uLong size_filename;
3477        uLong size_extra_field;
3478        int err=UNZ_OK;
3479
3480        *piSizeVar = 0;
3481        *poffset_local_extrafield = 0;
3482        *psize_local_extrafield = 0;
3483
3484        if (lufseek(s->file,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,SEEK_SET)!=0)
3485                return UNZ_ERRNO;
3486
3487
3488        if (err==UNZ_OK)
3489        {
3490                if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
3491                        err=UNZ_ERRNO;
3492                else if (uMagic!=0x04034b50)
3493                        err=UNZ_BADZIPFILE;
3494        }
3495
3496        if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
3497                err=UNZ_ERRNO;
3498//      else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
3499//              err=UNZ_BADZIPFILE;
3500        if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
3501                err=UNZ_ERRNO;
3502
3503        if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
3504                err=UNZ_ERRNO;
3505        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
3506                err=UNZ_BADZIPFILE;
3507
3508    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
3509                         (s->cur_file_info.compression_method!=Z_DEFLATED))
3510        err=UNZ_BADZIPFILE;
3511
3512        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // date/time
3513                err=UNZ_ERRNO;
3514
3515        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // crc
3516                err=UNZ_ERRNO;
3517        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
3518                                      ((uFlags & 8)==0))
3519                err=UNZ_BADZIPFILE;
3520
3521        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size compr
3522                err=UNZ_ERRNO;
3523        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
3524                                                          ((uFlags & 8)==0))
3525                err=UNZ_BADZIPFILE;
3526
3527        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size uncompr
3528                err=UNZ_ERRNO;
3529        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
3530                                                          ((uFlags & 8)==0))
3531                err=UNZ_BADZIPFILE;
3532
3533
3534        if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
3535                err=UNZ_ERRNO;
3536        else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
3537                err=UNZ_BADZIPFILE;
3538
3539        *piSizeVar += (uInt)size_filename;
3540
3541        if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
3542                err=UNZ_ERRNO;
3543        *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
3544                                                                        SIZEZIPLOCALHEADER + size_filename;
3545        *psize_local_extrafield = (uInt)size_extra_field;
3546
3547        *piSizeVar += (uInt)size_extra_field;
3548
3549        return err;
3550}
3551
3552
3553
3554
3555
3556//  Open for reading data the current file in the zipfile.
3557//  If there is no error and the file is opened, the return value is UNZ_OK.
3558int unzOpenCurrentFile (unzFile file, const char *password)
3559{
3560        int err;
3561        int Store;
3562        uInt iSizeVar;
3563        unz_s* s;
3564        file_in_zip_read_info_s* pfile_in_zip_read_info;
3565        uLong offset_local_extrafield;  // offset of the local extra field
3566        uInt  size_local_extrafield;    // size of the local extra field
3567
3568        if (file==NULL)
3569                return UNZ_PARAMERROR;
3570        s=(unz_s*)file;
3571        if (!s->current_file_ok)
3572                return UNZ_PARAMERROR;
3573
3574    if (s->pfile_in_zip_read != NULL)
3575        unzCloseCurrentFile(file);
3576
3577        if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
3578                                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
3579                return UNZ_BADZIPFILE;
3580
3581        pfile_in_zip_read_info = (file_in_zip_read_info_s*)zmalloc(sizeof(file_in_zip_read_info_s));
3582        if (pfile_in_zip_read_info==NULL)
3583                return UNZ_INTERNALERROR;
3584
3585        pfile_in_zip_read_info->read_buffer=(char*)zmalloc(UNZ_BUFSIZE);
3586        pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
3587        pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
3588        pfile_in_zip_read_info->pos_local_extrafield=0;
3589
3590        if (pfile_in_zip_read_info->read_buffer==NULL)
3591        {
3592                if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); //unused pfile_in_zip_read_info=0;
3593                return UNZ_INTERNALERROR;
3594        }
3595
3596        pfile_in_zip_read_info->stream_initialised=0;
3597
3598        if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED))
3599        { // unused err=UNZ_BADZIPFILE;
3600        }
3601        Store = s->cur_file_info.compression_method==0;
3602
3603        pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
3604        pfile_in_zip_read_info->crc32=0;
3605        pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
3606        pfile_in_zip_read_info->file=s->file;
3607        pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
3608
3609    pfile_in_zip_read_info->stream.total_out = 0;
3610
3611        if (!Store)
3612        {
3613          pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
3614          pfile_in_zip_read_info->stream.zfree = (free_func)0;
3615          pfile_in_zip_read_info->stream.opaque = (voidpf)0;
3616
3617          err=inflateInit2(&pfile_in_zip_read_info->stream);
3618          if (err == Z_OK)
3619            pfile_in_zip_read_info->stream_initialised=1;
3620        // windowBits is passed < 0 to tell that there is no zlib header.
3621        // Note that in this case inflate *requires* an extra "dummy" byte
3622        // after the compressed stream in order to complete decompression and
3623        // return Z_STREAM_END.
3624        // In unzip, i don't wait absolutely Z_STREAM_END because I known the
3625        // size of both compressed and uncompressed data
3626        }
3627        pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size ;
3628        pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size ;
3629  pfile_in_zip_read_info->encrypted = (s->cur_file_info.flag&1)!=0;
3630  bool extlochead = (s->cur_file_info.flag&8)!=0;
3631  if (extlochead) pfile_in_zip_read_info->crcenctest = (char)((s->cur_file_info.dosDate>>8)&0xff);
3632  else pfile_in_zip_read_info->crcenctest = (char)(s->cur_file_info.crc >> 24);
3633  pfile_in_zip_read_info->encheadleft = (pfile_in_zip_read_info->encrypted?12:0);
3634  pfile_in_zip_read_info->keys[0] = 305419896L;
3635  pfile_in_zip_read_info->keys[1] = 591751049L;
3636  pfile_in_zip_read_info->keys[2] = 878082192L;
3637  for (const char *cp=password; cp!=0 && *cp!=0; cp++) Uupdate_keys(pfile_in_zip_read_info->keys,*cp);
3638
3639        pfile_in_zip_read_info->pos_in_zipfile =
3640            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
3641                          iSizeVar;
3642
3643        pfile_in_zip_read_info->stream.avail_in = (uInt)0;
3644
3645        s->pfile_in_zip_read = pfile_in_zip_read_info;
3646
3647  return UNZ_OK;
3648}
3649
3650
3651//  Read bytes from the current file.
3652//  buf contain buffer where data must be copied
3653//  len the size of buf.
3654//  return the number of byte copied if somes bytes are copied (and also sets *reached_eof)
3655//  return 0 if the end of file was reached. (and also sets *reached_eof).
3656//  return <0 with error code if there is an error. (in which case *reached_eof is meaningless)
3657//    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
3658int unzReadCurrentFile  (unzFile file, voidp buf, unsigned len, bool *reached_eof)
3659{ int err=UNZ_OK;
3660  uInt iRead = 0;
3661  if (reached_eof!=0) *reached_eof=false;
3662
3663  unz_s *s = (unz_s*)file;
3664  if (s==NULL) return UNZ_PARAMERROR;
3665
3666  file_in_zip_read_info_s* pfile_in_zip_read_info = s->pfile_in_zip_read;
3667  if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR;
3668  if ((pfile_in_zip_read_info->read_buffer == NULL)) return UNZ_END_OF_LIST_OF_FILE;
3669  if (len==0) return 0;
3670
3671  pfile_in_zip_read_info->stream.next_out = (Byte*)buf;
3672  pfile_in_zip_read_info->stream.avail_out = (uInt)len;
3673
3674  if (len>pfile_in_zip_read_info->rest_read_uncompressed)
3675  { pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
3676  }
3677
3678  while (pfile_in_zip_read_info->stream.avail_out>0)
3679  { if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0))
3680    { uInt uReadThis = UNZ_BUFSIZE;
3681      if (pfile_in_zip_read_info->rest_read_compressed<uReadThis) uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
3682      if (uReadThis == 0) {if (reached_eof!=0) *reached_eof=true; return UNZ_EOF;}
3683      if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) return UNZ_ERRNO;
3684      if (lufread(pfile_in_zip_read_info->read_buffer,uReadThis,1,pfile_in_zip_read_info->file)!=1) return UNZ_ERRNO;
3685      pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
3686      pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
3687      pfile_in_zip_read_info->stream.next_in = (Byte*)pfile_in_zip_read_info->read_buffer;
3688      pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
3689      //
3690      if (pfile_in_zip_read_info->encrypted)
3691      { char *buf = (char*)pfile_in_zip_read_info->stream.next_in;
3692        for (unsigned int i=0; i<uReadThis; i++) buf[i]=zdecode(pfile_in_zip_read_info->keys,buf[i]);
3693      }
3694    }
3695
3696    unsigned int uDoEncHead = pfile_in_zip_read_info->encheadleft;
3697    if (uDoEncHead>pfile_in_zip_read_info->stream.avail_in) uDoEncHead=pfile_in_zip_read_info->stream.avail_in;
3698    if (uDoEncHead>0)
3699    { char bufcrc=pfile_in_zip_read_info->stream.next_in[uDoEncHead-1];
3700      pfile_in_zip_read_info->rest_read_uncompressed-=uDoEncHead;
3701      pfile_in_zip_read_info->stream.avail_in -= uDoEncHead;
3702      pfile_in_zip_read_info->stream.next_in += uDoEncHead;
3703      pfile_in_zip_read_info->encheadleft -= uDoEncHead;
3704      if (pfile_in_zip_read_info->encheadleft==0)
3705      { if (bufcrc!=pfile_in_zip_read_info->crcenctest) return UNZ_PASSWORD;
3706      }
3707    }
3708
3709    if (pfile_in_zip_read_info->compression_method==0)
3710    { uInt uDoCopy,i ;
3711      if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in)
3712      { uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
3713      }
3714      else
3715      { uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
3716      }
3717      for (i=0;i<uDoCopy;i++) *(pfile_in_zip_read_info->stream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i);
3718      pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,pfile_in_zip_read_info->stream.next_out,uDoCopy);
3719      pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
3720      pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
3721      pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
3722      pfile_in_zip_read_info->stream.next_out += uDoCopy;
3723      pfile_in_zip_read_info->stream.next_in += uDoCopy;
3724      pfile_in_zip_read_info->stream.total_out += uDoCopy;
3725      iRead += uDoCopy;
3726      if (pfile_in_zip_read_info->rest_read_uncompressed==0) {if (reached_eof!=0) *reached_eof=true;}
3727    }
3728    else
3729    { uLong uTotalOutBefore,uTotalOutAfter;
3730      const Byte *bufBefore;
3731      uLong uOutThis;
3732      int flush=Z_SYNC_FLUSH;
3733      uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
3734      bufBefore = pfile_in_zip_read_info->stream.next_out;
3735      //
3736      err=inflate(&pfile_in_zip_read_info->stream,flush);
3737      //
3738      uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
3739      uOutThis = uTotalOutAfter-uTotalOutBefore;
3740      pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,bufBefore,(uInt)(uOutThis));
3741      pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
3742      iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
3743      if (err==Z_STREAM_END || pfile_in_zip_read_info->rest_read_uncompressed==0)
3744      { if (reached_eof!=0) *reached_eof=true;
3745        return iRead;
3746      }
3747      if (err!=Z_OK) break;
3748    }
3749  }
3750
3751  if (err==Z_OK) return iRead;
3752  return err;
3753}
3754
3755
3756//  Give the current position in uncompressed data
3757z_off_t unztell (unzFile file)
3758{
3759        unz_s* s;
3760        file_in_zip_read_info_s* pfile_in_zip_read_info;
3761        if (file==NULL)
3762                return UNZ_PARAMERROR;
3763        s=(unz_s*)file;
3764    pfile_in_zip_read_info=s->pfile_in_zip_read;
3765
3766        if (pfile_in_zip_read_info==NULL)
3767                return UNZ_PARAMERROR;
3768
3769        return (z_off_t)pfile_in_zip_read_info->stream.total_out;
3770}
3771
3772
3773//  return 1 if the end of file was reached, 0 elsewhere
3774int unzeof (unzFile file)
3775{
3776        unz_s* s;
3777        file_in_zip_read_info_s* pfile_in_zip_read_info;
3778        if (file==NULL)
3779                return UNZ_PARAMERROR;
3780        s=(unz_s*)file;
3781    pfile_in_zip_read_info=s->pfile_in_zip_read;
3782
3783        if (pfile_in_zip_read_info==NULL)
3784                return UNZ_PARAMERROR;
3785
3786        if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
3787                return 1;
3788        else
3789                return 0;
3790}
3791
3792
3793
3794//  Read extra field from the current file (opened by unzOpenCurrentFile)
3795//  This is the local-header version of the extra field (sometimes, there is
3796//    more info in the local-header version than in the central-header)
3797//  if buf==NULL, it return the size of the local extra field that can be read
3798//  if buf!=NULL, len is the size of the buffer, the extra header is copied in buf.
3799//  the return value is the number of bytes copied in buf, or (if <0) the error code
3800int unzGetLocalExtrafield (unzFile file,voidp buf,unsigned len)
3801{
3802        unz_s* s;
3803        file_in_zip_read_info_s* pfile_in_zip_read_info;
3804        uInt read_now;
3805        uLong size_to_read;
3806
3807        if (file==NULL)
3808                return UNZ_PARAMERROR;
3809        s=(unz_s*)file;
3810    pfile_in_zip_read_info=s->pfile_in_zip_read;
3811
3812        if (pfile_in_zip_read_info==NULL)
3813                return UNZ_PARAMERROR;
3814
3815        size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
3816                                pfile_in_zip_read_info->pos_local_extrafield);
3817
3818        if (buf==NULL)
3819                return (int)size_to_read;
3820
3821        if (len>size_to_read)
3822                read_now = (uInt)size_to_read;
3823        else
3824                read_now = (uInt)len ;
3825
3826        if (read_now==0)
3827                return 0;
3828
3829        if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->offset_local_extrafield +  pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
3830                return UNZ_ERRNO;
3831
3832        if (lufread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
3833                return UNZ_ERRNO;
3834
3835        return (int)read_now;
3836}
3837
3838//  Close the file in zip opened with unzipOpenCurrentFile
3839//  Return UNZ_CRCERROR if all the file was read but the CRC is not good
3840int unzCloseCurrentFile (unzFile file)
3841{
3842        int err=UNZ_OK;
3843
3844        unz_s* s;
3845        file_in_zip_read_info_s* pfile_in_zip_read_info;
3846        if (file==NULL)
3847                return UNZ_PARAMERROR;
3848        s=(unz_s*)file;
3849    pfile_in_zip_read_info=s->pfile_in_zip_read;
3850
3851        if (pfile_in_zip_read_info==NULL)
3852                return UNZ_PARAMERROR;
3853
3854
3855        if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
3856        {
3857                if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
3858                        err=UNZ_CRCERROR;
3859        }
3860
3861
3862        if (pfile_in_zip_read_info->read_buffer!=0)
3863        { void *buf = pfile_in_zip_read_info->read_buffer;
3864          zfree(buf);
3865          pfile_in_zip_read_info->read_buffer=0;
3866        }
3867        pfile_in_zip_read_info->read_buffer = NULL;
3868        if (pfile_in_zip_read_info->stream_initialised)
3869                inflateEnd(&pfile_in_zip_read_info->stream);
3870
3871        pfile_in_zip_read_info->stream_initialised = 0;
3872        if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); // unused pfile_in_zip_read_info=0;
3873
3874    s->pfile_in_zip_read=NULL;
3875
3876        return err;
3877}
3878
3879
3880//  Get the global comment string of the ZipFile, in the szComment buffer.
3881//  uSizeBuf is the size of the szComment buffer.
3882//  return the number of byte copied or an error code <0
3883int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)
3884{ //int err=UNZ_OK;
3885  unz_s* s;
3886  uLong uReadThis ;
3887  if (file==NULL) return UNZ_PARAMERROR;
3888  s=(unz_s*)file;
3889  uReadThis = uSizeBuf;
3890  if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment;
3891  if (lufseek(s->file,s->central_pos+22,SEEK_SET)!=0) return UNZ_ERRNO;
3892  if (uReadThis>0)
3893  { *szComment='\0';
3894    if (lufread(szComment,(uInt)uReadThis,1,s->file)!=1) return UNZ_ERRNO;
3895  }
3896  if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0';
3897  return (int)uReadThis;
3898}
3899
3900
3901
3902
3903
3904int unzOpenCurrentFile (unzFile file, const char *password);
3905int unzReadCurrentFile (unzFile file, void *buf, unsigned len);
3906int unzCloseCurrentFile (unzFile file);
3907
3908
3909
3910
3911class TUnzip
3912{ public:
3913  TUnzip(const char *pwd) : uf(0), currentfile(-1), czei(-1), password(0), unzbuf(0)
3914  {
3915    if (pwd!=0)
3916    {
3917        password=new char[strlen(pwd)+1];
3918        strncpy(password,pwd,strlen(pwd)+1);
3919    }
3920  }
3921  ~TUnzip() {if (password!=0) delete[] password; password=0; if (unzbuf!=0) delete[] unzbuf; unzbuf=0;}
3922
3923  unzFile uf; int currentfile; ZIPENTRY cze; int czei;
3924  char *password;
3925  char *unzbuf;            // lazily created and destroyed, used by Unzip
3926  TCHAR rootdir[MAX_PATH]; // includes a trailing slash
3927
3928  ZRESULT Open(void *z,unsigned int len,DWORD flags);
3929  ZRESULT Get(int index,ZIPENTRY *ze);
3930  ZRESULT Find(const TCHAR *name,bool ic,int *index,ZIPENTRY *ze);
3931  ZRESULT Unzip(int index,void *dst,unsigned int len,DWORD flags);
3932  ZRESULT SetUnzipBaseDir(const TCHAR *dir);
3933  ZRESULT Close();
3934};
3935
3936
3937ZRESULT TUnzip::Open(void *z,unsigned int len,DWORD flags)
3938{ if (uf!=0 || currentfile!=-1) return ZR_NOTINITED;
3939  //
3940#ifdef ZIP_STD
3941  char* buf = GETCWD(rootdir,MAX_PATH-1);
3942  if (buf==0) return ZR_NOFILE;
3943#else
3944#ifdef GetCurrentDirectory
3945  GetCurrentDirectory(MAX_PATH-1,rootdir);
3946#else
3947  rootdir[0]='/'; rootdir[1]=0;
3948#endif
3949#endif
3950  TCHAR *lastchar = &rootdir[_tcslen(rootdir)-1];
3951  if (*lastchar!='\\' && *lastchar!='/') {lastchar[1]='/'; lastchar[2]=0;}
3952  //
3953  if (flags==ZIP_HANDLE)
3954  { // test if we can seek on it. We can't use GetFileType(h)==FILE_TYPE_DISK since it's not on CE.
3955    DWORD res = GetFilePosU((HANDLE)z);
3956    bool canseek = (res!=0xFFFFFFFF);
3957    if (!canseek) return ZR_SEEK;
3958  }
3959  ZRESULT e; LUFILE *f = lufopen(z,len,flags,&e);
3960  if (f==NULL) return e;
3961  uf = unzOpenInternal(f);
3962  if (uf==0) return ZR_NOFILE;
3963  return ZR_OK;
3964}
3965
3966ZRESULT TUnzip::SetUnzipBaseDir(const TCHAR *dir)
3967{
3968#ifdef ZIP_STD
3969 strncpy(rootdir,dir,MAX_PATH-1);
3970#else
3971  _tcsncpy_s(rootdir,MAX_PATH,dir,MAX_PATH-1);
3972#endif
3973  TCHAR *lastchar = &rootdir[_tcslen(rootdir)-1];
3974  if (*lastchar!='\\' && *lastchar!='/') {lastchar[1]='/'; lastchar[2]=0;}
3975  return ZR_OK;
3976}
3977
3978ZRESULT TUnzip::Get(int index,ZIPENTRY *ze)
3979{ if (index<-1 || index>=(int)uf->gi.number_entry) return ZR_ARGS;
3980  if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
3981  if (index==czei && index!=-1) {memcpy(ze,&cze,sizeof(ZIPENTRY)); return ZR_OK;}
3982  if (index==-1)
3983  { ze->index = uf->gi.number_entry;
3984    ze->name[0]=0;
3985    ze->attr=0;
3986#ifdef ZIP_STD
3987    ze->atime=0;
3988    ze->ctime=0;
3989    ze->mtime=0;
3990#else
3991    ze->atime.dwLowDateTime=0; ze->atime.dwHighDateTime=0;
3992    ze->ctime.dwLowDateTime=0; ze->ctime.dwHighDateTime=0;
3993    ze->mtime.dwLowDateTime=0; ze->mtime.dwHighDateTime=0;
3994#endif
3995    ze->comp_size=0;
3996    ze->unc_size=0;
3997    return ZR_OK;
3998  }
3999  if (index<(int)uf->num_file) unzGoToFirstFile(uf);
4000  while ((int)uf->num_file<index) unzGoToNextFile(uf);
4001  unz_file_info ufi; char fn[MAX_PATH];
4002  unzGetCurrentFileInfo(uf,&ufi,fn,MAX_PATH,NULL,0,NULL,0);
4003  // now get the extra header. We do this ourselves, instead of
4004  // calling unzOpenCurrentFile &c., to avoid allocating more than necessary.
4005  unsigned int extralen,iSizeVar; unsigned long offset;
4006  int res = unzlocal_CheckCurrentFileCoherencyHeader(uf,&iSizeVar,&offset,&extralen);
4007  if (res!=UNZ_OK) return ZR_CORRUPT;
4008  if (lufseek(uf->file,offset,SEEK_SET)!=0) return ZR_READ;
4009  unsigned char *extra = new unsigned char[extralen];
4010  if (lufread(extra,1,(uInt)extralen,uf->file)!=extralen) {delete[] extra; return ZR_READ;}
4011  //
4012  ze->index=uf->num_file;
4013  TCHAR tfn[MAX_PATH];
4014#ifdef UNICODE
4015  MultiByteToWideChar(CP_UTF8,0,fn,-1,tfn,MAX_PATH);
4016#else
4017//  strcpy_s(tfn,MAX_PATH,fn);
4018  strncpy(tfn,fn,MAX_PATH);
4019#endif
4020  // As a safety feature: if the zip filename had sneaky stuff
4021  // like "c:\windows\file.txt" or "\windows\file.txt" or "fred\..\..\..\windows\file.txt"
4022  // then we get rid of them all. That way, when the programmer does UnzipItem(hz,i,ze.name),
4023  // it won't be a problem. (If the programmer really did want to get the full evil information,
4024  // then they can edit out this security feature from here).
4025  // In particular, we chop off any prefixes that are "c:\" or "\" or "/" or "[stuff]\.." or "[stuff]/.."
4026  const TCHAR *sfn=tfn;
4027  for (;;)
4028  { if (sfn[0]!=0 && sfn[1]==':') {sfn+=2; continue;}
4029    if (sfn[0]=='\\') {sfn++; continue;}
4030    if (sfn[0]=='/') {sfn++; continue;}
4031    const TCHAR *c;
4032    c=_tcsstr(sfn,_T("\\..\\")); if (c!=0) {sfn=c+4; continue;}
4033    c=_tcsstr(sfn,_T("\\../")); if (c!=0) {sfn=c+4; continue;}
4034    c=_tcsstr(sfn,_T("/../")); if (c!=0) {sfn=c+4; continue;}
4035    c=_tcsstr(sfn,_T("/..\\")); if (c!=0) {sfn=c+4; continue;}
4036    break;
4037  }
4038
4039#ifdef ZIP_STD
4040  strncpy(ze->name,sfn,MAX_PATH);
4041#else
4042  _tcsncpy_s(ze->name,MAX_PATH, sfn,MAX_PATH);
4043#endif
4044
4045  unsigned long a = ufi.external_fa;
4046  // zip has an 'attribute' 32bit value. Its lower half is windows stuff
4047  // its upper half is standard unix stat.st_mode. We'll start trying
4048  // to read it in unix mode
4049  bool isdir  =   (a&0x40000000)!=0;
4050  bool readonly=  (a&0x00800000)==0;
4051  //bool readable=  (a&0x01000000)!=0; // unused
4052  //bool executable=(a&0x00400000)!=0; // unused
4053  // but in normal hostmodes these are overridden by the lower half...
4054  int host = ufi.version>>8;
4055  if (host==0 || host==7 || host==11 || host==14)
4056  { readonly=  (a&0x00000001)!=0;
4057    isdir=     (a&0x00000010)!=0;
4058  }
4059  // readonly; hidden; system; isdir; archive;
4060  ze->attr=0;
4061#ifdef ZIP_STD
4062  ze->attr = (a&0xFFFF0000)>>16;
4063  if (isdir) ze->attr |= S_IFDIR;
4064  if (readonly) ze->attr &= ~S_IWUSR;
4065#else
4066  bool hidden=false, system=false, archive=true;
4067  if (host==0 || host==7 || host==11 || host==14)
4068  {
4069    hidden=    (a&0x00000002)!=0;
4070    system=    (a&0x00000004)!=0;
4071    archive=   (a&0x00000020)!=0;
4072  }
4073
4074  if (isdir) ze->attr |= FILE_ATTRIBUTE_DIRECTORY;
4075  if (readonly) ze->attr|=FILE_ATTRIBUTE_READONLY;
4076  if (archive) ze->attr|=FILE_ATTRIBUTE_ARCHIVE;
4077  if (hidden) ze->attr|=FILE_ATTRIBUTE_HIDDEN;
4078  if (system) ze->attr|=FILE_ATTRIBUTE_SYSTEM;
4079#endif
4080  ze->comp_size = ufi.compressed_size;
4081  ze->unc_size = ufi.uncompressed_size;
4082  //
4083  WORD dostime = (WORD)(ufi.dosDate&0xFFFF);
4084  WORD dosdate = (WORD)((ufi.dosDate>>16)&0xFFFF);
4085  FILETIME ftd = dosdatetime2filetime(dosdate,dostime);
4086  FILETIME ft; LocalFileTimeToFileTime(&ftd,&ft);
4087  ze->atime=ft; ze->ctime=ft; ze->mtime=ft;
4088  // the zip will always have at least that dostime. But if it also has
4089  // an extra header, then we'll instead get the info from that.
4090  unsigned int epos=0;
4091  while (epos+4<extralen)
4092  { char etype[3]; etype[0]=extra[epos+0]; etype[1]=extra[epos+1]; etype[2]=0;
4093    int size = extra[epos+2];
4094    if (strcmp(etype,"UT")!=0) {epos += 4+size; continue;}
4095    int flags = extra[epos+4];
4096    bool hasmtime = (flags&1)!=0;
4097    bool hasatime = (flags&2)!=0;
4098    bool hasctime = (flags&4)!=0;
4099    epos+=5;
4100    if (hasmtime)
4101    { lutime_t mtime = ((extra[epos+0])<<0) | ((extra[epos+1])<<8) |((extra[epos+2])<<16) | ((extra[epos+3])<<24);
4102          epos+=4;
4103      ze->mtime = timet2filetime(mtime);
4104    }
4105    if (hasatime)
4106    { lutime_t atime = ((extra[epos+0])<<0) | ((extra[epos+1])<<8) |((extra[epos+2])<<16) | ((extra[epos+3])<<24);
4107      epos+=4;
4108      ze->atime = timet2filetime(atime);
4109    }
4110    if (hasctime)
4111    { lutime_t ctime = ((extra[epos+0])<<0) | ((extra[epos+1])<<8) |((extra[epos+2])<<16) | ((extra[epos+3])<<24);
4112      epos+=4;
4113      ze->ctime = timet2filetime(ctime);
4114    }
4115    break;
4116  }
4117  //
4118  if (extra!=0) delete[] extra;
4119  memcpy(&cze,ze,sizeof(ZIPENTRY)); czei=index;
4120  return ZR_OK;
4121}
4122
4123ZRESULT TUnzip::Find(const TCHAR *tname,bool ic,int *index,ZIPENTRY *ze)
4124{ char name[MAX_PATH];
4125#ifdef UNICODE
4126  WideCharToMultiByte(CP_UTF8,0,tname,-1,name,MAX_PATH,0,0);
4127#else
4128//  strcpy_s(name,MAX_PATH,tname);
4129  strncpy(name,tname, MAX_PATH);
4130#endif
4131  int res = unzLocateFile(uf,name,ic?CASE_INSENSITIVE:CASE_SENSITIVE);
4132  if (res!=UNZ_OK)
4133  { if (index!=0) *index=-1;
4134    if (ze!=NULL) {memset(ze,0,sizeof(ZIPENTRY)); ze->index=-1;}
4135    return ZR_NOTFOUND;
4136  }
4137  if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
4138  int i = (int)uf->num_file;
4139  if (index!=NULL) *index=i;
4140  if (ze!=NULL)
4141  { ZRESULT zres = Get(i,ze);
4142    if (zres!=ZR_OK) return zres;
4143  }
4144  return ZR_OK;
4145}
4146
4147void EnsureDirectory(const TCHAR *rootdir, const TCHAR *dir)
4148{ // first check that rootdir exists. nb. rootdir has a trailing slash
4149  if (rootdir!=0)
4150  { TCHAR rd[MAX_PATH+1];
4151
4152#ifdef ZIP_STD
4153  strncpy(rd,rootdir,MAX_PATH);
4154#else
4155  _tcsncpy_s(rd,MAX_PATH,rootdir,MAX_PATH);
4156#endif
4157
4158    // make sure there rd is always null terminated
4159    rd[MAX_PATH] = 0;
4160 
4161    size_t len=_tcslen(rd);
4162    if (len>0 && (rd[len-1]=='/' || rd[len-1]=='\\')) rd[len-1]=0;
4163#ifdef ZIP_STD
4164    if (!FileExists(rd)) lumkdir(rd);
4165#else
4166    if (!FileExists(rd)) CreateDirectory(rd,0);
4167#endif
4168  }
4169  if (*dir==0) return;
4170  const TCHAR *lastslash=dir, *c=lastslash;
4171  while (*c!=0) {if (*c=='/' || *c=='\\') lastslash=c; c++;}
4172  const TCHAR *name=lastslash;
4173  if (lastslash!=dir)
4174  { TCHAR tmp[MAX_PATH]; memcpy(tmp,dir,sizeof(TCHAR)*(lastslash-dir));
4175    tmp[lastslash-dir]=0;
4176    EnsureDirectory(rootdir,tmp);
4177    name++;
4178  }
4179  TCHAR cd[MAX_PATH]; *cd=0;
4180  if (rootdir!=0)
4181#ifdef ZIP_STD
4182  strncpy(cd,rootdir,MAX_PATH);
4183#else
4184  _tcsncpy_s(cd,MAX_PATH,rootdir,MAX_PATH);
4185#endif 
4186 
4187  cd[MAX_PATH-1]=0;
4188  size_t len=_tcslen(cd);
4189 
4190#ifdef ZIP_STD
4191  strncpy(cd+len,dir,MAX_PATH-len);
4192#else
4193  _tcsncpy_s(cd+len,MAX_PATH-len,dir,MAX_PATH-len);
4194#endif 
4195 
4196 
4197  cd[MAX_PATH-1]=0;
4198#ifdef ZIP_STD
4199  if (!FileExists(cd)) lumkdir(cd);
4200#else
4201  if (!FileExists(cd))
4202  { CreateDirectory(cd,0);
4203  }
4204#endif
4205}
4206
4207
4208
4209ZRESULT TUnzip::Unzip(int index,void *dst,unsigned int len,DWORD flags)
4210{ if (flags!=ZIP_MEMORY && flags!=ZIP_FILENAME && flags!=ZIP_HANDLE) return ZR_ARGS;
4211  if (flags==ZIP_MEMORY)
4212  { if (index!=currentfile)
4213    { if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
4214      if (index>=(int)uf->gi.number_entry) return ZR_ARGS;
4215      if (index<(int)uf->num_file) unzGoToFirstFile(uf);
4216      while ((int)uf->num_file<index) unzGoToNextFile(uf);
4217      unzOpenCurrentFile(uf,password); currentfile=index;
4218    }
4219    bool reached_eof;
4220    int res = unzReadCurrentFile(uf,dst,len,&reached_eof);
4221    if (res<=0)
4222    {
4223       unzCloseCurrentFile(uf); currentfile=-1;
4224    }
4225    if (reached_eof)
4226    {
4227       unzCloseCurrentFile(uf);
4228       currentfile=-1;
4229       return ZR_OK;
4230    }
4231    if (res>0)
4232    {
4233       return ZR_MORE;
4234    }
4235    if (res==UNZ_PASSWORD)
4236    {
4237       return ZR_PASSWORD;
4238    }
4239
4240    return ZR_FLATE;
4241  }
4242  // otherwise we're writing to a handle or a file
4243  if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
4244  if (index>=(int)uf->gi.number_entry) return ZR_ARGS;
4245  if (index<(int)uf->num_file) unzGoToFirstFile(uf);
4246  while ((int)uf->num_file<index) unzGoToNextFile(uf);
4247  ZIPENTRY ze; Get(index,&ze);
4248  // zipentry=directory is handled specially
4249#ifdef ZIP_STD
4250                 bool isdir = S_ISDIR(ze.attr);
4251#else
4252  bool isdir = (ze.attr&FILE_ATTRIBUTE_DIRECTORY)!=0;
4253#endif
4254  if (isdir)
4255  { if (flags==ZIP_HANDLE) return ZR_OK; // don't do anything
4256    const TCHAR *dir = (const TCHAR*)dst;
4257    bool isabsolute = (dir[0]=='/' || dir[0]=='\\' || (dir[0]!=0 && dir[1]==':'));
4258    if (isabsolute) EnsureDirectory(0,dir); else EnsureDirectory(rootdir,dir);
4259    return ZR_OK;
4260  }
4261  // otherwise, we write the zipentry to a file/handle
4262  HANDLE h; TCHAR fn[MAX_PATH]; fn[0]=0;
4263  if (flags==ZIP_HANDLE) h=(HANDLE)dst;
4264  else
4265  { const TCHAR *ufn = (const TCHAR*)dst;
4266    // We'll qualify all relative names to our root dir, and leave absolute names as they are
4267    // ufn="zipfile.txt"  dir=""  name="zipfile.txt"  fn="c:\\currentdir\\zipfile.txt"
4268    // ufn="dir1/dir2/subfile.txt"  dir="dir1/dir2/"  name="subfile.txt"  fn="c:\\currentdir\\dir1/dir2/subfiles.txt"
4269    // ufn="\z\file.txt"  dir="\z\"  name="file.txt"  fn="\z\file.txt"
4270    // This might be a security risk, in the case where we just use the zipentry's name as "ufn", where
4271    // a malicious zip could unzip itself into c:\windows. Our solution is that GetZipItem (which
4272    // is how the user retrieve's the file's name within the zip) never returns absolute paths.
4273    const TCHAR *name=ufn; const TCHAR *c=name; while (*c!=0) {if (*c=='/' || *c=='\\') name=c+1; c++;}
4274    TCHAR dir[MAX_PATH];
4275
4276#ifdef ZIP_STD
4277  strncpy(dir,ufn,MAX_PATH);
4278#else
4279  _tcsncpy_s(dir,MAX_PATH,ufn,MAX_PATH);
4280#endif 
4281       
4282
4283        if (name==ufn) *dir=0; else dir[name-ufn]=0;
4284    bool isabsolute = (dir[0]=='/' || dir[0]=='\\' || (dir[0]!=0 && dir[1]==':'));
4285
4286    if (isabsolute)
4287        {
4288               
4289#ifdef ZIP_STD
4290                size_t dirlen=_tcslen(dir);
4291                strncpy(fn,dir,MAX_PATH);
4292                strncpy(fn+dirlen,name,MAX_PATH-dirlen);
4293#else
4294                _tsprintf(fn,MAX_PATH,_T("%s%s"),dir,name);
4295#endif 
4296                EnsureDirectory(0,dir);
4297       
4298        }
4299    else 
4300        {
4301#ifdef ZIP_STD
4302                size_t rootdirlen=_tcslen(rootdir);
4303                size_t dirlen=_tcslen(dir);
4304                strncpy(fn,rootdir,MAX_PATH);
4305                strncpy(fn+rootdirlen,dir,MAX_PATH-rootdirlen);
4306                strncpy(fn+rootdirlen+dirlen,name,MAX_PATH-rootdirlen-dirlen);
4307#else
4308                _tsprintf(fn,MAX_PATH,_T("%s%s%s"),rootdir,dir,name);
4309#endif
4310                EnsureDirectory(rootdir,dir);
4311        }
4312    //
4313#ifdef ZIP_STD
4314    h = fopen(fn,"wb");
4315#else
4316    h = CreateFile(fn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,ze.attr,NULL);
4317#endif
4318  }
4319  if (h==INVALID_HANDLE_VALUE) return ZR_NOFILE;
4320  unzOpenCurrentFile(uf,password);
4321  if (unzbuf==0) unzbuf=new char[16384]; DWORD haderr=0;
4322  // 
4323
4324  for (; haderr==0;)
4325  { bool reached_eof;
4326    int res = unzReadCurrentFile(uf,unzbuf,16384,&reached_eof);
4327    if (res==UNZ_PASSWORD) {haderr=ZR_PASSWORD; break;}
4328    if (res<0) {haderr=ZR_FLATE; break;}
4329#ifdef ZIP_STD
4330    if (res>0) {size_t writ=fwrite(unzbuf,1,res,h); if (writ<(size_t)res) {haderr=ZR_WRITE; break;}}
4331#else
4332    if (res>0) {DWORD writ; BOOL bres=WriteFile(h,unzbuf,res,&writ,NULL); if (!bres) {haderr=ZR_WRITE; break;}}
4333#endif
4334    if (reached_eof) break;
4335    if (res==0) {haderr=ZR_FLATE; break;}
4336  }
4337  unzCloseCurrentFile(uf);
4338#ifdef ZIP_STD
4339  if (flags!=ZIP_HANDLE) fclose(h);
4340  if (*fn!=0) {struct utimbuf ubuf; ubuf.actime=ze.atime; ubuf.modtime=ze.mtime; utime(fn,&ubuf);}
4341#else
4342  if (!haderr) SetFileTime(h,&ze.ctime,&ze.atime,&ze.mtime); // may fail if it was a pipe
4343  if (flags!=ZIP_HANDLE) CloseHandle(h);
4344#endif
4345  if (haderr!=0) return haderr;
4346  return ZR_OK;
4347}
4348
4349ZRESULT TUnzip::Close()
4350{ if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1;
4351  if (uf!=0) unzClose(uf); uf=0;
4352  return ZR_OK;
4353}
4354
4355
4356
4357
4358
4359ZRESULT lasterrorU=ZR_OK;
4360
4361unsigned int FormatZipMessageU(ZRESULT code, TCHAR *buf,unsigned int len)
4362{ if (code==ZR_RECENT) code=lasterrorU;
4363  const TCHAR *msg=_T("unknown zip result code");
4364  switch (code)
4365  { case ZR_OK: msg=_T("Success"); break;
4366    case ZR_NODUPH: msg=_T("Culdn't duplicate handle"); break;
4367    case ZR_NOFILE: msg=_T("Couldn't create/open file"); break;
4368    case ZR_NOALLOC: msg=_T("Failed to allocate memory"); break;
4369    case ZR_WRITE: msg=_T("Error writing to file"); break;
4370    case ZR_NOTFOUND: msg=_T("File not found in the zipfile"); break;
4371    case ZR_MORE: msg=_T("Still more data to unzip"); break;
4372    case ZR_CORRUPT: msg=_T("Zipfile is corrupt or not a zipfile"); break;
4373    case ZR_READ: msg=_T("Error reading file"); break;
4374    case ZR_PASSWORD: msg=_T("Correct password required"); break;
4375    case ZR_ARGS: msg=_T("Caller: faulty arguments"); break;
4376    case ZR_PARTIALUNZ: msg=_T("Caller: the file had already been partially unzipped"); break;
4377    case ZR_NOTMMAP: msg=_T("Caller: can only get memory of a memory zipfile"); break;
4378    case ZR_MEMSIZE: msg=_T("Caller: not enough space allocated for memory zipfile"); break;
4379    case ZR_FAILED: msg=_T("Caller: there was a previous error"); break;
4380    case ZR_ENDED: msg=_T("Caller: additions to the zip have already been ended"); break;
4381    case ZR_ZMODE: msg=_T("Caller: mixing creation and opening of zip"); break;
4382    case ZR_NOTINITED: msg=_T("Zip-bug: internal initialisation not completed"); break;
4383    case ZR_SEEK: msg=_T("Zip-bug: trying to seek the unseekable"); break;
4384    case ZR_MISSIZE: msg=_T("Zip-bug: the anticipated size turned out wrong"); break;
4385    case ZR_NOCHANGE: msg=_T("Zip-bug: tried to change mind, but not allowed"); break;
4386    case ZR_FLATE: msg=_T("Zip-bug: an internal error during flation"); break;
4387  }
4388  unsigned int mlen=(unsigned int)_tcslen(msg);
4389  if (buf==0 || len==0) return mlen;
4390  unsigned int n=mlen; if (n+1>len) n=len-1;
4391
4392#ifdef ZIP_STD
4393  strncpy(buf,msg,n);
4394#else
4395  _tcsncpy_s(buf,_tcslen(buf),msg,n);
4396#endif 
4397 
4398 
4399 
4400 
4401  buf[n]=0;
4402  return mlen;
4403}
4404
4405
4406typedef struct
4407{ DWORD flag;
4408  TUnzip *unz;
4409} TUnzipHandleData;
4410
4411HZIP OpenZipInternal(void *z,unsigned int len,DWORD flags, const char *password)
4412{ TUnzip *unz = new TUnzip(password);
4413  lasterrorU = unz->Open(z,len,flags);
4414  if (lasterrorU!=ZR_OK) {delete unz; return 0;}
4415  TUnzipHandleData *han = new TUnzipHandleData;
4416  han->flag=1; han->unz=unz; return (HZIP)han;
4417}
4418HZIP OpenZipHandle(HANDLE h, const char *password) {return OpenZipInternal((void*)h,0,ZIP_HANDLE,password);}
4419HZIP OpenZip(const TCHAR *fn, const char *password) {return OpenZipInternal((void*)fn,0,ZIP_FILENAME,password);}
4420HZIP OpenZip(void *z,unsigned int len, const char *password) {return OpenZipInternal(z,len,ZIP_MEMORY,password);}
4421
4422
4423ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze)
4424{ ze->index=0; *ze->name=0; ze->unc_size=0;
4425  if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
4426  TUnzipHandleData *han = (TUnzipHandleData*)hz;
4427  if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
4428  TUnzip *unz = han->unz;
4429  lasterrorU = unz->Get(index,ze);
4430  return lasterrorU;
4431}
4432
4433ZRESULT FindZipItem(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze)
4434{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
4435  TUnzipHandleData *han = (TUnzipHandleData*)hz;
4436  if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
4437  TUnzip *unz = han->unz;
4438  lasterrorU = unz->Find(name,ic,index,ze);
4439  return lasterrorU;
4440}
4441
4442ZRESULT UnzipItemInternal(HZIP hz, int index, void *dst, unsigned int len, DWORD flags)
4443{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
4444  TUnzipHandleData *han = (TUnzipHandleData*)hz;
4445  if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
4446  TUnzip *unz = han->unz;
4447  lasterrorU = unz->Unzip(index,dst,len,flags);
4448  return lasterrorU;
4449}
4450ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h) {return UnzipItemInternal(hz,index,(void*)h,0,ZIP_HANDLE);}
4451ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn) {return UnzipItemInternal(hz,index,(void*)fn,0,ZIP_FILENAME);}
4452ZRESULT UnzipItem(HZIP hz, int index, void *z,unsigned int len) {return UnzipItemInternal(hz,index,z,len,ZIP_MEMORY);}
4453
4454ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir)
4455{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
4456  TUnzipHandleData *han = (TUnzipHandleData*)hz;
4457  if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
4458  TUnzip *unz = han->unz;
4459  lasterrorU = unz->SetUnzipBaseDir(dir);
4460  return lasterrorU;
4461}
4462
4463
4464ZRESULT CloseZipU(HZIP hz)
4465{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;}
4466  TUnzipHandleData *han = (TUnzipHandleData*)hz;
4467  if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;}
4468  TUnzip *unz = han->unz;
4469  lasterrorU = unz->Close();
4470  delete unz;
4471  delete han;
4472  return lasterrorU;
4473}
4474
4475bool IsZipHandleU(HZIP hz)
4476{ if (hz==0) return false;
4477  TUnzipHandleData *han = (TUnzipHandleData*)hz;
4478  return (han->flag==1);
4479}
Note: See TracBrowser for help on using the browser.