PureZIP library : ZIP / UNZIP files

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

Moderator: gnozal

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

Post by gnozal »

webbmeister wrote:Found the zip.pb example at last.
Using zip.pb (Num 3) on PB4B7 i get the following error message when I try to compile.....

[COMPILER] Line 34: 'Structure' or 'Interface' already declared: tm_date

any ideas?
If it's already declared, just inactivate the lines.

Code: Select all

; 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
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
webbmeister
User
User
Posts: 62
Joined: Thu Mar 16, 2006 5:20 pm
Location: Sheffield, UK

Post by webbmeister »

Where do I place the dll and lib files for this?
webbmeister
User
User
Posts: 62
Joined: Thu Mar 16, 2006 5:20 pm
Location: Sheffield, UK

Post by webbmeister »

Look folks, you will have to bear with me on this. Im not a beginner as far as general programming technique is concerned, but in terms of using libs & dlls etc and where to put them, I am a big clueless.
What I want to do is ZIP c:\test.txt to c:\test.zip. I am using version 4 beta 7. A simple working example would be great + which lib files / dlls do I need to place where.
I know it's a lot to ask :wink:
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

webbmeister wrote:Look folks, you will have to bear with me on this. Im not a beginner as far as general programming technique is concerned, but in terms of using libs & dlls etc and where to put them, I am a big clueless.
What I want to do is ZIP c:\test.txt to c:\test.zip. I am using version 4 beta 7. A simple working example would be great + which lib files / dlls do I need to place where.
I know it's a lot to ask :wink:
DLL in the same directory than the EXE
Libraries in %Purebasic%\PureLibraries\UserLibraries
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
PAMKKKKK
User
User
Posts: 18
Joined: Sun May 01, 2005 7:55 am
Location: Germany Braunschweig
Contact:

Dos Date to PBDate

Post by PAMKKKKK »

Hi gnozal!

I puzzled a bit arround the DOS Formated Date in the PureZIP_GetFileInfo Function.
I found some hints in the WinAPI-Help for the function DosDateTimeToFileTime_().

Here is my solution in pure PureB (only tested on WinXP !):

Code: Select all

ArchiveFileName.s = "c:\temp\test.zip"

Procedure.l DosDateToPBdate(dosDate.l)
  ; Converts a Zip-Dos-Date to PureBasic-Date
  
  ; The dosdate count only every 2 second. So you must do: second * 2
  ; Format is: %hh:%ii:%ss
  TimeDos.s = Str(dosDate>>11&%11111) +":" + Str(dosDate>>5&%111111) +":" + Str(dosDate&%11111 * 2)
  ; The dosdate beginns to count from 01.January.1980. So you must add 1980 to the Year
  ; DateDos.s = Format is the German dateformat : %dd.%mm.%yyyy
  DateDos.s = Str(dosDate>>16&%11111) +"." + Str(dosDate>>21&%1111) +"." + Str(dosDate>>25&%1111111 + 1980)
  
  ; Parse The Date and Time to System Date
  ProcedureReturn ParseDate("%dd.%mm.%yyyy %hh:%ii:%ss", DateDos + " " + TimeDos) 
EndProcedure

FileInfo.PureZIP_FileInfo

For FileNumberInArchive = 0 To PureZIP_GetFileCount(ArchiveFileName.s)
  PureZIP_GetFileInfo(ArchiveFileName.s, FileNumberInArchive, @FileInfo)
  
  Debug FileInfo\Version			; version made by
  Debug FileInfo\VersionNeeded		; version needed to extract
  Debug FileInfo\flag		; general purpose bit Flag
  Debug FileInfo\CompressionMethod	; compression method     
  
  ; last mod file date (in Dos format) 
  Debug FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss",DosDateToPBdate(FileInfo\dosDate)) 
  
  Debug FileInfo\Crc32			; crc-32
  Debug FileInfo\CompressedSize		; compressed size
  Debug FileInfo\unCompressedSize	; uncompressed size
  Debug FileInfo\SizeFilename		; filename length
  Debug FileInfo\SizeFileExtra		; extra field length
  Debug FileInfo\SizeFileComment		; file comment length
  Debug FileInfo\DiskNumStart		; disk number start
  Debug FileInfo\internal_fa		; internal file attributes
  Debug FileInfo\external_fa		; external file attributes
  
  ; The month in tm_date structur is month -1 for compatible reasons !! 
  ; See: http://www.purebasic.fr/english/viewtopic.php?p=115673#115673
  ; tm_date (Date)  
  Debug Str(FileInfo\tmu_date\tm_mday)+"."+Str(FileInfo\tmu_date\tm_mon)+"."+Str(FileInfo\tmu_date\tm_year)
  ; tm_date (Time)
  Debug Str(FileInfo\tmu_date\tm_hour)+":"+Str(FileInfo\tmu_date\tm_min)+":"+Str(FileInfo\tmu_date\tm_sec)
  
  Debug FileInfo\FileName		; filename
  Debug "-------------------------------------------------------"
