From 5c8fc16b34871807b11553849a751057f2f1eaba Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Mon, 28 Jan 2002 21:24:17 +0000 Subject: [PATCH] checked in package manager --- stepmania/src/RageBitmapTexture.cpp | 45 +- stepmania/src/RageTexture.cpp | 37 +- stepmania/src/ThemeManager.cpp | 16 +- .../src/smpackage/SMPackageInstallDlg.cpp | 172 ++ stepmania/src/smpackage/SMPackageInstallDlg.h | 54 + stepmania/src/smpackage/StdAfx.cpp | 8 + stepmania/src/smpackage/StdAfx.h | 26 + .../src/smpackage/ZipArchive/Appnote.txt | 1192 ++++++++++++++ .../src/smpackage/ZipArchive/CodeProject.html | 380 +++++ stepmania/src/smpackage/ZipArchive/StdAfx.cpp | 6 + stepmania/src/smpackage/ZipArchive/StdAfx.h | 23 + .../src/smpackage/ZipArchive/ZipArchive.cpp | 1381 +++++++++++++++++ .../src/smpackage/ZipArchive/ZipArchive.dsp | 283 ++++ .../src/smpackage/ZipArchive/ZipArchive.dsw | 29 + .../src/smpackage/ZipArchive/ZipArchive.h | 698 +++++++++ .../src/smpackage/ZipArchive/ZipArchive.opt | Bin 0 -> 48640 bytes .../smpackage/ZipArchive/ZipAutoBuffer.cpp | 104 ++ .../src/smpackage/ZipArchive/ZipAutoBuffer.h | 63 + .../src/smpackage/ZipArchive/ZipBigFile.cpp | 41 + .../src/smpackage/ZipArchive/ZipBigFile.h | 22 + .../smpackage/ZipArchive/ZipCentralDir.cpp | 677 ++++++++ .../src/smpackage/ZipArchive/ZipCentralDir.h | 156 ++ .../src/smpackage/ZipArchive/ZipException.cpp | 78 + .../src/smpackage/ZipArchive/ZipException.h | 71 + .../smpackage/ZipArchive/ZipFileHeader.cpp | 329 ++++ .../src/smpackage/ZipArchive/ZipFileHeader.h | 106 ++ .../smpackage/ZipArchive/ZipInternalInfo.cpp | 28 + .../smpackage/ZipArchive/ZipInternalInfo.h | 32 + .../src/smpackage/ZipArchive/ZipStorage.cpp | 428 +++++ .../src/smpackage/ZipArchive/ZipStorage.h | 134 ++ stepmania/src/smpackage/ZipArchive/zconf.h | 279 ++++ stepmania/src/smpackage/install.bmp | Bin 0 -> 31578 bytes stepmania/src/smpackage/manage.bmp | Bin 0 -> 31578 bytes stepmania/src/smpackage/resource.h | 26 + stepmania/src/smpackage/smpackage.ICO | Bin 0 -> 6006 bytes stepmania/src/smpackage/smpackage.clw | 66 + stepmania/src/smpackage/smpackage.cpp | 120 ++ stepmania/src/smpackage/smpackage.dsp | 170 ++ stepmania/src/smpackage/smpackage.h | 49 + stepmania/src/smpackage/smpackage.opt | Bin 0 -> 54784 bytes stepmania/src/smpackage/smpackage.rc | 209 +++ stepmania/src/smpackage/smpackageDlg.cpp | 210 +++ stepmania/src/smpackage/smpackageDlg.h | 57 + 43 files changed, 7760 insertions(+), 45 deletions(-) create mode 100644 stepmania/src/smpackage/SMPackageInstallDlg.cpp create mode 100644 stepmania/src/smpackage/SMPackageInstallDlg.h create mode 100644 stepmania/src/smpackage/StdAfx.cpp create mode 100644 stepmania/src/smpackage/StdAfx.h create mode 100644 stepmania/src/smpackage/ZipArchive/Appnote.txt create mode 100644 stepmania/src/smpackage/ZipArchive/CodeProject.html create mode 100644 stepmania/src/smpackage/ZipArchive/StdAfx.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/StdAfx.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipArchive.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipArchive.dsp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipArchive.dsw create mode 100644 stepmania/src/smpackage/ZipArchive/ZipArchive.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipArchive.opt create mode 100644 stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipBigFile.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipBigFile.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipCentralDir.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipCentralDir.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipException.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipException.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipFileHeader.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipFileHeader.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipInternalInfo.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipInternalInfo.h create mode 100644 stepmania/src/smpackage/ZipArchive/ZipStorage.cpp create mode 100644 stepmania/src/smpackage/ZipArchive/ZipStorage.h create mode 100644 stepmania/src/smpackage/ZipArchive/zconf.h create mode 100644 stepmania/src/smpackage/install.bmp create mode 100644 stepmania/src/smpackage/manage.bmp create mode 100644 stepmania/src/smpackage/resource.h create mode 100644 stepmania/src/smpackage/smpackage.ICO create mode 100644 stepmania/src/smpackage/smpackage.clw create mode 100644 stepmania/src/smpackage/smpackage.cpp create mode 100644 stepmania/src/smpackage/smpackage.dsp create mode 100644 stepmania/src/smpackage/smpackage.h create mode 100644 stepmania/src/smpackage/smpackage.opt create mode 100644 stepmania/src/smpackage/smpackage.rc create mode 100644 stepmania/src/smpackage/smpackageDlg.cpp create mode 100644 stepmania/src/smpackage/smpackageDlg.h diff --git a/stepmania/src/RageBitmapTexture.cpp b/stepmania/src/RageBitmapTexture.cpp index 98714eb639..d26fa58a81 100644 --- a/stepmania/src/RageBitmapTexture.cpp +++ b/stepmania/src/RageBitmapTexture.cpp @@ -62,38 +62,49 @@ void RageBitmapTexture::Create() { HRESULT hr; + /////////////////////// + // Figure out which texture format to use + /////////////////////// D3DFORMAT fmtTexture; - if( !GAMEINFO ) + + // look in the file name for a hint + m_sFilePath.MakeLower(); + if( -1 != m_sFilePath.Find("(no alpha)") ) + { + fmtTexture = D3DFMT_R5G6B5; + } + else if( -1 != m_sFilePath.Find("(1 alpha)") ) + { + fmtTexture = D3DFMT_A1R5G5B5; + } + else // no hint, assume full alpha { fmtTexture = D3DFMT_A4R4G4B4; } - else if( GAMEINFO->m_GameOptions.m_iDisplayColor == 16 ) + + // if the user has requested high color textures, use the higher color + if( GAMEINFO != NULL + && GAMEINFO->m_GameOptions.m_iDisplayColor == 32 + && GAMEINFO->m_GameOptions.m_iTextureColor == 32 ) { - fmtTexture = D3DFMT_A4R4G4B4; - } - else - { - switch( GAMEINFO->m_GameOptions.m_iTextureColor ) - { - case 16: fmtTexture = D3DFMT_A4R4G4B4; break; - case 32: fmtTexture = D3DFMT_A8R8G8B8; break; - default: ASSERT( true ); // invalid iTextureColor value - } + fmtTexture = D3DFMT_A8R8G8B8; } + + + // load texture and get image info D3DXIMAGE_INFO ddii; - // load texture if( FAILED( hr = D3DXCreateTextureFromFileEx( m_pd3dDevice, // device m_sFilePath, // soure file D3DX_DEFAULT, D3DX_DEFAULT, // width, height - 3, // mip map levels + 4, // mip map levels 0, // usage (is a render target?) - fmtTexture, // our preferred texture format + fmtTexture, // our preferred texture format D3DPOOL_MANAGED, // which memory pool - D3DX_FILTER_BOX | D3DX_FILTER_DITHER, // filter - D3DX_FILTER_BOX | D3DX_FILTER_DITHER, // mip filter + D3DX_FILTER_BOX, // filter + D3DX_FILTER_BOX, // mip filter 0, // no color key &ddii, // struct to fill with source image info NULL, // no palette diff --git a/stepmania/src/RageTexture.cpp b/stepmania/src/RageTexture.cpp index d500d7e2b6..bf0132b95e 100644 --- a/stepmania/src/RageTexture.cpp +++ b/stepmania/src/RageTexture.cpp @@ -75,35 +75,32 @@ void RageTexture::CreateFrameRects() #include "string.h" void RageTexture::GetFrameDimensionsFromFileName( CString sPath, UINT* puFramesWide, UINT* puFramesHigh ) const { - *puFramesWide = *puFramesHigh = 1; // initialize in case we don't find dimensions in the file name + *puFramesWide = *puFramesHigh = 1; // set default values in case we don't find the dimension in the file name sPath.MakeLower(); CString sDir, sFName, sExt; splitrelpath( sPath, sDir, sFName, sExt); - CStringArray sFileNameBits; - split( sFName, " ", sFileNameBits, false ); + CStringArray arrayBits; + split( sFName, " ", arrayBits, false ); - if( sFileNameBits.GetSize() < 2 ) - return; // there can't be dimensions in the file name if there's no space - - CString sDimensionsPart = sFileNameBits[ sFileNameBits.GetSize()-1 ]; // looks like "10x5" - - CStringArray sDimensionsBits; - split( sDimensionsPart, "x", sDimensionsBits, false ); - - if( sDimensionsBits.GetSize() != 2 ) + for( int i=0; iLoadIcon(IDR_MAINFRAME); + + m_sPackagePath = sPackagePath; +} + + +void CSMPackageInstallDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSMPackageInstallDlg) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSMPackageInstallDlg, CDialog) + //{{AFX_MSG_MAP(CSMPackageInstallDlg) + ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSMPackageInstallDlg message handlers + +BOOL CSMPackageInstallDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + + CString sMessage; + sMessage += ssprintf( + "You have chosen to install the Stepmania package:\r\n" + "\t%s\r\n" + "\r\n" + "This package contains the following files:\r\n", + m_sPackagePath + ); + + // add all the files in the zip to the message + try + { + m_zip.Open( m_sPackagePath ); + } + catch (CException* e) + { + AfxMessageBox( ssprintf("'%s' is not a valid zip archive.", m_sPackagePath), MB_ICONSTOP ); + e->Delete(); + exit( 1 ); + } + + for( int i=0; iSetWindowText( sMessage ); + + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CSMPackageInstallDlg::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + // TODO: Add your message handler code here + + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + + +void CSMPackageInstallDlg::OnOK() +{ + // TODO: Add extra validation here + + TCHAR szCurrentDirectory[MAX_PATH]; + GetCurrentDirectory( MAX_PATH, szCurrentDirectory ); + + // Unzip the SMzip package into the Stepmania installation folder + for( int i=0; iDelete(); + exit( 1 ); + } + } + + AfxMessageBox( "Package installed successfully!" ); + + // close the dialog + CDialog::OnOK(); +} diff --git a/stepmania/src/smpackage/SMPackageInstallDlg.h b/stepmania/src/smpackage/SMPackageInstallDlg.h new file mode 100644 index 0000000000..e5bce89590 --- /dev/null +++ b/stepmania/src/smpackage/SMPackageInstallDlg.h @@ -0,0 +1,54 @@ +#if !defined(AFX_SMPACKAGEINSTALLDLG_H__5E362C4C_CA11_4071_A8AB_A0231E985DAF__INCLUDED_) +#define AFX_SMPACKAGEINSTALLDLG_H__5E362C4C_CA11_4071_A8AB_A0231E985DAF__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SMPackageInstallDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSMPackageInstallDlg dialog + +#include "ZipArchive\ZipArchive.h" + + +class CSMPackageInstallDlg : public CDialog +{ +// Construction +public: + CSMPackageInstallDlg(CString sPackagePath, CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CSMPackageInstallDlg) + enum { IDD = IDD_INSTALL }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSMPackageInstallDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + CString m_sPackagePath; + CZipArchive m_zip; + + // Generated message map functions + //{{AFX_MSG(CSMPackageInstallDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnPaint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SMPACKAGEINSTALLDLG_H__5E362C4C_CA11_4071_A8AB_A0231E985DAF__INCLUDED_) diff --git a/stepmania/src/smpackage/StdAfx.cpp b/stepmania/src/smpackage/StdAfx.cpp new file mode 100644 index 0000000000..7b6205853b --- /dev/null +++ b/stepmania/src/smpackage/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// smpackage.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/stepmania/src/smpackage/StdAfx.h b/stepmania/src/smpackage/StdAfx.h new file mode 100644 index 0000000000..ea8977ee42 --- /dev/null +++ b/stepmania/src/smpackage/StdAfx.h @@ -0,0 +1,26 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__D450D5ED_5C49_4A8B_B887_076F62424F1F__INCLUDED_) +#define AFX_STDAFX_H__D450D5ED_5C49_4A8B_B887_076F62424F1F__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__D450D5ED_5C49_4A8B_B887_076F62424F1F__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/Appnote.txt b/stepmania/src/smpackage/ZipArchive/Appnote.txt new file mode 100644 index 0000000000..7b96643cad --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/Appnote.txt @@ -0,0 +1,1192 @@ +Revised: 03/01/1999 + +Disclaimer +---------- + +Although PKWARE will attempt to supply current and accurate +information relating to its file formats, algorithms, and the +subject programs, the possibility of error can not be eliminated. +PKWARE therefore expressly disclaims any warranty that the +information contained in the associated materials relating to the +subject programs and/or the format of the files created or +accessed by the subject programs and/or the algorithms used by +the subject programs, or any other matter, is current, correct or +accurate as delivered. Any risk of damage due to any possible +inaccurate information is assumed by the user of the information. +Furthermore, the information relating to the subject programs +and/or the file formats created or accessed by the subject +programs and/or the algorithms used by the subject programs is +subject to change without notice. + +General Format of a ZIP file +---------------------------- + + Files stored in arbitrary order. Large zipfiles can span multiple + diskette media. + + Overall zipfile format: + + [local file header + file data + data_descriptor] . . . + [central directory] end of central directory record + + + A. Local file header: + + local file header signature 4 bytes (0x04034b50) + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + filename length 2 bytes + extra field length 2 bytes + + filename (variable size) + extra field (variable size) + + B. Data descriptor: + + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + + This descriptor exists only if bit 3 of the general + purpose bit flag is set (see below). It is byte aligned + and immediately follows the last byte of compressed data. + This descriptor is used only when it was not possible to + seek in the output zip file, e.g., when the output zip file + was standard output or a non seekable device. + + C. Central directory structure: + + [file header] . . . end of central dir record + + File header: + + central file header signature 4 bytes (0x02014b50) + version made by 2 bytes + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + filename length 2 bytes + extra field length 2 bytes + file comment length 2 bytes + disk number start 2 bytes + internal file attributes 2 bytes + external file attributes 4 bytes + relative offset of local header 4 bytes + + filename (variable size) + extra field (variable size) + file comment (variable size) + + End of central dir record: + + end of central dir signature 4 bytes (0x06054b50) + number of this disk 2 bytes + number of the disk with the + start of the central directory 2 bytes + total number of entries in + the central dir on this disk 2 bytes + total number of entries in + the central dir 2 bytes + size of the central directory 4 bytes + offset of start of central + directory with respect to + the starting disk number 4 bytes + zipfile comment length 2 bytes + zipfile comment (variable size) + + D. Explanation of fields: + + version made by (2 bytes) + + The upper byte indicates the compatibility of the file + attribute information. If the external file attributes + are compatible with MS-DOS and can be read by PKZIP for + DOS version 2.04g then this value will be zero. If these + attributes are not compatible, then this value will + identify the host system on which the attributes are + compatible. Software can use this information to determine + the line record format for text files etc. The current + mappings are: + + 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + 1 - Amiga 2 - VAX/VMS + 3 - Unix 4 - VM/CMS + 5 - Atari ST 6 - OS/2 H.P.F.S. + 7 - Macintosh 8 - Z-System + 9 - CP/M 10 - Windows NTFS + 11 thru 255 - unused + + The lower byte indicates the version number of the + software used to encode the file. The value/10 + indicates the major version number, and the value + mod 10 is the minor version number. + + version needed to extract (2 bytes) + + The minimum software version needed to extract the + file, mapped as above. + + general purpose bit flag: (2 bytes) + + Bit 0: If set, indicates that the file is encrypted. + + (For Method 6 - Imploding) + Bit 1: If the compression method used was type 6, + Imploding, then this bit, if set, indicates + an 8K sliding dictionary was used. If clear, + then a 4K sliding dictionary was used. + Bit 2: If the compression method used was type 6, + Imploding, then this bit, if set, indicates + 3 Shannon-Fano trees were used to encode the + sliding dictionary output. If clear, then 2 + Shannon-Fano trees were used. + + (For Method 8 - Deflating) + Bit 2 Bit 1 + 0 0 Normal (-en) compression option was used. + 0 1 Maximum (-ex) compression option was used. + 1 0 Fast (-ef) compression option was used. + 1 1 Super Fast (-es) compression option was used. + + Note: Bits 1 and 2 are undefined if the compression + method is any other. + + Bit 3: If this bit is set, the fields crc-32, compressed + size and uncompressed size are set to zero in the + local header. The correct values are put in the + data descriptor immediately following the compressed + data. (Note: PKZIP version 2.04g for DOS only + recognizes this bit for method 8 compression, newer + versions of PKZIP recognize this bit for any + compression method.) + + Bit 4: Reserved for use with method 8, for enhanced + deflating. + + Bit 5: If this bit is set, this indicates that the file is + compressed patched data. (Note: Requires PKZIP + version 2.70 or greater) + + Bit 6: Currently unused. + + Bit 7: Currently unused. + + Bit 8: Currently unused. + + Bit 9: Currently unused. + + Bit 10: Currently unused. + + Bit 11: Currently unused. + + Bit 12: Reserved by PKWARE for enhanced compression. + + Bit 13: Reserved by PKWARE. + + Bit 14: Reserved by PKWARE. + + Bit 15: Reserved by PKWARE. + + compression method: (2 bytes) + + (see accompanying documentation for algorithm + descriptions) + + 0 - The file is stored (no compression) + 1 - The file is Shrunk + 2 - The file is Reduced with compression factor 1 + 3 - The file is Reduced with compression factor 2 + 4 - The file is Reduced with compression factor 3 + 5 - The file is Reduced with compression factor 4 + 6 - The file is Imploded + 7 - Reserved for Tokenizing compression algorithm + 8 - The file is Deflated + 9 - Reserved for enhanced Deflating + 10 - PKWARE Date Compression Library Imploding + + date and time fields: (2 bytes each) + + The date and time are encoded in standard MS-DOS format. + If input came from standard input, the date and time are + those at which compression was started for this data. + + CRC-32: (4 bytes) + + The CRC-32 algorithm was generously contributed by + David Schwaderer and can be found in his excellent + book "C Programmers Guide to NetBIOS" published by + Howard W. Sams & Co. Inc. The 'magic number' for + the CRC is 0xdebb20e3. The proper CRC pre and post + conditioning is used, meaning that the CRC register + is pre-conditioned with all ones (a starting value + of 0xffffffff) and the value is post-conditioned by + taking the one's complement of the CRC residual. + If bit 3 of the general purpose flag is set, this + field is set to zero in the local header and the correct + value is put in the data descriptor and in the central + directory. + + compressed size: (4 bytes) + uncompressed size: (4 bytes) + + The size of the file compressed and uncompressed, + respectively. If bit 3 of the general purpose bit flag + is set, these fields are set to zero in the local header + and the correct values are put in the data descriptor and + in the central directory. + + filename length: (2 bytes) + extra field length: (2 bytes) + file comment length: (2 bytes) + + The length of the filename, extra field, and comment + fields respectively. The combined length of any + directory record and these three fields should not + generally exceed 65,535 bytes. If input came from standard + input, the filename length is set to zero. + + disk number start: (2 bytes) + + The number of the disk on which this file begins. + + internal file attributes: (2 bytes) + + The lowest bit of this field indicates, if set, that + the file is apparently an ASCII or text file. If not + set, that the file apparently contains binary data. + The remaining bits are unused in version 1.0. + + Bits 1 and 2 are reserved for use by PKWARE. + + external file attributes: (4 bytes) + + The mapping of the external attributes is + host-system dependent (see 'version made by'). For + MS-DOS, the low order byte is the MS-DOS directory + attribute byte. If input came from standard input, this + field is set to zero. + + relative offset of local header: (4 bytes) + + This is the offset from the start of the first disk on + which this file appears, to where the local header should + be found. + + filename: (Variable) + + The name of the file, with optional relative path. + The path stored should not contain a drive or + device letter, or a leading slash. All slashes + should be forward slashes '/' as opposed to + backwards slashes '\' for compatibility with Amiga + and Unix file systems etc. If input came from standard + input, there is no filename field. + + extra field: (Variable) + + This is for future expansion. If additional information + needs to be stored in the future, it should be stored + here. Earlier versions of the software can then safely + skip this file, and find the next file or header. This + field will be 0 length in version 1.0. + + In order to allow different programs and different types + of information to be stored in the 'extra' field in .ZIP + files, the following structure should be used for all + programs storing data in this field: + + header1+data1 + header2+data2 . . . + + Each header should consist of: + + Header ID - 2 bytes + Data Size - 2 bytes + + Note: all fields stored in Intel low-byte/high-byte order. + + The Header ID field indicates the type of data that is in + the following data block. + + Header ID's of 0 thru 31 are reserved for use by PKWARE. + The remaining ID's can be used by third party vendors for + proprietary usage. + + The current Header ID mappings defined by PKWARE are: + + 0x0007 AV Info + 0x0009 OS/2 + 0x000a NTFS + 0x000c VAX/VMS + 0x000d Unix + 0x000f Patch Descriptor + + Several third party mappings commonly used are: + + 0x4b46 FWKCS MD5 (see below) + 0x07c8 Macintosh + 0x4341 Acorn/SparkFS + 0x4453 Windows NT security descriptor (binary ACL) + 0x4704 VM/CMS + 0x470f MVS + 0x4c41 OS/2 access control list (text ACL) + 0x4d49 Info-ZIP VMS (VAX or Alpha) + 0x5455 extended timestamp + 0x5855 Info-ZIP Unix (original, also OS/2, NT, etc) + 0x6542 BeOS/BeBox + 0x756e ASi Unix + 0x7855 Info-ZIP Unix (new) + 0xfd4a SMS/QDOS + + The Data Size field indicates the size of the following + data block. Programs can use this value to skip to the + next header block, passing over any data blocks that are + not of interest. + + Note: As stated above, the size of the entire .ZIP file + header, including the filename, comment, and extra + field should not exceed 64K in size. + + In case two different programs should appropriate the same + Header ID value, it is strongly recommended that each + program place a unique signature of at least two bytes in + size (and preferably 4 bytes or bigger) at the start of + each data area. Every program should verify that its + unique signature is present, in addition to the Header ID + value being correct, before assuming that it is a block of + known type. + + -OS/2 Extra Field: + + The following is the layout of the OS/2 attributes "extra" + block. (Last Revision 09/05/95) + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (OS/2) 0x0009 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + BSize 4 bytes Uncompressed Block Size + CType 2 bytes Compression type + EACRC 4 bytes CRC value for uncompress block + (var) variable Compressed block + + The OS/2 extended attribute structure (FEA2LIST) is + compressed and then stored in it's entirety within this + structure. There will only ever be one "block" of data in + VarFields[]. + + -UNIX Extra Field: + + The following is the layout of the Unix "extra" block. + Note: all fields are stored in Intel low-byte/high-byte + order. + + Value Size Description + ----- ---- ----------- + (UNIX) 0x000d 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + Atime 4 bytes File last access time + Mtime 4 bytes File last modification time + Uid 2 bytes File user ID + Gid 2 bytes File group ID + (var) variable Variable length data field + + The variable length data field will contain file type + specific data. Currently the only values allowed are + the original "linked to" file names for hard or symbolic + links. + + -VAX/VMS Extra Field: + + The following is the layout of the VAX/VMS attributes + "extra" block. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (VMS) 0x000c 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the total "extra" block + CRC 4 bytes 32-bit CRC for remainder of the block + Tag1 2 bytes VMS attribute tag value #1 + Size1 2 bytes Size of attribute #1, in bytes + (var.) Size1 Attribute #1 data + . + . + . + TagN 2 bytes VMS attribute tage value #N + SizeN 2 bytes Size of attribute #N, in bytes + (var.) SizeN Attribute #N data + + Rules: + + 1. There will be one or more of attributes present, which + will each be preceded by the above TagX & SizeX values. + These values are identical to the ATR$C_XXXX and + ATR$S_XXXX constants which are defined in ATR.H under + VMS C. Neither of these values will ever be zero. + + 2. No word alignment or padding is performed. + + 3. A well-behaved PKZIP/VMS program should never produce + more than one sub-block with the same TagX value. Also, + there will never be more than one "extra" block of type + 0x000c in a particular directory record. + + -NTFS Extra Field: + + The following is the layout of the NTFS attributes + "extra" block. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (NTFS) 0x000a 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the total "extra" block + Reserved 4 bytes Reserved for future use + Tag1 2 bytes NTFS attribute tag value #1 + Size1 2 bytes Size of attribute #1, in bytes + (var.) Size1 Attribute #1 data + . + . + . + TagN 2 bytes NTFS attribute tage value #N + SizeN 2 bytes Size of attribute #N, in bytes + (var.) SizeN Attribute #N data + + For NTFS, values for Tag1 through TagN are as follows: + (currently only one set of attributes is defined for NTFS) + + Tag Size Description + ----- ---- ----------- + 0x0001 2 bytes Tag for attribute #1 + Size1 2 bytes Size of attribute #1, in bytes + Mtime 8 bytes File last modification time + Atime 8 bytes File last access time + Ctime 8 bytes File creation time + + -PATCH Descriptor Extra Field: + + The following is the layout of the Patch Descriptor "extra" + block. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (Patch) 0x000f 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the total "extra" block + Version 2 bytes Version of the descriptor + Flags 4 bytes Actions and reactions (see below) + OldSize 4 bytes Size of the file about to be patched + OldCRC 4 bytes 32-bit CRC of the file to be patched + NewSize 4 bytes Size of the resulting file + NewCRC 4 bytes 32-bit CRC of the resulting file + + Actions and reactions + + Bits Description + ---- ---------------- + 0 Use for autodetection + 1 Treat as selfpatch + 2-3 RESERVED + 4-5 Action (see below) + 6-7 RESERVED + 8-9 Reaction (see below) to absent file + 10-11 Reaction (see below) to newer file + 12-13 Reaction (see below) to unknown file + 14-15 RESERVED + 16-31 RESERVED + + Actions + + Action Value + ------ ----- + none 0 + add 1 + delete 2 + patch 3 + + Reactions + + Reaction Value + -------- ----- + ask 0 + skip 1 + ignore 2 + fail 3 + + - FWKCS MD5 Extra Field: + + The FWKCS Contents_Signature System, used in + automatically identifying files independent of filename, + optionally adds and uses an extra field to support the + rapid creation of an enhanced contents_signature: + + Header ID = 0x4b46 + Data Size = 0x0013 + Preface = 'M','D','5' + followed by 16 bytes containing the uncompressed file's + 128_bit MD5 hash(1), low byte first. + + When FWKCS revises a zipfile central directory to add + this extra field for a file, it also replaces the + central directory entry for that file's uncompressed + filelength with a measured value. + + FWKCS provides an option to strip this extra field, if + present, from a zipfile central directory. In adding + this extra field, FWKCS preserves Zipfile Authenticity + Verification; if stripping this extra field, FWKCS + preserves all versions of AV through PKZIP version 2.04g. + + FWKCS, and FWKCS Contents_Signature System, are + trademarks of Frederick W. Kantor. + + (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer + Science and RSA Data Security, Inc., April 1992. + ll.76-77: "The MD5 algorithm is being placed in the + public domain for review and possible adoption as a + standard." + + file comment: (Variable) + + The comment for this file. + + number of this disk: (2 bytes) + + The number of this disk, which contains central + directory end record. + + number of the disk with the start of the central + directory: (2 bytes) + + The number of the disk on which the central + directory starts. + + total number of entries in the central dir on + this disk: (2 bytes) + + The number of central directory entries on this disk. + + total number of entries in the central dir: (2 bytes) + + The total number of files in the zipfile. + + size of the central directory: (4 bytes) + + The size (in bytes) of the entire central directory. + + offset of start of central directory with respect to + the starting disk number: (4 bytes) + + Offset of the start of the central directory on the + disk on which the central directory starts. + + zipfile comment length: (2 bytes) + + The length of the comment for this zipfile. + + zipfile comment: (Variable) + + The comment for this zipfile. + + D. General notes: + + 1) All fields unless otherwise noted are unsigned and stored + in Intel low-byte:high-byte, low-word:high-word order. + + 2) String fields are not null terminated, since the + length is given explicitly. + + 3) Local headers should not span disk boundaries. Also, even + though the central directory can span disk boundaries, no + single record in the central directory should be split + across disks. + + 4) The entries in the central directory may not necessarily + be in the same order that files appear in the zipfile. + +UnShrinking - Method 1 +---------------------- + +Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm +with partial clearing. The initial code size is 9 bits, and +the maximum code size is 13 bits. Shrinking differs from +conventional Dynamic Ziv-Lempel-Welch implementations in several +respects: + +1) The code size is controlled by the compressor, and is not + automatically increased when codes larger than the current + code size are created (but not necessarily used). When + the decompressor encounters the code sequence 256 + (decimal) followed by 1, it should increase the code size + read from the input stream to the next bit size. No + blocking of the codes is performed, so the next code at + the increased size should be read from the input stream + immediately after where the previous code at the smaller + bit size was read. Again, the decompressor should not + increase the code size used until the sequence 256,1 is + encountered. + +2) When the table becomes full, total clearing is not + performed. Rather, when the compressor emits the code + sequence 256,2 (decimal), the decompressor should clear + all leaf nodes from the Ziv-Lempel tree, and continue to + use the current code size. The nodes that are cleared + from the Ziv-Lempel tree are then re-used, with the lowest + code value re-used first, and the highest code value + re-used last. The compressor can emit the sequence 256,2 + at any time. + +Expanding - Methods 2-5 +----------------------- + +The Reducing algorithm is actually a combination of two +distinct algorithms. The first algorithm compresses repeated +byte sequences, and the second algorithm takes the compressed +stream from the first algorithm and applies a probabilistic +compression method. + +The probabilistic compression stores an array of 'follower +sets' S(j), for j=0 to 255, corresponding to each possible +ASCII character. Each set contains between 0 and 32 +characters, to be denoted as S(j)[0],...,S(j)[m], where m<32. +The sets are stored at the beginning of the data area for a +Reduced file, in reverse order, with S(255) first, and S(0) +last. + +The sets are encoded as { N(j), S(j)[0],...,S(j)[N(j)-1] }, +where N(j) is the size of set S(j). N(j) can be 0, in which +case the follower set for S(j) is empty. Each N(j) value is +encoded in 6 bits, followed by N(j) eight bit character values +corresponding to S(j)[0] to S(j)[N(j)-1] respectively. If +N(j) is 0, then no values for S(j) are stored, and the value +for N(j-1) immediately follows. + +Immediately after the follower sets, is the compressed data +stream. The compressed data stream can be interpreted for the +probabilistic decompression as follows: + +let Last-Character <- 0. +loop until done + if the follower set S(Last-Character) is empty then + read 8 bits from the input stream, and copy this + value to the output stream. + otherwise if the follower set S(Last-Character) is non-empty then + read 1 bit from the input stream. + if this bit is not zero then + read 8 bits from the input stream, and copy this + value to the output stream. + otherwise if this bit is zero then + read B(N(Last-Character)) bits from the input + stream, and assign this value to I. + Copy the value of S(Last-Character)[I] to the + output stream. + + assign the last value placed on the output stream to + Last-Character. +end loop + +B(N(j)) is defined as the minimal number of bits required to +encode the value N(j)-1. + +The decompressed stream from above can then be expanded to +re-create the original file as follows: + +let State <- 0. + +loop until done + read 8 bits from the input stream into C. + case State of + 0: if C is not equal to DLE (144 decimal) then + copy C to the output stream. + otherwise if C is equal to DLE then + let State <- 1. + + 1: if C is non-zero then + let V <- C. + let Len <- L(V) + let State <- F(Len). + otherwise if C is zero then + copy the value 144 (decimal) to the output stream. + let State <- 0 + + 2: let Len <- Len + C + let State <- 3. + + 3: move backwards D(V,C) bytes in the output stream + (if this position is before the start of the output + stream, then assume that all the data before the + start of the output stream is filled with zeros). + copy Len+3 bytes from this position to the output stream. + let State <- 0. + end case +end loop + +The functions F,L, and D are dependent on the 'compression +factor', 1 through 4, and are defined as follows: + +For compression factor 1: + L(X) equals the lower 7 bits of X. + F(X) equals 2 if X equals 127 otherwise F(X) equals 3. + D(X,Y) equals the (upper 1 bit of X) * 256 + Y + 1. +For compression factor 2: + L(X) equals the lower 6 bits of X. + F(X) equals 2 if X equals 63 otherwise F(X) equals 3. + D(X,Y) equals the (upper 2 bits of X) * 256 + Y + 1. +For compression factor 3: + L(X) equals the lower 5 bits of X. + F(X) equals 2 if X equals 31 otherwise F(X) equals 3. + D(X,Y) equals the (upper 3 bits of X) * 256 + Y + 1. +For compression factor 4: + L(X) equals the lower 4 bits of X. + F(X) equals 2 if X equals 15 otherwise F(X) equals 3. + D(X,Y) equals the (upper 4 bits of X) * 256 + Y + 1. + +Imploding - Method 6 +-------------------- + +The Imploding algorithm is actually a combination of two distinct +algorithms. The first algorithm compresses repeated byte +sequences using a sliding dictionary. The second algorithm is +used to compress the encoding of the sliding dictionary output, +using multiple Shannon-Fano trees. + +The Imploding algorithm can use a 4K or 8K sliding dictionary +size. The dictionary size used can be determined by bit 1 in the +general purpose flag word; a 0 bit indicates a 4K dictionary +while a 1 bit indicates an 8K dictionary. + +The Shannon-Fano trees are stored at the start of the compressed +file. The number of trees stored is defined by bit 2 in the +general purpose flag word; a 0 bit indicates two trees stored, a +1 bit indicates three trees are stored. If 3 trees are stored, +the first Shannon-Fano tree represents the encoding of the +Literal characters, the second tree represents the encoding of +the Length information, the third represents the encoding of the +Distance information. When 2 Shannon-Fano trees are stored, the +Length tree is stored first, followed by the Distance tree. + +The Literal Shannon-Fano tree, if present is used to represent +the entire ASCII character set, and contains 256 values. This +tree is used to compress any data not compressed by the sliding +dictionary algorithm. When this tree is present, the Minimum +Match Length for the sliding dictionary is 3. If this tree is +not present, the Minimum Match Length is 2. + +The Length Shannon-Fano tree is used to compress the Length part +of the (length,distance) pairs from the sliding dictionary +output. The Length tree contains 64 values, ranging from the +Minimum Match Length, to 63 plus the Minimum Match Length. + +The Distance Shannon-Fano tree is used to compress the Distance +part of the (length,distance) pairs from the sliding dictionary +output. The Distance tree contains 64 values, ranging from 0 to +63, representing the upper 6 bits of the distance value. The +distance values themselves will be between 0 and the sliding +dictionary size, either 4K or 8K. + +The Shannon-Fano trees themselves are stored in a compressed +format. The first byte of the tree data represents the number of +bytes of data representing the (compressed) Shannon-Fano tree +minus 1. The remaining bytes represent the Shannon-Fano tree +data encoded as: + + High 4 bits: Number of values at this bit length + 1. (1 - 16) + Low 4 bits: Bit Length needed to represent value + 1. (1 - 16) + +The Shannon-Fano codes can be constructed from the bit lengths +using the following algorithm: + +1) Sort the Bit Lengths in ascending order, while retaining the + order of the original lengths stored in the file. + +2) Generate the Shannon-Fano trees: + + Code <- 0 + CodeIncrement <- 0 + LastBitLength <- 0 + i <- number of Shannon-Fano codes - 1 (either 255 or 63) + + loop while i >= 0 + Code = Code + CodeIncrement + if BitLength(i) <> LastBitLength then + LastBitLength=BitLength(i) + CodeIncrement = 1 shifted left (16 - LastBitLength) + ShannonCode(i) = Code + i <- i - 1 + end loop + +3) Reverse the order of all the bits in the above ShannonCode() + vector, so that the most significant bit becomes the least + significant bit. For example, the value 0x1234 (hex) would + become 0x2C48 (hex). + +4) Restore the order of Shannon-Fano codes as originally stored + within the file. + +Example: + + This example will show the encoding of a Shannon-Fano tree + of size 8. Notice that the actual Shannon-Fano trees used + for Imploding are either 64 or 256 entries in size. + +Example: 0x02, 0x42, 0x01, 0x13 + + The first byte indicates 3 values in this table. Decoding the + bytes: + 0x42 = 5 codes of 3 bits long + 0x01 = 1 code of 2 bits long + 0x13 = 2 codes of 4 bits long + + This would generate the original bit length array of: + (3, 3, 3, 3, 3, 2, 4, 4) + + There are 8 codes in this table for the values 0 thru 7. Using + the algorithm to obtain the Shannon-Fano codes produces: + + Reversed Order Original +Val Sorted Constructed Code Value Restored Length +--- ------ ----------------- -------- -------- ------ +0: 2 1100000000000000 11 101 3 +1: 3 1010000000000000 101 001 3 +2: 3 1000000000000000 001 110 3 +3: 3 0110000000000000 110 010 3 +4: 3 0100000000000000 010 100 3 +5: 3 0010000000000000 100 11 2 +6: 4 0001000000000000 1000 1000 4 +7: 4 0000000000000000 0000 0000 4 + +The values in the Val, Order Restored and Original Length columns +now represent the Shannon-Fano encoding tree that can be used for +decoding the Shannon-Fano encoded data. How to parse the +variable length Shannon-Fano values from the data stream is beyond +the scope of this document. (See the references listed at the end of +this document for more information.) However, traditional decoding +schemes used for Huffman variable length decoding, such as the +Greenlaw algorithm, can be successfully applied. + +The compressed data stream begins immediately after the +compressed Shannon-Fano data. The compressed data stream can be +interpreted as follows: + +loop until done + read 1 bit from input stream. + + if this bit is non-zero then (encoded data is literal data) + if Literal Shannon-Fano tree is present + read and decode character using Literal Shannon-Fano tree. + otherwise + read 8 bits from input stream. + copy character to the output stream. + otherwise (encoded data is sliding dictionary match) + if 8K dictionary size + read 7 bits for offset Distance (lower 7 bits of offset). + otherwise + read 6 bits for offset Distance (lower 6 bits of offset). + + using the Distance Shannon-Fano tree, read and decode the + upper 6 bits of the Distance value. + + using the Length Shannon-Fano tree, read and decode + the Length value. + + Length <- Length + Minimum Match Length + + if Length = 63 + Minimum Match Length + read 8 bits from the input stream, + add this value to Length. + + move backwards Distance+1 bytes in the output stream, and + copy Length characters from this position to the output + stream. (if this position is before the start of the output + stream, then assume that all the data before the start of + the output stream is filled with zeros). +end loop + +Tokenizing - Method 7 +-------------------- + +This method is not used by PKZIP. + +Deflating - Method 8 +----------------- + +The Deflate algorithm is similar to the Implode algorithm using +a sliding dictionary of up to 32K with secondary compression +from Huffman/Shannon-Fano codes. + +The compressed data is stored in blocks with a header describing +the block and the Huffman codes used in the data block. The header +format is as follows: + + Bit 0: Last Block bit This bit is set to 1 if this is the last + compressed block in the data. + Bits 1-2: Block type + 00 (0) - Block is stored - All stored data is byte aligned. + Skip bits until next byte, then next word = block + length, followed by the ones compliment of the block + length word. Remaining data in block is the stored + data. + + 01 (1) - Use fixed Huffman codes for literal and distance codes. + Lit Code Bits Dist Code Bits + --------- ---- --------- ---- + 0 - 143 8 0 - 31 5 + 144 - 255 9 + 256 - 279 7 + 280 - 287 8 + + Literal codes 286-287 and distance codes 30-31 are + never used but participate in the huffman construction. + + 10 (2) - Dynamic Huffman codes. (See expanding Huffman codes) + + 11 (3) - Reserved - Flag a "Error in compressed data" if seen. + +Expanding Huffman Codes +----------------------- +If the data block is stored with dynamic Huffman codes, the Huffman +codes are sent in the following compressed format: + + 5 Bits: # of Literal codes sent - 256 (256 - 286) + All other codes are never sent. + 5 Bits: # of Dist codes - 1 (1 - 32) + 4 Bits: # of Bit Length codes - 3 (3 - 19) + +The Huffman codes are sent as bit lengths and the codes are built as +described in the implode algorithm. The bit lengths themselves are +compressed with Huffman codes. There are 19 bit length codes: + + 0 - 15: Represent bit lengths of 0 - 15 + 16: Copy the previous bit length 3 - 6 times. + The next 2 bits indicate repeat length (0 = 3, ... ,3 = 6) + Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will + expand to 12 bit lengths of 8 (1 + 6 + 5) + 17: Repeat a bit length of 0 for 3 - 10 times. (3 bits of length) + 18: Repeat a bit length of 0 for 11 - 138 times (7 bits of length) + +The lengths of the bit length codes are sent packed 3 bits per value +(0 - 7) in the following order: + + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + +The Huffman codes should be built as described in the Implode algorithm +except codes are assigned starting at the shortest bit length, i.e. the +shortest code should be all 0's rather than all 1's. Also, codes with +a bit length of zero do not participate in the tree construction. The +codes are then used to decode the bit lengths for the literal and +distance tables. + +The bit lengths for the literal tables are sent first with the number +of entries sent described by the 5 bits sent earlier. There are up +to 286 literal characters; the first 256 represent the respective 8 +bit character, code 256 represents the End-Of-Block code, the remaining +29 codes represent copy lengths of 3 thru 258. There are up to 30 +distance codes representing distances from 1 thru 32k as described +below. + + Length Codes + ------------ + Extra Extra Extra Extra + Code Bits Length Code Bits Lengths Code Bits Lengths Code Bits Length(s) + ---- ---- ------ ---- ---- ------- ---- ---- ------- ---- ---- --------- + 257 0 3 265 1 11,12 273 3 35-42 281 5 131-162 + 258 0 4 266 1 13,14 274 3 43-50 282 5 163-194 + 259 0 5 267 1 15,16 275 3 51-58 283 5 195-226 + 260 0 6 268 1 17,18 276 3 59-66 284 5 227-257 + 261 0 7 269 2 19-22 277 4 67-82 285 0 258 + 262 0 8 270 2 23-26 278 4 83-98 + 263 0 9 271 2 27-30 279 4 99-114 + 264 0 10 272 2 31-34 280 4 115-130 + + Distance Codes + -------------- + Extra Extra Extra Extra + Code Bits Dist Code Bits Dist Code Bits Distance Code Bits Distance + ---- ---- ---- ---- ---- ------ ---- ---- -------- ---- ---- -------- + 0 0 1 8 3 17-24 16 7 257-384 24 11 4097-6144 + 1 0 2 9 3 25-32 17 7 385-512 25 11 6145-8192 + 2 0 3 10 4 33-48 18 8 513-768 26 12 8193-12288 + 3 0 4 11 4 49-64 19 8 769-1024 27 12 12289-16384 + 4 1 5,6 12 5 65-96 20 9 1025-1536 28 13 16385-24576 + 5 1 7,8 13 5 97-128 21 9 1537-2048 29 13 24577-32768 + 6 2 9-12 14 6 129-192 22 10 2049-3072 + 7 2 13-16 15 6 193-256 23 10 3073-4096 + +The compressed data stream begins immediately after the +compressed header data. The compressed data stream can be +interpreted as follows: + +do + read header from input stream. + + if stored block + skip bits until byte aligned + read count and 1's compliment of count + copy count bytes data block + otherwise + loop until end of block code sent + decode literal character from input stream + if literal < 256 + copy character to the output stream + otherwise + if literal = end of block + break from loop + otherwise + decode distance from input stream + + move backwards distance bytes in the output stream, and + copy length characters from this position to the output + stream. + end loop +while not last block + +if data descriptor exists + skip bits until byte aligned + read crc and sizes +endif + +Decryption +---------- + +The encryption used in PKZIP was generously supplied by Roger +Schlafly. PKWARE is grateful to Mr. Schlafly for his expert +help and advice in the field of data encryption. + +PKZIP encrypts the compressed data stream. Encrypted files must +be decrypted before they can be extracted. + +Each encrypted file has an extra 12 bytes stored at the start of +the data area defining the encryption header for that file. The +encryption header is originally set to random values, and then +itself encrypted, using three, 32-bit keys. The key values are +initialized using the supplied encryption password. After each byte +is encrypted, the keys are then updated using pseudo-random number +generation techniques in combination with the same CRC-32 algorithm +used in PKZIP and described elsewhere in this document. + +The following is the basic steps required to decrypt a file: + +1) Initialize the three 32-bit keys with the password. +2) Read and decrypt the 12-byte encryption header, further + initializing the encryption keys. +3) Read and decrypt the compressed data stream using the + encryption keys. + +Step 1 - Initializing the encryption keys +----------------------------------------- + +Key(0) <- 305419896 +Key(1) <- 591751049 +Key(2) <- 878082192 + +loop for i <- 0 to length(password)-1 + update_keys(password(i)) +end loop + +Where update_keys() is defined as: + +update_keys(char): + Key(0) <- crc32(key(0),char) + Key(1) <- Key(1) + (Key(0) & 000000ffH) + Key(1) <- Key(1) * 134775813 + 1 + Key(2) <- crc32(key(2),key(1) >> 24) +end update_keys + +Where crc32(old_crc,char) is a routine that given a CRC value and a +character, returns an updated CRC value after applying the CRC-32 +algorithm described elsewhere in this document. + +Step 2 - Decrypting the encryption header +----------------------------------------- + +The purpose of this step is to further initialize the encryption +keys, based on random data, to render a plaintext attack on the +data ineffective. + +Read the 12-byte encryption header into Buffer, in locations +Buffer(0) thru Buffer(11). + +loop for i <- 0 to 11 + C <- buffer(i) ^ decrypt_byte() + update_keys(C) + buffer(i) <- C +end loop + +Where decrypt_byte() is defined as: + +unsigned char decrypt_byte() + local unsigned short temp + temp <- Key(2) | 2 + decrypt_byte <- (temp * (temp ^ 1)) >> 8 +end decrypt_byte + +After the header is decrypted, the last 1 or 2 bytes in Buffer +should be the high-order word/byte of the CRC for the file being +decrypted, stored in Intel low-byte/high-byte order. Versions of +PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is +used on versions after 2.0. This can be used to test if the password +supplied is correct or not. + +Step 3 - Decrypting the compressed data stream +---------------------------------------------- + +The compressed data stream can be decrypted as follows: + +loop until done + read a character into C + Temp <- C ^ decrypt_byte() + update_keys(temp) + output Temp +end loop + +In addition to the above mentioned contributors to PKZIP and PKUNZIP, +I would like to extend special thanks to Robert Mahoney for suggesting +the extension .ZIP for this software. + +References: + + Fiala, Edward R., and Greene, Daniel H., "Data compression with + finite windows", Communications of the ACM, Volume 32, Number 4, + April 1989, pages 490-505. + + Held, Gilbert, "Data Compression, Techniques and Applications, + Hardware and Software Considerations", John Wiley & Sons, 1987. + + Huffman, D.A., "A method for the construction of minimum-redundancy + codes", Proceedings of the IRE, Volume 40, Number 9, September 1952, + pages 1098-1101. + + Nelson, Mark, "LZW Data Compression", Dr. Dobbs Journal, Volume 14, + Number 10, October 1989, pages 29-37. + + Nelson, Mark, "The Data Compression Book", M&T Books, 1991. + + Storer, James A., "Data Compression, Methods and Theory", + Computer Science Press, 1988 + + Welch, Terry, "A Technique for High-Performance Data Compression", + IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19. + + Ziv, J. and Lempel, A., "A universal algorithm for sequential data + compression", Communications of the ACM, Volume 30, Number 6, + June 1987, pages 520-540. + + Ziv, J. and Lempel, A., "Compression of individual sequences via + variable-rate coding", IEEE Transactions on Information Theory, + Volume 24, Number 5, September 1978, pages 530-536. diff --git a/stepmania/src/smpackage/ZipArchive/CodeProject.html b/stepmania/src/smpackage/ZipArchive/CodeProject.html new file mode 100644 index 0000000000..82a927b70b --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/CodeProject.html @@ -0,0 +1,380 @@ + + + + +The Code Project + + + + + + + +
+Title:       Zip and Unzip in the MFC way
+Author:      Tadeusz Dracz 
+Email:       tdracz@artpol.com.pl
+Environment: VC++ 6.0, MFC, Windows 95/98/NT/2000/Me
+Keywords:    Zip, Unzip, MFC
+Level:       Intermediate
+Description: The library to create, modify and extract zip archives
+Section      Miscellaneous
+SubSection   General
+
+ +
+ + +
    +
  • Download source - 110 Kb
  • +
  • Download demo project - 40 Kb
  • +

    Overview

    +

    This library allows creating, modifying and extracting zip archives in the +compatible way with PKZIP (2.5 and higher) and WinZip. Supported are all +possible operations on the zip archive: creating, extracting, adding, deleting +files from the archive, modifications of the existing archive. There is also the +support for creating and extracting multiple disk archives (on non-removable +devices as well) and for password encryption and decryption. This module uses +compression and decompression functions from zlib library by Jean-loup Gailly +and Mark Adler.

    +

    How to integrate with the project

    +

    Zip is a static library and statically links to compiled zlib.lib (version +1.13 nowadays). The zlib library can be replaced with a newer version providing +you also replace the files: "zlib.h" and "zconf.h" in the +Zip project. The Zip library uses MFC in a shared library as a Release and Debug +Configuration. Your project must use MFC in the same way in the appropriate +project configuration. You may need to adapt this to your needs. To add Zip +library functionality to your project you need to link the library to the +project. You can do this in at least two ways (in both cases you need to include +ZipArchive.h header in your sources like this: #include "ZipArchive.h"):

    +

    Method 1

    +

    Add "..\Zip\debug(release)\Zip.lib" to Project +Settings->Link->Input->Object/library modules and add Zip +directory to the preprocessor searches (Project Settings -> C++ -> +Preprocessor -> Additional include directories).

    +

    Method 2 (simpler)

    +

    Insert Zip project into workspace and set project dependencies (your project +dependent on Zip project).

    +

    How to use

    +

    The details about using this library are in the sources. The example +available for download at the bottom of the page is an almost complete +compression\decompression program. There are only main issues mentioned below +about using this library. If you have a question about using the library and you +can't find the answer here, don't hesitate to ask.

    +

    Compression and decompression

    +

    There are some functions defined for fast operations on archive; among +others: AddNewFile(), ExtractFile(), DeleteFile(). You only need to call +functions Open() - before and Close() - after using them.
    +Remember to call Close() function when you finish working with CZipArchive +class.

    +

    Multi-disk archives

    +

    This library supports two kinds of multi-disk archives:
    +1. Disk spanning performed in the compatible way with all other main zip +programs. It means that the archive can only be created on a removable device, +the size of the volume is auto-detected and the label is written to the disk. To +use this kind of disk spanning you need to define a static callback function for +changing disks and set it with SetSpanCallback() function.
    +2. Disk spanning performed in the internal mode, called in the sources TD span +mode. This allows creating multi disk archives also on non-removable devices and +with user-defined volume size. There is no need to set callback function in this +mode.

    +

    This two disk spanning modes create volumes with compatible internal +structure. It means that you can easily convert the volumes created in one mode +to the other one by renaming the files (in TD mode each volume but last has a +number as an extension). To convert the archive from TD to PKZIP compatible +archive, copy each file to the removable media, giving them the extension +".zip". You should also label each disk with the appropriate label +starting from "pkback# 001".

    +

    There is a limited functions set available during work with multi-disk +archives. Only adding is allowed when creating an archive and only extracting +and testing when opening an existing one. Deleting files from these archives +isn't allowed in any of these cases.

    +

    Class CZipArchive uses write buffer to make write operations extremely fast. +You can change its size with SetAdvanced() function. While creating a multi-disk +archive, set the size of the buffer to the maximum size of the volume  for +the best performance.

    +

    The popular archivers such as PKZIP and WinZip cannot operate on archive in +TD span mode. You need to convert them to PKZIP span mode (have a look above). +Remember about copying the files to the removable media (it does not comply with +Winzip, which can extract a multi-disk archive from any media but only from the +fixed location on the drive).

    +

    Password encryption and decryption

    +

        This library supports creating and extracting of the +password protected archives. There are several issues you should be aware of +when using this feature. To set the password for the file to be added or +extracted call the function SetPassword() with the password as the argument. To +clear the password call this function without arguments or with an empty string +argument. The function has no effect on a closed archive and on the currently +opened file (whether new or existing) inside archive. During opening an archive +the password is cleared and it is not changed if the file inside archive is +opened. You can set different passwords for different files inside the same +archive, but remember to set it BEFORE opening the file. You cannot use ASCII +characters with codes above 127 in a password, if you do so, the function +SetPassword() returns false and the password is cleared. If the password is +cleared, no encryption or decryption take place.
    +    You can find out what files are password encrypted by calling +CZipArchive::GetFileInfo() which fills the structrure CZipFileHeader with data, +and then the method IsEncrypted() of this structure. If it returns true, the +file needs a password to extract.
    +   The successful extraction of the encrypted file doesn't always mean +that the password is correct. CZipArchive doesn't check for a crc if +m_info.m_uUncomprLeft is not zero in the function CZipArchive::CloseFile(). In +some cases bad password causes that this value is not zero, so you have to check +also for the return value of this function (it returns -1 in this case). You can +also check the size of the extracted file since it is smaller than it should be.

    +

    Self extract support

    +

    The library automatically detects self-extracting archives. This is the +simplest self-extract code :

    + +
    +int APIENTRY WinMain(HINSTANCE hInstance,
    +HINSTANCE hPrevInstance,
    +LPSTR lpCmdLine,
    +int nCmdShow)
    +{
    +	CZipArchive zip;
    +
    +	// get path of executable
    +	TCHAR szBuff[_MAX_PATH];
    +	if (!::GetModuleFileName(hInstance, szBuff, _MAX_PATH))
    +		return -1;
    +
    +	CString szDest;
    +	// ...
    +	// add the code here to get the destination directory from the user 
    +	// for example:
    +	/* CBrowseForFolder bf;
    +	   bf.strTitle = _T("Select directory to extract files");
    +	   if (!bf.GetFolder(szDest))
    +	       return -1;
    +	*/
    +	// class CBrowseForFolder is included in the example project
    +	// remember about including the header!
    +
    +	zip.Open(szBuff, CZipArchive::openReadOnly); 
    +	// openReadOnly mode is necessary for self extract archives
    +	for (WORD i = 0; i < zip.GetNoEntries(); i++)
    +		zip.ExtractFile(i, szDest);
    +
    +	zip.Close();
    +	return 0;
    +	// this code will not work for the encrypted archives since it is needed
    +	// to get the password from the user ( a small addition to the 
    +	// existing code I suppose )
    +}
    +
    +
    +
    +

    After compiling it and appending a zip archive to it (e.g. with the DOS +command: copy /b SelfExtract.exe + ZipFile.zip FinalFile.exe) we have a +self extracting archive.

    +

    Testing the integrity of the archive

    +

    The new functions has been provided to allow the testing of the integrity of +the archive. The first one is CZipArchive::TestFile which is a +comprehensive testing function, but if you need a different functionality, you +can make your own by taking advantage of the second function provided: CZipArchive::CloseFileAfterTestFailed. +The detailed description and the example of use are provided in the sources +and in the example project.

    +

    Exceptions

    +

    The library throws the following exceptions: CMemoryException, CFileExeption +and CZipException. The first two don't need an explanation. The last is thrown +when some internal error occurs. Handling them may be done in the following way:

    +
    +try
    +{
    +	// ...
    +	// some operations on Zip library
    +}
    +catch (CException* e)
    +{
    +	if (e->IsKindOf( RUNTIME_CLASS( CZipException )))
    +	{
    +		CZipException* p = (CZipException*) e;
    +		//... and so on 
    +	}
    +	else if (e->IsKindOf( RUNTIME_CLASS( CFileException )))
    +	{
    +		CFileException* p = (CFileException*) e;
    +		//... and so on 
    +	} 
    +	else
    +	{
    +		// the only possibility is a memory exception I suppose
    +		//... and so on 
    +	}
    +	e->Delete();
    +}
    +
    +

    Handling the extra field

    +

    The extra field of the file can be different in the local and central +headers. To set the extra filed in the local header set it in header +parameter of CZipArchive::OpenNewFile function. After +that the extra field is written to the local header and cleared. You should call +CZipArchive::SetExtraField function anytime after opening the new file +(but before closing it) to set the file extra field in the central directory.

    +

    Sample application

    +

    To run the example, integrate first Zip library into it (Zip library is not +included in the example, you must download it separately); you should be asked +at the beginning about the location of the Zip project, if not, use one of the +integration methods described above. If you don't put Zip library project at the +same directory level what the sample application is, you also have to change the path pointing +to ZipArchive.h in the file testzipdlgdlg.h.

    +

    Linking errors

    +

    When you experience linking errors (mostly LNK2005) you need to + make sure that the library and your program are both using + single-threaded or both multithreaded library. The option "Project->Settings-> + c/c++ ->Code Generation->Use run-time library" should be set + to the same value in the ZipArchive library and the program project options. +

    If it doesn't help, try recompiling the zlib library ( zlib.lib + provided with the project is compiled from a release configuration and using Multithreaded + DLL run-time library ). You can download the zlib library + sources from http://software.artpol.com.pl/d_zip.html. + Use zlibstat project. Set "Use run-time library" + option to the same value as you set it in ZipArchve library and your program + configurations. Compile the Release configuration of the zlib library and + replace with it the file zlib.lib in the ZipArchive folder. You may + however experience linking warnings or errors while compiling the Debug + configuration. To eliminate them do as follows: +

      +
    • compile Debug and Release configuraions of the zlib library +
    • copy zlib_d.lib from Debug and zlib.lib from Release + directories to the ZipArchive directory +
    • add these files to the ZipArchive project (Project -> Add To + Project -> Files...) +
    • go to the project setting dialog (Project -> Settings) +
    • select debug configurations (Setting For -> Multiple + Configurations) such as Debug and Unicode Debug +
    • select zlib.lib file, then the General tab, and check the box "Exclude + file from build" +
    • select release configurations +
    • select zlib_.lib and exclude it from these builds
    • +
    +

     

    +

    To Do and updates

    +

    I currently work on the non-MFC version of the library and a multi-platform +support. Make sure to check out the site http://software.artpol.com.pl +which is more likely to have an updated version. 

    +

    Downloads

    + + +

    Download source - 110 KB
    +Download example - 40 KB

    +

    History

    +

    03.2001

    +
      +
    • when the central directory was not located, the library throws + CZipException::cdirNotFound,
      + which allows distinguish from other exceptions (useful when we want to keep + prompting
      + the user to insert the last disk in a multi-disk spanning archive).
    • +
    +
+

 

+ +
    +02.2001 +
    +
    Features added: +
    +
      +
    • ability to reuse the archive after an exception thrown during + extraction +
    • added progress control possibilities to CZipArchive::AddNewFile, + CZipArchive::ExtractFile, CZipArchive::TestFile
    • +
    +
    +
    +
    +
    Changes: +
    +
      +
    • CZipArchive::FindFile operation boosted ( thanks to Darin Warling for + the idea) +
    • library name changed to ZipArchive
    • +
    +
    +
    +
    +
    Bugs fixed: +
    +
      +
    • removed bug during extracting an encrypted file with 0 size +
    • fixed bug when extracting a file with an extra field in a local file + header (CZipFileHeader::ReadLocal)
    • +
    +
    +
    +01.2001 +
      +
    • Disk numbering in a disk spanning archive begins now from PKBACK# 001 not + PKBACK# 000 +
    • Adding and extracting without a full path possible in + CZipArchive::AddNewFile and CZipArchive::ExtractFile. +
    • Several minor changes and enhancements +
    • Changed names for several classes.
    • +
    +11.2000 +
      +
    • Added support for password encryption and decryption. The encryption used + in PKZIP was generously supplied by Roger Schlafly. +
    • Testing the archive made easier +
    • Unicode support added
    • +
    +08.2000 +
      +
    • Bugs fixed
    • +
    +06.2000 +

    the code has been completely rewritten since the very beginning; the main +improvements are: +

      +
    • multi-disk archive support +
    • creation of the disk spanning archives with the user-defined volume size +
    • ability to modify existing archives (add, delete files) +
    • modification self-extracting archives +
    • write buffer used for faster disk write operations +
    • one class for zip and unzip functions +
    • fast adding, deleting and extracting files with a single function call
    • +
    +03.2000 +
      +
    • international characters in filenames inside archive are now converted in + a compatible way with other archiving programs (they are stored converted to + OEM inside archive).
    • +
    +01.2000 +

    first version; it is just modified code from zip.c and unzip.c files written +by Gilles Vollant and distributed with zlib library; the modifications are as +follows: +

      +
    • added class' wrappers +
    • several bugs fixed +
    • several enhancements added +
    • MFC support added +
    • memory leaks eliminated when write error occurred +
    • automatically free used memory on destruction or exception +
    • modern error notification using exceptions
    • +
    + + diff --git a/stepmania/src/smpackage/ZipArchive/StdAfx.cpp b/stepmania/src/smpackage/ZipArchive/StdAfx.cpp new file mode 100644 index 0000000000..35efe037ed --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/StdAfx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// Zip.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/stepmania/src/smpackage/ZipArchive/StdAfx.h b/stepmania/src/smpackage/ZipArchive/StdAfx.h new file mode 100644 index 0000000000..fef7146336 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/StdAfx.h @@ -0,0 +1,23 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) +#define AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include +#include + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipArchive.cpp b/stepmania/src/smpackage/ZipArchive/ZipArchive.cpp new file mode 100644 index 0000000000..ccff2a4545 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipArchive.cpp @@ -0,0 +1,1381 @@ +// ZipArchive.cpp: implementation of the CZipArchive class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ZipArchive.h" +#include +#include // for qsort + + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +#define ENCR_HEADER_LEN 12 +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +TCHAR CZipArchive::m_gszCopyright[] = {_T("Zip archive creation and modification Copyright 2000 Tadeusz Dracz")}; +CZipArchive::CZipArchive() +{ + m_bDetectZlibMemoryLeaks = true; + m_centralDir.m_pStorage= &m_storage; + m_info.m_stream.zalloc = (alloc_func)myalloc; + m_info.m_stream.zfree = (free_func)myfree; + m_iFileOpened = nothing; +} + + +CZipArchive::~CZipArchive() +{ + // Close(); // cannot be here: if an exception is thrown strange things can happen + EmptyPtrList(); +} + +void CZipArchive::Open(LPCTSTR szPathName, int iMode, int iVolumeSize) +{ + if (!IsClosed()) + { + TRACE(_T("ZipArchive already opened.\n")); + return; + } + m_pszPassword.Release(); + m_iFileOpened = nothing; + m_storage.Open(szPathName, iMode, iVolumeSize); + m_centralDir.Init(); + if ((iMode == open) ||(iMode == openReadOnly)) + m_centralDir.Read(); +} + +void CZipArchive::Open(CMemFile& mf, int iMode) +{ + if (!IsClosed()) + { + TRACE(_T("ZipArchive already opened.\n")); + return; + } + if (iMode != open && iMode != openReadOnly && iMode != create) + { + TRACE(_T("Mode not supported.\n")); + return; + } + m_pszPassword.Release(); + m_iFileOpened = nothing; + m_storage.Open(mf, iMode); + m_centralDir.Init(); + if ((iMode == open) ||(iMode == openReadOnly)) + m_centralDir.Read(); +} + + +bool CZipArchive::IsClosed(bool bArchive) +{ + return bArchive ?(m_storage.GetCurrentDisk() == -1):(!m_storage.m_pFile || m_storage.m_pFile->m_hFile == CFile::hFileNull); +} + + +void CZipArchive::ThrowError(int err) +{ + AfxThrowZipException(err, IsClosed() ? _T("") : m_storage.m_pFile->GetFilePath()); +} + +bool CZipArchive::DeleteFile(WORD uIndex) +{ + if (m_storage.IsSpanMode()) + { + TRACE(_T("You cannot delete files from the disk spannig archive.\n")); + return false; + } + + if (m_iFileOpened) + { + TRACE(_T("You cannot delete files if there is a file opened.\n")); + return false; + } + + if (!m_centralDir.IsValidIndex(uIndex)) + return false; + + m_info.Init(); + m_centralDir.RemoveFromDisk(); + DeleteInternal(uIndex); + m_info.m_pBuffer.Release(); + return true; +} + +int CZipArchive::GetNoEntries() +{ + return m_centralDir.m_headers.GetSize(); +} + + +bool CZipArchive::GetFileInfo(CZipFileHeader & fhInfo, WORD uIndex) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return false; + } + + if (!m_centralDir.IsValidIndex(uIndex)) + return false; + + fhInfo = *(m_centralDir.m_headers[uIndex]); + m_centralDir.ConvertFileName(true, false, &fhInfo); + return true; +} + +int CZipArchive::FindFile(CString szFileName, bool bCaseSensitive) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return (int)-1; + } + // this is required for fast finding and is done only once + if (!m_centralDir.m_bConvertAfterOpen) + { + TRACE(_T("Converting all filenames.")); + m_centralDir.ConvertAll(); + } + if (!m_centralDir.m_bFindFastEnabled) + EnableFindFast(); + int iResult = m_centralDir.FindFileNameIndex(szFileName, bCaseSensitive); + return iResult == -1 ? -1 : m_centralDir.m_findarray[iResult].m_uIndex; +} + +bool CZipArchive::OpenFile(WORD uIndex) +{ + if (!m_centralDir.IsValidIndex(uIndex)) + return false; + + if (m_storage.IsSpanMode() == 1) + { + TRACE(_T("You cannot extract from the span in creation.\n")); + return false; + } + + + if (m_iFileOpened) + { + TRACE(_T("A file already opened.\n")); + return false; + } + + m_info.Init(); + m_centralDir.OpenFile(uIndex); + if (CurrentFile()->IsEncrypted()) + { + + if (m_pszPassword.GetSize() == 0) + { + TRACE(_T("Password not set for the encrypted file.\n")); + return false; + } + CryptInitKeys(); + if (!CryptCheck()) + ThrowError(ZIP_BADPASSWORD); // invalid password + + } + else if (m_pszPassword.GetSize() != 0) + { + TRACE(_T("Password set for a not encrypted file. Ignoring password.\n")); + } + + WORD uMethod = CurrentFile()->m_uMethod; + if ((uMethod != 0) &&(uMethod != Z_DEFLATED)) + ThrowError(ZIP_BADZIPFILE); + + if (uMethod == Z_DEFLATED) + { + m_info.m_stream.opaque = m_bDetectZlibMemoryLeaks ? &m_list : 0; + int err = inflateInit2(&m_info.m_stream, -MAX_WBITS); + // * windowBits is passed < 0 to tell that there is no zlib header. + // * Note that in this case inflate *requires* an extra "dummy" byte + // * after the compressed stream in order to complete decompression and + // * return Z_STREAM_END. + CheckForError(err); + } + m_info.m_uComprLeft = CurrentFile()->m_uComprSize; + if (CurrentFile()->IsEncrypted()) + m_info.m_uComprLeft -= ENCR_HEADER_LEN; + m_info.m_uUncomprLeft = CurrentFile()->m_uUncomprSize; + m_info.m_uCrc32 = 0; + m_info.m_stream.total_out = 0; + m_info.m_stream.avail_in = 0; + + m_iFileOpened = extract; + return true; +} + + +int CZipArchive::GetLocalExtraField(char *pBuf, int iSize) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return -1; + } + + if (m_iFileOpened != extract) + { + TRACE(_T("A file must be opened to get the local extra field.\n")); + return -1; + } + + int size = m_centralDir.m_pLocalExtraField.GetSize(); + if (!pBuf|| !size) + return size; + + if (iSize < size) + size = iSize; + + memcpy(pBuf, m_centralDir.m_pLocalExtraField, size); + return size; +} + +void* CZipArchive::myalloc(void* opaque, UINT items, UINT size) +{ + void* p = new char[size * items]; + if (opaque) + { + CPtrList* list = (CPtrList*) opaque; + list->AddTail(p); + } + return p; +} + +void CZipArchive::myfree(void* opaque, void* address) +{ + if (opaque) + { + CPtrList* list = (CPtrList*) opaque; + POSITION pos = list->Find(address); + if (pos) + list->RemoveAt(pos); + } + delete[] address; +} + +void CZipArchive::CheckForError(int iErr) +{ + if ((iErr == Z_OK) ||(iErr == Z_NEED_DICT)) + return; + + ThrowError(iErr); +} + +CZipFileHeader* CZipArchive::CurrentFile() +{ + ASSERT(m_centralDir.m_pOpenedFile); + return m_centralDir.m_pOpenedFile; +} + +DWORD CZipArchive::ReadFile(void *pBuf, DWORD iSize) +{ + if (m_iFileOpened != extract) + { + TRACE(_T("Current file must be opened.\n")); + return 0; + } + + if (!pBuf || !iSize) + return 0; + + m_info.m_stream.next_out = (Bytef*)pBuf; + m_info.m_stream.avail_out = iSize > m_info.m_uUncomprLeft + ? m_info.m_uUncomprLeft : iSize; + + + DWORD iRead = 0; + + // may happen when the file is 0 sized + bool bForce = m_info.m_stream.avail_out == 0 && m_info.m_uComprLeft > 0; + while (m_info.m_stream.avail_out > 0 || (bForce && m_info.m_uComprLeft > 0)) + { + if ((m_info.m_stream.avail_in == 0) && + (m_info.m_uComprLeft > 0)) + { + DWORD uToRead = m_info.m_pBuffer.GetSize(); + if (m_info.m_uComprLeft < uToRead) + uToRead = m_info.m_uComprLeft; + + if (uToRead == 0) + return 0; + + m_storage.Read(m_info.m_pBuffer, uToRead, false); + CryptDecodeBuffer(uToRead); + m_info.m_uComprLeft -= uToRead; + + m_info.m_stream.next_in = (unsigned char*)(char*)m_info.m_pBuffer; + m_info.m_stream.avail_in = uToRead; + } + + if (CurrentFile()->m_uMethod == 0) + { + DWORD uToCopy = m_info.m_stream.avail_out < m_info.m_stream.avail_in + ? m_info.m_stream.avail_out : m_info.m_stream.avail_in; + + memcpy(m_info.m_stream.next_out, m_info.m_stream.next_in, uToCopy); + + m_info.m_uCrc32 = crc32(m_info.m_uCrc32, m_info.m_stream.next_out, uToCopy); + + m_info.m_uUncomprLeft -= uToCopy; + m_info.m_stream.avail_in -= uToCopy; + m_info.m_stream.avail_out -= uToCopy; + m_info.m_stream.next_out += uToCopy; + m_info.m_stream.next_in += uToCopy; + m_info.m_stream.total_out += uToCopy; + iRead += uToCopy; + } + else + { + DWORD uTotal = m_info.m_stream.total_out; + Bytef* pOldBuf = m_info.m_stream.next_out; + int err = inflate(&m_info.m_stream, Z_SYNC_FLUSH); + DWORD uToCopy = m_info.m_stream.total_out - uTotal; + + m_info.m_uCrc32 = crc32(m_info.m_uCrc32, pOldBuf, uToCopy); + + m_info.m_uUncomprLeft -= uToCopy; + iRead += uToCopy; + + if (err == Z_STREAM_END) + return iRead; + + CheckForError(err); + } + } + + return iRead; +} + +void CZipArchive::Close(bool bAfterException) +{ + // if after an exception - the archive may be closed, but the file may be opened + if (IsClosed() && (!bAfterException || IsClosed(false))) + { + TRACE(_T("ZipArchive is already closed.\n")); + return; + } + + if (!bAfterException) + { + if (m_iFileOpened == extract) + CloseFile(NULL); + + if (m_iFileOpened == compress) + CloseNewFile(); + + // write central directory + m_centralDir.Write(); + } + else + { + m_info.m_pBuffer.Release(); + m_iFileOpened = nothing; + EmptyPtrList(); + } + + m_centralDir.Clear(); + m_storage.Close(bAfterException); +} + +void CZipArchive::SetSpanCallback(ZIPCALLBACKFUN pFunc, void* pData) +{ + m_storage.m_pZIPCALLBACKFUN = pFunc; + m_storage.m_pCallbackData = pData; +} + +void CZipArchive::SetAdvanced(int iWriteBuffer, int iExtractBuffer, int iSearchBuffer) +{ + if (!IsClosed()) + { + TRACE(_T("Set this options before opening the archive.\n")); + return; + } + + m_storage.m_iWriteBufferSize = iWriteBuffer < 1024 ? 1024 : iWriteBuffer; + m_centralDir.m_iBufferSize = iSearchBuffer < 1024 ? 1024 : iSearchBuffer; + m_info.m_iBufferSize = iExtractBuffer < 1024 ? 1024 : iExtractBuffer; +} + +int CZipArchive::CloseFile(CFile &file) +{ + CString temp = file.GetFilePath(); + file.Close(); + return CloseFile(temp); +} + +int CZipArchive::CloseFile(LPCTSTR lpszFilePath, bool bAfterException) +{ + if (m_iFileOpened != extract) + { + TRACE(_T("No opened file.\n")); + return false; + } + + int iRet = 1; + if (!bAfterException) + { + if (m_info.m_uUncomprLeft == 0) + { + if (m_info.m_uCrc32 != CurrentFile()->m_uCrc32) + ThrowError(ZIP_BADCRC); + } + else + iRet = -1; + + + if (CurrentFile()->m_uMethod == Z_DEFLATED) + inflateEnd(&m_info.m_stream); + + + if (lpszFilePath) + { + try + { + CFileStatus fs; + fs.m_ctime = fs.m_atime = CTime::GetCurrentTime(); + fs.m_attribute = 0; + fs.m_mtime = CurrentFile()->GetTime(); + CFile::SetStatus(lpszFilePath, fs); + if (SetFileAttributes(lpszFilePath, CurrentFile()->m_uExternalAttr) == 0) + iRet = -2; + } + catch (CException* e) + { + e->Delete(); + return false; + } + } + } + m_centralDir.CloseFile(); + m_iFileOpened = nothing; + m_info.m_pBuffer.Release(); + EmptyPtrList(); + return iRet; +} + +bool CZipArchive::OpenNewFile(CZipFileHeader & header, int iLevel, LPCTSTR lpszFilePath) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return false; + } + + if (m_iFileOpened) + { + TRACE(_T("A file already opened.\n")); + return false; + } + + if (m_storage.IsSpanMode() == -1) + { + TRACE(_T("You cannot add the files to the existing disk spannig archive.\n")); + return false; + } + + if (GetNoEntries() ==(WORD)USHRT_MAX) + { + TRACE(_T("Maximum file count inside archive reached.\n")); + return false; + } + + + if (lpszFilePath) + { + bool bRet = true; + CFileStatus fs; + if (!CFile::GetStatus(lpszFilePath, fs)) + bRet = false; + else + { + header.SetTime(fs.m_mtime); + header.m_uExternalAttr = ::GetFileAttributes(lpszFilePath); // mfc bug: m_attribute is 1-byte + if (header.m_uExternalAttr == -1) + bRet = false; + } + + if (!bRet) + // do not continue - if the file was a directory then not recognizing it will cause + // serious errors + return false; + } + + m_info.Init(); + m_centralDir.AddNewFile(header); + + CString szFileName = CurrentFile()->GetFileName(); + + if (szFileName.IsEmpty()) + { + szFileName.Format(_T("file%i"), GetNoEntries());; + CurrentFile()->SetFileName(szFileName); + } + // this ensures the conversion will take place anyway (must take because we are going + // to write the local header in a moment + m_centralDir.ConvertFileName(false, m_centralDir.m_bConvertAfterOpen); + + + bool bIsDirectory = IsDirectory(CurrentFile()->m_uExternalAttr); + bool bEncrypted = m_pszPassword.GetSize() != 0; +#ifdef _DEBUG + if (bIsDirectory && bEncrypted) + TRACE(_T("Warning! Encrypting a directory. Possible but pointless.\n\ + Clear the password before adding a directory.\n")); +#endif + + + if (!CurrentFile()->PrepareData(iLevel, m_storage.IsSpanMode() == 1, bEncrypted)) + ThrowError(ZIP_TOOLONGFILENAME); + + CurrentFile()->WriteLocal(m_storage); + // we have written the local header, but if we keep filenames not converted + // in memory , we have to restore the non-converted value + if (m_centralDir.m_bConvertAfterOpen) + CurrentFile()->SetFileName(szFileName); + if (bEncrypted) + { + CZipAutoBuffer buf(ENCR_HEADER_LEN); + // use pseudo-crc since we don't know it yet + CryptCryptHeader((long)header.m_uModTime << 16, buf); + m_storage.Write(buf, ENCR_HEADER_LEN, false); + } + + + m_info.m_uComprLeft = 0; + m_info.m_stream.avail_in = (uInt)0; + m_info.m_stream.avail_out = (uInt)m_info.m_pBuffer.GetSize(); + m_info.m_stream.next_out = (unsigned char*)(char*)m_info.m_pBuffer; + m_info.m_stream.total_in = 0; + m_info.m_stream.total_out = 0; + + if (bIsDirectory && (CurrentFile()->m_uMethod != 0)) + CurrentFile()->m_uMethod = 0; + + if (CurrentFile()->m_uMethod == Z_DEFLATED) + { + m_info.m_stream.opaque = m_bDetectZlibMemoryLeaks ? &m_list : 0; + + int err = deflateInit2(&m_info.m_stream, iLevel, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + + CheckForError(err); + } + m_iFileOpened = compress; + return true; +} + +CString CZipArchive::GetFilePath(LPCTSTR lpszFilePath) +{ + TCHAR szDir[_MAX_DIR]; + TCHAR szDrive[_MAX_DRIVE]; + _tsplitpath(lpszFilePath, szDrive, szDir, NULL, NULL); + return CString(szDrive) + CString(szDir); +} + +CString CZipArchive::GetFileExt(LPCTSTR lpszFilePath) +{ + TCHAR szExt[_MAX_EXT]; + _tsplitpath(lpszFilePath, NULL, NULL, NULL, szExt); + return CString(szExt); +} + +CString CZipArchive::GetFileTitle(LPCTSTR lpszFilePath) +{ + TCHAR szFname[_MAX_FNAME]; + _tsplitpath(lpszFilePath, NULL, NULL, szFname, NULL); + return CString(szFname); +} + +CString CZipArchive::GetFileDirAndName(LPCTSTR lpszFilePath) +{ + TCHAR szDir[_MAX_DIR]; + TCHAR szFname[_MAX_FNAME]; + TCHAR szExt[_MAX_EXT]; + _tsplitpath(lpszFilePath, NULL , szDir, szFname, szExt); + CString Dir = szDir; + Dir.TrimLeft(_T("\\")); + return Dir + szFname + szExt; +} + + +CString CZipArchive::GetFileName(LPCTSTR lpszFilePath) +{ + TCHAR szExt[_MAX_EXT]; + TCHAR szName[_MAX_FNAME]; + _tsplitpath(lpszFilePath, NULL, NULL, szName, szExt); + return CString(szName) + CString(szExt); +} + +bool CZipArchive::ForceDirectory(LPCTSTR lpDirectory) +{ + ASSERT(lpDirectory); + CString szDirectory = lpDirectory; + szDirectory.TrimRight(_T("\\")); + if ((GetFilePath(szDirectory) == szDirectory) || + (FileExists(szDirectory) == -1)) + return true; + if (!ForceDirectory(GetFilePath(szDirectory))) + return false; + if (!CreateDirectory(szDirectory, NULL)) + return false; + return true; +} + +int CZipArchive::FileExists(LPCTSTR lpszName) +{ + CFileFind fileFind; + if (!fileFind.FindFile(lpszName)) + { + if (DirectoryExists(lpszName)) // if root ex. "C:\" + return -1; + return 0; + } + fileFind.FindNextFile(); + return fileFind.IsDirectory() ? -1 : 1; +} + +bool CZipArchive::DirectoryExists(LPCTSTR lpszDir) +{ + TCHAR curPath[_MAX_PATH]; /* Get the current working directory: */ + if (!_tgetcwd(curPath, _MAX_PATH)) + return false; + if (_tchdir(lpszDir)) // retruns 0 if error + return false; + _tchdir(curPath); + return true; +} + +bool CZipArchive::IsFileDirectory(WORD uIndex) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return false; + } + + if (!m_centralDir.IsValidIndex(uIndex)) + return false; + + return IsDirectory(m_centralDir.m_headers[uIndex]->m_uExternalAttr); +} +bool CZipArchive::ExtractFile(WORD uIndex, + LPCTSTR lpszPath, + bool bFullPath, + LPCTSTR lpszNewName, + ZIPCALLBACKFUN pCallback, + void* pUserData, + DWORD nBufSize) +{ + if (!nBufSize && !lpszPath) + return false; + + CZipFileHeader header; + GetFileInfo(header, uIndex); // to ensure that slash and oem conversions take place + CString szFile = lpszPath, szFileName = lpszNewName ? lpszNewName : header.GetFileName(); + szFile.TrimRight(_T("\\")); + szFile += _T("\\") + (bFullPath ? GetFileDirAndName(szFileName) + : GetFileName(szFileName)); // just in case in the archive there are file names with drives + + if (IsFileDirectory(uIndex)) + { + ForceDirectory(szFile); + SetFileAttributes(szFile, header.m_uExternalAttr); + return true; + } + else + { + if (!OpenFile(uIndex)) + return false; + + ForceDirectory(GetFilePath(szFile)); + CFile f(szFile, CFile::modeWrite | CFile::modeCreate | CFile::shareDenyWrite); + DWORD iRead, iFileLength = pCallback ? header.GetSize() : 0, iSoFar = 0; + CZipAutoBuffer buf(nBufSize); + do + { + iRead = ReadFile(buf, buf.GetSize()); + if (iRead) + { + f.Write(buf, iRead); + iSoFar += iRead; + if (pCallback) + if (!pCallback(iFileLength, iSoFar, pUserData)) + break; + } + } + while (iRead == buf.GetSize()); + return CloseFile(f) == 1; + } +} + +void CZipArchive::SetExtraField(char *pBuf, WORD iSize) +{ + if (m_iFileOpened != compress) + { + TRACE(_T("A new file must be opened.\n")); + return; + } + if (!pBuf || !iSize) + return; + + CurrentFile()->m_pExtraField.Allocate(iSize); + memcpy(CurrentFile()->m_pExtraField, pBuf, iSize); +} + +bool CZipArchive::WriteNewFile(void *pBuf, DWORD iSize) +{ + if (m_iFileOpened != compress) + { + TRACE(_T("A new file must be opened.\n")); + return false; + } + + + m_info.m_stream.next_in = (unsigned char*)pBuf; + m_info.m_stream.avail_in = iSize; + CurrentFile()->m_uCrc32 = crc32(CurrentFile()->m_uCrc32, (unsigned char*)pBuf, iSize); + + + while (m_info.m_stream.avail_in > 0) + { + if (m_info.m_stream.avail_out == 0) + { + CryptEncodeBuffer(); + m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); + m_info.m_uComprLeft = 0; + m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize(); + m_info.m_stream.next_out = (unsigned char*)(char*)m_info.m_pBuffer; + } + + if (CurrentFile()->m_uMethod == Z_DEFLATED) + { + DWORD uTotal = m_info.m_stream.total_out; + int err = deflate(&m_info.m_stream, Z_NO_FLUSH); + CheckForError(err); + m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal; + } + else + { + DWORD uToCopy = (m_info.m_stream.avail_in < m_info.m_stream.avail_out) + ? m_info.m_stream.avail_in : m_info.m_stream.avail_out; + + memcpy(m_info.m_stream.next_out, m_info.m_stream.next_in, uToCopy); + + m_info.m_stream.avail_in -= uToCopy; + m_info.m_stream.avail_out -= uToCopy; + m_info.m_stream.next_in += uToCopy; + m_info.m_stream.next_out += uToCopy; + m_info.m_stream.total_in += uToCopy; + m_info.m_stream.total_out += uToCopy; + m_info.m_uComprLeft += uToCopy; + } + } + + return true; +} + +bool CZipArchive::CloseNewFile() +{ + if (m_iFileOpened != compress) + { + TRACE(_T("A new file must be opened.\n")); + return false; + } + + m_info.m_stream.avail_in = 0; + + int err = Z_OK; + if (CurrentFile()->m_uMethod == Z_DEFLATED) + while (err == Z_OK) + { + if (m_info.m_stream.avail_out == 0) + { + CryptEncodeBuffer(); + m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); + m_info.m_uComprLeft = 0; + m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize(); + m_info.m_stream.next_out = (unsigned char*)(char*)m_info.m_pBuffer; + } + DWORD uTotal = m_info.m_stream.total_out; + err = deflate(&m_info.m_stream, Z_FINISH); + m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal; + } + + if (err == Z_STREAM_END) + err = Z_OK; + CheckForError(err); + + if (m_info.m_uComprLeft > 0) + { + CryptEncodeBuffer(); + m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); + } + + if (CurrentFile()->m_uMethod == Z_DEFLATED) + { + err = deflateEnd(&m_info.m_stream); + CheckForError(err); + } + + + // it may be increased by the encrypted header size + CurrentFile()->m_uComprSize += m_info.m_stream.total_out; + CurrentFile()->m_uUncomprSize = m_info.m_stream.total_in; + + m_centralDir.CloseNewFile(); + m_iFileOpened = nothing; + m_info.m_pBuffer.Release(); + return true; +} + +void CZipArchive::DeleteFiles(CStringArray &aNames, bool bCaseSensitive) +{ + CWordArray indexes; + + for (WORD i = 0; i < GetNoEntries(); i++) + { + CZipFileHeader fh; + GetFileInfo(fh, i); + CString szFileName = fh.GetFileName(); + for (int j = 0; j < aNames.GetSize(); j++) + { + bool bEqual = (bCaseSensitive ? aNames[j].Collate(szFileName) + : aNames[j].CollateNoCase(szFileName)) == 0; + if (bEqual) + { + indexes.Add(i); + break; + } + } + } + + DeleteFiles(indexes); +} + + +void CZipArchive::DeleteFiles(CWordArray &aIndexes) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return; + } + + if (m_storage.IsSpanMode()) + { + TRACE(_T("You cannot delete files from the disk spannig archive.\n")); + return; + } + + if (m_iFileOpened) + { + TRACE(_T("You cannot delete files if there is a file opened.\n")); + return; + } + + // sorting the index table using qsort + int uSize = aIndexes.GetSize(); + if (!uSize) + return; + qsort((void*)&aIndexes[0], uSize, sizeof(WORD), CompareWords); + + m_centralDir.RemoveFromDisk(); + + m_info.Init(); + // remove in a reverse order + for (int i = uSize - 1; i >= 0; i--) + DeleteInternal(aIndexes[i]); + m_info.m_pBuffer.Release(); +} + +DWORD CZipArchive::RemovePackedFile(DWORD uStartOffset, DWORD uEndOffset) +{ + uStartOffset += m_centralDir.m_uBytesBeforeZip; + uEndOffset += m_centralDir.m_uBytesBeforeZip; + DWORD BytesToCopy = m_storage.m_pFile->GetLength() - uEndOffset; + DWORD uTotalToWrite = BytesToCopy; + + char* buf = (char*)m_info.m_pBuffer; + if (BytesToCopy > m_info.m_pBuffer.GetSize()) + BytesToCopy = m_info.m_pBuffer.GetSize(); + + + + DWORD TotalWritten = 0; + DWORD size_read; + + do + { + m_storage.m_pFile->Seek(uEndOffset + TotalWritten, CFile::begin); + size_read = m_storage.m_pFile->Read(buf, BytesToCopy); + if (size_read > 0) + { + m_storage.m_pFile->Seek(uStartOffset + TotalWritten, CFile::begin); + m_storage.m_pFile->Write(buf, size_read); + } + TotalWritten += size_read; + } + while (size_read == BytesToCopy); + if (uTotalToWrite != TotalWritten) + ThrowError(CZipException::generic); + DWORD uRemoved = (uEndOffset - uStartOffset); + m_storage.m_pFile->SetLength(m_storage.m_pFile->GetLength() - uRemoved); + return uRemoved; +} + + +void CZipArchive::DeleteInternal(WORD uIndex) +{ + CZipFileHeader* pfh = m_centralDir.m_headers[uIndex]; + DWORD uOtherOffsetChanged = 0; + + if (uIndex == GetNoEntries() - 1) // last entry or the only one entry + m_storage.m_pFile->SetLength(pfh->m_uOffset + m_centralDir.m_uBytesBeforeZip); + else + uOtherOffsetChanged = RemovePackedFile(pfh->m_uOffset, m_centralDir.m_headers[uIndex + 1]->m_uOffset); + + + m_centralDir.RemoveFile(uIndex); + + // teraz uaktualnij offsety w pozosta³ych pozycjach central dir + // (update offsets in file headers in the central dir) + if (uOtherOffsetChanged) + for (int i = uIndex; i < GetNoEntries(); i++) + m_centralDir.m_headers[i]->m_uOffset -= uOtherOffsetChanged; +} + +bool CZipArchive::IsDriveRemovable(LPCTSTR lpszFilePath) +{ + return GetDriveType(GetDrive(lpszFilePath)) == DRIVE_REMOVABLE; +} + +CString CZipArchive::GetDrive(LPCTSTR lpszFilePath) +{ + TCHAR szDrive[_MAX_DRIVE]; + _tsplitpath(lpszFilePath, szDrive, NULL, NULL, NULL); + return szDrive; +} + +bool CZipArchive::AddNewFile(LPCTSTR lpszFilePath, + int iLevel, + bool bFullPath, + ZIPCALLBACKFUN pCallback, + void* pUserData, + unsigned long nBufSize) +{ + if (!nBufSize) + return false; + + CZipFileHeader header; + header.SetFileName(bFullPath ? GetFileDirAndName(lpszFilePath) : GetFileName(lpszFilePath)); + if (header.GetFileNameSize() == 0) + return false; + if (!OpenNewFile(header, iLevel, lpszFilePath)) + return false; + + if (!IsDirectory(header.m_uExternalAttr)) + { + CFile f; + CFileException* e = new CFileException; + BOOL bRet = f.Open(lpszFilePath, CFile::modeRead | CFile::shareDenyWrite, e); + e->Delete(); + if (!bRet) + return false; + + DWORD iRead, iFileLength = pCallback ? f.GetLength() : 0, iSoFar = 0; + CZipAutoBuffer buf(nBufSize); + do + { + iRead = f.Read(buf, nBufSize); + if (iRead) + { + WriteNewFile(buf, iRead); + iSoFar += iRead; + if (pCallback) + if (!pCallback(iFileLength, iSoFar, pUserData)) + break; + } + } + while (iRead == buf.GetSize()); + } + CloseNewFile(); + return true; +} + +int CZipArchive::GetSpanMode() +{ + return m_storage.m_iSpanMode * m_storage.IsSpanMode(); +} + +CString CZipArchive::GetArchivePath() +{ + return m_storage.m_pFile->GetFilePath(); +} + +CString CZipArchive::GetGlobalComment() +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return _T(""); + } + CString temp; + if (SingleToWide(m_centralDir.m_pszComment, temp) != -1) + return temp; + else + return _T(""); +} + +bool CZipArchive::SetGlobalComment(const CString &szComment) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return false; + } + if (m_storage.IsSpanMode() == -1) + { + TRACE(_T("You cannot modify the global comment of the existing disk spanning archive.\n")); + return false; + } + + WideToSingle(szComment, m_centralDir.m_pszComment); + m_centralDir.RemoveFromDisk(); + return true; +} + +bool CZipArchive::IsDirectory(DWORD uAttr) +{ + return (uAttr & FILE_ATTRIBUTE_DIRECTORY) != 0; +} + +int CZipArchive::GetCurrentDisk() +{ + return m_storage.GetCurrentDisk() + 1; +} + +bool CZipArchive::SetFileComment(WORD uIndex, CString szComment) +{ + if (IsClosed()) + { + TRACE(_T("ZipArchive is closed.\n")); + return false; + } + if (m_storage.IsSpanMode() == -1) + { + TRACE(_T("You cannot modify the file comment in the existing disk spanning archive.\n")); + return false; + } + + if (!m_centralDir.IsValidIndex(uIndex)) + return false; + m_centralDir.m_headers[uIndex]->SetComment(szComment); + m_centralDir.RemoveFromDisk(); + return true; +} + +int CZipArchive::CompareWords(const void *pArg1, const void *pArg2) +{ + WORD w1 = *(WORD*)pArg1; + WORD w2 = *(WORD*)pArg2; + return w1 == w2 ? 0 :(w1 < w2 ? - 1 : 1); +} + +void CZipArchive::CryptInitKeys() +{ + ASSERT(m_pszPassword.GetSize()); + m_keys[0] = 305419896L; + m_keys[1] = 591751049L; + m_keys[2] = 878082192L; + for (DWORD i = 0; i < m_pszPassword.GetSize(); i++) + CryptUpdateKeys(m_pszPassword[i]); +} + +void CZipArchive::CryptUpdateKeys(char c) +{ + + m_keys[0] = CryptCRC32(m_keys[0], c); + m_keys[1] += m_keys[0] & 0xff; + m_keys[1] = m_keys[1] * 134775813L + 1; + c = char(m_keys[1] >> 24); + m_keys[2] = CryptCRC32(m_keys[2], c); +} + +bool CZipArchive::CryptCheck() +{ + CZipAutoBuffer buf(ENCR_HEADER_LEN); + m_storage.Read(buf, ENCR_HEADER_LEN, false); + BYTE b = 0; + for (int i = 0; i < ENCR_HEADER_LEN; i++) + { + b = buf[i]; // only temporary + CryptDecode((char&)b); + } + // check the last byte + if (CurrentFile()->IsDataDescr()) // Data descriptor present + return BYTE(CurrentFile()->m_uModTime >> 8) == b; + else + return BYTE(CurrentFile()->m_uCrc32 >> 24) == b; +} + +char CZipArchive::CryptDecryptByte() +{ + int temp = (m_keys[2] & 0xffff) | 2; + return (char)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +void CZipArchive::CryptDecode(char &c) +{ + c ^= CryptDecryptByte(); + CryptUpdateKeys(c); +} + +bool CZipArchive::SetPassword(LPCTSTR lpszPassword) +{ + if (m_iFileOpened != nothing) + { + TRACE(_T("You cannot change the password when the file is opened\n")); + return false; // it's important not to change the password when the file inside archive is opened + } + if (IsClosed()) + { + TRACE(_T("Setting the password for a closed archive has no effect.\n")); + } + if (lpszPassword) + { + int iLen = WideToSingle(lpszPassword, m_pszPassword); + if (iLen == -1) + return false; + for (size_t i = 0; (int)i < iLen; i++) + if (m_pszPassword[i] > 127) + { + m_pszPassword.Release(); + TRACE(_T("The password contains forbidden characters. Password cleared.\n")); + return false; + } + } + else + m_pszPassword.Release(); + return true; +} + +DWORD CZipArchive::CryptCRC32(DWORD l, char c) +{ + const DWORD *CRC_TABLE = get_crc_table(); + return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8); +} + +void CZipArchive::CryptCryptHeader(long iCrc, CZipAutoBuffer &buf) +{ + CryptInitKeys(); + srand(UINT(GetTickCount()*time(NULL))); + // genereate pseudo-random sequence + char c; + for (int i = 0; i < ENCR_HEADER_LEN - 2; i++) + { + int t1 = rand(); + c = (char)(t1 >> 6); + if (!c) + c = (char)t1; + CryptEncode(c); + buf[i] = c; + + } + c = (char)((iCrc >> 16) & 0xff); + CryptEncode(c); + buf[ENCR_HEADER_LEN - 2] = c; + c = (char)((iCrc >> 24) & 0xff); + CryptEncode(c); + buf[ENCR_HEADER_LEN - 1] = c; +} + +void CZipArchive::CryptEncode(char &c) +{ + char t = CryptDecryptByte(); + CryptUpdateKeys(c); + c ^= t; +} + +void CZipArchive::CryptEncodeBuffer() +{ + if (CurrentFile()->IsEncrypted()) + for (DWORD i = 0; i < m_info.m_uComprLeft; i++) + CryptEncode(m_info.m_pBuffer[i]); +} + +void CZipArchive::CloseFileAfterTestFailed() +{ + if (m_iFileOpened != extract) + { + TRACE(_T("No file opened.\n")); + return; + } + m_info.m_pBuffer.Release(); + m_centralDir.Clear(false); + m_iFileOpened = nothing; +} + +bool CZipArchive::TestFile(WORD uIndex, ZIPCALLBACKFUN pCallback, void* pUserData, DWORD uBufSize) +{ + if (!uBufSize) + return false; + CZipFileHeader* pHeader = m_centralDir.m_headers[uIndex]; + if (IsFileDirectory(uIndex)) + { + + // we do not test whether the password for the encrypted directory + // is correct, since it seems to be senseless (anyway password + // encrypted directories should be avoided - it adds 12 bytes) + DWORD iSize = pHeader->m_uComprSize; + if ((iSize != 0 || iSize != pHeader->m_uUncomprSize) + // different treating compressed directories + && !(pHeader->IsEncrypted() && iSize == 12 && !pHeader->m_uUncomprSize)) + ThrowError(CZipException::dirWithSize); + return true; + } + else + { + try + { + if (!OpenFile(uIndex)) + return false; + CZipAutoBuffer buf(uBufSize); + DWORD iRead, iSoFar = 0; + do + { + iRead = ReadFile(buf, buf.GetSize()); + iSoFar += iRead; + if (pCallback) + if (!pCallback(pHeader->m_uUncomprSize, iSoFar, pUserData)) + break; + } + while (iRead == buf.GetSize()); + CloseFile(); + } + catch(CException*) + { + CloseFileAfterTestFailed(); + throw; + } + } + return true; + +} + +int CZipArchive::WideToSingle(LPCTSTR lpWide, CZipAutoBuffer &szSingle) +{ + size_t wideLen = _tcslen(lpWide); + if (wideLen == 0) + { + szSingle.Release(); + return 0; + } + +#ifdef _UNICODE + // iLen does not include terminating character + int iLen = WideCharToMultiByte(CP_ACP,0, lpWide, wideLen, szSingle, + 0, NULL, NULL); + if (iLen > 0) + { + szSingle.Allocate(iLen, true); + iLen = WideCharToMultiByte(CP_ACP,0, lpWide , wideLen, szSingle, + iLen, NULL, NULL); + ASSERT(iLen != 0); + } + else // here it means error + { + szSingle.Release(); + iLen --; + } + return iLen; + +#else // if not UNICODE just copy + // iLen does not include the NULL character + szSingle.Allocate(wideLen); + memcpy(szSingle, lpWide, wideLen); + return wideLen; +#endif + +} + +int CZipArchive::SingleToWide(CZipAutoBuffer &szSingle, CString& szWide) +{ + int singleLen = szSingle.GetSize(); +#ifdef _UNICODE + // iLen doesn't include terminating character + int iLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSingle, singleLen, NULL, 0); + if (iLen > 0) + { + iLen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szSingle, singleLen, + szWide.GetBuffer(iLen) , iLen); + szWide.ReleaseBuffer(iLen); + ASSERT(iLen != 0); + } + else + { + szWide.Empty(); + iLen --; + } + return iLen; + +#else // if not UNICODE just copy + // iLen does not include the NULL character + memcpy(szWide.GetBuffer(singleLen), szSingle, singleLen); + szWide.ReleaseBuffer(singleLen); + return singleLen; +#endif +} + +const DWORD* CZipArchive::GetCRCTable() +{ + return get_crc_table(); +} + +void CZipArchive::CryptDecodeBuffer(DWORD uCount) +{ + if (CurrentFile()->IsEncrypted()) + for (DWORD i = 0; i < uCount; i++) + CryptDecode(m_info.m_pBuffer[i]); +} + +void CZipArchive::EmptyPtrList() +{ + if (m_list.GetCount()) + { + // if some memory hasn't been freed due to an error in zlib, so free it now + POSITION pos = m_list.GetHeadPosition(); + while (pos) + delete[] m_list.GetNext(pos); + } + +} + + + +void CZipArchive::EnableFindFast(bool bEnable) +{ + if (IsClosed()) + { + TRACE(_T("Set it after opening the archive")); + return; + } + + if (m_centralDir.m_bFindFastEnabled == bEnable) + return; + m_centralDir.m_bFindFastEnabled = bEnable; + if (bEnable) + m_centralDir.BuildFindFastArray(); + else + m_centralDir.m_findarray.RemoveAll(); +} diff --git a/stepmania/src/smpackage/ZipArchive/ZipArchive.dsp b/stepmania/src/smpackage/ZipArchive/ZipArchive.dsp new file mode 100644 index 0000000000..a2cfd40326 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipArchive.dsp @@ -0,0 +1,283 @@ +# Microsoft Developer Studio Project File - Name="ZipArchive" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=ZipArchive - Win32 Unicode Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ZipArchive.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ZipArchive.mak" CFG="ZipArchive - Win32 Unicode Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ZipArchive - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ZipArchive - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "ZipArchive - Win32 Static Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ZipArchive - Win32 Unicode Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "ZipArchive - Win32 Unicode Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ZipArchive - Win32 Unicode Static Release" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ZipArchive - Win32 Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "ZLIB_DLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c +# ADD BASE RSC /l 0x415 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x415 /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "ZipArchive - Win32 Debug" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "ZLIB_DLL" /D "_AFXDLL" /Fr /Yu"stdafx.h" /FD /GZ /c +# ADD BASE RSC /l 0x415 /d "_DEBUG" /d "_AFXDLL" +# ADD RSC /l 0x415 /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "ZipArchive - Win32 Static Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Zip___Win32_Static_Release" +# PROP BASE Intermediate_Dir "Zip___Win32_Static_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 1 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Static_Release" +# PROP Intermediate_Dir "Static_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "ZLIB_DLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "ZLIB_DLL" /Yu"stdafx.h" /FD /c +# ADD BASE RSC /l 0x415 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x415 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "ZipArchive - Win32 Unicode Debug" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Zip___Win32_Unicode_Debug" +# PROP BASE Intermediate_Dir "Zip___Win32_Unicode_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Unicode_Debug" +# PROP Intermediate_Dir "Unicode_Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "ZLIB_DLL" /Fr /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W4 /Gm /GX /ZI /Od /D "ZLIB_DLL" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "_UNICODE" /Fr /Yu"stdafx.h" /FD /GZ /c +# ADD BASE RSC /l 0x415 /d "_DEBUG" /d "_AFXDLL" +# ADD RSC /l 0x415 /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "ZipArchive - Win32 Unicode Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Zip___Win32_Unicode_Release" +# PROP BASE Intermediate_Dir "Zip___Win32_Unicode_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Unicode_Release" +# PROP Intermediate_Dir "Unicode_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "ZLIB_DLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W4 /GX /O2 /D "ZLIB_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_AFXDLL" /D "_UNICODE" /Yu"stdafx.h" /FD /c +# ADD BASE RSC /l 0x415 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x415 /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "ZipArchive - Win32 Unicode Static Release" + +# PROP BASE Use_MFC 1 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Zip___Win32_Unicode_Static_Release" +# PROP BASE Intermediate_Dir "Zip___Win32_Unicode_Static_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 1 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Unicode_Static_Release" +# PROP Intermediate_Dir "Unicode_Static_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "ZLIB_DLL" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "ZLIB_DLL" /D "_UNICODE" /Yu"stdafx.h" /FD /c +# ADD BASE RSC /l 0x415 /d "NDEBUG" +# ADD RSC /l 0x415 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "ZipArchive - Win32 Release" +# Name "ZipArchive - Win32 Debug" +# Name "ZipArchive - Win32 Static Release" +# Name "ZipArchive - Win32 Unicode Debug" +# Name "ZipArchive - Win32 Unicode Release" +# Name "ZipArchive - Win32 Unicode Static Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\ZipArchive.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipAutoBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipBigFile.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipCentralDir.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipException.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipFileHeader.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipInternalInfo.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipStorage.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\zconf.h +# End Source File +# Begin Source File + +SOURCE=.\ZipArchive.h +# End Source File +# Begin Source File + +SOURCE=.\ZipAutoBuffer.h +# End Source File +# Begin Source File + +SOURCE=.\ZipBigFile.h +# End Source File +# Begin Source File + +SOURCE=.\ZipCentralDir.h +# End Source File +# Begin Source File + +SOURCE=.\ZipException.h +# End Source File +# Begin Source File + +SOURCE=.\ZipFileHeader.h +# End Source File +# Begin Source File + +SOURCE=.\ZipInternalInfo.h +# End Source File +# Begin Source File + +SOURCE=.\ZipStorage.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\Appnote.txt +# End Source File +# Begin Source File + +SOURCE=.\zlib.lib +# End Source File +# End Target +# End Project +# Section ZipArchive : {427B9281-D5E8-11D3-B7C7-E75054E13747} +# 2:12:AutoBuffer.h:AutoBuffer.h +# 2:18:CLASS: CAutoBuffer:CAutoBuffer +# 2:19:Application Include:Zip.h +# 2:14:AutoBuffer.cpp:AutoBuffer.cpp +# End Section diff --git a/stepmania/src/smpackage/ZipArchive/ZipArchive.dsw b/stepmania/src/smpackage/ZipArchive/ZipArchive.dsw new file mode 100644 index 0000000000..b4d097172a --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipArchive.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ZipArchive"=.\ZipArchive.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/stepmania/src/smpackage/ZipArchive/ZipArchive.h b/stepmania/src/smpackage/ZipArchive/ZipArchive.h new file mode 100644 index 0000000000..9f9eef92de --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipArchive.h @@ -0,0 +1,698 @@ +// ZipArchive.h: interface for the CZipArchive class. +// +////////////////////////////////////////////////////////////////////// +// ZipArchive 1.5.1, March 2001 +// +// +// This library allows to crate ZIP files in the compatible way with +// PKZIP version 2.6. Some important issues: +// - multiple disk spanning is supported +// - encyption is not supported +// - allows to create disk spanning archive also on non removable devices +// and with user-defined volume size +// - this library uses the zlib library by Jean-loup Gailly and Mark Adler +// to perform inflate, deflate operations +// +// +// +// Copyright (C) 2000 - 2001 Tadeusz Dracz +// +// +// Permission is granted to anyone to use this software for any purpose +// and to alter it and redistribute it freely, subject to the +// following restrictions: +// +// 1. Using this software in commercial applications requires an author permission. +// The permission will be granted to everyone excluding the cases when +// someone simply tries to resell the code. +// +// 2. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 3. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 4. This notice may not be removed or altered from any source distribution. +// +// +// You can contact me at: +// tdracz@artpol.com.pl +// +// For new versions check the site: +// http://software.artpol.com.pl +// +// History: +// 03.2001 +// +// - when the central directory was not located, the library throws CZipException::cdirNotFound, +// which allows distinguish from other exceptions (useful when we want to keep prompting +// the user to insert the last disk in a multi-disk spanning archive). +// +// +// 02.2001 +// Features added: +// - ability to reuse the archive after an exception thrown during extraction +// - added progress control possibilities to CZipArchive::AddNewFile, CZipArchive::ExtractFile, CZipArchive::TestFile +// Changes: +// - CZipArchive::FindFile operation boosted ( thanks to Darin Warling for the idea) +// - library name changed to ZipArchive +// Bugs fixed: +// - removed bug during extracting an encrypted file with 0 size +// - fixed bug when extracting a file with an extra field in a local file header (CZipFileHeader::ReadLocal) +// +// 01.2001 +// - Disk numbering in a disk spanning archive begins now from PKBACK# 001 not PKBACK# 000 +// - Adding and extracting without a full path possible in CZipArchive::AddNewFile and CZipArchive::ExtractFile. +// - Several minor changes and enhancements +// - Changed names for several classes. +// +// 11.2000 +// - Added support for password encryption and decryption. +// The encryption used in PKZIP was generously supplied by Roger +// Schlafly. +// - Testing the archive made easier +// - Unicode support added +// +// 08.2000 +// - Bugs fixed +// +// 06.2000 +// +// the code has been completely rewritten since the very beginning; +// the main improvements are: +// - multi-disk archive support +// - creation of the disk spanning archives with the user-defined volume size +// - ability to modify existing archives (add, delete files) +// - modification self-extracting archives +// - write buffer used for faster disk write operations +// - one class for zip and unzip functions +// - fast adding, deleting and extracting files with a single function call +// +// 03.2000 +// - international characters in filenames inside archive are now +// converted in a compatible way with other archiving programs (they are stored +// converted to OEM inside archive). +// +// 01.2000 +// +// first version; it is just modified code from zip.c and unzip.c files +// written by Gilles Vollant and distributed with zlib library; +// the modifications are as follows: +// - added class' wrappers +// - several bugs fixed +// - several enhancements added +// - MFC support added +// - memory leaks eliminated when write error occurred +// - automatically free used memory on destruction or exception +// - modern error notification using exceptions +// +// for more info about .ZIP format, see +// ftp://ftp.pkware.com/appnote.zip +// the unpacked file (appnote.txt) from this archive is a part of this project +// +// +// Note: +// if a file added to the archive is bigger after compressing +// (e.g. it is an other archive) it should be delted from the archive and +// added once again with store method (it may be done only on the files +// not divided between volumes) + +#if !defined(AFX_ZIPARCHIVE_H__A7F528A6_1872_4071_BE66_D56CC2DDE0E6__INCLUDED_) +#define AFX_ZIPARCHIVE_H__A7F528A6_1872_4071_BE66_D56CC2DDE0E6__INCLUDED_ + +#include "ZipStorage.h" // Added by ClassView +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ZipException.h" +#include "ZipCentralDir.h" // Added by ClassView +#include "ZipInternalInfo.h" // Added by ClassView + + +////////////////////////////////////////////////////////////////////////// +///////////////////// CZipArchive ///////////////////////////////////// + +class CZipArchive +{ +public: + static int SingleToWide(CZipAutoBuffer &szSingle, CString& szWide); + static int WideToSingle(LPCTSTR lpWide, CZipAutoBuffer &szSingle); + +// Function name : TestFile +// Description : Test the file with the given index +// the function throws CException*, but performs all the necessary cleanup +// before, so that the next file can be tested after catchig the exception +// and examining it for the reason of error. +// Return type : bool +// return false if the incorrect action has been taken by +// the user or the programmer (it is when OpenFile(WORD nIndex) or +// GetFileInfo(CZipFileHeader & fhInfo, WORD uIndex) return false or uBufSize +// is 0 +// Argument : WORD uIndex +// index of the file to test +// Argument : ZIPCALLBACKFUN pCallback = NULL +// See the description at AddNewFile +// Argument : void* pUserData = NULL +// Argument : DWORD uBufSize = 65535 +// the size of the buffer used during extraction + bool TestFile(WORD uIndex, ZIPCALLBACKFUN pCallback = NULL, void* pUserData = NULL, DWORD uBufSize = 65535); + +// Function name : CloseFileAfterTestFailed +// Description : Perform the necessary cleanup after the exception +// while testing the archive so that next files in the archive can be tested +// Return type : void + void CloseFileAfterTestFailed(); + + +// Function name : SetPassword +// Description : set the password for the file that is going to be opened or created +// use this function BEFORE opening or adding a file +// Return type : bool +// return false if the password contains ASCII characters +// with values 128 or higher or the file inside archive is +// opened +// Argument : LPCTSTR lpszPassword = NULL +// set it to NULL to clear password + bool SetPassword(LPCTSTR lpszPassword = NULL); + +// Function name : SetAdvanced +// Description : set advanced options +// Return type : void +// Argument : int iWriteBuffer = 65535 +// buffer used during write operation to the disk, the bigger, the better; +// it is pointless, however, to set it bigger than the size of the volume; +// the optimal size is the size of the volume +// Argument : int iExtractBuffer = 16384 +// set the size of the buffer used in extracting and compressing files +// default 16384, must not be < 1024 +// set it before opening the archive +// Argument : int iSearchBuffer = 32768 +// set the size of the buffer used in searching for the central dir +// useful with big archives, default 32768, must not be < 1024 + void SetAdvanced(int iWriteBuffer = 65535, int iExtractBuffer = 16384, int iSearchBuffer = 32768); + +// Function name : SetSpanCallback +// Description : set callback function used during operations on a +// pkzip compatible disk spanning archive to change disks; +// set it usualy before opening the archive for reading +// Return type : void +// Argument : ZIPCALLBACKFUN pFunc +// for the description of callback function see CZipStorage.h +// Argument : void* pData +// user data to be passed to the callback function as the last parameter + void SetSpanCallback(ZIPCALLBACKFUN pFunc, void* pData = NULL); + +// archive open modes + enum {open, openReadOnly, create, createSpan}; + +// Disk spanning archive modes: +// pkzip compatible mode (pkSpan): +// - only on removeble devices +// - autodetect the size of the volume +// - write a label to the disk +// - there is a need to set the span callback function +// TD mode (tdSpan): +// - may be created on non removable devices +// - uses user-defined volume size +// - no need to set the span callback function + +// Function name : Open +// Description : Open a zip archive +// Return type : void +// Argument : LPCTSTR szPathName +// Path to the archive +// Argument : int iMode= CZipArchive::open; +// open mode flags: +// open open an existing archive +// openReadOnly open an existing archive as read only file +// (this mode is intended to use in self extract code) +// if you try to add or delete a file in this mode, an exception will be thrown +// create create a new archive +// createSpan create a disk spanning archive +// Argument : int iVolumeSize = 0 +// if iMode == createSpan and iVolumeSize <= 0 then create disk spanning +// archive in pkzip mode +// if iMode == createSpan and iVolumeSize > 0 then create disk spanning +// archive in TD mode +// if iMode == open and the exisitng archive is a spanned archive +// the pkSpan mode is assumed if the archive is on a removable device +// or tdSpan otherwise; +// if you want to open tdSpan archive on a removable device, set iVolumeSize +// to a value different from 0 +// if iMode == create this argument doesn't matter + void Open(LPCTSTR szPathName, int iMode = open, int iVolumeSize = 0); + +// Function name : Open +// Description : Open or create an archive in CMemFile +// Return type : void +// Argument : CMemFile& mf +// Argument : int iMode = open +// the following modes are valid: open, openReadOnly, create + void Open(CMemFile& mf, int iMode = open); + + +// Function name : AddNewFile +// Description : add quickly a new file to the archive +// Return type : bool +// Argument : LPCTSTR lpszFilePath +// file to be added +// Argument : int iLevel = Z_DEFAULT_COMPRESSION +// the compression level (see OpenNewFile() for detailed desciption) +// Argument : bool bFullPath +// if true, include full path of the file inside the archive +// Argument : ZIPCALLBACKFUN pCallback = NULL +// callback function (may be NULL) +// To set the callback function for this operation pass its pointer as the +// argument (do not use SetSpanCallback for it - its for different purposes). +// The callback function, if set, is called after reading and writing one portion of data. +// - the first argument (DWORD): +// total number of bytes to read (the size of the file) +// - the second one (int) : +// total number bytes already read +// - the third argument (void*): +// pUserData argument passed to #AddNewFile +// Argument : void* pUserData = NULL +// user - defined data passed on to the callback function +// (doesn't matter if there is no callback function defined) +// Argument : DWORD nBufSize = 65535 +// the size of the buffer used during compression + +/* +*/ + bool AddNewFile(LPCTSTR lpszFilePath, int iLevel = -1, bool bFullPath = true, ZIPCALLBACKFUN pCallback = NULL, void* pUserData = NULL, unsigned long nBufSize = 65535); + +// Function name : OpenNewFile +// Description : add a new file to the zip archive +// Return type : bool +// return false in the following cases: +// - the lpszFilePath is not NULL and the file attributes and data was not correctly retreived +// - a file is already opened for extraction or compression +// - archive is an existing disk span archive +// - maximum file count inside archive reached (65535) +// Argument : CZipFileHeader & header +// structure that have addtional information; the following fields are valid: +// - m_uMethod - file compression method; can be 0 (storing) or Z_DEFLATE (deflating) +// otherwise Z_DEFLATE is assumed +// - m_uModDate, m_uModTime - use SetTime method of CFileHeadeer to set them +// if lpszFilePath is not NULL this fields are updated automaticaly +// - m_uExternalAttr - attributes of the file +// if lpszFilePath is not NULL this field is updated automaticaly +// - m_szFileName - file name (may be with path) to be stored inside archive +// to represent this file +// - m_szComment - file comment +// - m_pExtraField - LOCAL extra field, use SetExtraField() after opening +// a new file, but before closing it to set the extra field +// in the header in the central directory +// other fields are ignored - they are updated automaticaly +// Argument : int iLevel = Z_DEFAULT_COMPRESSION +// the level of compression (-1, 0 - 9); named values: +// Z_DEFAULT_COMPRESSION : -1 +// Z_NO_COMPRESSION : 0 +// Z_BEST_SPEED : 1 +// Z_BEST_COMPRESSION : 9 +// Argument : LPCTSTR lpszFilePath = NULL +// the path to the file to retreive date and attributes from + bool OpenNewFile(CZipFileHeader & header, int iLevel = Z_DEFAULT_COMPRESSION, LPCTSTR lpszFilePath = NULL); + +// Function name : WriteNewFile +// Description : compress the contents of the buffer and write it to a new file +// Return type : bool +// return false if the new file hasn't been opened +// Argument : void *pBuf +// buffer containing the data to be compressed and written +// Argument : DWORD iSize +// the size of the buffer + bool WriteNewFile(void *pBuf, DWORD iSize); + +// Function name : SetExtraField +// Description : set the extra field in the file header in the central directory +// must be used after opening a new file in the archive, but before closing it +// Return type : void +// Argument : char *pBuf +// bufer with the data to be copied +// Argument : DWORD iSize +// size of the buffer + void SetExtraField(char *pBuf, WORD iSize); + +// Function name : CloseNewFile +// Description : close the new file in the archive +// Return type : bool +// return false if no new file is opened +// Argument : bool bAfterException = false +// set it to true if you want to reuse CZipArchive after is has thrown an exception + bool CloseNewFile(); + +// Function name : ExtractFile +// Description : fast extracting +// Return type : bool +// Argument : WORD uIndex +// the index of the file +// Argument : LPCTSTR lpszPath +// PATH only to extract the file to +// Argument : bool bFullPath = true +// extract the file with full path (if there is a path stored with the filename) +// or just with the filename alone +// (it means that the resulting file path is lpszPath + one of the above) +// Argument : LPCTSTR lpszNewName = NULL +// if NULL the default file name is taken (from the archive) +// Argument : ZIPCALLBACKFUN pCallback = NULL +// See the description at AddNewFile +// Argument : void* pUserData = NULL +// Argument : DWORD nBufSize = 65535 +// the size of the buffer used during extraction + bool ExtractFile(WORD uIndex, LPCTSTR lpszPath, bool bFullPath = true, LPCTSTR lpszNewName = NULL, ZIPCALLBACKFUN pCallback = NULL, void* pUserData = NULL, DWORD nBufSize = 65535); + +// Function name : OpenFile +// Description : open the file with the given index in the archive for extracting +// Argument : WORD uIndex +// Return type : bool + bool OpenFile(WORD uIndex); + +// Function name : ReadFile +// Description : decompress currently opened file to the bufor +// Return type : DWORD +// number of bytes read +// Argument : void *pBuf +// buffer to receive data +// Argument : DWORD iSize +// the size of the buffer + DWORD ReadFile(void *pBuf, DWORD iSize); + +// Function name : GetLocalExtraField +// Description : get the local extra filed of the currently opened +// for extraction file in the archive +// Return type : int +// if pBuf == NULL return the size of the local extra field +// Argument : char* pBuf +// the buffer to receive the data +// Argument : int iSize +// the size of the buffer + int GetLocalExtraField(char* pBuf, int iSize); + +// Function name : CloseFile +// Description : close current file and update +// date and attribute information of CFile, closes CFile +// Return type : int +// see below +// Argument : CFile & file +// OPENED CFile structure of the extracted file + int CloseFile(CFile &file); + + +/** + Close the file opened for extraction in the archive and copy its date and + attributes to the file pointed by \e lpszFilePath + \param lpszFilePath + Points to the path of the file to have the date and attributes information updated. + \param bAfterException + Set to \c true to close the file inside archive after an exception has been + thrown, to allow futher operations on the archive. + \warning Close the file pointed by \e lpszFilePath before using this method, + because the system may not be able to retrieve information from it. + \return + - "1" = ok + - "-1" = some bytes left to uncompress - probably due to a bad password + - "-2" = setting extracted file date and attributes was not successful + \note Throws exceptions. +*/ + int CloseFile(LPCTSTR lpszFilePath = NULL, bool bAfterException = false); + +// Function name : DeleteFile +// Description : delete the file with the given index +// Return type : bool +// Argument : WORD uIndex +// index of the file to be deleted + bool DeleteFile(WORD uIndex); + +/* delete files from the archive opened in the Delete mode specified by aIndexes + or aNames + + aIndexes is a array of indexes of the files inside the archive; + the index no. 0 is the first file in the archive + + aNames is a array of file names inside the archive; they must be the + same as they apppear in the archive (the name and the path (if persists) + is required, lower and upper case are not distinguished) + +*/ + void DeleteFiles(CWordArray &aIndexes); + void DeleteFiles(CStringArray &aNames, bool bCaseSensitive = false); + + +// Function name : SetGlobalComment +// Description : set the global comment in the archive +// Return type : bool +// return false if the archive is closed or if it is an existing disk spanning archive +// Argument : const CString& szComment + bool SetGlobalComment(const CString& szComment); + +// Function name : GetGlobalComment +// Description : get the global commment +// Return type : CString +// return an empty string if the archive is closed + CString GetGlobalComment(); + + +// Function name : SetFileComment +// Description : set the comment of the file with the given index +// Return type : bool +// return false if the comment change is imposible +// Argument : WORD uIndex +// index of the file +// Argument : CString szComment +// comment to add + bool SetFileComment(WORD uIndex, CString szComment); + +// Function name : GetArchivePath +// Description : return the path of the currently opended archive volume +// Return type : CString + CString GetArchivePath(); + +// Function name : GetCurrentDisk +// Description : return the zero-base number of the current disk +// Return type : int +// return -1 if there is no current disk (archive is closed) + int GetCurrentDisk(); + +// Function name : GetSpanMode +// Description : return the disk spanning mode of the cuurrent archive +// Return type : int +// CZipStorage::tdSpan == - 2 - exisitng TD compatible disk spanning +// CZipStorage::pkzipSpan == - 1 - exisitng pkzip compatible disk spanning +// CZipStorage::noSpan == 0 - no disk spanning +// CZipStorage::pkzipSpan == 1 - pkzip compatible disk spanning in creation +// CZipStorage::tdSpan == 2 - TD compatible disk spanning in creation + int GetSpanMode(); + +// Function name : IsFileDirectory +// Description : check if the file with the given index is a directory +// Argument : WORD uIndex +// index of the file +// Return type : bool +// return true if the file is a directory +// return false if the file is not a directory or if there is no file +// with the given index + bool IsFileDirectory(WORD uIndex); + +// Function name : FindFile +// Description : find the file in the archive +// This function requires CZipCentralDir::m_bFindFastEnabled set to true +// Use EnableFindFast() +// Return type : int +// the index of the file found or -1 if no file was found +// Argument : CString szFileName +// the name of the file to be found +// Argument : bool bCaseSensitive = false +// if true - perform case sensitive search + int FindFile(CString szFileName, bool bCaseSensitive = false); + + +/* + Function name : EnableFindFast + Description : + Enable fast finding by the file name of the files inside the archive. + Set CZipCentralDir::m_bFindFastEnabled to true, which is required by FindFile. + Do not enable it, if you don't plan to use FindFile function + + Return type : void + Argument : bool bEnable = true +*/ + void EnableFindFast(bool bEnable = true); + + +/* + Function name : SetConvertAfterOpen + Description : Set CZipCentralDir::m_bConvertAfterOpen value. Use before opening the archive + see CZipCentralDir::m_bConvertAfterOpen + Return type : void + Argument : bool bConvertAfterOpen +*/ + void SetConvertAfterOpen (bool bConvertAfterOpen) + { + if (!IsClosed()) + { + TRACE(_T("Set it before opening the archive")); + return; + } + m_centralDir.m_bConvertAfterOpen = bConvertAfterOpen; + + } + + +// Function name : GetFileInfo +// Description : get the info of the file with the given index +// Return type : bool +// true if successful +// Argument : CZipFileHeader & fhInfo +// structure to receive info +// Argument : WORD uIndex +// zero-based index of the file + bool GetFileInfo(CZipFileHeader & fhInfo, WORD uIndex); + + +// Function name : GetNoEntries +// Description : get number of files in the archive +// Return type : int + int GetNoEntries(); + +// Function name : Close +// Description : close archive +// Return type : void +// Argument : bool bAfterException = false +// set it to true if you want to close and reuse CZipArchive after is has thrown an exception +// ( it doesn't write any data to the file but only makes some cleaning then) + void Close(bool bAfterException = false); + + + +// Function name : IsClosed +// Description : test if the archive or the current volume file is closed +// Return type : bool +// Argument : bool bArchive = true +// if true test for the whole archive, if false - for the volume file only + bool IsClosed(bool bArchive = true); + +// specify whether to control memory allocation and freeing by zlib library +// strongly suggested to set it to true (default) +// set it before opening a file (new or current) in the archive + bool m_bDetectZlibMemoryLeaks; + + + CZipArchive(); + virtual ~CZipArchive(); + +//////////////////////////////////////////////////////////////////////// +////////////////////// static helper functions /////////////////////// +//////////////////////////////////////////////////////////////////////// + +// Function name : GetFileTitle +// Description : get the title of the file +// Return type : CString +// Argument : LPCTSTR lpszFilePath + static CString GetFileTitle(LPCTSTR lpszFilePath); + +// Function name : GetFileDirAndName +// Description : get the directory and the file name from the file path +// Return type : static CString +// Argument : LPCTSTR lpszFilePath + static CString GetFileDirAndName(LPCTSTR lpszFilePath); + +// Function name : GetDrive +// Description : return the (drive:) part from the path +// Return type : static CString +// Argument : LPCTSTR lpszFilePath + static CString GetDrive(LPCTSTR lpszFilePath); + +// Function name : IsDriveRemovable +// Description : return true if the file, path or (disk:) specified by the +// argument is (on) a removable drive +// Return type : static bool +// Argument : LPCTSTR lpszFilePath + static bool IsDriveRemovable(LPCTSTR lpszFilePath); + +// Function name : DirectoryExists +// Description : check if the given directory exists +// Return type : static bool +// Argument : LPCTSTR lpszDir + static bool DirectoryExists(LPCTSTR lpszDir); + + +// Function name : FileExists +// Description : check if the given file or directory exists +// Return type : static int +// return -1 if the given file is a directory, 1 if is a file +// or 0 if there is no such a file +// Argument : LPCTSTR lpszName + static int FileExists(LPCTSTR lpszName); + +// Function name : ForceDirectory +// Description : create nested directories with a single command +// Return type : static bool +// Argument : LPCTSTR lpDirectory + static bool ForceDirectory(LPCTSTR lpDirectory); + +// Function name : GetFilePath +// Description : get the path of the given file +// Return type : static CString +// Argument : LPCTSTR strFilePath + static CString GetFilePath(LPCTSTR lpszFilePath); + + +// Function name : GetFileExt +// Description : return the file extension +// Return type : static CString +// Argument : LPCTSTR lpszFilePath + static CString GetFileExt(LPCTSTR lpszFilePath); + + +// Function name : GetFileName +// Description : return the name of the file (title + extension) +// Return type : static CString +// Argument : LPCTSTR lpszFilePath + static CString GetFileName(LPCTSTR lpszFilePath); + + // just a helper for a various purposes + static const DWORD* GetCRCTable(); + // function for a VERY advanced use - you normally never need that + CZipStorage* GetStorage(){return &m_storage;} + +protected: + void EmptyPtrList(); + void CryptDecodeBuffer(DWORD uCount); + void CryptEncodeBuffer(); + void CryptEncode(char &c); + void CryptCryptHeader(long iCrc, CZipAutoBuffer& buf); + DWORD CryptCRC32(DWORD l, char c); + void CryptDecode(char &c); + char CryptDecryptByte(); + bool CryptCheck(); + void CryptUpdateKeys(char c); + void CryptInitKeys(); + CZipAutoBuffer m_pszPassword; + DWORD m_keys[3]; + + static int CompareWords(const void *pArg1, const void *pArg2); + bool IsDirectory(DWORD uAttr); + void DeleteInternal(WORD uIndex); + DWORD RemovePackedFile(DWORD uStartOffset, DWORD uEndOffset); + CZipFileHeader* CurrentFile(); + void CheckForError(int iErr); + CZipInternalInfo m_info; + CZipStorage m_storage; + CPtrList m_list; + static void* myalloc(void* opaque, UINT items, UINT size); + static void myfree(void* opaque, void* address); + enum {extract = -1, nothing, compress}; + // 0 - no file inside archive opened + // -1 - current opened for extract + // 1 - new opened for compression + char m_iFileOpened; + void ThrowError(int err); + CZipCentralDir m_centralDir; + static TCHAR m_gszCopyright[]; +}; + +#endif // !defined(AFX_ZIPARCHIVE_H__A7F528A6_1872_4071_BE66_D56CC2DDE0E6__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipArchive.opt b/stepmania/src/smpackage/ZipArchive/ZipArchive.opt new file mode 100644 index 0000000000000000000000000000000000000000..fe0f7099462c190196c3db63663cf2d71a766375 GIT binary patch literal 48640 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 literal 0 HcmV?d00001 diff --git a/stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.cpp b/stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.cpp new file mode 100644 index 0000000000..1197be39c1 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.cpp @@ -0,0 +1,104 @@ +// ZipAutoBuffer.cpp: implementation of the CZipAutoBuffer class. +// Part of the ZipArchive library +// +// Copyright (C) 2000 - 2001 Tadeusz Dracz. +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// For the licensing details see the file License.txt +//////////////////////////////////////////////////////////////////////////////// + + +#include "stdafx.h" +#include "ZipAutoBuffer.h" +#include + +// #ifdef _DEBUG +// #undef THIS_FILE +// static char THIS_FILE[]=__FILE__; +// #define new DEBUG_NEW +// #endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CZipAutoBuffer::CZipAutoBuffer() +{ + m_iSize = 0; + m_pBuffer = NULL; +} + +CZipAutoBuffer::CZipAutoBuffer(DWORD iSize, bool bZeroMemory) +{ + m_iSize = 0; + m_pBuffer = NULL; + Allocate(iSize, bZeroMemory); +} + +CZipAutoBuffer::~CZipAutoBuffer() +{ + Release(); +} + + +void CZipAutoBuffer::Release() +{ + if (m_pBuffer) + { + delete [] m_pBuffer; + m_iSize = 0; + m_pBuffer = NULL; + } +} + +char* CZipAutoBuffer::Allocate(DWORD iSize, bool bZeroMemory) +{ + if (iSize != m_iSize) + Release(); + else + { + if (bZeroMemory) + memset(m_pBuffer, 0, iSize); // zerowanie bufora + return m_pBuffer; + } + + if (iSize > 0) + { + m_pBuffer = new char [iSize]; + if (bZeroMemory) + memset(m_pBuffer, 0, iSize); // zerowanie bufora + m_iSize = iSize; + } + else + m_pBuffer = NULL; + + return m_pBuffer; +} + + +CZipAutoBuffer::CZipAutoBuffer(const CZipAutoBuffer& buffer) +{ + m_pBuffer = NULL; + m_iSize = 0; + + if (buffer.m_pBuffer) + { + Allocate(buffer.m_iSize); + memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize); + } +} +CZipAutoBuffer& CZipAutoBuffer::operator=(const CZipAutoBuffer& buffer) +{ + if (this == &buffer) + return *this; + Release(); + if (buffer.m_pBuffer) + { + Allocate(buffer.m_iSize); + memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize); + } + return *this; +} \ No newline at end of file diff --git a/stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.h b/stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.h new file mode 100644 index 0000000000..404e6fb765 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipAutoBuffer.h @@ -0,0 +1,63 @@ +/** +* \file ZipAutoBuffer.h +* Interface for the CZipAutoBuffer class. +* +* \author Tadeusz Dracz +*/ +// Part of the ZipArchive library +// +// Copyright (C) 2000 - 2001 Tadeusz Dracz. +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// For the licensing details see the file License.txt +//////////////////////////////////////////////////////////////////////////////// + + +#if !defined(AFX_ZIPAUTOBUFFER_H__DEC28C20_83FE_11D3_B7C3_EDEC47A8A86C__INCLUDED_) +#define AFX_ZIPAUTOBUFFER_H__DEC28C20_83FE_11D3_B7C3_EDEC47A8A86C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +/** + A smart buffer freeing its contents on destruction. +*/ +class CZipAutoBuffer +{ +public: + operator char*() + { + return m_pBuffer; + } + + // may produce ambiguity on some compilers +// operator const char*() const +// { +// return m_pBuffer; +// } + const char* GetBuffer() const {return m_pBuffer;} + char* Allocate(DWORD iSize, bool bZeroMemory = false); + void Release(); + DWORD GetSize() const + { + return m_iSize; + } + bool IsAllocated() const + { + return (m_pBuffer != NULL); + } + CZipAutoBuffer(DWORD iSize, bool bZeroMemory = false); + CZipAutoBuffer(); + CZipAutoBuffer(const CZipAutoBuffer& buffer); + virtual ~CZipAutoBuffer(); + CZipAutoBuffer& operator=(const CZipAutoBuffer& buffer); +protected: + char* m_pBuffer; + DWORD m_iSize; +}; + +#endif // !defined(AFX_ZIPAUTOBUFFER_H__DEC28C20_83FE_11D3_B7C3_EDEC47A8A86C__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipBigFile.cpp b/stepmania/src/smpackage/ZipArchive/ZipBigFile.cpp new file mode 100644 index 0000000000..1239e8e355 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipBigFile.cpp @@ -0,0 +1,41 @@ +// ZipBigFile.cpp: implementation of the CZipBigFile class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ZipBigFile.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +IMPLEMENT_DYNAMIC(CZipBigFile, CFile) + +CZipBigFile::CZipBigFile() +{ + +} + +CZipBigFile::~CZipBigFile() +{ + +} + +_int64 CZipBigFile::Seek(_int64 dOff, UINT nFrom) +{ + ASSERT_VALID(this); + ASSERT(m_hFile != (UINT)hFileNull); + ASSERT(nFrom == begin || nFrom == end || nFrom == current); + ASSERT(begin == FILE_BEGIN && end == FILE_END && current == FILE_CURRENT); + LARGE_INTEGER li; + li.QuadPart = dOff; + + li.LowPart = ::SetFilePointer((HANDLE)m_hFile, li.LowPart, &li.HighPart, (DWORD)nFrom); + DWORD dw = GetLastError(); + if ((li.LowPart == (DWORD)-1) && (dw != NO_ERROR)) + { + CFileException::ThrowOsError((LONG)dw); + } + + return li.QuadPart; + +} diff --git a/stepmania/src/smpackage/ZipArchive/ZipBigFile.h b/stepmania/src/smpackage/ZipArchive/ZipBigFile.h new file mode 100644 index 0000000000..3790dd3c56 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipBigFile.h @@ -0,0 +1,22 @@ +// ZipBigFile.h: interface for the CZipBigFile class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_ZipBigFile_H__79E0E6BD_25D6_4B82_85C5_AB397D9EC368__INCLUDED_) +#define AFX_ZipBigFile_H__79E0E6BD_25D6_4B82_85C5_AB397D9EC368__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CZipBigFile : public CFile +{ + DECLARE_DYNAMIC(CZipBigFile) +public: + _int64 Seek(_int64 dOff, UINT nFrom); + CZipBigFile(); + virtual ~CZipBigFile(); + +}; + +#endif // !defined(AFX_ZipBigFile_H__79E0E6BD_25D6_4B82_85C5_AB397D9EC368__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipCentralDir.cpp b/stepmania/src/smpackage/ZipArchive/ZipCentralDir.cpp new file mode 100644 index 0000000000..012c21ab79 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipCentralDir.cpp @@ -0,0 +1,677 @@ +// ZipCentralDir.cpp: implementation of the CZipCentralDir class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + + +#include "stdafx.h" +#include "ZipCentralDir.h" +#include "ZipArchive.h" + +struct CZipAutoHandle +{ + HANDLE m_hFileMap; + LPVOID m_pFileMap; + CZipAutoHandle() + { + m_hFileMap = NULL; + m_pFileMap = NULL; + } + bool CreateMapping(HANDLE hFile) + { + m_hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, + 0, 0, _T("ZipArchive Mapping File")); + if (!m_hFileMap) + return false; + // Get pointer to memory representing file + m_pFileMap = MapViewOfFile(m_hFileMap, FILE_MAP_WRITE, 0, 0, 0); + return (m_pFileMap != NULL); + } + void RemoveMapping() + { + if (m_pFileMap) + { + UnmapViewOfFile(m_pFileMap); + m_pFileMap = NULL; + } + if (m_hFileMap) + { + CloseHandle(m_hFileMap); + m_hFileMap = NULL; + } + + } + ~CZipAutoHandle() + { + RemoveMapping(); + } +}; + +#define ZIPCENTRALDIRSIZE 22 + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +char CZipCentralDir::m_gszSignature[] = {0x50, 0x4b, 0x05, 0x06}; +CZipCentralDir::CZipCentralDir() +{ + m_bConvertAfterOpen = true; + m_bFindFastEnabled = false; + m_pStorage = NULL; + m_pOpenedFile = NULL; + m_iBufferSize = 32768; + +} + +void CZipCentralDir::Init() +{ + m_bOnDisk = false; + m_uBytesBeforeZip = m_uCentrDirPos = 0; + m_pOpenedFile = NULL; + m_pszComment.Release(); +} + +CZipCentralDir::~CZipCentralDir() +{ + Clear(); +} + +void CZipCentralDir::Read() +{ + ASSERT(m_pStorage); + WORD uCommentSize; + m_uCentrDirPos = Locate(); + m_pStorage->m_pFile->Seek(m_uCentrDirPos, CFile::begin); + CZipAutoBuffer buf(ZIPCENTRALDIRSIZE); + DWORD uRead = m_pStorage->m_pFile->Read(buf, ZIPCENTRALDIRSIZE ); + if (uRead != ZIPCENTRALDIRSIZE) + ThrowError(ZIP_BADZIPFILE); + memcpy(&m_szSignature, buf, 4); + memcpy(&m_uThisDisk, buf + 4, 2); + memcpy(&m_uDiskWithCD, buf + 6, 2); + memcpy(&m_uDiskEntriesNo, buf + 8, 2); + memcpy(&m_uEntriesNumber, buf + 10, 2); + memcpy(&m_uSize, buf + 12, 4); + memcpy(&m_uOffset, buf + 16, 4); + memcpy(&uCommentSize, buf + 20, 2); + buf.Release(); + + + m_pStorage->UpdateSpanMode(m_uThisDisk); + // if m_uThisDisk is not zero, it is enough to say that it is multi archive + ASSERT((!m_uThisDisk && (m_uEntriesNumber == m_uDiskEntriesNo) && !m_uDiskWithCD) || m_uThisDisk); + + + + if (!m_pStorage->IsSpanMode() && ((DWORD)m_uCentrDirPos < m_uOffset + m_uSize)) + ThrowError(ZIP_BADZIPFILE); + + if (uCommentSize) + { + m_pszComment.Allocate(uCommentSize); + uRead = m_pStorage->m_pFile->Read(m_pszComment, uCommentSize); + if (uRead != uCommentSize) + ThrowError(ZIP_BADZIPFILE); + } + + m_uBytesBeforeZip = m_pStorage->IsSpanMode() ? 0 : m_uCentrDirPos - m_uSize - m_uOffset; + + if ((!m_uSize && m_uEntriesNumber) || (!m_uEntriesNumber && m_uSize)) + ThrowError(ZIP_BADZIPFILE); + + m_bOnDisk = true; + m_pStorage->ChangeDisk(m_uDiskWithCD); + + if (!m_uSize) + return; + + ReadHeaders(); +} + +// return the location of the beginning of the "end" record in the file +DWORD CZipCentralDir::Locate() +{ + + // maximum size of end of central dir record + long uMaxRecordSize = 0xffff + ZIPCENTRALDIRSIZE; + DWORD uFileSize = m_pStorage->m_pFile->GetLength(); + + if ((DWORD)uMaxRecordSize > uFileSize) + uMaxRecordSize = uFileSize; + + CZipAutoBuffer buf(m_iBufferSize); + + long uPosInFile = 0; + int uRead = 0; + // backward reading + while (uPosInFile < uMaxRecordSize) + { + uPosInFile = uRead + m_iBufferSize; + if (uPosInFile > uMaxRecordSize) + uPosInFile = uMaxRecordSize; + + int iToRead = uPosInFile - uRead; + + m_pStorage->m_pFile->Seek(-uPosInFile, CFile::end); + int iActuallyRead = m_pStorage->m_pFile->Read(buf, iToRead); + if (iActuallyRead != iToRead) + ThrowError(ZIP_BADZIPFILE); + // search from the very last bytes to prevent an error if inside archive + // there are packed other arhives + for (int i = iToRead - 4; i >=0 ; i--) + if (!memcmp((char*)buf + i, m_gszSignature, 4)) + return uFileSize - (uPosInFile - i); + + uRead += iToRead - 3; + + } + + ThrowError(ZIP_CDIR_NOTFOUND); + return 0; +} + +void CZipCentralDir::ThrowError(int err) +{ + AfxThrowZipException(err, m_pStorage->m_pFile->GetFilePath()); +} + + +void CZipCentralDir::ReadHeaders() +{ + m_pStorage->m_pFile->Seek(m_uOffset + m_uBytesBeforeZip, CFile::begin); + RemoveHeaders(); + for (int i = 0; i < m_uEntriesNumber; i++) + { + CZipFileHeader* pHeader = new CZipFileHeader; + m_headers.Add(pHeader); // bezpoœrednio nastêpuje w razie wyj¹tku + + if (!pHeader->Read(m_pStorage)) + ThrowError(ZIP_BADZIPFILE); + ConvertFileName(true, true, pHeader); + } + if (m_bFindFastEnabled) + BuildFindFastArray(); + +} + +// remove all headers from the central dir +void CZipCentralDir::Clear(bool bEverything) +{ + m_pOpenedFile = NULL; + m_pLocalExtraField.Release(); + + if (bEverything) + { + RemoveHeaders(); + m_findarray.RemoveAll(); + m_pszComment.Release(); + + } +} + + +bool CZipCentralDir::IsValidIndex(WORD uIndex) +{ + + bool ret = uIndex < m_headers.GetSize(); +#ifdef _DEBUG + if (!ret) + TRACE(_T("Not a valid index.\n")); +#endif + return ret; +} + +// open the file for extracting +void CZipCentralDir::OpenFile(WORD uIndex) +{ + WORD uLocalExtraFieldSize; + m_pOpenedFile = m_headers[uIndex]; + m_pStorage->ChangeDisk(m_pOpenedFile->m_uDiskStart); + m_pStorage->m_pFile->Seek(m_pOpenedFile->m_uOffset + m_uBytesBeforeZip, CFile::begin); + if (!m_pOpenedFile->ReadLocal(m_pStorage, uLocalExtraFieldSize)) + ThrowError(ZIP_BADZIPFILE); + + + m_pLocalExtraField.Release(); // just in case + if (uLocalExtraFieldSize) + { + int iCurrDsk = m_pStorage->GetCurrentDisk(); + m_pLocalExtraField.Allocate(uLocalExtraFieldSize); + m_pStorage->Read(m_pLocalExtraField, uLocalExtraFieldSize, true); + if (m_pStorage->GetCurrentDisk() != iCurrDsk) + ThrowError(ZIP_BADZIPFILE); + } + +} + +void CZipCentralDir::CloseFile() +{ + if (!m_pOpenedFile) + return; + m_pLocalExtraField.Release(); + if (m_pOpenedFile->IsDataDescr()) + { + CZipAutoBuffer buf(12); + m_pStorage->Read(buf, 4, false); + // in span mode, files that are divided between disks have bit 3 of flag set + // which tell about the presence of the data descriptor after the compressed data + // This signature may be in the disk spanning archive that is one volume only + // (it is detected as a non disk spanning archive) + if (memcmp(buf, CZipStorage::m_gszExtHeaderSignat, 4) != 0) // there is no signature + m_pStorage->m_pFile->Seek(-4, CFile::current); + + + m_pStorage->Read(buf, 12, false); + if (!m_pOpenedFile->CheckCrcAndSizes(buf)) + ThrowError(ZIP_BADZIPFILE); + } + m_pOpenedFile = NULL; +} + +// add new header using the argument as a template +void CZipCentralDir::AddNewFile(CZipFileHeader & header) +{ + CZipFileHeader* pHeader = new CZipFileHeader(header); + m_pOpenedFile = pHeader; + m_headers.Add(pHeader); + if (m_bFindFastEnabled) + InsertFindFastElement(pHeader, WORD(m_headers.GetSize() - 1)); // GetSize IS > 0, 'cos we've just added a header + RemoveFromDisk(); + m_pStorage->m_pFile->SeekToEnd(); +} + +// called during adding or deleting files; remove the central dir from the disk +void CZipCentralDir::RemoveFromDisk() +{ + if (m_bOnDisk) + { + ASSERT(!m_pStorage->IsSpanMode()); // you can't add files to the existing disk span archive or to delete them from it + m_pStorage->m_pFile->SetLength(m_uBytesBeforeZip + m_uOffset); + m_bOnDisk = false; + } +} + + +void CZipCentralDir::CloseNewFile() +{ + CZipAutoBuffer buf(12 + 4); + short iToWrite = 0; + bool bIsSpan = m_pStorage->IsSpanMode() != 0; + bool bEncrypted = m_pOpenedFile->IsEncrypted(); + if (m_pOpenedFile->IsDataDescr()) + { + if (bIsSpan || bEncrypted) + { + memcpy(buf, m_pStorage->m_gszExtHeaderSignat, 4); + iToWrite += 4; + } + } + else /*if (!IsSpan)*/ + { + ASSERT(!bIsSpan && !bEncrypted); + m_pStorage->Flush(); + m_pStorage->m_pFile->Seek(m_pOpenedFile->m_uOffset + 14, CFile::begin); + // we don't have to restore the pointer, because before adding a new file, + // the pointer is moved to the end + } + + m_pOpenedFile->GetCrcAndSizes(buf + iToWrite); + iToWrite += 12; + + // offset set during writting the local header + m_pOpenedFile->m_uOffset -= m_uBytesBeforeZip; + + // write the data descriptor and a disk spanning signature at once + m_pStorage->Write(buf, iToWrite, true); + if (!bIsSpan && bEncrypted) + { + // write the information to the local header too + m_pStorage->Flush(); + m_pStorage->m_pFile->Seek(m_pOpenedFile->m_uOffset + 14, CFile::begin); + m_pStorage->Write(buf + 4, 12, true); + } + + if (!bIsSpan) + m_pStorage->Flush(); + + m_pOpenedFile = NULL; + +} + +void CZipCentralDir::Write() +{ + if (m_bOnDisk) + return; + if (!m_pStorage->IsSpanMode()) + { + m_pStorage->Flush(); + m_pStorage->m_pFile->SeekToEnd(); + } + m_uEntriesNumber = (WORD)m_headers.GetSize(); + m_uSize = 0; + bool bDontAllowDiskChange = false; + // if there is a disk spanning archive in creation and it is only one-volume, + // (current disk is 0 so far, no bytes has been written so we know they are + // all in the buffer) make sure that it will be after writting central dir + // and make it a non disk spanning archive + if (m_pStorage->IsSpanMode() && m_pStorage->GetCurrentDisk() == 0) + { + DWORD uVolumeFree = m_pStorage->VolumeLeft(); + // calculate the size of data descriptors already in the buffer or on the disk + // (they will be removed in the non disk spanning archive): + // multi span signature at the beginnig (4 bytes) + the size of the data + // descr. for each file (multi span signature + 12 bytes data) + // the count of bytes to add: central dir size - total to remove; + DWORD uToGrow = GetSize(true) - (4 + m_uEntriesNumber * (4 + 12)); + if (uVolumeFree >= uToGrow) + // lets make sure it will be one-disk archive + { + // can the operation be done only in the buffer? + if (!m_pStorage->m_iBytesWritten && // no bytes on the disk yet + (m_pStorage->GetFreeInBuffer() >= uToGrow)) // is the buffer big enough? + { + RemoveDataDescr(true); + bDontAllowDiskChange = true; // if the disk change occurs somehow, we'll throw an error later + } + else + { + m_pStorage->Flush(); + m_pStorage->m_pFile->Flush(); + if (RemoveDataDescr(false)) + bDontAllowDiskChange = true; // if the disk change occurs somehow, we'll throw an error later + } + } + } + + WriteHeaders(); + m_uThisDisk = (WORD)m_pStorage->GetCurrentDisk(); + DWORD uSize = WriteCentralEnd(); + if (bDontAllowDiskChange && (m_pStorage->GetCurrentDisk() != 0)) + ThrowError(ZIP_BADZIPFILE); + // if after adding a central directory there is a disk change, + // update the information and write it again + if (m_uThisDisk != m_pStorage->GetCurrentDisk()) + { + m_uThisDisk = (WORD)m_pStorage->GetCurrentDisk(); + if (m_uEntriesNumber) + { + m_uDiskEntriesNo = 0; + } + else + { + m_uDiskWithCD = m_uThisDisk; + m_uOffset = 0; + } + + if (m_pStorage->m_uBytesInWriteBuffer >= uSize) + // if the data is still in the buffer, simply remove it + m_pStorage->m_uBytesInWriteBuffer -= uSize; + else + { + m_pStorage->Flush(); + m_pStorage->m_iBytesWritten -= uSize; + m_pStorage->m_pFile->SeekToBegin(); + } + + WriteCentralEnd(); + } + +} + +void CZipCentralDir::WriteHeaders() +{ + m_uDiskEntriesNo = 0; + m_uDiskWithCD = (WORD)m_pStorage->GetCurrentDisk(); + m_uOffset = m_pStorage->GetPosition() - m_uBytesBeforeZip; + if (!m_uEntriesNumber) + return; + + WORD iDisk = m_uDiskWithCD; + for (int i = 0; i < m_uEntriesNumber; i++) + { + CZipFileHeader* pHeader = m_headers[i]; + ConvertFileName(false, true, pHeader); + m_uSize += pHeader->Write(m_pStorage); + if (m_pStorage->GetCurrentDisk() != iDisk) + { + m_uDiskEntriesNo = 1; + iDisk = (WORD)m_pStorage->GetCurrentDisk(); + // update the information about the offset and starting disk if the + // first header was written on the new disk + if (i == 0) + { + m_uOffset = 0; + m_uDiskWithCD = iDisk; + } + } + else + m_uDiskEntriesNo++; + } +} + +DWORD CZipCentralDir::WriteCentralEnd() +{ + DWORD uSize = GetSize(); + CZipAutoBuffer buf(uSize); + WORD uCommentSize = (WORD)m_pszComment.GetSize(); + memcpy(buf, m_gszSignature, 4); + memcpy(buf + 4, &m_uThisDisk, 2); + memcpy(buf + 6, &m_uDiskWithCD, 2); + memcpy(buf + 8, &m_uDiskEntriesNo, 2); + memcpy(buf + 10, &m_uEntriesNumber, 2); + memcpy(buf + 12, &m_uSize, 4); + memcpy(buf + 16, &m_uOffset, 4); + memcpy(buf + 20, &uCommentSize, 2); + memcpy(buf + 22, m_pszComment, uCommentSize); + m_pStorage->Write(buf, uSize, true); + return uSize; +} + + +void CZipCentralDir::RemoveFile(WORD uIndex) +{ + CZipFileHeader* pHeader = m_headers[uIndex]; + if (m_bFindFastEnabled) + { + int i = FindFileNameIndex(pHeader->GetFileName(), true); + ASSERT(i != -1); + int uIndex = m_findarray[i].m_uIndex; + m_findarray.RemoveAt(i); + // shift down the indexes + for (int j = 0; j < m_findarray.GetSize(); j++) + { + if (m_findarray[j].m_uIndex > uIndex) + m_findarray[j].m_uIndex--; + } + } + delete pHeader; + m_headers.RemoveAt(uIndex); +} + + +DWORD CZipCentralDir::GetSize(bool bWhole) +{ + DWORD uHeaders = 0; + if (bWhole) + { + for (int i = 0; i < m_headers.GetSize(); i++) + uHeaders += m_headers[i]->GetSize(); + } + return ZIPCENTRALDIRSIZE + m_pszComment.GetSize() + uHeaders; +} + +// remove data descriptors from the write buffer in the disk spanning volume +// that is one-disk only (do not remove from password encrypted files) +bool CZipCentralDir::RemoveDataDescr(bool bFromBuffer) +{ + CZipAutoHandle ah; + char* pFile = NULL; + DWORD uSize; + if (bFromBuffer) + { + uSize = m_pStorage->m_uBytesInWriteBuffer; + pFile = m_pStorage->m_pWriteBuffer; + } + else + { + uSize = m_pStorage->m_pFile->GetLength(); + if (!ah.CreateMapping((HANDLE)m_pStorage->m_pFile->m_hFile)) + return false; + pFile = (char*)ah.m_pFileMap; + } + + DWORD uOffsetToChange = 4; + DWORD uToCopy = 0; + DWORD uPosInBuffer = 0; + DWORD uExtraHeaderLen; + // this will work providing the order in the m_headers is the same as + // in the archive + for (int i = 0; i < m_headers.GetSize(); i++) + { + // update the flag value in the local and central header +// int uDataDescr = (m_headers[i]->m_uFlag & 8) ? (4 + 12) : 0; + + CZipFileHeader* pHeader = m_headers[i]; + + + char* pSour = pFile + pHeader->m_uOffset; + + if (!pHeader->IsEncrypted()) + { + // removing data descriptor + pHeader->m_uFlag &= ~8; + // update local header: + // write modified flag in the local header + memcpy(pSour + 6, &pHeader->m_uFlag, 2); + uExtraHeaderLen = 4/*ext. header signature*/ + 12/*data descriptor*/; + } + else + // do not remove data descriptors from encrypted files + uExtraHeaderLen = 0; + + // update crc32 and sizes' values + pHeader->GetCrcAndSizes(pSour+ 14); + + uToCopy = (i == (m_headers.GetSize() - 1) ? uSize : m_headers[i + 1]->m_uOffset) + - pHeader->m_uOffset - uExtraHeaderLen; + + memmove(pFile + uPosInBuffer, pSour, uToCopy); + + uPosInBuffer += uToCopy; + pHeader->m_uOffset -= uOffsetToChange; + uOffsetToChange += uExtraHeaderLen; + } + + if (bFromBuffer) + m_pStorage->m_uBytesInWriteBuffer = uPosInBuffer; + else + { + m_pStorage->m_iBytesWritten = uPosInBuffer; + ah.RemoveMapping(); + m_pStorage->m_pFile->SetLength(uPosInBuffer); + } + return true; +} + +void CZipCentralDir::RemoveHeaders() +{ + for (int i = 0; i < m_headers.GetSize(); i++) + delete m_headers[i]; + m_headers.RemoveAll(); +} + +void CZipCentralDir::ConvertAll() +{ + ASSERT(!m_bConvertAfterOpen); + for (int i = 0; i < m_headers.GetSize(); i++) + ConvertFileName(true, false, m_headers[i]); + m_bConvertAfterOpen = true; +} + + +void CZipCentralDir::BuildFindFastArray() +{ + m_findarray.RemoveAll();// just in case + for (int i = 0; i < m_headers.GetSize(); i++) + InsertFindFastElement(m_headers[i], (WORD)i); +} + +void CZipCentralDir::InsertFindFastElement(CZipFileHeader* pHeader, WORD uIndex) +{ + CString fileName = pHeader->GetFileName(); + + + int iSize = m_findarray.GetSize(); + + // Our initial binary search range encompasses the entire array of filenames: + int start = 0; + int end = iSize; + + // Keep halving our search range until we find the right place + // to insert the new element: + while ( start < end ) + { + // Find the midpoint of the search range: + int midpoint = ( start + end ) / 2; + + // Compare the filename with the filename at the midpoint of the current search range: + int result = CompareElement(fileName, (WORD)midpoint, true); + + // If our filename is larger, it must fall in the first half of the search range: + if ( result > 0 ) + { + end = midpoint; + } + + // If it's smaller, it must fall in the last half: + else if ( result < 0 ) + { + start = midpoint + 1; + } + + // If they're equal, we can go ahead and insert here: + else + { + start = midpoint; break; + } + } + m_findarray.InsertAt(start, CZipFindFast(pHeader, WORD(uIndex == -1 ? iSize : uIndex /* just in case */))); +} + +int CZipCentralDir::FindFileNameIndex(LPCTSTR lpszFileName, bool bCaseSensitive) +{ + int start = 0; + int end = m_findarray.GetUpperBound(); + + // Keep halving our search range until we find the given element: + while ( start <= end ) + { + // Find the midpoint of the search range: + int midpoint = ( start + end ) / 2; + + // Compare the given filename with the filename at the midpoint of the search range: + int result = CompareElement(lpszFileName, (WORD)midpoint, bCaseSensitive); + + // If our filename is smaller, it must fall in the first half of the search range: + if ( result > 0 ) + { + end = midpoint - 1; + } + + // If it's larger, it must fall in the last half: + else if ( result < 0 ) + { + start = midpoint + 1; + } + + // If they're equal, return the result: + else + { + return midpoint; + } + } + + // Signal failure: + return -1; +} diff --git a/stepmania/src/smpackage/ZipArchive/ZipCentralDir.h b/stepmania/src/smpackage/ZipArchive/ZipCentralDir.h new file mode 100644 index 0000000000..25170ee5d0 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipCentralDir.h @@ -0,0 +1,156 @@ +// ZipCentralDir.h: interface for the CZipCentralDir class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_ZipCentralDir_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_) +#define AFX_ZipCentralDir_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include "ZipException.h" +#include +#include "ZipFileHeader.h" +#include "ZipAutoBuffer.h" + +/** + Used in fast finding files by the filename. + \see CZipCentralDir::m_findarray + \see CZipArchive::FindFile +*/ +struct CZipFindFast +{ + CZipFindFast() + { + m_uIndex = 0; + m_pHeader= NULL; + } + CZipFindFast(CZipFileHeader* pHeader, WORD uIndex):m_pHeader(pHeader), m_uIndex(uIndex){} + /** + We extract a name from it. + */ + CZipFileHeader* m_pHeader; + + /** + The index in the central directory of the \e m_pHeader. + */ + WORD m_uIndex; +}; + + +class CZipCentralDir +{ + +public: + +// end of central dir signature 4 bytes (0x06054b50) + char m_szSignature[4]; +// number of this disk 2 bytes + WORD m_uThisDisk; +// number of the disk with the +// start of the central directory 2 bytes + WORD m_uDiskWithCD; +// total number of entries in +// the central dir on this disk 2 bytes + WORD m_uDiskEntriesNo; +// total number of entries in +// the central dir 2 bytes + WORD m_uEntriesNumber; +// size of the central directory 4 bytes + DWORD m_uSize; +// offset of start of central +// directory with respect to +// the starting disk number 4 bytes + DWORD m_uOffset; +// zipfile comment length 2 bytes +// WORD m_uCommentSize; +// zipfile comment (variable size) + CZipAutoBuffer m_pszComment; + bool m_bFindFastEnabled; + CZipFileHeader* m_pOpenedFile; + void RemoveFile(WORD uIndex); + void Clear(bool bEverything = true); + CZipStorage* m_pStorage; + DWORD m_uCentrDirPos; + DWORD m_uBytesBeforeZip; + CZipCentralDir(); + virtual ~CZipCentralDir(); + void CloseFile(); + void OpenFile(WORD uIndex); + bool IsValidIndex(WORD uIndex); + void Read(); + void Init(); + void CloseNewFile(); + void Write(); + int m_iBufferSize; + bool m_bOnDisk; + static char m_gszSignature[]; + CTypedPtrArray m_headers; + CZipAutoBuffer m_pLocalExtraField; + void AddNewFile(CZipFileHeader & header); + void RemoveFromDisk(); + DWORD GetSize(bool bWhole = false); + CArray m_findarray; + int FindFileNameIndex(LPCTSTR lpszFileName, bool bCaseSensitive); + void BuildFindFastArray(); + /** + - If \c true, the conversion of the filenames takes + place after opening the archive (after reading the central directory + from the file), and before writing the central directory back to + the archive. + - If \c false, the conversion takes place on each call to CZipArchive::GetFileInfo + + Set it to \c true when you plan to use CZipArchive::FindFile or get the stored files information.
    + Set it to \c false when you plan mostly to only modify the archive. + + \b Default: \c true + \note Set it before opening the archive. + \see ConvertFileName + */ + bool m_bConvertAfterOpen; + +/** + Convert the filename of the CZipFileHeader. + \param bFromZip + if \c true, convert from archive format + \param bAfterOpen + if \c true, called after opening the archive or before closing + \param pHeader + the header to have filename converted; if \c NULL convert the currently + opened file + \see m_bConvertAfterOpen +*/ + void ConvertFileName(bool bFromZip, bool bAfterOpen, CZipFileHeader* pHeader = NULL) + { + if (bAfterOpen != m_bConvertAfterOpen) + return; + if (!pHeader) + { + pHeader = m_pOpenedFile; + ASSERT(pHeader); + } + pHeader->AnsiOem(!bFromZip); + pHeader->SlashChange(bFromZip); + } + void ConvertAll(); +protected: + void InsertFindFastElement(CZipFileHeader* pHeader, WORD uIndex); + void RemoveHeaders(); + bool RemoveDataDescr(bool bFromBuffer); + DWORD WriteCentralEnd(); + void WriteHeaders(); + void ReadHeaders(); + void ThrowError(int err); + DWORD Locate(); + int CompareElement(LPCTSTR lpszFileName, WORD uIndex, bool bCaseSensitive) + { + return bCaseSensitive ? m_findarray[uIndex].m_pHeader->GetFileName().Collate(lpszFileName) + : m_findarray[uIndex].m_pHeader->GetFileName().CollateNoCase(lpszFileName); + } + +}; + +#endif // !defined(AFX_ZipCentralDir_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipException.cpp b/stepmania/src/smpackage/ZipArchive/ZipException.cpp new file mode 100644 index 0000000000..e9e43fe6a6 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipException.cpp @@ -0,0 +1,78 @@ +// ZipException.cpp: implementation of the CZipException class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ZipException.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +IMPLEMENT_DYNAMIC( CZipException, CException) + +CZipException::CZipException(int iCause, LPCTSTR lpszZipName):CException(TRUE) +{ + m_iCause = iCause; + + if (lpszZipName) + m_szFileName = lpszZipName; +} + +CZipException::~CZipException() +{ + +} + +void AfxThrowZipException(int iZipError, LPCTSTR lpszZipName) +{ + throw new CZipException(CZipException::ZipErrToCause(iZipError), lpszZipName); +} + +int CZipException::ZipErrToCause(int iZipError) +{ + switch (iZipError) + { + case 2://Z_NEED_DICT: + return CZipException::needDict; + case 1://Z_STREAM_END: + return CZipException::streamEnd; + case -1://Z_ERRNO: + return CZipException::errNo; + case -2://Z_STREAM_ERROR: + return CZipException::streamError; + case -3://Z_DATA_ERROR: + return CZipException::dataError; + case -4://Z_MEM_ERROR: + return CZipException::memError; + case -5://Z_BUF_ERROR: + return CZipException::bufError; + case -6://Z_VERSION_ERROR: + return CZipException::versionError; + case ZIP_BADZIPFILE: + return CZipException::badZipFile; + case ZIP_BADCRC: + return CZipException::badCrc; + case ZIP_ABORTED: + return CZipException::aborted; + case ZIP_NOCALLBACK: + return CZipException::noCallback; + case ZIP_NONREMOVABLE: + return CZipException::nonRemovable; + case ZIP_TOOMANYVOLUMES: + return CZipException::tooManyVolumes; + case ZIP_TOOLONGFILENAME: + return CZipException::tooLongFileName; + case ZIP_BADPASSWORD: + return CZipException::badPassword; + case ZIP_CDIR_NOTFOUND: + return CZipException::cdirNotFound; + + + default: + return CZipException::generic; + } + +} diff --git a/stepmania/src/smpackage/ZipArchive/ZipException.h b/stepmania/src/smpackage/ZipArchive/ZipException.h new file mode 100644 index 0000000000..93640ca030 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipException.h @@ -0,0 +1,71 @@ +// ZipException.h: interface for the CZipException class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_ZIPEXCEPTION_H__E3546921_D728_11D3_B7C7_E77339672847__INCLUDED_) +#define AFX_ZIPEXCEPTION_H__E3546921_D728_11D3_B7C7_E77339672847__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +typedef unsigned short uShort; +// errors number definitions +#define ZIP_BADZIPFILE (-101) +#define ZIP_BADCRC (-102) +#define ZIP_NOCALLBACK (-103) +#define ZIP_ABORTED (-104) +#define ZIP_NONREMOVABLE (-105) +#define ZIP_TOOMANYVOLUMES (-106) +#define ZIP_TOOLONGFILENAME (-107) +#define ZIP_BADPASSWORD (-108) +#define ZIP_CDIR_NOTFOUND (-109) + +class CZipException : public CException +{ +public: + DECLARE_DYNAMIC(CZipException) + // convert zlib library and internal error code to a ZipException code + static int ZipErrToCause(int iZipError); + // name of the zip file where the error occured + CString m_szFileName; + + enum + { + noError, // no error + generic, // unknown error + streamEnd, // zlib library errors + needDict, // + errNo, // + streamError, // + dataError, // + memError, // + bufError, // + versionError, // + badZipFile, // damaged or not a zip file + badCrc, // crc mismatched + noCallback, // no callback function set + aborted, // disk change callback function returned false + nonRemovable, // the disk selected for pkSpan archive is non removable + tooManyVolumes, // limit of the maximum volumes reached (999) + tooLongFileName, // the file name of the file added to the archive is too long + badPassword, // incorrect password set for the file being decrypted + cdirNotFound, ///< the central directory was not found in the archive + dirWithSize // during testing: found the directory with the size greater than 0 + }; + // cause - takes one of the codes above + int m_iCause; + CZipException(int iCause = generic, LPCTSTR lpszZipName = NULL); + virtual ~CZipException(); + +}; + +// throw zip exception +// Parameters: +// iZipError - zlib or internal error code +// lpszZipName - name of the file where the error occured +void AfxThrowZipException(int iZipError = 1000, LPCTSTR lpszZipName = NULL); + +#endif // !defined(AFX_ZIPEXCEPTION_H__E3546921_D728_11D3_B7C7_E77339672847__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipFileHeader.cpp b/stepmania/src/smpackage/ZipArchive/ZipFileHeader.cpp new file mode 100644 index 0000000000..5487e02d44 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipFileHeader.cpp @@ -0,0 +1,329 @@ +// ZipFileHeader.cpp: implementation of the CZipFileHeader class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ZipFileHeader.h" +#include "zlib.h" +#include "ZipAutoBuffer.h" +#include "ZipArchive.h" + +#define ZipFileHeaderSIZE 46 +#define LOCALZipFileHeaderSIZE 30 +#define VERSIONMADEBY 20 +#define ENCR_HEADER_LEN 12 +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +char CZipFileHeader::m_gszSignature[] = {0x50, 0x4b, 0x01, 0x02}; +char CZipFileHeader::m_gszLocalSignature[] = {0x50, 0x4b, 0x03, 0x04}; +CZipFileHeader::CZipFileHeader() +{ + m_uExternalAttr = FILE_ATTRIBUTE_ARCHIVE; + m_uModDate = m_uModTime = m_uInternalAttr = 0; + m_uMethod = Z_DEFLATED; +} + +CZipFileHeader::~CZipFileHeader() +{ + +} + +// read the header from the central dir +bool CZipFileHeader::Read(CZipStorage *pStorage) +{ +// // just in case +// m_pszComment.Release(); +// m_pszFileName.Release(); + WORD uFileNameSize, uCommentSize, uExtraFieldSize; + CZipAutoBuffer buf(ZipFileHeaderSIZE); + pStorage->Read(buf, ZipFileHeaderSIZE, true); + memcpy(&m_szSignature, buf, 4); + memcpy(&m_uVersionMadeBy, buf + 4, 2); + memcpy(&m_uVersionNeeded, buf + 6, 2); + memcpy(&m_uFlag, buf + 8, 2); + memcpy(&m_uMethod, buf + 10, 2); + memcpy(&m_uModTime, buf + 12, 2); + memcpy(&m_uModDate, buf + 14, 2); + memcpy(&m_uCrc32, buf + 16, 4); + memcpy(&m_uComprSize, buf + 20, 4); + memcpy(&m_uUncomprSize, buf + 24, 4); + memcpy(&uFileNameSize, buf + 28, 2); + memcpy(&uExtraFieldSize, buf + 30, 2); + memcpy(&uCommentSize, buf + 32, 2); + memcpy(&m_uDiskStart, buf + 34, 2); + memcpy(&m_uInternalAttr, buf + 36, 2); + memcpy(&m_uExternalAttr, buf + 38, 4); + memcpy(&m_uOffset, buf + 42, 4); + buf.Release(); + + if (memcmp(m_szSignature, m_gszSignature, 4) != 0) + return false; + + int iCurDsk = pStorage->GetCurrentDisk(); + m_pszFileName.Allocate(uFileNameSize); // don't add NULL at the end + pStorage->m_pFile->Read(m_pszFileName, uFileNameSize); + if (uExtraFieldSize) + { + ASSERT(!m_pExtraField.IsAllocated()); + m_pExtraField.Allocate(uExtraFieldSize); + pStorage->m_pFile->Read(m_pExtraField, uExtraFieldSize); + } + if (uCommentSize) + { + m_pszComment.Allocate(uCommentSize); + pStorage->m_pFile->Read(m_pszComment, uCommentSize); + } + + return pStorage->GetCurrentDisk() == iCurDsk; // check that the while header is on the one disk +} + +// return CTime representation of m_uModDate, m_uModTime +CTime CZipFileHeader::GetTime() +{ + return CTime(m_uModDate, m_uModTime); +} + +// write the header to the central dir +DWORD CZipFileHeader::Write(CZipStorage *pStorage) +{ + WORD uFileNameSize = GetFileNameSize(), uCommentSize = GetCommentSize(), + uExtraFieldSize = GetExtraFieldSize(); + DWORD iSize = GetSize(); + CZipAutoBuffer buf(iSize); + memcpy(buf, &m_szSignature, 4); + memcpy(buf + 4, &m_uVersionMadeBy, 2); + memcpy(buf + 6, &m_uVersionNeeded, 2); + memcpy(buf + 8, &m_uFlag, 2); + memcpy(buf + 10, &m_uMethod, 2); + memcpy(buf + 12, &m_uModTime, 2); + memcpy(buf + 14, &m_uModDate, 2); + memcpy(buf + 16, &m_uCrc32, 4); + memcpy(buf + 20, &m_uComprSize, 4); + memcpy(buf + 24, &m_uUncomprSize, 4); + memcpy(buf + 28, &uFileNameSize, 2); + memcpy(buf + 30, &uExtraFieldSize, 2); + memcpy(buf + 32, &uCommentSize, 2); + memcpy(buf + 34, &m_uDiskStart, 2); + memcpy(buf + 36, &m_uInternalAttr, 2); + memcpy(buf + 38, &m_uExternalAttr, 4); + memcpy(buf + 42, &m_uOffset, 4); + + memcpy(buf + 46, m_pszFileName, uFileNameSize); + + if (uExtraFieldSize) + memcpy(buf + 46 + uFileNameSize, m_pExtraField, uExtraFieldSize); + + if (uCommentSize) + memcpy(buf + 46 + uFileNameSize + uExtraFieldSize, m_pszComment, uCommentSize); + + pStorage->Write(buf, iSize, true); + return iSize; +} + +// read local header +bool CZipFileHeader::ReadLocal(CZipStorage *pStorage, WORD& iLocExtrFieldSize) +{ + char buf[LOCALZipFileHeaderSIZE]; + pStorage->Read(buf, LOCALZipFileHeaderSIZE, true); + if (memcmp(buf, m_gszLocalSignature, 4) != 0) + return false; + + bool bIsDataDescr = (((WORD)*(buf + 6)) & 8) != 0; + + WORD uFileNameSize = GetFileNameSize(); + if ((memcmp(buf + 6, &m_uFlag, 2) != 0) + ||(memcmp(buf + 8, &m_uMethod, 2) != 0) + || (m_uMethod && (m_uMethod != Z_DEFLATED)) + || (memcmp(buf + 26, &uFileNameSize, 2) != 0)) + return false; + +// jeszcze mo¿naby porównaæ nazwy plików + + if (!bIsDataDescr/* || !pStorage->IsSpanMode()*/) + if (!CheckCrcAndSizes(buf + 14)) + return false; + + memcpy(&iLocExtrFieldSize, buf + 28, 2); + pStorage->m_pFile->Seek(uFileNameSize, CFile::current); + + return true; +} + +// set the m_uModDate, m_uModTime values using CTime object +void CZipFileHeader::SetTime(const CTime &time) +{ + WORD year = (WORD)time.GetYear(); + if (year <= 1980) + year = 0; + else + year -= 1980; + m_uModDate = (WORD) (time.GetDay() + (time.GetMonth() << 5) + (year << 9)); + m_uModTime = (WORD) ((time.GetSecond() >> 1) + (time.GetMinute() << 5) + + (time.GetHour() << 11)); +} +// the buffer contains crc32, compressed and uncompressed sizes to be compared +// with the actual values +bool CZipFileHeader::CheckCrcAndSizes(char *pBuf) +{ + return (memcmp(pBuf, &m_uCrc32, 4) == 0) && (memcmp(pBuf + 4, &m_uComprSize, 4) == 0) + && (memcmp(pBuf + 8, &m_uUncomprSize, 4) == 0); +} + +// write the local header +void CZipFileHeader::WriteLocal(CZipStorage& storage) +{ + // extra field is local by now + WORD uFileNameSize = GetFileNameSize(), uExtraFieldSize = GetExtraFieldSize(); + DWORD iLocalSize = LOCALZipFileHeaderSIZE + uExtraFieldSize + uFileNameSize; + CZipAutoBuffer buf(iLocalSize); + memcpy(buf, m_gszLocalSignature, 4); + memcpy(buf + 4, &m_uVersionNeeded, 2); + memcpy(buf + 6, &m_uFlag, 2); + memcpy(buf + 8, &m_uMethod, 2); + memcpy(buf + 10, &m_uModTime, 2); + memcpy(buf + 12, &m_uModDate, 2); + memcpy(buf + 14, &m_uCrc32, 4); + memcpy(buf + 18, &m_uComprSize, 4); + memcpy(buf + 22, &m_uUncomprSize, 4); + memcpy(buf + 26, &uFileNameSize, 2); + memcpy(buf + 28, &uExtraFieldSize, 2); + memcpy(buf + 30, m_pszFileName, uFileNameSize); + memcpy(buf + 30 + uFileNameSize, m_pExtraField, uExtraFieldSize); + + // possible disk change before writting to the file in the disk spanning mode + // so write the local header first + storage.Write(buf, iLocalSize, true); + // it was only local information, use CZipArchive::SetExtraField to set the file extra field in the central directory + m_pExtraField.Release(); + + m_uDiskStart = (WORD)storage.GetCurrentDisk(); + m_uOffset = storage.GetPosition() - iLocalSize; +} + +// prepare the data before adding a new file +bool CZipFileHeader::PrepareData(int iLevel, bool bExtraHeader, bool bEncrypted) +{ + memcpy(m_szSignature, m_gszSignature, 4); + m_uInternalAttr = 0; + m_uVersionMadeBy = VERSIONMADEBY; + m_uVersionNeeded = 20; + + m_uCrc32 = 0; + m_uComprSize = 0; + m_uUncomprSize = 0; + if (iLevel == 0) + m_uMethod = 0; + + if ((m_uMethod != Z_DEFLATED) && (m_uMethod != 0)) + m_uMethod = Z_DEFLATED; + + m_uFlag = 0; + if (m_uMethod == Z_DEFLATED) + switch (iLevel) + { + case 1: + m_uFlag |= 6; + break; + case 2: + m_uFlag |= 4; + break; + case 8: + case 9: + m_uFlag |= 2; + break; + } + + if (bExtraHeader) + m_uFlag |= 8; // data descriptor present + + if (bEncrypted) + { + m_uComprSize = ENCR_HEADER_LEN; // encrypted header + m_uFlag |= 9; // encrypted file + } + + return !(m_pszComment.GetSize() > USHRT_MAX || m_pszFileName.GetSize() > USHRT_MAX + || m_pExtraField.GetSize() > USHRT_MAX); +} + +// fill the buffer with the current values +void CZipFileHeader::GetCrcAndSizes(char * pBuffer) +{ + memcpy(pBuffer, &m_uCrc32, 4); + memcpy(pBuffer + 4, &m_uComprSize, 4); + memcpy(pBuffer + 8, &m_uUncomprSize, 4); +} + +DWORD CZipFileHeader::GetSize() +{ + return ZipFileHeaderSIZE + GetExtraFieldSize() + GetFileNameSize() + GetCommentSize(); +} + + +bool CZipFileHeader::IsEncrypted() +{ + return (m_uFlag & (WORD) 1) != 0; +} + +bool CZipFileHeader::IsDataDescr() +{ + return (m_uFlag & (WORD) 8) != 0; +} + +bool CZipFileHeader::SetComment(LPCTSTR lpszComment) +{ + return CZipArchive::WideToSingle(lpszComment, m_pszComment) != -1; +} + +CString CZipFileHeader::GetComment() +{ + CString temp; + CZipArchive::SingleToWide(m_pszComment, temp); + return temp; + +} + +bool CZipFileHeader::SetFileName(LPCTSTR lpszFileName) +{ + return CZipArchive::WideToSingle(lpszFileName, m_pszFileName) != -1; +} + +CString CZipFileHeader::GetFileName() +{ + CString temp; + CZipArchive::SingleToWide(m_pszFileName, temp); + return temp; +} + + +void CZipFileHeader::SlashChange(bool bWindowsStyle) +{ + char t1 = '\\', t2 = '/', c1, c2; + if (bWindowsStyle) + { + c1 = t1; + c2 = t2; + } + else + { + c1 = t2; + c2 = t1; + } + for (DWORD i = 0; i < m_pszFileName.GetSize(); i++) + { + if (m_pszFileName[i] == c2) + m_pszFileName[i] = c1; + } +} + +void CZipFileHeader::AnsiOem(bool bAnsiToOem) +{ + if (bAnsiToOem) + CharToOemBuffA(m_pszFileName, m_pszFileName, m_pszFileName.GetSize()); + else + OemToCharBuffA(m_pszFileName, m_pszFileName, m_pszFileName.GetSize()); +} diff --git a/stepmania/src/smpackage/ZipArchive/ZipFileHeader.h b/stepmania/src/smpackage/ZipArchive/ZipFileHeader.h new file mode 100644 index 0000000000..b582345c38 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipFileHeader.h @@ -0,0 +1,106 @@ +// ZipFileHeader.h: interface for the CZipFileHeader class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_ZipFileHeader_H__0081FC65_C9C9_4D48_AF72_DBF37DF5E0CF__INCLUDED_) +#define AFX_ZipFileHeader_H__0081FC65_C9C9_4D48_AF72_DBF37DF5E0CF__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ZipException.h" +#include "ZipStorage.h" +#include "ZipAutoBuffer.h" + +class CZipFileHeader +{ +public: +// convert characters in the filename from oem to ansi or vice-versa + void AnsiOem(bool bAnsiToOem); +// change slash to backslash or vice-versa + void SlashChange(bool bWindowsStyle); +// return the filename size in characters (without NULL); + WORD GetFileNameSize(){return (WORD)m_pszFileName.GetSize();} +// return the comment size in characters (without NULL); + WORD GetCommentSize(){return (WORD)m_pszComment.GetSize();} +// return the extra field size in characters (without NULL); + WORD GetExtraFieldSize(){return (WORD)m_pExtraField.GetSize();} + + CString GetFileName(); +// return true if confersion from unicode to single byte was successful + bool SetFileName(LPCTSTR lpszFileName); + CString GetComment(); +// return true if confersion from unicode to single byte was successful + bool SetComment(LPCTSTR lpszComment); +// return true if the data descriptor is present + bool IsDataDescr(); +// return true if the file is encrypted + bool IsEncrypted(); +// central file header signature 4 bytes (0x02014b50) + char m_szSignature[4]; +// version made by 2 bytes + WORD m_uVersionMadeBy; +// version needed to extract 2 bytes + WORD m_uVersionNeeded; +// general purpose bit flag 2 bytes + WORD m_uFlag; +// compression method 2 bytes + WORD m_uMethod; +// last mod file time 2 bytes + WORD m_uModTime; +// last mod file date 2 bytes + WORD m_uModDate; +// crc-32 4 bytes + DWORD m_uCrc32; +// compressed size 4 bytes + DWORD m_uComprSize; +// uncompressed size 4 bytes + DWORD m_uUncomprSize; +// filename length 2 bytes +// WORD m_uFileNameSize; +// extra field length 2 bytes +// WORD m_uExtraFieldSize; +// file comment length 2 bytes +// WORD m_uCommentSize; +// disk number start 2 bytes + WORD m_uDiskStart; +// internal file attributes 2 bytes + WORD m_uInternalAttr; +// external file attributes 4 bytes + DWORD m_uExternalAttr; +// relative offset of local header 4 bytes + DWORD m_uOffset; +// extra field (variable size) + CZipAutoBuffer m_pExtraField; + + CZipFileHeader(); + virtual ~CZipFileHeader(); + CTime GetTime(); + void SetTime(const CTime& time); + static char m_gszSignature[]; + static char m_gszLocalSignature[]; +// return the total size of the structure as stored in the central directory + DWORD GetSize(); +protected: +// filename (variable size) + CZipAutoBuffer m_pszFileName; +// file comment (variable size) + CZipAutoBuffer m_pszComment; + + void GetCrcAndSizes(char * pBuffer); + bool PrepareData(int iLevel, bool bExtraHeader, bool bEncrypted); + void WriteLocal(CZipStorage& storage); + bool CheckCrcAndSizes(char* pBuf); + friend class CZipCentralDir; + friend class CZipArchive; + bool Read(CZipStorage *pStorage); + bool ReadLocal(CZipStorage *pStorage, WORD& iLocExtrFieldSize); + DWORD Write(CZipStorage *pStorage); + +}; + +#endif // !defined(AFX_ZipFileHeader_H__0081FC65_C9C9_4D48_AF72_DBF37DF5E0CF__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipInternalInfo.cpp b/stepmania/src/smpackage/ZipArchive/ZipInternalInfo.cpp new file mode 100644 index 0000000000..653310dce0 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipInternalInfo.cpp @@ -0,0 +1,28 @@ +// ZipInternalInfo.cpp: implementation of the CZipInternalInfo class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ZipInternalInfo.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CZipInternalInfo::CZipInternalInfo() +{ + m_iBufferSize = 16384; +} + +CZipInternalInfo::~CZipInternalInfo() +{ + +} + +void CZipInternalInfo::Init() +{ + m_pBuffer.Allocate(m_iBufferSize); +} diff --git a/stepmania/src/smpackage/ZipArchive/ZipInternalInfo.h b/stepmania/src/smpackage/ZipArchive/ZipInternalInfo.h new file mode 100644 index 0000000000..86792fc989 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipInternalInfo.h @@ -0,0 +1,32 @@ +// ZipInternalInfo.h: interface for the CZipInternalInfo class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_ZIPINTERNALINFO_H__C6749101_590C_4F74_8121_B82E3BE9FA44__INCLUDED_) +#define AFX_ZIPINTERNALINFO_H__C6749101_590C_4F74_8121_B82E3BE9FA44__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include "ZipAutoBuffer.h" +#include "zlib.h" + +class CZipInternalInfo +{ +public: + DWORD m_iBufferSize; + z_stream m_stream; + DWORD m_uUncomprLeft; + DWORD m_uComprLeft; + DWORD m_uCrc32; + void Init(); + CZipAutoBuffer m_pBuffer; + CZipInternalInfo(); + virtual ~CZipInternalInfo(); + +}; + +#endif // !defined(AFX_ZIPINTERNALINFO_H__C6749101_590C_4F74_8121_B82E3BE9FA44__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/ZipStorage.cpp b/stepmania/src/smpackage/ZipArchive/ZipStorage.cpp new file mode 100644 index 0000000000..0a295d8612 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipStorage.cpp @@ -0,0 +1,428 @@ +// ZipStorage.cpp: implementation of the CZipStorage class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ZipStorage.h" +#include "ZipArchive.h" + +////////////////////////////////////////////////////////////////////// +// disk spanning objectives: +// - sinature at the first disk at the beginning +// - headers and central dir records not divided between disks +// - each file has a data descriptor preceded by the signature +// (bit 3 set in flag); + + +char CZipStorage::m_gszExtHeaderSignat[] = {0x50, 0x4b, 0x07, 0x08}; +CZipStorage::CZipStorage() +{ + m_pCallbackData = m_pZIPCALLBACKFUN = NULL; + m_iWriteBufferSize = 65535; + m_iCurrentDisk = -1; + m_pFile = NULL; +} + +CZipStorage::~CZipStorage() +{ + +} + +DWORD CZipStorage::Read(void *pBuf, DWORD iSize, bool bAtOnce) +{ + if (iSize == 0) + return 0; + DWORD iRead = 0; + while (!iRead) + { + iRead = m_pFile->Read(pBuf, iSize); + if (!iRead) + if (IsSpanMode()) + ChangeDisk(m_iCurrentDisk + 1); + else + ThrowError(ZIP_BADZIPFILE); + } + + if (iRead == iSize) + return iRead; + else if (bAtOnce || !IsSpanMode()) + ThrowError(ZIP_BADZIPFILE); + + while (iRead < iSize) + { + ChangeDisk(m_iCurrentDisk + 1); + UINT iNewRead = m_pFile->Read((char*)pBuf + iRead, iSize - iRead); + if (!iNewRead && iRead < iSize) + ThrowError(ZIP_BADZIPFILE); + iRead += iNewRead; + } + + return iRead; +} + +void CZipStorage::Open(LPCTSTR szPathName, int iMode, int iVolumeSize) +{ + m_pWriteBuffer.Allocate(m_iWriteBufferSize); + m_uBytesInWriteBuffer = 0; + m_bNewSpan = false; + m_pFile = &m_internalfile; + + if ((iMode == CZipArchive::create) ||(iMode == CZipArchive::createSpan)) // create new archive + { + m_iCurrentDisk = 0; + if (iMode == CZipArchive::create) + { + m_iSpanMode = noSpan; + OpenFile(szPathName, CFile::modeCreate | CFile::modeReadWrite); + } + else // create disk spanning archive + { + m_bNewSpan = true; + m_iBytesWritten = 0; + if (iVolumeSize <= 0) // pkzip span + { + if (!m_pZIPCALLBACKFUN) + ThrowError(ZIP_NOCALLBACK); + if (!CZipArchive::IsDriveRemovable(szPathName)) + ThrowError(ZIP_NONREMOVABLE); + m_iSpanMode = pkzipSpan; + } + else + { + m_iTdSpanData = iVolumeSize; + m_iSpanMode = tdSpan; + } + + NextDisk(4, szPathName); + Write(m_gszExtHeaderSignat, 4, true); + } + } + else // open existing + { + OpenFile(szPathName, CFile::modeNoTruncate | ((iMode == CZipArchive::openReadOnly) ? CFile::modeRead : CFile::modeReadWrite)); + // m_uData, m_bAllowModif i m_iSpanMode ustalane automatycznie podczas odczytu central dir + m_iSpanMode = iVolumeSize == 0 ? suggestedAuto : suggestedTd; + } + +} + + +void CZipStorage::Open(CMemFile& mf, int iMode) +{ + m_pWriteBuffer.Allocate(m_iWriteBufferSize); + m_uBytesInWriteBuffer = 0; + m_bNewSpan = false; + m_pFile = &mf; + + if (iMode == CZipArchive::create) + { + m_iCurrentDisk = 0; + m_iSpanMode = noSpan; + mf.SetLength(0); + } + else // open existing + { + mf.SeekToBegin(); + m_iSpanMode = suggestedAuto; + } +} + + +int CZipStorage::IsSpanMode() +{ + return m_iSpanMode == noSpan ? 0 : (m_bNewSpan ? 1 : -1); +} + +void CZipStorage::ChangeDisk(int iNumber) +{ + if (iNumber == m_iCurrentDisk) + return; + + ASSERT(m_iSpanMode != noSpan); + m_iCurrentDisk = iNumber; + OpenFile(m_iSpanMode == pkzipSpan ? ChangePkzipRead() : ChangeTdRead(), + CFile::modeNoTruncate | CFile::modeRead); +} + +void CZipStorage::ThrowError(int err) +{ + AfxThrowZipException(err, m_pFile->GetFilePath()); +} + +bool CZipStorage::OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow) +{ + CFileException* e = new CFileException; + BOOL bRet = m_pFile->Open(lpszName, uFlags | CFile::shareDenyWrite, e); + if (!bRet && bThrow) + throw e; + e->Delete(); + return bRet != 0; +} + +// zapobiega konstrukcji ChangeDisk(++m_iCurrentDisk) +void CZipStorage::SetCurrentDisk(int iNumber) +{ + m_iCurrentDisk = iNumber; +} + +int CZipStorage::GetCurrentDisk() +{ + return m_iCurrentDisk; +} + +CString CZipStorage::ChangePkzipRead() +{ + CString szTemp = m_pFile->GetFilePath(); + m_pFile->Close(); + CallCallback(-1 , szTemp); + return szTemp; +} + +CString CZipStorage::ChangeTdRead() +{ + CString szTemp = GetTdVolumeName(m_iCurrentDisk == m_iTdSpanData); + m_pFile->Close(); + return szTemp; +} + +void CZipStorage::Close(bool bAfterException) +{ + if (!bAfterException) + { + Flush(); + if ((m_iSpanMode == tdSpan) && (m_bNewSpan)) + { + // give to the last volume the zip extension + CString szFileName = m_pFile->GetFilePath(); + CString szNewFileName = GetTdVolumeName(true); + m_pFile->Close(); + if (CZipArchive::FileExists(szNewFileName)) + CFile::Remove(szNewFileName); + CFile::Rename(szFileName, szNewFileName); + } + else +#ifdef _DEBUG // to prevent assertion if the file is already closed + if (m_pFile->m_hFile != (UINT)CFile::hFileNull) +#endif + m_pFile->Close(); + } + else +#ifdef _DEBUG // to prevent assertion if the file is already closed + if (m_pFile->m_hFile != (UINT)CFile::hFileNull) +#endif + m_pFile->Close(); + + + m_pWriteBuffer.Release(); + m_iCurrentDisk = -1; + m_iSpanMode = noSpan; + m_pFile = NULL; +} + +CString CZipStorage::GetTdVolumeName(bool bLast, LPCTSTR lpszZipName) +{ + CString szFilePath = lpszZipName ? lpszZipName : m_pFile->GetFilePath(); + CString szPath = CZipArchive::GetFilePath(szFilePath); + CString szName = CZipArchive::GetFileTitle(szFilePath); + CString szExt; + if (bLast) + szExt = _T("zip"); + else + szExt.Format(_T("%.3d"), m_iCurrentDisk); + return szPath + szName + _T(".") + szExt; +} + +void CZipStorage::NextDisk(int iNeeded, LPCTSTR lpszFileName) +{ + Flush(); + ASSERT(m_iSpanMode != noSpan); + if (m_iBytesWritten) + { + m_iBytesWritten = 0; + m_iCurrentDisk++; + if (m_iCurrentDisk >= 999) + ThrowError(ZIP_TOOMANYVOLUMES); + } + CString szFileName; + bool bPkSpan = (m_iSpanMode == pkzipSpan); + if (bPkSpan) + szFileName = lpszFileName ? lpszFileName : m_pFile->GetFilePath(); + else + szFileName = GetTdVolumeName(false, lpszFileName); + +#ifdef _DEBUG // to prevent assertion if the file is already closed + if (m_pFile->m_hFile != (UINT)CFile::hFileNull) +#endif + m_pFile->Close(); // if it is closed, so it will not close + + if (bPkSpan) + { + int iCode = iNeeded; + while (true) + { + CallCallback(iCode, szFileName); + if (CZipArchive::FileExists(szFileName)) + iCode = -2; + else + { + CString label; + label.Format(_T("pkback# %.3d"), m_iCurrentDisk + 1); + if (!SetVolumeLabel(CZipArchive::GetDrive(szFileName), label)) /*not write label*/ + iCode = -3; + else if (!OpenFile(szFileName, CFile::modeCreate | CFile::modeReadWrite, false)) + iCode = -4; + else + break; + } + + } + m_uCurrentVolSize = GetFreeVolumeSpace(); + } + else + { + m_uCurrentVolSize = m_iTdSpanData; + OpenFile(szFileName, CFile::modeCreate | CFile::modeReadWrite); + } +} + +void CZipStorage::CallCallback(int iCode, CString szTemp) +{ + ASSERT(m_pZIPCALLBACKFUN); + if (!(*m_pZIPCALLBACKFUN)(m_iCurrentDisk + 1, iCode, m_pCallbackData)) + throw new CZipException(CZipException::aborted, szTemp); +} + +DWORD CZipStorage::GetFreeVolumeSpace() +{ + ASSERT (m_iSpanMode == pkzipSpan); + DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters; + if (!GetDiskFreeSpace( + CZipArchive::GetDrive(m_pFile->GetFilePath()), + &SectorsPerCluster, + &BytesPerSector, + &NumberOfFreeClusters, + &TotalNumberOfClusters)) + return 0; + _int64 total = SectorsPerCluster * BytesPerSector * NumberOfFreeClusters; + return (DWORD)total; +} + + +void CZipStorage::UpdateSpanMode(WORD uLastDisk) +{ + m_iCurrentDisk = uLastDisk; + if (uLastDisk) + { + // disk spanning detected + + if (m_iSpanMode == suggestedAuto) + m_iSpanMode = CZipArchive::IsDriveRemovable(m_pFile->GetFilePath()) ? + pkzipSpan : tdSpan; + else + m_iSpanMode = tdSpan; + + if (m_iSpanMode == pkzipSpan) + { + if (!m_pZIPCALLBACKFUN) + ThrowError(ZIP_NOCALLBACK); + } + else /*if (m_iSpanMode == tdSpan)*/ + m_iTdSpanData = uLastDisk; // disk with .zip extension ( the last one) + + m_pWriteBuffer.Release(); // no need for this in this case + } + else + m_iSpanMode = noSpan; + +} + +void CZipStorage::Write(void *pBuf, DWORD iSize, bool bAtOnce) +{ + if (!IsSpanMode()) + WriteInternalBuffer((char*)pBuf, iSize); + else + { + // if not at once, one byte is enough free space + DWORD iNeeded = bAtOnce ? iSize : 1; + DWORD uTotal = 0; + + while (uTotal < iSize) + { + DWORD uFree; + while ((uFree = VolumeLeft()) < iNeeded) + { + if ((m_iSpanMode == tdSpan) && !m_iBytesWritten && !m_uBytesInWriteBuffer) + // in the tdSpan mode, if the size of the archive is less + // than the size of the packet to be written at once, + // increase once the size of the volume + m_uCurrentVolSize = iNeeded; + else + NextDisk(iNeeded); + } + + DWORD uLeftToWrite = iSize - uTotal; + DWORD uToWrite = uFree < uLeftToWrite ? uFree : uLeftToWrite; + WriteInternalBuffer((char*)pBuf + uTotal, uToWrite); + if (bAtOnce) + return; + else + uTotal += uToWrite; + } + + } +} + + +void CZipStorage::WriteInternalBuffer(char *pBuf, DWORD uSize) +{ + DWORD uWritten = 0; + while (uWritten < uSize) + { + DWORD uFreeInBuffer = GetFreeInBuffer(); + if (uFreeInBuffer == 0) + { + Flush(); + uFreeInBuffer = m_pWriteBuffer.GetSize(); + } + DWORD uLeftToWrite = uSize - uWritten; + DWORD uToCopy = uLeftToWrite < uFreeInBuffer ? uLeftToWrite : uFreeInBuffer; + memcpy(m_pWriteBuffer + m_uBytesInWriteBuffer, pBuf + uWritten, uToCopy); + uWritten += uToCopy; + m_uBytesInWriteBuffer += uToCopy; + } +} + +DWORD CZipStorage::VolumeLeft() +{ + // for pkzip span m_uCurrentVolSize is updated after each flush() + return m_uCurrentVolSize - m_uBytesInWriteBuffer - ((m_iSpanMode == pkzipSpan) ? 0 : m_iBytesWritten); +} + +void CZipStorage::Flush() +{ + m_iBytesWritten += m_uBytesInWriteBuffer; + if (m_uBytesInWriteBuffer) + { + m_pFile->Write(m_pWriteBuffer, m_uBytesInWriteBuffer); + m_uBytesInWriteBuffer = 0; + } + if (m_iSpanMode == pkzipSpan) + // after writting it is difficult to predict the free space due to + // not completly written clusters, write operation may start from + // the new cluster + m_uCurrentVolSize = GetFreeVolumeSpace(); +} + +DWORD CZipStorage::GetPosition() +{ + return m_pFile->GetPosition() + m_uBytesInWriteBuffer; +} + + +DWORD CZipStorage::GetFreeInBuffer() +{ + return m_pWriteBuffer.GetSize() - m_uBytesInWriteBuffer; +} diff --git a/stepmania/src/smpackage/ZipArchive/ZipStorage.h b/stepmania/src/smpackage/ZipArchive/ZipStorage.h new file mode 100644 index 0000000000..9d203ae32e --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/ZipStorage.h @@ -0,0 +1,134 @@ +// ZipStorage.h: interface for the CZipStorage class. +// +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2000 Tadeusz Dracz. +// For conditions of distribution and use, see copyright notice in ZipArchive.h +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_ZIPSTORAGE_H__941824FE_3320_4794_BDE3_BE334ED8984B__INCLUDED_) +#define AFX_ZIPSTORAGE_H__941824FE_3320_4794_BDE3_BE334ED8984B__INCLUDED_ + +#include "ZipBigFile.h" // Added by ClassView +#include "ZipAutoBuffer.h" // Added by ClassView +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// callback function called when there is a need for a disk change +// calling CZipArchive functions, apart from the static ones, may have unexpected results +// iNumber - disk number needed +// iCode : +// -1 - disk needed for reading +// other codes occurs during writting +// >=0 : number of bytes needed +// -2 - the file with the archive name already exists on the disk +// -3 - the disk is probably write - protected +// -4 - couldn't create a file +// pData - user defined data +// return false to abort operation: the proper exception will be thrown +typedef bool (*ZIPCALLBACKFUN )(int iNumber, int iCode, void* pData); + +class CZipStorage +{ +public: + void Open(CMemFile& mf, int iMode); +// return the position in the file, taking into account the bytes in the write buffer + DWORD GetPosition(); + +// flush the data from the read buffer to the disk + void Flush(); + +// only called by CZipCentralDir when opening an existing archive + void UpdateSpanMode(WORD uLastDisk); +// the preset size of the write buffer + int m_iWriteBufferSize; + +// user data to be passed to the callback function + void* m_pCallbackData; + +// function used to change disks during writing to the disk spanning archive + void NextDisk(int iNeeded, LPCTSTR lpszFileName = NULL); + + void Close(bool bAfterException); + +// return the numer of the current disk + int GetCurrentDisk(); + + void SetCurrentDisk(int iNumber); + +// change the disk during extract operations + void ChangeDisk(int iNumber); + +// Function name : IsSpanMode +// Description : detect span mode +// Return type : int +// -1 - existing span opened +// 0 - no span +// 1 - new span + int IsSpanMode(); + + void Open(LPCTSTR szPathName, int iMode, int iVolumeSize); + void Write(void *pBuf, DWORD iSize, bool bAtOnce); + DWORD Read(void* pBuf, DWORD iSize, bool bAtOnce); + CZipBigFile m_internalfile; + CFile* m_pFile; + CZipStorage(); + virtual ~CZipStorage(); + enum {noSpan, pkzipSpan, tdSpan, suggestedAuto, suggestedTd}; + int m_iSpanMode; + ZIPCALLBACKFUN m_pZIPCALLBACKFUN; + static char m_gszExtHeaderSignat[]; + +// open tdspan: last disk number, create tdspan: volume size +// create pkspan: not used + int m_iTdSpanData; + +protected: +// how many bytes left free in the write buffer + DWORD GetFreeInBuffer(); + friend class CZipCentralDir; +// numer of bytes available in the write buffer + DWORD m_uBytesInWriteBuffer; + +// tdSpan : the total size of the current volume, pkSpan : free space on the current volume + DWORD m_uCurrentVolSize; + +// return the number of bytes left on the current volume + DWORD VolumeLeft(); + +// write data to the internal buffer + void WriteInternalBuffer(char *pBuf, DWORD uSize); + +// number of bytes left free in the write buffer + DWORD m_uVolumeFreeInBuffer; + + CZipAutoBuffer m_pWriteBuffer; + +// return the number of free bytes on the current removable disk + DWORD GetFreeVolumeSpace(); + + void CallCallback(int iCode, CString szTemp); + +// only disk spanning creation: tells how many bytes have been written physically to the current volume + DWORD m_iBytesWritten; + +// construct the name of the volume in tdSpan mode + CString GetTdVolumeName(bool bLast, LPCTSTR lpszZipName = NULL); + +// change the disk in tdSpan mode + CString ChangeTdRead(); + +// change the disk in pkSpan mode + CString ChangePkzipRead(); + +// you can only add a new files to the new disk spanning archive and only extract +// them from the existing one + bool m_bNewSpan; + + int m_iCurrentDisk; + bool OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow = true); + void ThrowError(int err); + +}; + +#endif // !defined(AFX_ZIPSTORAGE_H__941824FE_3320_4794_BDE3_BE334ED8984B__INCLUDED_) diff --git a/stepmania/src/smpackage/ZipArchive/zconf.h b/stepmania/src/smpackage/ZipArchive/zconf.h new file mode 100644 index 0000000000..6d450fc793 --- /dev/null +++ b/stepmania/src/smpackage/ZipArchive/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/stepmania/src/smpackage/install.bmp b/stepmania/src/smpackage/install.bmp new file mode 100644 index 0000000000000000000000000000000000000000..64107b2f2be90d74bc2b33d9db0a4791b043b875 GIT binary patch literal 31578 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 EKU95#%m4rY literal 0 HcmV?d00001 diff --git a/stepmania/src/smpackage/manage.bmp b/stepmania/src/smpackage/manage.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0024c614391d424b893fe1b3eadd4d3fe2634723 GIT binary patch literal 31578 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
    OZF zlX6T4qpWw1*Kx}00Rtbyda&0_<+$s5R@NCe9o!nP*OII7dY)q3Y+83*d(`m0aO`-6 z?O+%ZUDvaEAKP&~za8&7Tf+N(b*SCC^TIRYE;Yo1(i#k}4}9=4`UB&}@pi?4$68`f zSv-D#I)9_7HgRRbZ9*vAvhTsWS+3*vwwrxtSWeBtJ?)G8{29q^-@{jhze)IH@JB;B z+HENn_wPf+=J^xDI&F|UV6m#~!@TuP;_ZMNXs^3m+tqdiZ7J)LOqQqrp>LE_6x!|b zJ3df>Z_u|a^=3*IsQ%1RdcPqpl=GcOB0 z(kEH^8fx2i2vcjUM{7xzr!>R%3q%3tAp4kuJi{Dh4|9iB94syFjK%d?T!1<7${y^l zDZgd-gFWRR{TvT-vd}BpuPpR8bew^@9>SE?zw@)+{vi;O zpJ2bwM+t#S8zA&aM#}Uy`URT6-9@#9NS)nAH!N9wwnruLjHOFW;E0vo-p*z4HB(1I zVI2%LBi7V6GM7tpKU>ztwqUolWGtQX{_?Yi;8S0F|7bM&kES^(zi;cW8j*S#b5K>J=j#EQKSVSc~8f@+KE_Wv=q)PVqY z)P{lG`X{`%Z}HDfE>U9~`)6y%>hiC9t1)yBMYOitzwWL?jWIc9*n38of8CGyk&}_A z^36|N<5$3CBRt;J*2@!ftabTbi5Z5Y&F5i0+q!`2gmaq3cJlj_dO<7$t?N_xd409? z^YYJb=lH)8=`@ya`})%FhwjhizIFNa^k6+yLN>~OmGy7V$~yKSsMl!(8;=iW%0&IR zu$L(GHUfve_5N~yz4tUw@2LkGzWR)$(;1?FV@EO)NPpsmx SuOIr#4%=kgr!ZZoe)&I3EM-0b literal 0 HcmV?d00001 diff --git a/stepmania/src/smpackage/smpackage.clw b/stepmania/src/smpackage/smpackage.clw new file mode 100644 index 0000000000..899035d676 --- /dev/null +++ b/stepmania/src/smpackage/smpackage.clw @@ -0,0 +1,66 @@ +; CLW file contains information for the MFC ClassWizard + +[General Info] +Version=1 +LastClass=CSMPackageInstallDlg +LastTemplate=CDialog +NewFileInclude1=#include "stdafx.h" +NewFileInclude2=#include "smpackage.h" + +ClassCount=3 +Class1=CSmpackageApp +Class2=CSmpackageDlg + +ResourceCount=3 +Resource1=IDR_MAINFRAME +Resource2=IDD_MANAGER +Class3=CSMPackageInstallDlg +Resource3=IDD_INSTALL + +[CLS:CSmpackageApp] +Type=0 +HeaderFile=smpackage.h +ImplementationFile=smpackage.cpp +Filter=N +LastObject=CSmpackageApp + +[CLS:CSmpackageDlg] +Type=0 +HeaderFile=smpackageDlg.h +ImplementationFile=smpackageDlg.cpp +Filter=D +LastObject=CSmpackageDlg +BaseClass=CDialog +VirtualFilter=dWC + + + +[DLG:IDD_MANAGER] +Type=1 +Class=CSmpackageDlg +ControlCount=5 +Control1=IDOK,button,1342242817 +Control2=IDC_LIST_SONGS,listbox,1352728835 +Control3=IDC_BUTTON_PLAY,button,1342242816 +Control4=IDC_BUTTON_EXPORT,button,1476460544 +Control5=IDC_STATIC,static,1342177294 + +[DLG:IDD_INSTALL] +Type=1 +Class=CSMPackageInstallDlg +ControlCount=5 +Control1=IDC_EDIT_MESSAGE,edit,1342179460 +Control2=IDOK,button,1342242817 +Control3=IDCANCEL,button,1342242816 +Control4=IDC_BUTTON_BACK,button,1476460544 +Control5=IDC_STATIC,static,1342177294 + +[CLS:CSMPackageInstallDlg] +Type=0 +HeaderFile=SMPackageInstallDlg.h +ImplementationFile=SMPackageInstallDlg.cpp +BaseClass=CDialog +Filter=D +LastObject=CSMPackageInstallDlg +VirtualFilter=dWC + diff --git a/stepmania/src/smpackage/smpackage.cpp b/stepmania/src/smpackage/smpackage.cpp new file mode 100644 index 0000000000..c6cb30c7d3 --- /dev/null +++ b/stepmania/src/smpackage/smpackage.cpp @@ -0,0 +1,120 @@ +// smpackage.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "smpackage.h" +#include "smpackageDlg.h" +#include "smpackageInstallDlg.h" +#include "../RageUtil.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSmpackageApp + +BEGIN_MESSAGE_MAP(CSmpackageApp, CWinApp) + //{{AFX_MSG_MAP(CSmpackageApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSmpackageApp construction + +CSmpackageApp::CSmpackageApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CSmpackageApp object + +CSmpackageApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CSmpackageApp initialization + +BOOL CSmpackageApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + + + // Make sure the current directory is the root program directory + if( !DoesFileExist("Songs") ) + { + // change dir to path of the execuctable + TCHAR szFullAppPath[MAX_PATH]; + GetModuleFileName(NULL, szFullAppPath, MAX_PATH); + + // strip off executable name + LPSTR pLastBackslash = strrchr(szFullAppPath, '\\'); + *pLastBackslash = '\0'; // terminate the string + + SetCurrentDirectory(szFullAppPath); + + if( !DoesFileExist("Songs") ) + { + AfxMessageBox( "Your Songs folder could not be located. Be sure 'smpackage.exe' is in your Stepmania installation folder.", MB_ICONSTOP ); + exit( 1 ); + } + + } + + // check if there's a .smzip command line argument + CStringArray arrayCommandLineBits; + split( ::GetCommandLine(), "\"", arrayCommandLineBits ); + for( int i=0; i +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=smpackage - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "smpackage.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "smpackage.mak" CFG="smpackage - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "smpackage - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "smpackage - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "smpackage - Win32 Release" + +# PROP BASE Use_MFC 5 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 6 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_AFXDLL" /FR /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 +# ADD LINK32 /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "smpackage - Win32 Debug" + +# PROP BASE Use_MFC 5 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 6 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "smpackage - Win32 Release" +# Name "smpackage - Win32 Debug" +# Begin Group "Stepmania Package files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\RageUtil.cpp +# End Source File +# Begin Source File + +SOURCE=..\RageUtil.h +# End Source File +# Begin Source File + +SOURCE=.\Resource.h +# End Source File +# Begin Source File + +SOURCE=.\smpackage.cpp +# End Source File +# Begin Source File + +SOURCE=.\smpackage.h +# End Source File +# Begin Source File + +SOURCE=.\res\smpackage.ico +# End Source File +# Begin Source File + +SOURCE=.\smpackage.rc +# End Source File +# Begin Source File + +SOURCE=.\res\smpackage.rc2 +# End Source File +# Begin Source File + +SOURCE=.\smpackageDlg.cpp +# End Source File +# Begin Source File + +SOURCE=.\smpackageDlg.h +# End Source File +# Begin Source File + +SOURCE=.\SMPackageInstallDlg.cpp +# End Source File +# Begin Source File + +SOURCE=.\SMPackageInstallDlg.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\install.bmp +# End Source File +# Begin Source File + +SOURCE=.\manage.bmp +# End Source File +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# Begin Source File + +SOURCE=.\smpackage.ICO +# End Source File +# Begin Source File + +SOURCE=.\res\StepMania.ICO +# End Source File +# End Target +# End Project diff --git a/stepmania/src/smpackage/smpackage.h b/stepmania/src/smpackage/smpackage.h new file mode 100644 index 0000000000..fab6370972 --- /dev/null +++ b/stepmania/src/smpackage/smpackage.h @@ -0,0 +1,49 @@ +// smpackage.h : main header file for the SMPACKAGE application +// + +#if !defined(AFX_SMPACKAGE_H__FBCA9E6C_86A9_4271_8304_83CC34A31687__INCLUDED_) +#define AFX_SMPACKAGE_H__FBCA9E6C_86A9_4271_8304_83CC34A31687__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CSmpackageApp: +// See smpackage.cpp for the implementation of this class +// + +class CSmpackageApp : public CWinApp +{ +public: + CSmpackageApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSmpackageApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CSmpackageApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SMPACKAGE_H__FBCA9E6C_86A9_4271_8304_83CC34A31687__INCLUDED_) diff --git a/stepmania/src/smpackage/smpackage.opt b/stepmania/src/smpackage/smpackage.opt new file mode 100644 index 0000000000000000000000000000000000000000..d96c8d6eb0f4f72d67085e507a3aff504aa48152 GIT binary patch literal 54784 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",IDOK,200,215,55,15 + PUSHBUTTON "Cancel",IDCANCEL,275,215,50,15 + PUSHBUTTON "< Back",IDC_BUTTON_BACK,145,215,55,15,WS_DISABLED + CONTROL 133,IDC_STATIC,"Static",SS_BITMAP,0,0,258,37 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "smpackage MFC Application\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "smpackage\0" + VALUE "LegalCopyright", "Copyright (C) 2002\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "smpackage.EXE\0" + VALUE "ProductName", "smpackage Application\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_MANAGER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 325 + TOPMARGIN, 7 + BOTTOMMARGIN, 227 + END + + IDD_INSTALL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 325 + TOPMARGIN, 7 + BOTTOMMARGIN, 227 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +INSTALL BITMAP DISCARDABLE "install.bmp" +MANAGE BITMAP DISCARDABLE "manage.bmp" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\smpackage.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/stepmania/src/smpackage/smpackageDlg.cpp b/stepmania/src/smpackage/smpackageDlg.cpp new file mode 100644 index 0000000000..b9ab0f9168 --- /dev/null +++ b/stepmania/src/smpackage/smpackageDlg.cpp @@ -0,0 +1,210 @@ +// smpackageDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "smpackage.h" +#include "smpackageDlg.h" +#include "../RageUtil.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSmpackageDlg dialog + +CSmpackageDlg::CSmpackageDlg(CWnd* pParent /*=NULL*/) + : CDialog(CSmpackageDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSmpackageDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CSmpackageDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSmpackageDlg) + DDX_Control(pDX, IDC_BUTTON_EXPORT, m_buttonExport); + DDX_Control(pDX, IDC_LIST_SONGS, m_listBoxSongs); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CSmpackageDlg, CDialog) + //{{AFX_MSG_MAP(CSmpackageDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_LBN_SELCHANGE(IDC_LIST_SONGS, OnSelchangeListSongs) + ON_BN_CLICKED(IDC_BUTTON_EXPORT, OnButtonExport) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSmpackageDlg message handlers + +BOOL CSmpackageDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // + // TODO: Add extra initialization here + // + + // Find all song directories + CStringArray arrayGroupDirs; + GetDirListing( "Songs\\*.*", arrayGroupDirs, true ); + + for( int i=0; iDelete(); + return; + } + + + CStringArray arrayFiles; + GetDirListing( sSongDir + "\\*.*", arrayFiles ); + //m_zip.AddNewFile( sRelPathToSelectedSong, 0, true ); // add the directory + + m_zip.AddNewFile( "Songs", 0, true ); + m_zip.AddNewFile( sGroupDir, 0, true ); + m_zip.AddNewFile( sSongDir, 0, true ); + + for( int i=0; iDelete(); + return; + } + } + + AfxMessageBox( ssprintf("Successfully exported '%s' to '%s' on your Desktop.", sSongDir, sZipFileName) ); + + + m_zip.Close(); + +} + + + diff --git a/stepmania/src/smpackage/smpackageDlg.h b/stepmania/src/smpackage/smpackageDlg.h new file mode 100644 index 0000000000..1e196b5ae8 --- /dev/null +++ b/stepmania/src/smpackage/smpackageDlg.h @@ -0,0 +1,57 @@ +// smpackageDlg.h : header file +// + +#if !defined(AFX_SMPACKAGEDLG_H__E60DA2DD_D8D6_42BC_9049_631EAFBAA1F6__INCLUDED_) +#define AFX_SMPACKAGEDLG_H__E60DA2DD_D8D6_42BC_9049_631EAFBAA1F6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CSmpackageDlg dialog + + +#include "ZipArchive\ZipArchive.h" + + +class CSmpackageDlg : public CDialog +{ +// Construction +public: + CSmpackageDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CSmpackageDlg) + enum { IDD = IDD_SMPACKAGE_DIALOG }; + CButton m_buttonExport; + CListBox m_listBoxSongs; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSmpackageDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + CZipArchive m_zip; + + + // Generated message map functions + //{{AFX_MSG(CSmpackageDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnSelchangeListSongs(); + afx_msg void OnButtonExport(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SMPACKAGEDLG_H__E60DA2DD_D8D6_42BC_9049_631EAFBAA1F6__INCLUDED_)