DEFINE CLASS ZipUtils AS custom > cZipComment = "" > nErrorNum = 0 > cErrorMsg = "" > cZipFileName = "" > nBufferSize = 2^16-1 > hZipFile = 0 > > PROCEDURE GetZipComment > * End of central dir record: > * 1 4 end of central dir signature (0x06054b50) > * 5 2 number of this disk > * 7 2 number of the disk with the start of the central directory > * 9 2 total number of entries in the central directory on this disk > * 11 2 total number of entries in the central directory > * 13 4 size of the central directory > * 17 4 offset of start of central directory with respect to the starting disk number > * 21 2 .ZIP file comment size > * 23 nnn ZIP file comment (variable size) > > LPARAMETERS tcZipFileName > LOCAL lcZipSignature, lcZipEoCdrSignature, lcReadBuffer, lnPos, lcZipEoCdr, lcZipComment, lnZipCommentSize > > This.cZipComment = "" > This.cZipFileName = tcZipFileName > lcZipSignature = "PK" + CHR(03) + CHR(04) > lcZipEoCdrSignature = "PK" + CHR(05) + CHR(06) > > This.hZipFile = FOPEN(tcZipFileName) > IF This.hZipFile < 1 > This.cErrorMsg = "Cannot open ZIP file " + This.cZipFileName > This.nErrorNum = 1 > RETURN .F. > ENDIF > lcReadBuffer = FREAD(This.hZipFile, This.nBufferSize) > > IF NOT( lcZipSignature $ lcReadBuffer ) > FCLOSE(This.hZipFile) > This.cErrorMsg = "Cannot find ZIP signature for file " + This.cZipFileName > This.nErrorNum = 2 > RETURN .F. > ENDIF > > lnPos = 0 > FSEEK(This.hZipFile,0) > lcReadBuffer = "" > DO WHILE NOT FEOF(This.hZipFile) > lcReadBuffer = RIGHT(lcReadBuffer,4) + FREAD(This.hZipFile, This.nBufferSize) > lnPos = AT(lcZipEoCdrSignature, lcReadBuffer) > IF lnPos > 0 > lcReadBuffer = lcReadBuffer + FREAD(This.hZipFile, This.nBufferSize) > EXIT > ENDIF > ENDDO > > IF lnPos = 0 > FCLOSE(This.hZipFile) > This.cErrorMsg = "Cannot find the end of central index signature for file " + This.cZipFileName > This.nErrorNum = 3 > RETURN .F. > ENDIF > > lcZipEoCdr = SUBSTR(lcReadBuffer, lnPos) > *lcZipComment = SUBSTR(lcZipEoCdr,23) > lnZipCommentSize = ASC(SUBSTR(lcZipEoCdr,21)) + ASC(SUBSTR(lcZipEoCdr,22))*256 > This.cZipComment = SUBSTR(lcZipEoCdr,23, lnZipCommentSize) > FCLOSE(This.hZipFile) > RETURN .T. > ENDPROC > > PROCEDURE GetZipFilesList > * 1 4 central file header signature 4 bytes (0x02014b50) > * 5 2 version made by 2 bytes > * 7 2 version needed to extract 2 bytes > * 9 2 general purpose bit flag 2 bytes > * 11 2 compression method 2 bytes > * 13 2 last mod file time 2 bytes > * 15 2 last mod file date 2 bytes > * 17 4 crc-32 4 bytes > * 21 4 compressed size 4 bytes > * 25 4 uncompressed size 4 bytes > * 29 2 file name length 2 bytes > * 31 2 extra field length 2 bytes > * 33 2 file comment length 2 bytes > * 35 2 disk number start 2 bytes > * 37 2 internal file attributes 2 bytes > * 39 4 external file attributes 4 bytes > * 43 4 relative offset of local header 4 bytes > * 47 file name (variable size) > * extra field (variable size) > * file comment (variable size) > > LPARAMETERS tcZipFileName, taFileList > LOCAL lcZipSignature, lcZipEoCdrSignature, lcReadBuffer, lnPos, lcZipEoCdr, lcZipComment, lnZipCommentSize > LOCAL lcZipCfh, lnFileCount, lnFileNameLen, lnExtraFieldLen, lnFileCommentLen, lnCfhFixLen, llZipEoCdrSignature > > This.cZipFileName = tcZipFileName > lcZipSignature = "PK" + CHR(03) + CHR(04) > lcZipEoCdrSignature = "PK" + CHR(05) + CHR(06) > lcZipCfhSignature = "PK" + CHR(01) + CHR(02) > > lnFileCount = 0 > > This.hZipFile = FOPEN(tcZipFileName) > > IF This.hZipFile < 1 > This.cErrorMsg = "Cannot open ZIP file " + This.cZipFileName > This.nErrorNum = 1 > RETURN -1 > ENDIF > lcReadBuffer = FREAD(This.hZipFile, This.nBufferSize) > > IF NOT( lcZipSignature $ lcReadBuffer ) > FCLOSE(This.hZipFile) > This.cErrorMsg = "Cannot find ZIP signature for file " + This.cZipFileName > This.nErrorNum = 2 > RETURN -1 > ENDIF > > lnPos = 0 > FSEEK(This.hZipFile,0) > lcReadBuffer = "" > DO WHILE NOT FEOF(This.hZipFile) > lcReadBuffer = lcReadBuffer + FREAD(This.hZipFile, This.nBufferSize) > lnPos = AT(lcZipCfhSignature, lcReadBuffer) > IF lnPos > 0 > lcReadBuffer = SUBSTR(lcReadBuffer, lnPos) > EXIT > ENDIF > ENDDO > > IF lnPos = 0 > FCLOSE(This.hZipFile) > This.cErrorMsg = "Cannot find central file header signature for file " + This.cZipFileName > This.nErrorNum = 3 > RETURN -1 > ENDIF > > llZipEoCdrSignature = (lcZipEoCdrSignature $ lcReadBuffer) > > DO WHILE NOT FEOF(This.hZipFile) AND NOT llZipEoCdrSignature > * --sb-- 02/25/2004 -- Fixed bug > lcReadBuffer = lcReadBuffer + FREAD(This.hZipFile, This.nBufferSize) > *lcReadBuffer = RIGHT(lcReadBuffer,8) + FREAD(This.hZipFile, This.nBufferSize) > IF (lcZipEoCdrSignature $ lcReadBuffer) > llZipEoCdrSignature = .T. > EXIT > ENDIF > ENDDO > FCLOSE(This.hZipFile) > > IF NOT llZipEoCdrSignature > *FCLOSE(This.hZipFile) > This.cErrorMsg = "Cannot find the end of central index signature for file " + This.cZipFileName > This.nErrorNum = 3 > RETURN -1 > ENDIF > > lcZipCfh = lcReadBuffer > lcReadBuffer = "" > > ccCfhFixLen = 47 > > > > DO WHILE lcZipCfh = lcZipCfhSignature > lnFileCount = lnFileCount + 1 > DIMENSION taFileList[lnFileCount, 9] > lnFileNameLen = This.Short2Num(SUBSTR(lcZipCfh,29,2)) > lnExtraFieldLen = This.Short2Num(SUBSTR(lcZipCfh,31,2)) > lnFileCommentLen = This.Short2Num(SUBSTR(lcZipCfh,33,2)) > lnCfhLen = ccCfhFixLen + lnFileNameLen + lnExtraFieldLen + lnFileCommentLen > * Name > taFileList[lnFileCount, 1] = SUBSTR(lcZipCfh, 47, lnFileNameLen) > * Size > taFileList[lnFileCount, 2] = This.Long2Num(SUBSTR(lcZipCfh,25,4)) > * Date & Time > taFileList[lnFileCount, 3] = This.ConvertDosDate(This.Short2Num(SUBSTR(lcZipCfh,15,2))) > taFileList[lnFileCount, 4] = This.ConvertDosTime(This.Short2Num(SUBSTR(lcZipCfh,13,2))) > taFileList[lnFileCount, 5] = "" > * Compressed size > taFileList[lnFileCount, 6] = This.Long2Num(SUBSTR(lcZipCfh,21,4)) > * File Comment > IF lnFileCommentLen > 0 > taFileList[lnFileCount, 7] = SUBSTR(lcZipCfh, 47 + lnFileNameLen, lnFileCommentLen ) > ELSE > taFileList[lnFileCount, 7] = "" > ENDIF > taFileList[lnFileCount, 8] = "" > taFileList[lnFileCount, 9] = "" > > lcZipCfh = SUBSTR(lcZipCfh, lnCfhLen) > ENDDO > > RETURN lnFileCount > ENDPROC > > PROCEDURE Long2Num(tcLong) > DECLARE RtlMoveMemory IN WIN32API AS RtlCopyLong ; > INTEGER @ DestNum, ; > STRING @ pVoidSource, ; > INTEGER nLength > LOCAL nNum > nNum = 0 > =RtlCopyLong(@nNum, tcLong, 4) > RETURN nNum > *----------------------------------------------------------------------------- > > PROCEDURE Short2Num(tcInt) > * Converts a 16 bit signed integer in a structure to a VFP Numeric > LOCAL b0,b1,nRetVal > b0 = ASC(tcInt) > b1 = ASC(SUBSTR(tcInt,2,1)) > IF b1<128 > * > * positive - do a straight conversion > * > nRetVal=b1 * 256 + b0 > ELSE > * > * negative value - take twos complement and negate > * > b1=255-b1 > b0=256-b0 > nRetVal= -( (b1 * 256) + b0) > ENDIF > RETURN nRetVal > ENDPROC >****************************************************************** > >PROCEDURE ConvertDosDate(tnDosDate) >lnDosDate = BITAND(tnDosDate, 0xFFFF) >* Year 7 bit, Month 4 bit, Day 5 bit >RETURN DATE( 1980 + BITRSHIFT(lnDosDate, 9), ; > BITRSHIFT(BITAND(lnDosDate, 0x1E0), 5), ; > BITAND(lnDosDate, 0x1F)) >ENDPROC >****************************************************************** > >PROCEDURE ConvertDosTime(tnDosTime) >lnDosTime = BITAND(tnDosTime, 0xFFFF) >* Hours 5 bit, Minutes 6 bit, Bi-Seconds 5 bit >RETURN PADL(BITRSHIFT(lnDosTime, 11), 2,"0") + ":" + ; > PADL(BITRSHIFT(BITAND(lnDosTime, 0x7E0), 5), 2,"0") + ":" + ; > PADL(BITAND(lnDosTime, 0x1F) * 2, 2,"0") >ENDPROC > > >ENDDEFINE >>