PureZIP library : ZIP / UNZIP files

All PureFORM, JaPBe, Libs and useful code maintained by gnozal

Moderator: gnozal

webbmeister
User
User
Posts: 62
Joined: Thu Mar 16, 2006 5:20 pm
Location: Sheffield, UK

Post by webbmeister »

gnozal wrote:Sorry, I don't know the zip package you are using, it does not seem to be PureZIP. Maybe the author can help ?
Now I'm confused. This was the original code.


Code: Select all


; Final Version Working
; Use has include File !

; Num3 - 12/03/2006


Global ZIP_PERCENTAGE.l

#dictionary = 102400

#UNZ_OK                           = 0
#UNZ_END_OF_LIST_OF_FILE          = -100
#UNZ_EOF                          = 0
#UNZ_PARAMERROR                   = -102
#UNZ_BADZIPFILE                   = -103
#UNZ_INTERNALERROR                = -104
#UNZ_CRCERROR                     = -105

#Z_DEFLATED                       = 8

#Z_NO_COMPRESSION                 = 0
#Z_BEST_SPEED                     = 1
#Z_BEST_COMPRESSION               = 9
#Z_DEFAULT_COMPRESSION            = -1

#APPEND_STATUS_CREATE             = 0
#APPEND_STATUS_CREATEAFTER        = 1
#APPEND_STATUS_ADDINZIP           = 2

#ZLIBWAPI_LIB = 11





Structure tm_date
  tm_sec.l;            /* seconds after the minute - [0,59] */
  tm_min.l;            /* minutes after the hour - [0,59] */
  tm_hour.l;           /* hours since midnight - [0,23] */
  tm_mday.l;           /* day of the month - [1,31] */
  tm_mon.l;            /* months since January - [0,11] */
  tm_year.l;           /* years - [1980..2044] */
EndStructure

Structure unz_global_info
  number_entry.l;         /* total number of entries in
  size_comment.l;         /* size of the global comment of the zipfile */
EndStructure