Next
Please do this code in your Helpfile as an example for using the PureZIP_GetFileInfo()
Develop Standards, and you develop the World!
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Re: Dos Date to PBDate

Post by gnozal »

PAMKKKKK wrote:Please do this code in your Helpfile as an example for using the PureZIP_GetFileInfo()
Thanks.
For the next release.
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
User avatar
cabaptista
User
User
Posts: 86
Joined: Sun Nov 30, 2003 11:42 pm
Location: Lisboa, Portugal

Many Thanks

Post by cabaptista »

Very good library. Thanks for sharing it with us.

Just a thing: It is possible to add a parameter to AddFile(s) Function(s) telling what is the compreesion rate that we want to compress files ?
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Re: Many Thanks

Post by gnozal »

cabaptista wrote:Very good library. Thanks for sharing it with us.

Just a thing: It is possible to add a parameter to AddFile(s) Function(s) telling what is the compreesion rate that we want to compress files ?
It's allways the maximum compression rate (method Z_DEFLATED with Z_BEST_COMPRESSION).
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
User avatar
cabaptista
User
User
Posts: 86
Joined: Sun Nov 30, 2003 11:42 pm
Location: Lisboa, Portugal

Post by cabaptista »

Ok gnozal,

Thanks for the info about compression rate.
But my question is:

Why don´t you let us choose which compression rate we want ?

Like in WinRAR when we add files, we can choose if we want to compress in BEST, NORMAL, ...

This could be a extra optional parameter in AddFile(s) Function(s).

If you can managed that, i will start to make an application to use your LIB. :D :D :D
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

cabaptista wrote:Why don´t you let us choose which compression rate we want ?
It's not very usefull : not much speed difference between NORMAL and BEST, if that's your concern. Why do you need it ?
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
User avatar
cabaptista
User
User
Posts: 86
Joined: Sun Nov 30, 2003 11:42 pm
Location: Lisboa, Portugal

Post by cabaptista »

Well, check this image from a ZIP application for instance.

http://pwp.netcabo.pt/cesar-baptista/images/ZipAddFiles.jpg

They use the compression method.
I would like to use this in the application i want to do with your LIB. :wink:

By the way, what about a SFX archive function ?
That would be nice, also.
If it could be done, of course. :wink: :wink: :wink:
PAMKKKKK
User
User
Posts: 18
Joined: Sun May 01, 2005 7:55 am
Location: Germany Braunschweig
Contact:

Post by PAMKKKKK »

@cabaptista
I really agree with gnozal that the kompression strenght an acutual Computer dosn´t itch.

You have 2choices for the User
Kompression or no compression.

if you want, make al list box with the following Picks::wink: :wink: :wink:

Normal (is with compression)
Fastest (is witout compression)
Best (is with best compression. )

by the way, here my DosDate back and forward solution:

Code: Select all

Procedure.l DosDateToPBdate(dosDate.l)
  ; Converts a Zip-Dos-Date to PureBasic-Date
  ; The dosdate count only every 2 second. So you must do: second * 2
  ; The dosdate beginns to count from 01.January.1980. So you must add 1980 to the Year
  ProcedureReturn Date(dosDate>>25&127 + 1980,dosDate>>21&15,dosDate>>16&31,dosDate>>11&31,dosDate>>5&63,dosDate&31 * 2)
