The function HB_UnzipFile(...) in ziparc.prg of Harbour has a few bugs.
I prepared a modified function HB_UnzipFileRevd(...) in this module and link with my Harbour applications. I use HB_UnzipFileRevd(...) instead of HB_UnzipFile(...) when using Harbour.
hbunzip.prg:
Code: Select all
// hbunzip.prg
#include "fileio.ch"
#define UNZ_OK 0 // from hbmzip.ch
#define REVD
#ifdef __XHARBOUR__
#error This module is for Harbour Only
#else
//----------------------------------------------------------------------------//
#ifdef REVD
FUNCTION hb_UnzipFileRevd( cFileName, bUpdate, lWithPath, cPassword, cPath, acFiles, bProgress )
#else
FUNCTION hb_UnzipFile( cFileName, bUpdate, lWithPath, cPassword, cPath, acFiles, bProgress ) // ziparc.prg
#endif
LOCAL lRetVal := .T.
LOCAL hUnzip
LOCAL nErr
LOCAL nPos
LOCAL cZipName
LOCAL lExtract
LOCAL hHandle
LOCAL nSize
LOCAL nRead
LOCAL nLen
LOCAL dDate
LOCAL cTime
LOCAL cBuffer := Space( 32768 )
#ifdef REVD
IF lWithPath == nil
lWithPath := .t.
ENDIF
#else
IF hb_defaultValue( lWithPath, .F. ) .AND. ! hb_DirExists( cPath ) .AND. hb_DirCreate( cPath ) != 0
lRetVal := .F.
ENDIF
#endif
IF Empty( cPassword )
cPassword := NIL
ENDIF
IF Set( _SET_DEFEXTENSIONS )
cFileName := hb_FNameExtSetDef( cFileName, ".zip" )
ENDIF
IF Empty( hUnzip := hb_unzipOpen( cFileName ) )
lRetVal := .F.
ELSE
IF HB_ISNUMERIC( acFiles ) .OR. ;
HB_ISSTRING( acFiles )
acFiles := { acFiles }
ENDIF
IF Empty( cPath )
cPath := hb_FNameDir( cFileName )
ENDIF
cPath := hb_DirSepAdd( cPath )
nPos := 0
nErr := hb_unzipFileFirst( hUnzip )
DO WHILE nErr == 0
nPos++
IF hb_unzipFileInfo( hUnzip, @cZipName, @dDate, @cTime,,,, @nSize ) == 0
/* NOTE: As opposed to original hbziparch we don't do a second match without path. */
#ifdef REVD
lExtract := Empty( acFiles ) .OR. ;
AScan( acFiles, nPos ) > 0 .OR. ;
AScan( acFiles, {| cMask | hb_FileMatch( StrTran( cZipName, '/', '\' ), StrTran( cMask, '/', '\' ) ) } ) > 0
IF lExtract .AND. ( hHandle := FCreateEx( cPath, cZipName, lWithPath ) ) != F_ERROR
#else
lExtract := Empty( acFiles ) .OR. ;
AScan( acFiles, nPos ) > 0 .OR. ;
AScan( acFiles, {| cMask | hb_FileMatch( cZipName, cMask ) } ) > 0
IF lExtract .AND. ( hHandle := FCreate( cPath + cZipName ) ) != F_ERROR
#endif
IF hb_unzipFileOpen( hUnzip, cPassword ) != UNZ_OK
lRetVal := .F.
EXIT
ENDIF
nRead := 0
DO WHILE ( nLen := hb_unzipFileRead( hUnzip, @cBuffer, hb_BLen( cBuffer ) ) ) > 0
IF HB_ISEVALITEM( bProgress )
nRead += nLen
Eval( bProgress, nRead, nSize )
ENDIF
FWrite( hHandle, cBuffer, nLen )
ENDDO
hb_unzipFileClose( hUnzip )
FClose( hHandle )
hb_FSetDateTime( cPath + cZipName, dDate, cTime )
IF HB_ISEVALITEM( bUpdate )
Eval( bUpdate, cZipName, nPos )
ENDIF
ENDIF
ENDIF
nErr := hb_unzipFileNext( hUnzip )
ENDDO
hb_unzipClose( hUnzip )
ENDIF
RETURN lRetVal
//----------------------------------------------------------------------------//
#ifdef REVD
static function FCreateEx( cPath, cZipName, lWithPath )
local nRet := -1
local cFile
cZipName := StrTran( cZipName, '/', '\' )
cFile := cPath + If( lWithPath, cZipName, cFileNoPath( cZipName ) )
cPath := cFilePath( cFile )
if ! hb_DirExists( cPath )
hb_DirBuild( cPath )
endif
return FCreate( cFile )
//----------------------------------------------------------------------------//
#endif // ifdef REVD
#endif // ifndef __XHARBOUR__