Page 1 of 1

Extrafunctions for ZipPacker (Crossplattform)

Posted: Sun Jan 13, 2013 10:21 am
by ts-soft
Here some extra functions for the zippacker comes with PB5.10

This include should work crossplattform:
- windows full tested
- linux works only in ascii-mode
- macos not tested!

Functions:
- ZIP_AddDir(zip, dir.s) ; add a empty directory to archiv
- ZIP_CountEntries(zip, flags = 0) ; returns the number of files in the zip archive, or -1 if archive is NULL
- ZIP_GetIndex(zip, FileName.s, flags = 0) ; Found index by Name
- ZIP_GetArchComment(zip, flags = 0) ; reads the archiv comment
- ZIP_GetFileComment(zip, index, flags = 0) ; reads the file comment
- ZIP_SetArchComment(zip, comment.s) ; add a comment to archiv
- ZIP_SetFileComment(zip, index, comment.s) ; add a comment to file
- ZIP_SetDefaultPassword(zip, password.s) ; works only for unpacking!

Includefile with example:

Code: Select all

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  CompilerIf #PB_Compiler_Unicode
    Debug "Please disable " + #DQUOTE$ + "Unicode" + #DQUOTE$ +
            "! Unicode is not supported!"
    End
  CompilerEndIf
CompilerEndIf

UseZipPacker()

#ZIP_FL_NOCASE = 1
#ZIP_FL_NODIR =	2
#ZIP_FL_UNCHANGED = 8

ImportC ""
  zip_add_dir(hZip.i, dir.p-Ascii)
  zip_get_num_entries(hZip.i, flags.l = 0)
  zip_get_archive_comment(hZip.i, *lenp, flags.l = 0)
  zip_set_archive_comment(hZip.i, comment.p-Ascii, length.l)
  zip_get_file_comment(hZip.i, index.q, *lenp, flags.l = 0)
  zip_set_file_comment(hZip.i, index.q, comment.p-Ascii, length.l)
  zip_name_locate(hZip.i, fname.p-Ascii, flags.l = 0)
  zip_set_default_password(hZip.i, password.p-Ascii)
EndImport

Procedure ZIP_AddDir(*zip.Integer, dir.s) ; add a empty directory to archiv
  ProcedureReturn zip_add_dir(*zip\i, dir)
EndProcedure

Procedure ZIP_CountEntries(*zip.Integer, flags = 0) ; returns the number of files in the zip archive, or -1 if archive is NULL
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  ProcedureReturn zip_get_num_entries(*zip\i, flags)
EndProcedure

Procedure.l ZIP_GetIndex(*zip.Integer, FileName.s, flags = 0) ; Found index by Name
  ; Directories are denoted by a trailing slash
  ; Supported Flags:
  ;   #ZIP_FL_NOCASE = case insensitive search
  ;   #ZIP_FL_NODIR  = ignore the path
  
  ;   Result = -1 is an error!
  ProcedureReturn zip_name_locate(*zip\i, FileName, flags)
EndProcedure