EndProcedure

Procedure.l PBdateToDosDate(PBdate.l)
  DosYear = Year(PBdate)
  ; Dosdate can only between 1.1.1980 and 31.12.2107
  If DosYear < 1980 Or DosYear > 2107
    ProcedureReturn 0
  EndIf
  
  DosYear = (DosYear-1980)<<25
  DosMonth = Month(PBdate)<<21
  DosDay = Day(PBdate)<<16
  DosHour = Hour(PBdate)<<11
  DosMinute = Minute(PBdate)<<5
  ; Dos Time Ticks only every 2. second
  DosSecond = Second(PBdate)/2
  
  ProcedureReturn DosYear + DosMonth + DosDay + DosHour + DosMinute + DosSecond
EndProcedure

; Lets Test ......
Debug FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss",DosDateToPBdate(PBdateToDosDate(Date())))
Develop Standards, and you develop the World!
User avatar
cabaptista
User
User
Posts: 86
Joined: Sun Nov 30, 2003 11:42 pm
Location: Lisboa, Portugal

Post by cabaptista »

Ok,

I agree with you PAMKKKKK and i might have a combo box for user to choose from Fastest, Normal and Best compression method.

But then, when i'm compressing the files i've to tell the application which method to use (by default, compresson is always made with Best says Gnozal), so i must have a optional parameter to choose from.

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

Post by gnozal »

