DEV Community

loading...

Kinx Library - Zip

Kray-G
Although I used to be a C++/Boost lover, I was back to C with the spirit of Zen, or the spirit of "simple is the best". Also returning to rock and roll from metal, I'm really into Rolling Stones.
・5 min read

Hello, everybody!

The script language Kinx is published with the concept of Looks like JavaScript, Feels like Ruby, Stable like AC/DC(?).

This time it's a Zip library.

The Zip function is indispensable when making apps. By the way, everybody says that it is vulnerable, but it is also true that Zip with password is at least required in business applications. So, if it is not possible to make a password-protected Zip, in some cases it won't be accepted by a customer. Sometimes.

That is why Kinx is of course supporting a password-protected Zip even if it's vulnerable.

Zip

Zip archive creation

Create Zip Instance (class Zip)

Basically it looks like this.

var zip = new Zip("zipfile.zip", File.READ|File.WRITE);
Enter fullscreen mode Exit fullscreen mode

Specify the file name and mode.

Mode
Mode Meaning Operation overview
File.READ Read mode When specified alone and the file does not exist, throw ZipException.
File.WRITE Write mode Mode to create a new file even if it exists.
File.APPEND Append mode Appends to the file if it exists.

These are same as File.

Methods

The methods of the Zip instance are as follows.

Method Content Options
extract(name, [opts]) Extract and get it as a string. { password, overwrite, skip, }
extractTo(name, file [, opts]) Extract to file. (same as above)
find(name) Finds an entry and returns the entry object.
addFile(filename [, opts]) Adds an entry to the Zip file. { password, method, aes, level }
addString(text [, opts]) Adds an entry to the Zip file. (same as above)
setPassword(password) Sets the password that is used for all Zip entries.
setOverwrite(truefalse) Used to specify overwrite settings for all.

Add entry (addFile()/addString())

Use addFile() or addString(). The entry is added immediately.

zip.addFile("README.md");
Enter fullscreen mode Exit fullscreen mode

If a directory name is given to the file, the files will be added as the files inside the directory. You can also pass an option as the second argument. The options are as follows.

  • password: Password for the Zip with password. No default.
  • method: Compression method. The default is deflate. In addition, you can specify "store", "bzip2", "lzma".
  • aes: Whether to enable WinZIP compatible AES encryption (true/false). Default false. It is ignored in the case of addString.
  • level: Compression level. 0-9.

An example of adding options is as below.

zip.addFile("README.md", {
    method: "bzip2",
    password: "password",
    aes: true,
});
zip.addString("test/test1.txt", {
    content: "test/test\n",
    // aes: true, // ignored by addString.
});
Enter fullscreen mode Exit fullscreen mode

The password can be set separately for each entry if it is specified individually during extracting.

encryption

It can be specified as an option at the time of addFile(), but if you want to set it all at the beginning, you can use setPassword().

var zip = new Zip("zipfile.zip", File.READ|File.WRITE);
zip.setPassword("password");
Enter fullscreen mode Exit fullscreen mode

Display Zip file list

The zip instance already contains the entry objects as an array. A list can be displayed as follows. The number of entries is stored in zip.totalFiles.

var zip = new Zip("zipfile.zip", File.READ);
System.println("totalFiles = ", zip.totalFiles);
zip.each(function(e) {
    System.println("%s:" % e.filename);
    e.keySet().each(&(key) => {
        if (e[key].isFunction || e[key].isObject || e[key].isUndefined) {
            return; // Skip a function, etc.
        }
        if (key == "crc32") { // CRC is in hex.
            System.println("    %-14s = %10X" % key % e[key]);
        } else if (key != "time" && key != "filename") { // Display in another.
            System.println("    %-14s = %10d" % key % e[key]);
        }
    });
    // time is a structure of an object.
    e.time.keySet().each(&(k) => {
        System.println("      time.%-7d = %10d" % k % e.time[k]);
    });
    // // Entry can be extracted for each.
    // if (e.filename == "README.md") {
    //     e.extractTo("READMEXX.md", { password: "text", overwrite: true });
    // }
});
Enter fullscreen mode Exit fullscreen mode