Procedure.s  ZIP_GetArchComment(*zip.Integer, flags = 0) ; reads the archiv comment
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_archive_comment(*zip\i, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure.s  ZIP_GetFileComment(*zip.Integer, index, flags = 0) ; reads the file comment
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_file_comment(*zip\i, index, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure ZIP_SetArchComment(*zip.Integer, comment.s) ; add a comment to archiv
  If zip_set_archive_comment(*zip\i, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetFileComment(*zip.Integer, index, comment.s) ; add a comment to file
  If zip_set_file_comment(*zip\i, index, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetDefaultPassword(*zip.Integer, password.s) ; works only for unpacking!
  If zip_set_default_password(*zip\i, password) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

CompilerIf Not #PB_Compiler_IsIncludeFile
  ; Example
  Define zip
  zip = CreatePack(0, GetTemporaryDirectory() + "myzip.zip")
  AddPackFile(0, #PB_Compiler_Home + "sdk/compilerinterface.txt", "CompilerInterface.txt")
  ZIP_SetFileComment(zip, ZIP_GetIndex(zip, "compilerinterface.txt", #ZIP_FL_NOCASE), "File from SDK")
  ZIP_AddDir(zip, "test/")
  ZIP_SetFileComment(zip, ZIP_GetIndex(zip, "test/"), "My empty dir")
  ZIP_SetArchComment(zip, "Feel the ..Pure.. Power")
  ClosePack(0)
  
  zip = OpenPack(0, GetTemporaryDirectory() + "myzip.zip")
  
  Define i
  If ExaminePack(0)
    While NextPackEntry(0)
      Debug PackEntryName(0)
      Select PackEntryType(0)
        Case #PB_Packer_File
          Debug "Is a File"
        Case #PB_Packer_Directory
          Debug "Is a Directory"
      EndSelect
      Debug ZIP_GetFileComment(zip, i)
      Debug "---------------"
      i + 1
    Wend
  EndIf
  MessageRequester("Archiv Comment", ZIP_GetArchComment(zip))
  ClosePack(0)
CompilerEndIf

Re: Extrafunctions for ZipPacker

Posted: Sun Jan 13, 2013 5:17 pm
by jassing
Nicely done -- and timely too. (project/database backups)

Re: Extrafunctions for ZipPacker

Posted: Sun Jan 13, 2013 5:47 pm
by idle
thanks

Re: Extrafunctions for ZipPacker

Posted: Sun Jan 13, 2013 8:44 pm
by Zebuddi123
Thanks. as usual your code is always welcome and useful :idea:

Zebuddi. :D

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Mon Jan 14, 2013 2:11 pm
by ts-soft
Update!

include is crossplattform with some limitations

added:
+ ZIP_CountEntries()
+ ZIP_SetDefaultPassword()
The password works only for unpacking of zip-files protected by another zippacker!

Greetings - Thomas

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Mon Jan 14, 2013 2:21 pm
by Perkin
@ts-soft
Many thanks for these, was just about to use Zipping functions, cross-platform too.
Much easier now.
Thanks.

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Tue Jan 15, 2013 11:07 pm
by Perkin
@ts-soft

One (hopefully) simple addition... is it possible to get/set the compression for any further files until it's changed again, allowing STORE (compression=0) rather than the level it's set at -- DEFLATE (8).

I want to loop through a dir and depending on filetype just store a file rather than compress it.
(on both windows and linux - I can do it on windows with gnozal' PureZip, but that doesn't work on linux)

Any ideas if that would be possible here?
Thanks.

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Tue Jan 15, 2013 11:27 pm
by ts-soft
Your wish is to many work, it is much easier the PB-TEAM implement this, see here:
http://www.purebasic.fr/english/viewtop ... 45#p399245

Information to the lib can you find here: http://www.nih.at/libzip/libzip.html

Greetings - Thomas

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Tue Jan 15, 2013 11:45 pm
by Perkin
Thanks.
Checked out the your Request topic, seems to cover everything.

I'd looked through some of the libzip docs to see if I could do it myself, but way beyond my abilities at present, also I'm just getting back into coding.

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Fri Jan 18, 2013 9:57 pm
by ts-soft
This code is broken with PB5.10Beta4, sorry :cry:

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Sat Jan 19, 2013 10:51 pm
by ts-soft
I have problems to get the code working on other os as windows. I will update the source in the first thread, when it is done!
Here the windows-only source:

Code: Select all

EnableExplicit

UseZipPacker()

#ZIP_FL_NOCASE = 1
#ZIP_FL_NODIR =	2
#ZIP_FL_UNCHANGED = 8

Import ""
  PB_Object_IsObject(object, id)
  PB_Packer_Objects
EndImport

ImportC ""
  zip_add_dir(hZip.i, dir.p-ascii)
  zip_get_num_entries(hZip.i, flags.l = 0)
  zip_get_archive_comment(hZip.i, *lenp, flags.l = 0)
  zip_set_archive_comment(hZip.i, comment.p-Ascii, length.l)
  zip_get_file_comment(hZip.i, index.q, *lenp, flags.l = 0)
  zip_set_file_comment(hZip.i, index.q, comment.p-Ascii, length.l)
  zip_name_locate(hZip.i, fname.p-Ascii, flags.l = 0)
  zip_set_default_password(hZip.i, password.p-Ascii)
EndImport

Procedure ZIP_PackerID(id)
 Protected obj, hZip
 obj = PB_Object_IsObject(PB_Packer_Objects, id) 
 If obj
  hZip = PeekI(obj + 4 * SizeOf(integer))
 EndIf
 
 ProcedureReturn hZip 
EndProcedure

Procedure ZIP_AddDir(ID, dir.s) ; add a empty directory to archiv
  Protected hZip = ZIP_PackerID(ID)
  ProcedureReturn zip_add_dir(hZip, dir)
EndProcedure

Procedure ZIP_CountEntries(ID, flags = 0) ; returns the number of files in the zip archive, or -1 if archive is NULL
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  ProcedureReturn zip_get_num_entries(hZip, flags)
EndProcedure

Procedure.l ZIP_GetIndex(ID, FileName.s, flags = 0) ; Found index by Name
  Protected hZip = ZIP_PackerID(ID)
  ; Directories are denoted by a trailing slash
  ; Supported Flags:
  ;   #ZIP_FL_NOCASE = case insensitive search
  ;   #ZIP_FL_NODIR  = ignore the path
  
  ;   Result = -1 is an error!
  ProcedureReturn zip_name_locate(hZip, FileName, flags)
EndProcedure

Procedure.s  ZIP_GetArchComment(ID, flags = 0) ; reads the archiv comment
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_archive_comment(hZip, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure.s  ZIP_GetFileComment(ID, index, flags = 0) ; reads the file comment
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_file_comment(hZip, index, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure ZIP_SetArchComment(ID, comment.s) ; add a comment to archiv
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_archive_comment(hZip, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetFileComment(ID, index, comment.s) ; add a comment to file
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_file_comment(hZip, index, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetDefaultPassword(ID, password.s) ; works only for unpacking!
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_default_password(hZip, password) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

CompilerIf Not #PB_Compiler_IsIncludeFile
  ; Example
  CreatePack(0, GetTemporaryDirectory() + "myzip.zip")
  AddPackFile(0, #PB_Compiler_Home + "sdk/compilerinterface.txt", "CompilerInterface.txt")
  ZIP_SetFileComment(0, ZIP_GetIndex(0, "compilerinterface.txt", #ZIP_FL_NOCASE), "File from SDK")
  ZIP_AddDir(0, "test/")
  ZIP_SetFileComment(0, ZIP_GetIndex(0, "test/"), "My empty dir")
  ZIP_SetArchComment(0, "Feel the ..Pure.. Power")
  ClosePack(0)
  
  Define zip = OpenPack(#PB_Any, GetTemporaryDirectory() + "myzip.zip")
  
  Define i
  If ExaminePack(zip)
    While NextPackEntry(zip)
      Debug PackEntryName(zip)
      Select PackEntryType(zip)
        Case #PB_Packer_File
          Debug "Is a File"
        Case #PB_Packer_Directory
          Debug "Is a Directory"
      EndSelect
      Debug ZIP_GetFileComment(zip, i)
      Debug "---------------"
      i + 1
    Wend
    Debug ZIP_CountEntries(zip)
  EndIf
  MessageRequester("Archiv Comment", ZIP_GetArchComment(zip))
  ClosePack(zip)
CompilerEndIf
Greetings - Thomas

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Mon Jan 21, 2013 7:43 pm
by breeze4me
It's very useful, thank you!

I added Zip_GetStat function. It works fine on Win 7 x64, but I got an IMA error on Win 7 x86. :cry:
Any ideas?

Code: Select all

EnableExplicit

UseZipPacker()

#ZIP_FL_NOCASE = 1
#ZIP_FL_NODIR =   2
#ZIP_FL_UNCHANGED = 8

#ZIP_STAT_NAME = $0001
#ZIP_STAT_INDEX = $0002
#ZIP_STAT_SIZE = $0004
#ZIP_STAT_COMP_SIZE = $0008
#ZIP_STAT_MTIME = $0010
#ZIP_STAT_CRC = $0020
#ZIP_STAT_COMP_METHOD = $0040
#ZIP_STAT_ENCRYPTION_METHOD = $0080
#ZIP_STAT_FLAGS = $0100

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
  Structure zip_stat
    valid.q;                 /* which fields have valid values */ 
    *name;                   /* name of the file */ 
    pad1.l
    index.q;                 /* index within archive */ 
    size.q;                  /* size of file (uncompressed) */ 
    comp_size.q;             /* size of file (compressed) */ 
    mtime.l;                       /* modification time */ 
    crc.l;                   /* crc of file data */ 
    comp_method.u;           /* compression method used */ 
    encryption_method.u;     /* encryption method used */ 
    flags.l;                 /* reserved for future use */ 
  EndStructure
CompilerElse
  Structure zip_stat Align 8
    valid.q;                 /* which fields have valid values */ 
    *name;                   /* name of the file */ 
    index.q;                 /* index within archive */ 
    size.q;                  /* size of file (uncompressed) */ 
    comp_size.q;             /* size of file (compressed) */ 
    mtime.l;                       /* modification time */ 
    crc.l;                   /* crc of file data */ 
    comp_method.u;           /* compression method used */ 
    encryption_method.u;     /* encryption method used */ 
    flags.l;                 /* reserved for future use */ 
  EndStructure
CompilerEndIf

Import ""
  PB_Object_IsObject(object, id)
  PB_Packer_Objects
EndImport

ImportC ""
  zip_add_dir(hZip.i, dir.p-ascii)
  zip_get_num_entries(hZip.i, flags.l = 0)
  zip_get_archive_comment(hZip.i, *lenp, flags.l = 0)
  zip_set_archive_comment(hZip.i, comment.p-Ascii, length.l)
  zip_get_file_comment(hZip.i, index.q, *lenp, flags.l = 0)
  zip_set_file_comment(hZip.i, index.q, comment.p-Ascii, length.l)
  zip_name_locate(hZip.i, fname.p-Ascii, flags.l = 0)
  zip_set_default_password(hZip.i, password.p-Ascii)
  zip_stat_index(hZip.i, index.q, flags.l, *sb)
EndImport

Procedure ZIP_PackerID(id)
 Protected obj, hZip
 obj = PB_Object_IsObject(PB_Packer_Objects, id) 
 If obj
  hZip = PeekI(obj + 4 * SizeOf(integer))
 EndIf
 
 ProcedureReturn hZip 
EndProcedure

Procedure ZIP_GetStat(ID, index, *zipstat, flags = 0)
  Protected hZip = ZIP_PackerID(ID)
  ProcedureReturn zip_stat_index(hZip, index, flags, *zipstat)
EndProcedure

Procedure ZIP_AddDir(ID, dir.s) ; add a empty directory to archiv
  Protected hZip = ZIP_PackerID(ID)
  ProcedureReturn zip_add_dir(hZip, dir)
EndProcedure

Procedure ZIP_CountEntries(ID, flags = 0) ; returns the number of files in the zip archive, or -1 if archive is NULL
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  ProcedureReturn zip_get_num_entries(hZip, flags)
EndProcedure

Procedure.l ZIP_GetIndex(ID, FileName.s, flags = 0) ; Found index by Name
  Protected hZip = ZIP_PackerID(ID)
  ; Directories are denoted by a trailing slash
  ; Supported Flags:
  ;   #ZIP_FL_NOCASE = case insensitive search
  ;   #ZIP_FL_NODIR  = ignore the path
  
  ;   Result = -1 is an error!
  ProcedureReturn zip_name_locate(hZip, FileName, flags)
EndProcedure

Procedure.s  ZIP_GetArchComment(ID, flags = 0) ; reads the archiv comment
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_archive_comment(hZip, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure.s  ZIP_GetFileComment(ID, index, flags = 0) ; reads the file comment
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_file_comment(hZip, index, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure ZIP_SetArchComment(ID, comment.s) ; add a comment to archiv
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_archive_comment(hZip, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetFileComment(ID, index, comment.s) ; add a comment to file
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_file_comment(hZip, index, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetDefaultPassword(ID, password.s) ; works only for unpacking!
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_default_password(hZip, password) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

CompilerIf Not #PB_Compiler_IsIncludeFile
  ; Example
  CreatePack(0, GetTemporaryDirectory() + "myzip.zip")
  AddPackFile(0, #PB_Compiler_Home + "sdk/compilerinterface.txt", "CompilerInterface.txt")
  ZIP_SetFileComment(0, ZIP_GetIndex(0, "compilerinterface.txt", #ZIP_FL_NOCASE), "File from SDK")
  ZIP_AddDir(0, "test/")
  ZIP_SetFileComment(0, ZIP_GetIndex(0, "test/"), "My empty dir")
  ZIP_SetArchComment(0, "Feel the ..Pure.. Power")
  ClosePack(0)
  
  Define zipstat.zip_stat
  zipstat\valid = #ZIP_STAT_SIZE | #ZIP_STAT_COMP_SIZE | #ZIP_STAT_MTIME | #ZIP_STAT_CRC
  
  Define zip = OpenPack(#PB_Any, GetTemporaryDirectory() + "myzip.zip")
  
  Define i
  If ExaminePack(zip)
    While NextPackEntry(zip)
      Debug PackEntryName(zip)
      Select PackEntryType(zip)
        Case #PB_Packer_File
          Debug "Is a File"
        Case #PB_Packer_Directory
          Debug "Is a Directory"
      EndSelect
      Debug ZIP_GetFileComment(zip, i)
      ZIP_GetStat(zip, i, zipstat)
      Debug Hex(zipstat\crc, #PB_Long)
      Debug zipstat\size
      Debug zipstat\comp_size
      Debug "GMT? " + Month(zipstat\mtime) + "/" + Day(zipstat\mtime) + "/" + Year(zipstat\mtime) + " " + Hour(zipstat\mtime) + ":" + Minute(zipstat\mtime) + ":" + Second(zipstat\mtime)
      Debug "---------------"
      i + 1
    Wend
    Debug ZIP_CountEntries(zip)
  EndIf
  
  Debug "-----"
  Debug "Archiv Comment: " + ZIP_GetArchComment(zip)
  ClosePack(zip)
CompilerEndIf

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Mon Jan 21, 2013 8:28 pm
by ts-soft
@breeze4me
I have test the same before some days, with the same bad results :?
For me, libzip is not good documented.

Re: Extrafunctions for ZipPacker (Crossplattform)

Posted: Tue Jan 22, 2013 9:53 pm
by breeze4me
I just noticed it works without the debugger. (Compiler - Compile without Debugger)
something wrong with x86 debugger???

Code: Select all

EnableExplicit

UseZipPacker()

#ZIP_FL_NOCASE = 1
#ZIP_FL_NODIR =   2
#ZIP_FL_UNCHANGED = 8

#ZIP_STAT_NAME = $0001
#ZIP_STAT_INDEX = $0002
#ZIP_STAT_SIZE = $0004
#ZIP_STAT_COMP_SIZE = $0008
#ZIP_STAT_MTIME = $0010
#ZIP_STAT_CRC = $0020
#ZIP_STAT_COMP_METHOD = $0040
#ZIP_STAT_ENCRYPTION_METHOD = $0080
#ZIP_STAT_FLAGS = $0100

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
  Structure zip_stat
    valid.q;                 /* which fields have valid values */ 
    *name;                   /* name of the file */ 
    pad1.l
    index.q;                 /* index within archive */ 
    size.q;                  /* size of file (uncompressed) */ 
    comp_size.q;             /* size of file (compressed) */ 
    mtime.l;                 /* modification time */ 
    crc.l;                   /* crc of file data */ 
    comp_method.u;           /* compression method used */ 
    encryption_method.u;     /* encryption method used */ 
    flags.l;                 /* reserved for future use */ 
  EndStructure
CompilerElse
  Structure zip_stat Align 8
    valid.q;                 /* which fields have valid values */ 
    *name;                   /* name of the file */ 
    index.q;                 /* index within archive */ 
    size.q;                  /* size of file (uncompressed) */ 
    comp_size.q;             /* size of file (compressed) */ 
    mtime.l;                 /* modification time */ 
    crc.l;                   /* crc of file data */ 
    comp_method.u;           /* compression method used */ 
    encryption_method.u;     /* encryption method used */ 
    flags.l;                 /* reserved for future use */ 
  EndStructure
CompilerEndIf

Import ""
  PB_Object_IsObject(object, id)
  PB_Packer_Objects
EndImport

ImportC ""
  zip_add_dir(hZip.i, dir.p-ascii)
  zip_get_num_entries(hZip.i, flags.l = 0)
  zip_get_archive_comment(hZip.i, *lenp, flags.l = 0)
  zip_set_archive_comment(hZip.i, comment.p-Ascii, length.l)
  zip_get_file_comment(hZip.i, index.q, *lenp, flags.l = 0)
  zip_set_file_comment(hZip.i, index.q, comment.p-Ascii, length.l)
  zip_name_locate(hZip.i, fname.p-Ascii, flags.l = 0)
  zip_set_default_password(hZip.i, password.p-Ascii)
  zip_stat_index(hZip.i, index.q, flags.l, *sb)
EndImport

Procedure ZIP_PackerID(id)
 Protected obj, hZip
 obj = PB_Object_IsObject(PB_Packer_Objects, id) 
 If obj
  hZip = PeekI(obj + 4 * SizeOf(integer))
 EndIf
 
 ProcedureReturn hZip 
EndProcedure

Procedure ZIP_GetStat(ID, index, *zipstat, flags = 0)
  Protected hZip = ZIP_PackerID(ID)
  ProcedureReturn zip_stat_index(hZip, index, flags, *zipstat)
EndProcedure

Procedure ZIP_AddDir(ID, dir.s) ; add a empty directory to archiv
  Protected hZip = ZIP_PackerID(ID)
  ProcedureReturn zip_add_dir(hZip, dir)
EndProcedure

Procedure ZIP_CountEntries(ID, flags = 0) ; returns the number of files in the zip archive, or -1 if archive is NULL
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  ProcedureReturn zip_get_num_entries(hZip, flags)
EndProcedure

Procedure.l ZIP_GetIndex(ID, FileName.s, flags = 0) ; Found index by Name
  Protected hZip = ZIP_PackerID(ID)
  ; Directories are denoted by a trailing slash
  ; Supported Flags:
  ;   #ZIP_FL_NOCASE = case insensitive search
  ;   #ZIP_FL_NODIR  = ignore the path
  
  ;   Result = -1 is an error!
  ProcedureReturn zip_name_locate(hZip, FileName, flags)
EndProcedure

Procedure.s  ZIP_GetArchComment(ID, flags = 0) ; reads the archiv comment
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_archive_comment(hZip, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure.s  ZIP_GetFileComment(ID, index, flags = 0) ; reads the file comment
  Protected hZip = ZIP_PackerID(ID)
  ; Supported Flags:
  ;   #ZIP_FL_UNCHANGED = use original data, ignoring changes
  Protected length.l, result.i
  result = zip_get_file_comment(hZip, index, @length, flags)
  If result And length > 0
    ProcedureReturn PeekS(result, length, #PB_Ascii)
  EndIf
EndProcedure

Procedure ZIP_SetArchComment(ID, comment.s) ; add a comment to archiv
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_archive_comment(hZip, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetFileComment(ID, index, comment.s) ; add a comment to file
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_file_comment(hZip, index, comment, Len(comment)) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ZIP_SetDefaultPassword(ID, password.s) ; works only for unpacking!
  Protected hZip = ZIP_PackerID(ID)
  If zip_set_default_password(hZip, password) = 0
    ProcedureReturn #True
  EndIf
EndProcedure

CompilerIf Not #PB_Compiler_IsIncludeFile
  ; Example
  CreatePack(0, GetTemporaryDirectory() + "myzip.zip")
  AddPackFile(0, #PB_Compiler_Home + "sdk/compilerinterface.txt", "CompilerInterface.txt")
  AddPackFile(0, #PB_Compiler_Home + "sdk/Readme.txt", "Readme.txt")
  ZIP_SetFileComment(0, ZIP_GetIndex(0, "compilerinterface.txt", #ZIP_FL_NOCASE), "File from SDK")
  ZIP_AddDir(0, "test/")
  ZIP_SetFileComment(0, ZIP_GetIndex(0, "test/"), "My empty dir")
  ZIP_SetArchComment(0, "Feel the ..Pure.. Power")
  ClosePack(0)
  
  Define zipstat.zip_stat, i, txt$
  Define zip = OpenPack(#PB_Any, GetTemporaryDirectory() + "myzip.zip")
  
  If ExaminePack(zip)
    While NextPackEntry(zip)
      txt$ + PackEntryName(zip)
      Select PackEntryType(zip)
        Case #PB_Packer_File
          txt$ + " Is a File." + #CR$
        Case #PB_Packer_Directory
          txt$ + " Is a Directory." + #CR$
      EndSelect
      txt$ + "Comment: " + ZIP_GetFileComment(zip, i) + #CR$
      
      ZIP_GetStat(zip, i, zipstat)
      If zipstat\valid & #ZIP_STAT_CRC
        txt$ + "CRC32: " + Hex(zipstat\crc, #PB_Long) + #CR$
      EndIf
      If zipstat\valid & #ZIP_STAT_SIZE
        txt$ + "Size:" + zipstat\size + #CR$
      EndIf
      If zipstat\valid & #ZIP_STAT_COMP_SIZE
        txt$ + "CompSize:" + zipstat\comp_size + #CR$
      EndIf
      If zipstat\valid & #ZIP_STAT_MTIME
        txt$ + "GMT: " + Str(Month(zipstat\mtime)) + "/" + Str(Day(zipstat\mtime)) + "/" + Str(Year(zipstat\mtime)) + " " + Str(Hour(zipstat\mtime)) + ":" + Str(Minute(zipstat\mtime)) + ":" + Str(Second(zipstat\mtime)) + #CR$
      EndIf
      
      i + 1
      txt$ + #CR$
    Wend
    Define cnt = ZIP_CountEntries(zip)
  EndIf
  
  MessageRequester("", "Archiv Comment: " + ZIP_GetArchComment(zip) + #CR$ + "Entries: " + Str(cnt) + #CR$ + #CR$ + txt$)
  
  ClosePack(zip)
CompilerEndIf