cabaptista wrote:By the way, what about a SFX archive function ?
That would be nice, also.
If it could be done, of course. :wink: :wink: :wink:
A SFX is only an archive that opens itself : it's easy to do. I've done it for my LIB installer (it's a ZIP SFX) http://www.purebasic.fr/english/viewtopic.php?t=18514. Just copy SFXstub + ZIParchive = SFXZIP (in the SFXstub is the code to open itself, like any other archive : If PureZIP_Archive_Read(GetFullExePath()) etc... ).
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
PAMKKKKK
User
User
Posts: 18
Joined: Sun May 01, 2005 7:55 am
Location: Germany Braunschweig
Contact:

Post by PAMKKKKK »

:oops: I dont remark that gnozal hasn´t made any choice to change compression mode......

If you read the explanation for the Zipfile you see Zipfiles are very easy to made. (i done it yesterday in a quickhack)
Read the appnote-xxxxxxxxx-pk.zip at: ftp://ftp.info-zip.org/pub/infozip/doc and Code youre own ZIPfiles :wink:

Here is my solution of making Zipfiles without compression.
NOT TESTED VERY WELL !! only tested on WinXP.

Code: Select all

; example to make (uncompressed) Zipfiles
; For ZIP-Documention see ftp://ftp.info-zip.org/pub/infozip/doc (the appnote-pk.txt)
; author PAMKKKKK 25.March.2006
; PB 3.93

Structure ZipFileHeader
  exV.w ;Version needed To extract       2 bytes
  gpbFl.w ;general purpose bit flag        2 bytes
  cM.w  ;compression method              2 bytes
  lMod.l ;last mod File time  2 bytes last mod File Date 2 bytes
  Crc32.l ;crc-32                          4 bytes
  cSz.l ;compressed size                 4 bytes
  uncSz.l ;uncompressed size               4 bytes
  Flen.w ;FileName length                 2 bytes
  extra.w ;extra field length              2 bytes
  lenComnt.w ; File comment length             2 bytes
  Disk.w ; disk number start               2 bytes
  inFAttr.w  ; internal File attributes        2 bytes
  exFAttr.l ; external File attributes        4 bytes
  Offs.l ; relative offset of local header 4 bytes
  
  Comment.s; File comment (variable size)
  Fname.s ;filename (variable size)
  Fextra.s ;extra field (variable size)
  
  OFilename.s ; Original Filename
EndStructure

NewList LocalFile.ZipFileHeader()

; WIN-API !!!!!!
Procedure.l FileDateToDosDate(File.s)
; Converts the last writetime to a Dos-Formated Time
; THE TIME CAN BE INCORRECT, IN CONTRYS WITH SUMMER AND WINTER TIME !!! 
  Handle=CreateFile_(@File.s,#GENERIC_READ,#FILE_SHARE_READ|#FILE_SHARE_WRITE,0,#OPEN_EXISTING,#FILE_ATTRIBUTE_NORMAL,0)
  If Handle<>#INVALID_HANDLE_VALUE
    GetFileTime_(Handle,0,0,FT.FILETIME) ; Last Writetime
  Else
    ProcedureReturn -1 ; Error File dosnt exist or not accesable
  EndIf
  FileTimeToDosDateTime_(FT,@FatDate.w,@FatTime.w)
  CloseHandle_(Handle) ; Close the File
  ProcedureReturn FatDate<<16 + FatTime
EndProcedure

;-Add_to_Locallist***********************************************
Procedure Add_to_Locallist(FileToAdd.s,Flags)
  ; Store Path relative or not...
  If Flags&%1
    FileName.s = FileToAdd
  Else
    FileName.s = GetFilePart(FileToAdd)
  EndIf
  
 ; Filling LocalList
  AddElement(LocalFile())  
  ;WriteLong($04034B50) ; local File header signature     4 bytes  (0x04034b50)
  LocalFile()\exV = $000A ; Hardcoded Version need to be extract
  LocalFile()\gpbFl = $0000 ; Hardcoded Flags
  LocalFile()\cM = $0000 ; Hardcoded compression methode, cause no compression used yet!
  LocalFile()\lMod = FileDateToDosDate(FileToAdd) ; Last mod FileDat in Dos Format (big-endian)
  ;LocalFile()\Crc32 = CRC32FileFingerprint(FileToAdd) CRC calculation made in Make_Zip (for performance) 
  LocalFile()\cSz = FileSize(FileToAdd) ; We dont compress so the Filesize is = compressionsize
  LocalFile()\uncSz = FileSize(FileToAdd) ; simple the Uncompressed Filesize
  LocalFile()\Flen = Len(FileName) ; length of the Filename
  LocalFile()\extra = 0 ; Not used yet !
  LocalFile()\lenComnt = 0 ; Not used yet ! ; File comment length             2 bytes
  LocalFile()\Disk = 0 ; Not used yet ! ; disk number start               2 bytes
  LocalFile()\inFAttr = 0  ; Not used yet ! ; internal File attributes        2 bytes
  LocalFile()\exFAttr = 0 ; Not used yet ! ; external File attributes        4 bytes
  ;Offs.l ; Not used here ! relative offset is set by file writing.
  
  LocalFile()\Comment = "" ; Not used yet ! ; File comment (variable size)
  LocalFile()\Fname = FileName ; Path relative or not was made at the start of these Procedure 
  LocalFile()\Fextra = "" ; Not used yet !
  
  LocalFile()\OFilename = FileToAdd ; Original File Path where the File is taken from
  
EndProcedure

;-Add_End_of_central_dir_record ********************************************
Procedure Add_End_of_central_dir_record(ZipFile.s,DirSz.l,headOffset.l)
  ResetList(LocalFile())
  HFile = OpenFile(#PB_Any, ZipFile)
  If HFile
    FileSeek(Lof()) ; append the header
    WriteLong($06054B50) ;End of central dir signature    4 bytes  (0x06054b50)
    WriteWord(0) ;number of this Disk             2 bytes
    WriteWord(0) ;number of the Disk with the start of the central Directory  2 bytes
    WriteWord(CountList(LocalFile())) ;total number of entries in the central dir on this Disk    2 bytes
    WriteWord(CountList(LocalFile())) ;total number of entries in the central dir                 2 bytes
    WriteLong(DirSz) ;size of the central Directory   4 bytes
    WriteLong(headOffset) ;offset of start of central Directory with respect To the starting Disk number        4 bytes
    WriteWord(0) ;ZipFile Comment length          2 bytes
    WriteString("") ;ZipFile comment (variable size)
    CloseFile(HFile)
  EndIf
EndProcedure

;-Add_Central_Directory_Structure ********************************************
Procedure Add_Central_Directory_Structure(ZipFile.s)
  ResetList(LocalFile())
  HFile = OpenFile(#PB_Any, ZipFile)
If HFile
  FileSeek(Lof()) ; append the header
  headOffset = Lof()
  While NextElement(LocalFile())
    WriteLong($02014B50) ; central File header signature   4 bytes  (0x02014b50)
    WriteWord($0014)  ;Version made by                 2 bytes
    WriteWord(LocalFile()\exV)
    WriteWord(LocalFile()\gpbFl)
    WriteWord(LocalFile()\cM)
    WriteLong(LocalFile()\lMod)
    WriteLong(LocalFile()\Crc32)
    WriteLong(LocalFile()\cSz)
    WriteLong(LocalFile()\uncSz)
    WriteWord(LocalFile()\Flen)
    WriteWord(LocalFile()\extra)
    WriteWord(LocalFile()\lenComnt) 
    WriteWord(LocalFile()\Disk)
    WriteWord(LocalFile()\inFAttr)
    WriteLong($00000020);LocalFile()\exFAttr)
    WriteLong(LocalFile()\Offs) ; relative offset of local header 4 bytes
  
    WriteString(LocalFile()\Fname)
    WriteString(LocalFile()\Fextra); extra field (variable size)
    WriteString(LocalFile()\Comment); File comment (variable size)
  Wend
  DirSz.l =  Lof() - headOffset
CloseFile(HFile)
EndIf
Add_End_of_central_dir_record(ZipFile,DirSz,headOffset)
EndProcedure

;- Make_Zip **************************************************
Procedure Make_Zip(ZipFile.s)
  ResetList(LocalFile())
  HFile = CreateFile(#PB_Any, ZipFile)
If HFile  
  While NextElement(LocalFile())
      LocalFile()\Offs = Lof()
      WriteLong($04034B50) ; local File header signature     4 bytes  (0x04034b50)
      WriteWord(LocalFile()\exV)
      WriteWord(LocalFile()\gpbFl)
      WriteWord(LocalFile()\cM)
      WriteLong(LocalFile()\lMod)
      
      ; open File and do CRC32
      FileSz=FileSize(LocalFile()\OFilename)
      If FileSz
        FileBuffer = AllocateMemory(FileSz); Buffer error dosn´t catch !
        If FileBuffer
          HAddFile = ReadFile(#PB_Any,LocalFile()\OFilename)  
         If HAddFile
            L0 = ReadData(FileBuffer, FileSz) ; Buffer error dosn´t catch !
            LocalFile()\Crc32 = CRC32Fingerprint(FileBuffer, FileSz)
            CloseFile(HAddFile) ;closing File, File is in Buffer now
          EndIf
        EndIf
      EndIf
      WriteLong(LocalFile()\Crc32)
      
      ; compression is not used yet!
      ;if you want to compress do it here with the FileBuffer !!
       
      WriteLong(LocalFile()\cSz)
      WriteLong(LocalFile()\uncSz)
      WriteWord(LocalFile()\Flen)
      WriteWord(LocalFile()\extra)
      WriteString(LocalFile()\Fname)
      WriteString(LocalFile()\Fextra) 
 
      ; writing File from Buffer to Zipfile
      UseFile(HFile)
      FileSeek(Lof()) ; append mode
      WriteData( FileBuffer, FileSz)
      FreeMemory(FileBuffer) ; clean up ;-)
  Wend
CloseFile(HFile)
EndIf
; Adding the global header
Add_Central_Directory_Structure(ZipFile)
EndProcedure

; **************************************************
; MAIN
; **************************************************

; First add the files to the list
; Flag is only used for pathrelative or not at this time
; 0 = store filename only, 1 = store absolut path
Add_to_Locallist("C:\temp\Text1.txt",0)
Add_to_Locallist("C:\temp\Text2.txt",0)
Add_to_Locallist("C:\temp\Text3.txt",0)
Add_to_Locallist("C:\Windows\notepad.exe",0)
Add_to_Locallist("C:\temp\example.pdf",0)
; if the List is ready make the Zipfile
Make_Zip("C:\temp\ziptest.zip")

; Note
; at this time compression, diskspanning or other is not supported !!!
; if you want to compress see Note in Procedure Make_Zip()
Develop Standards, and you develop the World!
Post Reply