It is displayed as below.

totalFiles = 4
README.md:
    compsize       =       4413
    size           =      11621
    isDirectory    =          0
    crc32          =   EFD9A09C
    isEncrypted    =          1
    method         =    deflate
      time.month   =          3
      time.minute  =          1
      time.day     =         19
      time.year    =       2020
      time.second  =          2
      time.hour    =         16
...
Enter fullscreen mode Exit fullscreen mode

Extract

There are two ways to extract the Zip file.

  • Extract directly from a Zip instance.
  • Extract from Zip entry object.

Extracting from a Zip entry is to do for each entry. In that case, there are two methods as follows.

  • Iterating and selecting an entry.
  • Using the find method to get directly your target entry.

The find method returns a Zip entry object if there is an entry with the specified filename.

The meanings of the options when extracting are as follows.

  • password: Password to use for extraction. If not specified, the one set with setPassword() is used. If it is not set even with setPassword(), it tries to expand without a password.
  • overwrite: Specify true and overwrite if a file with the same name already exists.
  • skip: Specify true and skip if a file with the same name already exists.

If overwrite or skip is not specified and a file with the same name exists, a ZipException exception is thrown.

Extract all

To extract all, execute extractTo on the iterated entry. The necessary directories will be created automatically.

zip.each(&(e) => e.extractTo("examples/zip/dst" / e.filename, {password: "text", skip: true }));
Enter fullscreen mode Exit fullscreen mode

Although I've not explained anything about it, when the / operator is applied to a string, it becomes a string concatenated with /.

Specify the file and extract

You can use the extract or extractTo methods directly to the Zip instance.

zip.extractTo("README.md", "READMEXX.md", {password: "text", skip: true });
Enter fullscreen mode Exit fullscreen mode

If you use extract, it returns the extracted contents as a string.

var text = zip.extract("README.md", {password: "text" });
Enter fullscreen mode Exit fullscreen mode

For Zip entry objects, there are no arguments to specify the entry name.

Method Content Options
extract([opts]) Extract and acquire as a string { password, overwrite, skip, }
extractTo(file [, opts]) Extract to file (same as above)

Here is an example using find.

zip.find("README.md")
   .extractTo("READMEXX.md", {password: "text", skip: true });
Enter fullscreen mode Exit fullscreen mode
var text = zip.find("README.md")
              .extract({ password: "text" });
Enter fullscreen mode Exit fullscreen mode

Other

Library that Kinx used

It is this.

Here is the list of features. I don't feel like a Mini at all.

  • Features
    • Creating and extracting zip archives.
    • Adding and removing entries from zip archives.
    • Read and write raw zip entry data.
    • Reading and writing zip archives from memory.
    • Zlib, BZIP2, and LZMA compression methods.
    • Password protection through Traditional PKWARE and WinZIP AES encryption.
    • Buffered streaming for improved I/O performance.
    • NTFS timestamp support for UTC last modified, last accessed, and creation dates.
    • Disk split support for splitting zip archives into multiple files.
    • Preservation of file attributes across file systems.
    • Follow and store symbolic links.
    • Unicode filename support through UTF-8 encoding.
    • Legacy character encoding support CP437, CP932, CP936, CP950.
    • Turn off compilation of compression, decompression, or encryption.
    • Windows (Win32 & WinRT), macOS and Linux platform support.
    • Streaming interface for easy implementation of additional platforms.
    • Support for Apple's compression library ZLIB implementation.
    • Zero out local file header information.
    • Zip/unzip of central directory to reduce size.
    • Ability to generate and verify CMS signature for each entry.
    • Recover the central directory if it is corrupt or missing.
    • Example minizip command line tool.

Zip64 compatible

It seems that Zip64 is also supported. It is said that it is possible even if it exceeds 4G, but it has not been tested.

Conclusion

Zip/Unzip would be one of a wanted feature for using scripting languages. I never want to handle it in C, and I guess everybody want to easily create a Zip file.

See you next time.

Discussion (0)