VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "Cls_Zip"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
'This class file can be used to show/extract the contents of an ZIP-archive
Private Type Local_Header_Type
VerExt As Integer 'version needed to extract
Flags As Integer 'encrypt and compression flags
Method As Integer 'compression method
FTime As Integer 'time last modifies, dos format
FDate As Integer 'date last modifies, dos format
CRC32 As Long 'CRC32 for uncompressed file
CSize As Long 'compressed size
USize As Long 'uncompressed size
LenFname As Integer 'lenght filename
LenExt As Integer 'lenght for extra field
End Type
Private Type Central_Header_Type
VerMade As Integer 'version made by
VerExt As Integer 'version needed to extract
Flags As Integer 'encrypt and compression flags
Method As Integer 'compression method
FTime As Integer 'time last modifies, dos format
FDate As Integer 'date last modifies, dos format
CRC32 As Long 'CRC32 for uncompressed file
CSize As Long 'compressed size
USize As Long 'uncompressed size
LenFname As Integer 'lenght filename
LenExt As Integer 'lenght for extra field
LenCom As Integer 'lenght for comment field
DiskStart As Integer 'start disk number
AttribI As Integer 'internal file attributes
AttribX As Long 'external file attributes
Offset As Long 'relative offset of local header
End Type
Private Type End_Header_Type
signature As Long 'Signature
DiskNum As Integer 'this disk number
DiskStart As Integer 'start disk number
Entries As Integer 'Entries on this disk
TotEntr As Integer 'Number of total entries
CenSize As Long 'size of entire cetral directory
CenOff As Long 'offset of central on starting disk
LenCom As Integer 'lenght of comment field
End Type
Private Type Extended_Local_Header_Type
CRC32 As Long 'CRC32 for uncompressed file
CSize As Long 'compressed size
USize As Long 'uncompressed size
End Type
Private Type CentralData_Type
VerMade As Integer 'version made by
VerExt As Integer 'version needed to extract
Flags As Integer 'encrypt and compression flags
Method As Integer 'compression method
FTime As Integer 'time last modifies, dos format
FDate As Integer 'date last modifies, dos format
CRC32 As Long 'CRC32 for uncompressed file
CSize As Long 'compressed size
USize As Long 'uncompressed size
DiskStart As Integer 'start disk number
AttribI As Integer 'internal file attributes
AttribX As Long 'external file attributes
Offset As Long 'relative offset of local header
FileName As String 'Name of the compressed file
ExtField As String 'Data from extended fields
ComField As String 'data from comments fields
End Type
'Signatures long version
Private Const ZipLocalSigLng As Long = &H4034B50
Private Const ZipCentralSigLng As Long = &H2014B50
Private Const ZipEndSigLng As Long = &H6054B50
Private Const ZipExtLocalSigLng As Long = &H8074B50
'Flags values for ZIP-files
Private Const ZipFlgEncrypted As Byte = 1 'bit 0 set = file is encrypted
Private Const ZipFlgUsedMed As Byte = 6 'bit 1+2 depending on compression type
'type = 6 (imploding)
'bit 1 set = use 8k dictionary else 4k dictionary
'bit 2 set = use 3 trees else use 2 trees
'type = 8 (deflating)
'bit 2 : 1
' 0 0 = Normal (-en) compression option was used.
' 0 1 = Maximum (-exx/-ex) compression option was used
' 1 0 = Fast (-ef) compression option was used
' 1 1 = Super Fast (-es) compression option was used
'bits are undified if other methods are used
Private Const ZipFlgExtLocHead As Byte = 8 'bit 3 set = Extended local header is used to store CRC and size
Private Const ZipFlgRes64 As Byte = 16 'bit 4 Reserved for ZIP64
Private Const ZipFlgPathed As Byte = 32 'bit 5 set = file is compressed pathed data
Private Const ZipFlgEncStrong As Byte = 64 'bit 6 set = file is encrypted using strong encryption
'##ZIPFileData.ArrayBounds ForceZero
Private ZIPFileData() As CentralData_Type
Private CRC As New Cls_CRC32
Private Encrypt As New Cls_Encrypt
Private Const m_Unpack_Supported As Boolean = True
Public Function Get_Contents(ZipName As String) As Integer
Dim NextByte As Byte '1 byte
Dim Byte2 As Integer '2 bytes
Dim FileNum As Long
Dim FileLenght As Long
Dim Header As Integer
Dim LngHeader As Long
Dim UnKnown As Boolean
Dim TextBytes() As Byte
Dim EndCentralSig As End_Header_Type
Dim CentDat As Central_Header_Type
Dim LocDat As Local_Header_Type
Dim ExtDat As Extended_Local_Header_Type
Dim LN As Long
Dim X As Long
PackFileName = ZipName
PackComments = ""
PackFileType = 0
FileNum = FreeFile
Open PackFileName For Binary Access Read As #FileNum
FileLenght = LOF(FileNum)
'get the end of central date
Get #FileNum, FileLenght - Len(EndCentralSig) + 1, EndCentralSig
If EndCentralSig.signature <> ZipEndSigLng Then
'EndSignature not found (probably comments are added)
'Search for central data from start
Seek #FileNum, 1
PackTotFiles = 0
Do
Get #FileNum, , LngHeader
Select Case LngHeader
Case ZipLocalSigLng
Get #FileNum, , LocDat
Seek #FileNum, Seek(FileNum) + LocDat.CSize + LocDat.LenFname + LocDat.LenExt
PackTotFiles = PackTotFiles + 1
Case ZipCentralSigLng
Seek #FileNum, Seek(FileNum) - 4
Exit Do
Case ZipExtLocalSigLng
Get #FileNum, , ExtDat
Case Else
MsgBox "Unknown header"
End Select
Loop
Else
'position pointer to the start of the central header
Seek #FileNum, EndCentralSig.CenOff + 1
PackTotFiles = EndCentralSig.Entries
End If
ReDim ZIPFileData(1 To PackTotFiles)
'Read the central header and store the information
PackFileType = ZipFileType 'Zip file type
For X = 1 To PackTotFiles
Get #FileNum, , LngHeader 'read the header
Get #FileNum, , CentDat 'read the data
With ZIPFileData(X)
.VerMade = CentDat.VerMade
.VerExt = CentDat.VerExt
.Flags = CentDat.Flags
.Method = CentDat.Method
.FTime = CentDat.FTime
.FDate = CentDat.FDate
.CRC32 = CentDat.CRC32
.CSize = CentDat.CSize
.USize = CentDat.USize
.DiskStart = CentDat.DiskStart
.AttribI = CentDat.AttribI
.AttribX = CentDat.AttribX
.Offset = CentDat.Offset
If CentDat.LenFname <> 0 Then
ReDim TextBytes(0 To Int2Lng(CentDat.LenFname) - 1)
Get #FileNum, , TextBytes
.FileName = StrConv(TextBytes, vbUnicode)
End If
If CentDat.LenExt <> 0 Then
ReDim TextBytes(0 To Int2Lng(CentDat.LenExt) - 1)
Get #FileNum, , TextBytes
.ExtField = StrConv(TextBytes, vbUnicode)
End If
If CentDat.LenCom Then
ReDim TextBytes(0 To Int2Lng(CentDat.LenCom) - 1)
Get #FileNum, , TextBytes
.ComField = StrConv(TextBytes, vbUnicode)
End If
End With
Next
Get #FileNum, , EndCentralSig
PackComments = String(EndCentralSig.LenCom, 0)
Get #FileNum, , PackComments
Close FileNum
End Function
'Unzip as file and return 0 for good decompression or others for error
Public Function UnPack(ZippedFile() As Boolean, ToPath As String) As Integer
Dim ZipHead As Local_Header_Type 'Local Zip Header
Dim Header As Long
Dim X As Long
Dim PassWord As String
Dim FileNum As Long
Dim Y As Long
Dim TotDir As String 'Used for new pathnames
If PackTotFiles = 0 Then UnPack = -10: Exit Function 'nothing to UnPack
If PackTotFiles <> UBound(ZippedFile) Then
UnPack = -10 'need same amount as files in zipfile
Exit Function
End If
Erase PackData
FileNum = FreeFile
Open PackFileName For Binary Access Read As #FileNum
For X = 1 To PackTotFiles
If ZippedFile(X) = True Then
If Not IsDir(X) Then 'decompress if it is not a pathname
Seek #FileNum, ZIPFileData(X).Offset + 1
Get #FileNum, , Header
If Header = ZipLocalSigLng Then
'read the header
Get #FileNum, , ZipHead
'skip data whe already know
Seek #FileNum, Seek(FileNum) + ZipHead.LenFname + ZipHead.LenExt
If ZIPFileData(X).CSize = 0 Then
Erase PackData
Else
ReDim PackData(ZIPFileData(X).CSize - 1)
Get #FileNum, , PackData() 'Read the compressed file
End If
If Encrypted(X) Then
If PassWord = "" Then
PassWord = InputBox("Give Password", "Password requered")
If PassWord = "" Then
UnPack = -1
Close FileNum
MsgBox "Password is incorrect"
Exit Function
End If
End If
Encrypt.ZipPrepareKey PackData, PassWord
If PackData(11) <> (((ZIPFileData(X).CRC32 And &HFF000000) \ &H1000000) And 255&) Then
UnPack = -1
Close FileNum
MsgBox "Password is incorrect"
Exit Function
End If
'adjust the size of instream to delete the decryption data
For Y = 0 To UBound(PackData) - 12
PackData(Y) = PackData(Y + 12)
Next
ReDim Preserve PackData(UBound(PackData) - 12)
Encrypt.ZipDecryptArray PackData
End If
Select Case ZIPFileData(X).Method
Case 0
Call Write_Uncompressed_Data(X, ToPath)
Case 1
UnPack = -10 'not supported
Case 2
UnPack = UnReduce(PackData, 2, ZIPFileData(X).USize - 1)
Case 3
UnPack = UnReduce(PackData, 3, ZIPFileData(X).USize - 1)
Case 4
UnPack = UnReduce(PackData, 4, ZIPFileData(X).USize - 1)
Case 5
UnPack = UnReduce(PackData, 5, ZIPFileData(X).USize - 1)
Case 6
UnPack = -10 'not supported
Case 7
UnPack = -10 'not supported
Case 8
Call Inflate(PackData, ZIPFileData(X).USize - 1, False)
Call Write_Uncompressed_Data(X, ToPath)
Case 9
Call Inflate(PackData, ZIPFileData(X).USize - 1, True)
Call Write_Uncompressed_Data(X, ToPath)
Case 10
UnPack = -10 'not supported
End Select
Else
MsgBox "Error in zipfile"
End If
Else
TotDir = ToPath
If Right(TotDir, 1) <> "\" And Right(TotDir, 1) <> "/" Then TotDir = TotDir & "\"
TotDir = TotDir & ZIPFileData(X).FileName
If CreatePath(TotDir) = False Then
'room for error message
End If
End If
End If
Next
Close FileNum
Erase PackData
End Function
Public Function Pack(ZipName As String, Files() As String, CompType As Integer, CompLevel As Integer, Optional IncludeDir As String = "") As Integer
End Function
Public Property Get CanUnpack() As Boolean
CanUnpack = m_Unpack_Supported
End Property
Public Property Get FileCount() As Long
FileCount = PackTotFiles
End Property
Public Property Get FileName(FileNum As Long) As String
If NotGood(FileNum) Then Exit Property
FileName = ZIPFileData(FileNum).FileName
End Property
Public Property Get CommentsFile(FileNum As Long) As String
If NotGood(FileNum) Then Exit Property
CommentsFile = ZIPFileData(FileNum).ComField
End Property
Public Property Get CommentsPack() As String
CommentsPack = PackComments
End Property
Public Property Get IsDir(FileNum As Long) As Boolean
If NotGood(FileNum) Then Exit Property
If ZIPFileData(FileNum).CSize = 0 Then
If Right(ZIPFileData(FileNum).FileName, 1) = "/" Then IsDir = True
End If
End Property
Public Property Get Method(FileNum As Long) As String
If NotGood(FileNum) Then Exit Property
Method = Methods(ZIPFileData(FileNum).Method)
End Property
Public Property Get CRC32(FileNum As Long) As Long
If NotGood(FileNum) Then Exit Property
CRC32 = ZIPFileData(FileNum).CRC32
End Property
Public Property Get Compressed_Size(FileNum As Long) As Long
If NotGood(FileNum) Then Exit Property
Compressed_Size = ZIPFileData(FileNum).CSize
End Property
Public Property Get UnCompressed_Size(FileNum As Long) As Long
If NotGood(FileNum) Then Exit Property
UnCompressed_Size = ZIPFileData(FileNum).USize
End Property
Public Property Get Encrypted(FileNum As Long) As Boolean
If NotGood(FileNum) Then Exit Property
Encrypted = (ZIPFileData(FileNum).Flags And 1) = 1
End Property
Public Property Get FileDateTime(FileNum As Long) As Date
If NotGood(FileNum) Then Exit Property
FileDateTime = GetZipDate(ZIPFileData(FileNum).FDate, ZIPFileData(FileNum).FTime)
End Property
Public Property Get SystemMadeBy(FileNum As Long) As String
If NotGood(FileNum) Then Exit Property
SystemMadeBy = SystemName(Fix(ZIPFileData(FileNum).VerMade / 256) And 255)
End Property
Public Property Get VersionMadeBy(FileNum As Long) As String
If NotGood(FileNum) Then Exit Property
VersionMadeBy = VersionTo(ZIPFileData(FileNum).VerMade And 255)
End Property
Public Property Get SystemNeeded(FileNum As Long) As String
If NotGood(FileNum) Then Exit Property
SystemNeeded = SystemName(Fix(ZIPFileData(FileNum).VerExt / 256) And 255)
End Property
Public Property Get VersionNeeded(FileNum As Long) As String
If NotGood(FileNum) Then Exit Property
VersionNeeded = VersionTo(ZIPFileData(FileNum).VerExt And 255)
End Property
Private Function NotGood(FileNum As Long) As Boolean
If FileNum = 0 Then NotGood = True: Exit Function
If FileNum > PackTotFiles Then NotGood = True: Exit Function
If PackFileType = 0 Then NotGood = True: Exit Function
End Function
Private Function Int2Lng(Value As Integer) As Long
If Value < 0 Then Int2Lng = &HFFFF& + Value + 1 Else Int2Lng = Value
End Function
Private Sub Write_Uncompressed_Data(FileNum As Long, ToPath As String)
Dim DSize As Long
DSize = DataSize
If DSize > 0 Then
If ZIPFileData(FileNum).CRC32 <> CRC.CalcCRC32File(PackData) Then 'calcCRC32(PackData) Then
MsgBox "CRC calculation failed"
End If
Else
If ZIPFileData(FileNum).CRC32 <> 0 Then
MsgBox "CRC error"
End If
End If
If ZIPFileData(FileNum).USize <> DSize Then
MsgBox "Error in decompressed size"
End If
If Write_File(ZIPFileData(FileNum).FileName, ToPath, PackData(), ZIPFileData(FileNum).FDate, ZIPFileData(FileNum).FTime) <> 0 Then
MsgBox "error writing file"
End If
End Sub
Private Function DataSize() As Long
On Error Resume Next
DataSize = UBound(PackData) + 1
If Err.Number <> 0 Then
Err.Clear
DataSize = 0
End If
End Function
Private Function SystemName(System As Byte) As String
Select Case System
Case 0: SystemName = "MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)"
Case 1: SystemName = "Amiga"
Case 2: SystemName = "2 - OpenVMS"
Case 3: SystemName = "UNIX"
Case 4: SystemName = "VM/CMS"
Case 5: SystemName = "Atari ST"
Case 6: SystemName = "OS/2 H.P.F.S."
Case 7: SystemName = "Macintosh"
Case 8: SystemName = "Z-System"
Case 9: SystemName = "CP/M"
Case 10: SystemName = "Windows NTFS"
Case 11: SystemName = "MVS (OS/390 - Z/OS)"
Case 12: SystemName = "VSE"
Case 13: SystemName = "Acorn Risc"
Case 14: SystemName = "VFAT"
Case 15: SystemName = "Alternate MVS"
Case 16: SystemName = "BeOS"
Case 17: SystemName = "Tandem"
Case 18: SystemName = "OS/400"
Case Else: SystemName = "UnKnown"
End Select
End Function
Private Function VersionTo(Version As Byte) As String
VersionTo = Fix(Version / 10) & "." & Version Mod 10
End Function
Private Function Methods(MethodType As Integer) As String
Select Case MethodType
Case 0: Methods = "No Compression"
Case 1: Methods = "Shrunk"
Case 2: Methods = "Reduce Factor 1"
Case 3: Methods = "Reduce Factor 2"
Case 4: Methods = "Reduce Factor 3"
Case 5: Methods = "Reduce Factor 4"
Case 6: Methods = "Imploded"
Case 7: Methods = "Tokenized"
Case 8: Methods = "Deflated"
Case 9: Methods = "Enhanced Deflating"
Case 10: Methods = "PKWARE Imploding"
Case 11: Methods = "Reserved"
Case 12: Methods = "BZip2"
Case Else: Methods = "Unknown"
End Select
End Function