Structure unz_file_info
  Version.l;              /* version made by                 2 bytes */
 version_needed.l;       /* version needed to extract       2 bytes */
 flag.l  ;                 /* general purpose bit flag        2 bytes */
 compression_method.l;   /* compression method              2 bytes */
 dosDate.l;              /* last mod file date in Dos fmt   4 bytes */
 crc.l   ;                  /* crc-32                          4 bytes */
 compressed_size.l;      /* compressed size                 4 bytes */
 uncompressed_size.l;    /* uncompressed size               4 bytes */
  size_filename.l;        /* filename length                 2 bytes */;
  size_file_extra.l;      /* extra field length              2 bytes */
  size_file_comment.l;    /* file comment length             2 bytes */
  disk_num_start.l;       /* disk number start               2 bytes */
  internal_fa.l;          /* internal file attributes        2 bytes */
  external_fa.l;          /* external file attributes        4 bytes */
  tmu_date.tm_date;
  FileName.s;  /* Extra-Info
EndStructure

Structure zip_file_info
  tm_zip.tm_date
  dosDate.l
  internal_fa.l
  external_fa.l
EndStructure




Procedure ZIP_Lib_Init()
  Global Zip_DLL
  Zip_DLL=LoadLibraryM(?zipdll)
  
  Global unzOpen.l,unzGetGlobalInfo.l,unzGoToFirstFile.l,unzGoToNextFile.l
  Global unzGetCurrentFileInfo.l, unzReadCurrentFile.l,zipOpen.l, unzOpenCurrentFile.l
  Global zipOpenNewFileInZip.l, zipWriteInFileInZip.l, zipCloseFileInZip.l,zipClose.l
  
  If Zip_DLL
    unzOpen.l=GetProcAddressM(Zip_DLL,"unzOpen")
    unzGetGlobalInfo.l=GetProcAddressM(Zip_DLL,"unzGetGlobalInfo")
    unzGoToFirstFile.l=GetProcAddressM(Zip_DLL,"unzGoToFirstFile")
    unzGoToNextFile.l=GetProcAddressM(Zip_DLL,"unzGoToNextFile")
    unzGetCurrentFileInfo.l=GetProcAddressM(Zip_DLL,"unzGetCurrentFileInfo")
    unzReadCurrentFile.l=GetProcAddressM(Zip_DLL,"unzReadCurrentFile")
    unzOpenCurrentFile.l=GetProcAddressM(Zip_DLL,"unzOpenCurrentFile")
    zipOpen.l=GetProcAddressM(Zip_DLL,"zipOpen")
    zipOpenNewFileInZip.l=GetProcAddressM(Zip_DLL,"zipOpenNewFileInZip")
    zipWriteInFileInZip.l=GetProcAddressM(Zip_DLL,"zipWriteInFileInZip")
    zipCloseFileInZip.l=GetProcAddressM(Zip_DLL,"zipCloseFileInZip")
    zipClose.l=GetProcAddressM(Zip_DLL,"zipClose")
    ProcedureReturn #True
  EndIf
  
  ; If OpenLibrary(#ZLIBWAPI_LIB,"zlibwapi.dll")
  ; ProcedureReturn #True
  ; Else
  ; ProcedureReturn #False
  ; EndIf
EndProcedure

Procedure ZIP_Lib_Stop()
  If FreeLibraryM(Zip_DLL)
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure ZIP_FileCount(Zip_FileName$)
  
  GlobalInfo.unz_global_info
  FileInfo.unz_file_info
  
  Handle.l=CallFunctionFast(unzOpen,Zip_FileName$)
  If Handle
    result.l=CallFunctionFast(unzGetGlobalInfo,Handle,@GlobalInfo)
    NrOfCompressed.l=GlobalInfo\number_entry
    ProcedureReturn NrOfCompressed
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure ZIP_GetFileInfo(Zip_FileName$,FileNumber.l,*FileInfo.unz_file_info)
  
  GlobalInfo.unz_global_info
  
  FileName=AllocateMemory(500)
  Comment=AllocateMemory(500)
  ExtraField=AllocateMemory(500)
  
  Handle.l=CallFunctionFast(unzOpen,Zip_FileName$)
  If Handle
    result.l=CallFunctionFast(unzGoToFirstFile,Handle)
    For a=1 To FileNumber
      result.l=CallFunctionFast(unzGoToNextFile,Handle)
    Next
    result.l=CallFunctionFast(unzGetCurrentFileInfo,Handle,*FileInfo,FileName,100,ExtraField,100,Comment,100)
    *FileInfo\FileName=Trim(PeekS(FileName))
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
  
EndProcedure

Procedure ZIP_ExtractFile(Zip_FileName$,FileNumber.l,Output_Path.s,CreatePath.b)
  
  GlobalInfo.unz_global_info
  FileInfo.unz_file_info
  FileName=AllocateMemory(500)
  Comment=AllocateMemory(500)
  ExtraField=AllocateMemory(500)
  
  Handle.l=CallFunctionFast(unzOpen,Zip_FileName$)
  If Handle
    result.l=CallFunctionFast(unzGoToFirstFile,Handle)
    For a=1 To FileNumber
      result.l=CallFunctionFast(unzGoToNextFile,Handle)
    Next
    result.l=CallFunctionFast(unzGetCurrentFileInfo,Handle,FileInfo,FileName,100,ExtraField,100,Comment,100)
    FileInfo\FileName=Trim(PeekS(FileName))
    
    result.l=CallFunctionFast(unzOpenCurrentFile,Handle)
    Size.l=FileInfo\uncompressed_size
    
    If Size=0 And CreatePath=#True
      
      filename$=FileInfo\FileName
      
      Count.l=CountString(filename$,"/") 
      
      Dim path.s(Count)
      For a=1 To Count
        path(a)=StringField(filename$,a,"/")
      Next
      
      filename_a$=""
      
      For a=1 To Count
        
        filename_a$+path(a)+"/"
        
        If FileSize(Output_Path+filename_a$)<>-2
          CreateDirectory(Output_Path+filename_a$)
        EndIf
        
        
      Next
      
      Dim path.s(0)
      
      
    ElseIf Size>0
      
      divider.f=100/ (Size)
      
      filename$=Trim(PeekS(FileName))
      
      If CreatePath=#False
        ReplaceString(filename$,"/","",2)
        filename$=GetFilePart(filename$)
      EndIf
      
      If CreateFile(0,Output_Path+filename$)
        FileBuffersSize(0,#dictionary+1)
        out_buffer.l=AllocateMemory(#dictionary)
        current_size.l=0
        Repeat
          
          result.l=CallFunctionFast(unzReadCurrentFile,Handle,out_buffer,#dictionary)
          
          WriteData(0,out_buffer,result)
          FlushFileBuffers(0)
          current_size+result
          ZIP_PERCENTAGE.l=Int(current_size*divider)
        Until result=0
        
        CloseFile(0)
        FreeMemory(out_buffer)
        date.l=Date(FileInfo\tmu_date\tm_year,FileInfo\tmu_date\tm_mon,FileInfo\tmu_date\tm_mday,FileInfo\tmu_date\tm_hour,FileInfo\tmu_date\tm_min,0)
        SetFileDate(Output_Path+filename$,#PB_Date_Created,date.l)
      EndIf
      
      
    EndIf
    
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

Procedure ZIP_FileCreate(Zip_FileName$,Append_Method.l); Return ZipHandle if suceful
  
  If ZIP_FileCount(Zip_FileName$)>0
    Append_Method = #APPEND_STATUS_ADDINZIP
  EndIf
  
  Handle.l=CallFunctionFast(zipOpen,Zip_FileName$,Append_Method)
  If Handle
    ProcedureReturn Handle 
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

Procedure ZIP_FileAdd(ZipHandle.l,filename$,Archive_Filename$); Add Files to zip
  
  file_date.l=GetFileDate(filename$,#PB_Date_Created)
  
  zfi.zip_file_info
  zfi\tm_zip\tm_sec=Val(FormatDate("%ss",file_date))
  zfi\tm_zip\tm_min=Val(FormatDate("%ii",file_date))
  zfi\tm_zip\tm_hour=Val(FormatDate("%hh",file_date))
  zfi\tm_zip\tm_mday=Val(FormatDate("%dd",file_date))
  zfi\tm_zip\tm_mon=Val(FormatDate("%mm",file_date))
  zfi\tm_zip\tm_year=Val(FormatDate("%yyyy",file_date))
  zfi\dosDate=0
  zfi\internal_fa=0
  zfi\external_fa=0
  
  result=CallFunctionFast(zipOpenNewFileInZip,ZipHandle,@Archive_Filename$,@zfi,#Null,0,#Null,0,#Null,#Z_DEFLATED,#Z_BEST_COMPRESSION)
  
  in_filesize.l=FileSize(filename$)
  
  divider.f=100/ (in_filesize)
  
  If ReadFile(0,filename$)
    ;- Bug Here!
    FileBuffersSize(0,#dictionary+1) ; Remove the +1 and all files you pack get corrupted!
    Buffer.l=AllocateMemory(#dictionary)
    tab.l=0
    While Not Eof(0)
      lenght.l=ReadData(0,Buffer,#dictionary)
      If CallFunctionFast(zipWriteInFileInZip,ZipHandle,Buffer,lenght)<>#UNZ_OK
        ProcedureReturn #False
      EndIf
      
      ZIP_PERCENTAGE.l=Int(Loc(0)*divider)
      Debug Str(ZIP_PERCENTAGE)+"%"
      Delay(10)
      
    Wend
    
    CloseFile(0)
    result=CallFunctionFast(zipCloseFileInZip,ZipHandle)
    FreeMemory(Buffer)
    ProcedureReturn #True
    
  EndIf
  
  
  
EndProcedure

Procedure ZIP_FileClose(ZipHandle.l)
  CallFunctionFast(zipClose,ZipHandle,0)
EndProcedure


Procedure ZIP_TEST(); Small procedure to test the procedures
  
  If ZIP_Lib_Init()
    
    
    ;****  Create Zip File **********
    MessageRequester("Message","Select a new zip filename to create")
    

    
    file.s=SaveFileRequester("Select a Zip Filename to save","*.zip","Zip|*.zip",0)
    
              MessageRequester("message",file)
    
    If file
      add_file.s=OpenFileRequester("Select File to Add","*.*","*.*",1)
      
      If add_file
      
      MessageRequester("message",add_file)

        Handle.l=ZIP_FileCreate(file,#APPEND_STATUS_CREATE)
        
        If Handle
          
          MessageRequester("Message","Select a file to insert into the zip")
          
          
          If ZIP_FileAdd(Handle,add_file,GetFilePart(add_file))

            
            Debug "File Added to Archive..."
            
          EndIf
          
          
          ZIP_FileClose(Handle)
          
        EndIf
        
      EndIf
      
      
    EndIf
    
    
    
    file.s=OpenFileRequester("Select a Zip","*.zip","Zip|*.zip",0)
    
    If file
      
      myFileinfo.unz_file_info
      
      Count.l=ZIP_FileCount(file)
      Debug "This zip has " + Str(Count) + " itens"
      
      out_path.s=PathRequester("Extracto to:" ,"d:\temp")
      For a=0 To Count-1
        
        ZIP_GetFileInfo(file,a,@myFileinfo)
        Filesize.l=myFileinfo\uncompressed_size
        
        If Filesize>0
          
          Debug "Filename: " + myFileinfo\FileName
          Debug "Compressed Size: " + Str(myFileinfo\compressed_size)
          Debug "Uncompressed Size: "+ Str(Filesize)
          
          If ZIP_ExtractFile(file,a,out_path,#False)
            Debug "File Extracted"
          EndIf
          Debug "***************"
          
        Else
          Debug "Directory: " + myFileinfo\FileName
          Debug "***************"
        EndIf
        
      Next
      
    EndIf
    
    
    
    ZIP_Lib_Stop()
  EndIf
  End
EndProcedure

; Call ZIP_Test to test the procedures...
DataSection
zipdll: IncludeBinary "zlibwapi.dll"
EndDataSection

ZIP_TEST()


End




gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

Yep, it's not PureZIP. I think it's Num3 code ?
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Yup, my very own code & bug :D

I'm checking...
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Bug fixed, you can download the corrected version HERE:

PB_ZIP.zip (46k)
Image

Important Notice
This include file is not related to gnozal's great Zip Library.
This is another library, and it will be oficially released when PB 4.0 final is released.

You must place PBOSL_LoadDLLMemory in the PureLibraries\UserLibraries directory!
(This way the zip.dll will be included in the final executable and doesn't need to be distributed has a separate file)

Uncomment ZIP_TEST() procedure at the end of the code to test the package.

About the bug
I was forgetting to free the unzopen function.... upsss ;)

Your code was also malformed, it should be like this:

Code: Select all


;-------------------------------
; This block should be outside the loop

ZIP_Lib_Init()
myFileinfo.unz_file_info

;-------------------------------

jumper:

file.s=OpenFileRequester("Select a Zip","*.zip","Zip|*.zip",0)

If file
  
  
  
  Count.l=ZIP_File_Count(file)
  Debug "This zip has " + Str(Count) + " itens"
  
  ; out_path.s=PathRequester("Extracto to:" ,"d:\temp")
  For a=0 To Count-1
    
    ZIP_File_GetInfo(file,a,@myFileinfo)
    Filesize.l=myFileinfo\uncompressed_size
    
    If Filesize>0
      
      Debug "Filename: " + myFileinfo\FileName
      Debug "Compressed Size: " + Str(myFileinfo\compressed_size)
      Debug "Uncompressed Size: "+ Str(Filesize)
      
      ; If ZIP_ExtractFile(file,a,out_path,#False)
      ;Debug "File Extracted"
      ; EndIf
      Debug "***************"
      
    Else
      Debug "Directory: " + myFileinfo\FileName
      Debug "***************"
    EndIf
    
  Next
  
EndIf

  
Goto jumper 

;-------------------------------
; This block should be outside the loop

ZIP_Lib_Stop()
End

;-------------------------------


webbmeister
User
User
Posts: 62
Joined: Thu Mar 16, 2006 5:20 pm
Location: Sheffield, UK

Post by webbmeister »

Thanks Num3, That did the trick.
webbmeister
User
User
Posts: 62
Joined: Thu Mar 16, 2006 5:20 pm
Location: Sheffield, UK

Post by webbmeister »

Num3, are you thinking of including an encryption option with your code?
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Yes, if someone tells me how it's done ;)

I've searched for it, but didn't get any straight answers...
webbmeister
User
User
Posts: 62
Joined: Thu Mar 16, 2006 5:20 pm
Location: Sheffield, UK

Post by webbmeister »

Num3 wrote:Yes, if someone tells me how it's done ;)

I've searched for it, but didn't get any straight answers...
Just come across another strange one... I get a number 1 appear in the console window whenever I extract from an archive. I have tracked this down to be within the FILE_ZIP_EXTRACT procedure, but can't seem to find what is generating it!
Any Ideas?
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Any chances for a linux version?
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Eruditio
New User
New User
Posts: 2
Joined: Mon Jun 19, 2006 4:02 am

Compression Size

Post by Eruditio »

I don't know if this has been addressed already, but the version of this library for PB 4.0 has a serious problem, unless I am not using it correctly.
When I use it (either with the PureZIP_Archive_Compress or simply by the PureZIP_AddFile function), the packed size of the file is not correct if the original file was >= 1 Kilobyte. If for example, the file is 176KB, the packed size is 176,128 byes. The file in question SHOULD be 180,224 (180,224/1024 = 176 KB). Similar tests show that it consistently packs (# of kilobytes * 1000) bytes instead of (# of kilobytes * 1024) bytes.

Again, this may be something idiotic that I am doing, but it looks like a bug to me. The lines that I am using to compress the files using either of the two compression functions are below:

Code: Select all

PureZIP_Archive_Compress(GetDatabaseString(Database,1),#True)
or

Code: Select all

PureZIP_AddFile(ArchiveName,GetDatabaseString(Database,1),#PureZIP_StorePathAbsolute )
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Re: Compression Size

Post by gnozal »

Eruditio wrote:I don't know if this has been addressed already, but the version of this library for PB 4.0 has a serious problem
Note that you have to download the purebasic beta libs ( www.purebasic.com/beta ) when using PureZIP because of the ReadData()/Eof() bug.
References :
- http://www.purebasic.fr/english/viewtop ... c&start=44
- http://www.purebasic.fr/english/viewtop ... highlight=
If this doesn't fix your problem please report again.
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

Inf0Byt3 wrote:Any chances for a linux version?
No.
The ZLIB package I am using ( http://www.winimage.com/zLibDll/ ) only exists for Windows.
Sorry.
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
Eruditio
New User
New User
Posts: 2
Joined: Mon Jun 19, 2006 4:02 am

Post by Eruditio »

Yep, that did it! Thanks so much for your prompt and very helpful reply. :P
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Post by zapman* »

Unfortunatelly, I can't use the fantastic Gnozal library because of a compatibility problem with the SafeThread mode.

So, I had to use the Num3 one and I made some modification to it:

Code: Select all

; Num3 - 29/04/2006 (Severe bug fix)
; a small bug fixed by Zapman in the File_Extract function - 18/06/2006
; ZIP_ExtractFiles function by Zapman - 18/06/2006
; Function calls modified to be Unicode compatible - Zapman - 18/06/2006
;
; need the "zlibwapi.dll" file to be in the same folder as your program
If this work is helpfull for anybody, it can be downloaded at:
http://www.rankspirit.com/downloads/num3_pb_zip.zip
Don't try - DO it !
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

zapman* wrote:Unfortunatelly, I can't use the fantastic Gnozal library because of a compatibility problem with the SafeThread mode.
Did you try the threadsafe version ?

http://www.purebasic.fr/english/viewtopic.php?t=22347
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
Post Reply