GithubHelp home page GithubHelp logo

zip's People

Contributors

alexisad avatar araq avatar ba0f3 avatar bung87 avatar dom96 avatar emekoi avatar idiot-with-a-keyboard avatar karantin2020 avatar krux02 avatar lemonboy avatar markus-oberhumer avatar narimiran avatar nigredo-tori avatar parashurama avatar recloser avatar snej avatar vegansk avatar vklayd avatar yglukhov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zip's Issues

Update to newer zlib, add new functions

I don't know what version of zlib zlib.nim was converted from, but it's missing a bunch of newer functions like (deep breath) deflateTune, deflatePending, deflatePrime, deflateSetHeader, inflateGetDictionary, inflateCopy, inflateReset2, inflatePrime, inflateMark, inflateGetHeader, zlibCompileFlags.

Not compiling on windows

Hello, this package doesn't seem's to compile on Windows:

CC: libzip_all
Error: execution of an external compiler program 'clang.exe -c  -w -DWIN32_LEAN_AND_MEAN -IC:\Users\roman\Documents\vcpkg/installed/x64-windows/include  -IC:\Users\roman\Desktop\nim-1.0.4\lib -IC:\Users\roman\CLionProjects\atomicDEX-QT\atomic_dex_desktop\tools -o C:\Users\roman\nimcache\dependencies_d\libzip_all.c.o C:\Users\roman\.nimble\pkgs\zip-0.2.1\zip\private\libzip_all.c' failed with exit code: 1

C:\Users\roman\.nimble\pkgs\zip-0.2.1\zip\private\libzip_all.c:193:17: error: function cannot return function type 'int (void *, void *, size_t, enum zip_source_cmd)' (aka 'int (void *, void *, unsigned long long, enum zip_source_cmd)')
typedef ssize_t (*zip_source_callback)(void *state, void *data,
                ^
C:\Users\roman\.nimble\pkgs\zip-0.2.1\zip\private\libzip_all.c:226:29: error: function cannot return function type 'ssize_t' (aka 'int (int *)')
ZIP_EXTERN ssize_t zip_fread(struct zip_file *, void *, size_t);
                            ^
C:\Users\roman\.nimble\pkgs\zip-0.2.1\zip\private\libzip_all.c:505:5: error: unknown type name 'zip_source_callback'
    zip_source_callback f;
    ^
C:\Users\roman\.nimble\pkgs\zip-0.2.1\zip\private\libzip_all.c:719:9: error: use of undeclared identifier 'pid_t'
        pid_t pid;
        ^
C:\Users\roman\.nimble\pkgs\zip-0.2.1\zip\private\libzip_all.c:727:9: error: use of undeclared identifier 'pid'
        pid = getpid();

Compiler: clang-9
Nim Compiler: 1.0.4
Windows 10.

Usage:

when defined(windows):
    {.passC: "-I"  & os.getEnv("VCPKG_ROOT") & "/installed/x64-windows/include"}
    {.passL: "-L"  & os.getEnv("VCPKG_ROOT") & "/installed/x64-windows-static/lib -lzlib -lz"}
import zip/zipfiles

zipfiles library does not work with Unicode.

Problem

zipfiles library does not work against a filename with Unicode(multibyte character).
(ex : ใ€ฮฑฮฒฮณโ˜…ใ€‘.zip)

Temporary solution

I tried sending WideCString in nim and recieving wchar_t pointer in C at calling 'zip_open' in libzip_all.c library.
(have to fix zipfiles.nim, libzip.nim, and libzip_all.c)
It seems looks working fine.
But, this solution is maybe only valid in 'zipfiles.open' on Windows platform.

Permanent solution

How to comply with Unicode as a whole ?
Please give me a hand...

ZIP Password

  • Implement the ability to Create and Extract a ZIP file with Password.

Thanks for the great work.
๐Ÿ˜ธ

ZIP Comments

  • The lib needs to implement the ability to set Comment strings on ZIP files, is missing from code and docs, its a plain text string of up to 256 chars I think.

Thanks for the great work on the lib tho.
๐Ÿ˜ผ

allow passing flags to zip_open via open

AFAICT, files larger than 4.2 GB are not actually supported because we need to pass: ZIP_CM_DEFLATE64 to zip_open, but that's not possible via zip.open

I can open a PR changing:

proc open*(z: var ZipArchive, filename: string, mode: FileMode = fmRead): bool =

to

proc open*(z: var ZipArchive, filename: string, mode: FileMode = fmRead, flags:int32=0): bool =

here is the code I am using to check the problem. should fail for any file > 4.2GB.

import zip/zipfiles
import zip/libzip

var z:ZipArchive

# 5 GB zip file
var path  = "gnomad.v3.genome.zip"

if not z.open(path):
  # does not open and no way ? to get err value
  echo "couldn't open"

import zip/libzip

var err:int32
var flags:int32

flags = ZIP_CM_DEFLATE64

var w = zip_open(path, 0, addr(err))
# gives not a zip archive
echo err


err = 0
w = zip_open(path, flags, addr(err))
# gives 0
echo err

Issues cross-compiling with MinGW

I am having similar issues with what was going on with is post: #33 (comment)

The solution that worked for that poster is not working for me in this case by adding the {.passl: "-lz".} option to the libzip.nim file. I am simply just trying to compile a test of zip/zipfiles. The error output is below.

Hint:  [Link]
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x3c8): undefined reference to `crc32'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x445): undefined reference to `deflateInit2_'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x4a0): undefined reference to `deflateEnd'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x4c5): undefined reference to `crc32'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x4d2): undefined reference to `deflate'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x556): undefined reference to `deflateEnd'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x61d): undefined reference to `zError'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x1408): undefined reference to `zError'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x1470): undefined reference to `inflateEnd'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x1528): undefined reference to `crc32'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x1570): undefined reference to `crc32'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x188b): undefined reference to `crc32'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x1997): undefined reference to `inflateInit2_'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x261b): undefined reference to `crc32'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x2649): undefined reference to `inflate'
/usr/bin/x86_64-w64-mingw32-ld: /home/chris/.cache/nim/zip_r/libzip_all.c.o:libzip_all.c:(.text+0x26a8): undefined reference to `crc32'
collect2: error: ld returned 1 exit status
Error: execution of an external program failed: '/usr/bin/x86_64-w64-mingw32-gcc   -o /home/chris/Desktop/Nim/Client/Test/zip.exe  /home/chris/.cache/nim/zip_r/libzip_all.c.o /home/chris/.cache/nim/zip_r/stdlib_digitsutils.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_assertions.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_dollars.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_widestrs.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_io.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_system.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_streams.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_math.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_dynlib.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_winlean.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_times.nim.c.o /home/chris/.cache/nim/zip_r/@m..@s..@s..@s..@[email protected]@[email protected]@[email protected] /home/chris/.cache/nim/zip_r/stdlib_win_setenv.nim.c.o /home/chris/.cache/nim/zip_r/stdlib_os.nim.c.o /home/chris/.cache/nim/zip_r/@m..@s..@s..@s..@[email protected]@[email protected]@[email protected] /home/chris/.cache/nim/zip_r/@mzip.nim.c.o   -s  '

I was also having issues before this where it was unable to find zlib.h during compilation so I put zlib.h with ~/.nimble/pkgs/zip-0.3.1/zip/private/libzip_all.c in the same directory and changed the #include <zlib.h> to #include "zlib.h" because it wasn't finding it in /usr/include even when I compiled with --cincludes:/usr/include. So after I made that change it was able to find zlib.h and now I am getting the error above with the undefined references.

Anybody know why this is or what I could do to work around it?

I am running Nim Compiler ver 1.6.4 and the latest Zip which is pretty old. Are there any other more recent options for zipping up files?

Thanks.

Issue trying to read stats on file in zip files

I am only starting to learn Nim and I want to read the stats of files inside a zip file. Zipfiles.nim does not expose this information, so I am attempting to modify it by creating a new iterator like this

iterator walkFileStats*(z: var ZipArchive): ZipStat =
  ## walks over all files in the archive `z` and returns the File stats
  var i = 0'i32
  var num = zip_get_num_files(z.w)
  while i < num:
    var name : cstring = $zip_get_name(z.w, i, 0'i32)

    var stat : ZipStat 

    var r = zip_stat(z.w , name, ZIP_FL_UNCHANGED , addr(stat)) ;
    if (r == 0) : 
        yield stat
    inc(i)

But this does not return the correct results. I am building on 64-bit windows and the name and date look correct but the size and compressed size are not. But I need the final program to run on some 32-bit windows machines and when I compile for 32-bit, the name is still correct, but the date is just garbage and the sizes are also incorrect.

I got a little further by looking at the definition of ZipStat in libzip.nim which declares mtime to be of type time. If I change this to int32 then the fromUnix method returns the correct time for both 32-bit and 64-bit versions. The sizes are correct for the 32-bit
version, but not when compiled for 64-bit.

Since I don't need a 64-bit version of the program, this gives me what I need, but I would prefer to fix the issue properly.

Has anyone any ideas?

Stream version of `addFile` broken with the new libzip

var z: ZipArchive
require z.open(filename, fmWrite)
z.addFile("foo.bar", newStringStream("content"))
z.close

This fails an assertion at runtime.
The problem was triggered by the new ZIP_SOURCE_SUPPORTS command. Libzip now uses it to query the acceptable operations from the zip_source_function callback. This alone would not have broken the compatibility, though, were it not for the fact that our callback raises an exception on unsupported command.
The proper way to handle this situation is to return -1, as is specified in zip_source_function documentation.

ZlibStreamError due to size mismatch of data types (Linux)

I was trying out the zlib wrapper on my Linux machine (amd64, zlib 1.2.11) with the following program:

import zip/zlib

let c = compress("Compress me!")

Compilation goes well but the program yields the following run-time error:

Error: unhandled exception: zlib version mismatch! [ZlibStreamError]

I went digging through the source code and I think I've figured out what's going on.

The version mismatch exception is (in this case) caused by zlib's deflateInit2() returning Z_VERSION_ERROR. According to the docs, that can happen for two reasons:

  • the requested version is not compatible with the library version or
  • the z_stream size differs from that used by the library.

The wrapper defines the ZStream object to represent z_stream and passes sizeof(ZStream) as the size that gets validated by the library. That causes a mismatch on my system since the library expects a 112-byte struct but instead gets one that's 88 bytes.

There is a zlib function called zlibCompileFlags() that defines the sizes of the types used by the library. Compile the following with gcc:

#include <stdio.h>
#include <zlib.h>

unsigned int get_zlib_size(unsigned long flag)
{
    switch (flag)
    {
    case 0:
    case 1:
    case 2:
        return (1u << (1 + flag));
    default:
        break;
    }

    printf("Unknown size flag '%lu'.\n", flag);
    return 0;
}

int main(int argc, const char *argv[])
{
    z_stream s;
    printf("Size of z_stream: %lu.\n", sizeof(s));

    unsigned long cflags = zlibCompileFlags();

    printf("zlib compile flags:\n");
    printf("  size of uInt: %u.\n", get_zlib_size(cflags & 0x3));
    printf("  size of uLong: %u.\n", get_zlib_size((cflags >> 2) & 0x3));
    printf("  size of voidpf: %u.\n", get_zlib_size((cflags >> 4) & 0x3));
    printf("  size of z_off_t: %u.\n", get_zlib_size((cflags >> 6) & 0x3));

    return 0;
}

For me that yields the output:

Size of z_stream: 112.
zlib compile flags:
  size of uInt: 4.
  size of uLong: 8.
  size of voidpf: 8.
  size of z_off_t: 8.

Merge request #35 changed the data type for Ulong to int32 instead of Nim's int type. This should be the source of the issue on my machine and other's too, I'm sure.

I'm guessing a solution has to work around the fact that #35 was needed on Windows, without breaking the wrapper for other platforms. Just changing the types back to int or int64 works for me. Additionally, looking at the output from zlibCompileFlags(), there seems to be a mismatch for the ZoffT type too.

[mac os x]: could not import: gzopen

Actually, I have problems to run example from Arraymancer, which uses zip module to read files

So I isolated the problem into simple gz.nim file:

import zip/gzipfiles

let stream = newGzFileStream("./build/mnist.zip", mode = fmRead)
nim c gz.nim
Hint: used config file '/usr/local/Cellar/nim/0.20.0_1/nim/config/nim.cfg' [Conf]
Hint: used config file '/Users/deem0n/Documents/Projects/Arraymancer/nim.cfg' [Conf]
Hint: system [Processing]
Hint: widestrs [Processing]
Hint: io [Processing]
Hint: gz [Processing]
Hint: gzipfiles [Processing]
Hint: os [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: math [Processing]
Hint: bitops [Processing]
Hint: macros [Processing]
Hint: algorithm [Processing]
Hint: unicode [Processing]
Hint: pathnorm [Processing]
Hint: osseps [Processing]
Hint: posix [Processing]
Hint: times [Processing]
Hint: options [Processing]
Hint: typetraits [Processing]
Hint: zlib [Processing]
Hint: streams [Processing]
/Users/deem0n/Documents/Projects/Arraymancer/examples/gz.nim(3, 5) Hint: 'stream' is declared but not used [XDeclaredButNotUsed]
CC: stdlib_assertions.nim
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: stdlib_posix.nim
CC: stdlib_times.nim
CC: stdlib_os.nim
CC: ../../../../.nimble/pkgs/zip-0.2.1/zip/zlib.nim
CC: stdlib_streams.nim
CC: ../../../../.nimble/pkgs/zip-0.2.1/zip/gzipfiles.nim
CC: gz.nim
Hint:  [Link]
Hint: operation successful (37824 lines compiled; 0.896 sec total; 46.707MiB peakmem; Debug Build) [SuccessX]

When I run compiled executable, I got:

./gz
could not import: gzopen

It is mac os x 10.14.4 (Mojave)

 nimble list -i
arraymancer  [0.5.0]
c2nim  [0.9.14]
clblast  [0.0.1]
cligen  [0.9.17]
commandeer  [0.12.3]
compiler  [0.19.0]
docopt  [0.6.5]
nats  [1.0.0]
nimblas  [0.2.2]
nimcl  [0.1.3]
nimcuda  [0.1.5]
nimgen  [0.4.0]
nimlapack  [0.1.1]
nimssh2  [0.1.2]
nimssl  [0.1.2]
opencl  [1.0]
regex  [0.8.1]
rosencrantz  [0.3.3]
stb_image  [2.3]
unicodedb  [0.6.0]
unicodeplus  [0.4.0]
untar  [0.1.0]
zip  [0.2.1]
ls -l /usr/lib/libz.*
lrwxr-xr-x  1 root  wheel      12 27 ะฐะฟั€ 20:34 /usr/lib/libz.1.1.3.dylib -> libz.1.dylib
lrwxr-xr-x  1 root  wheel      12 27 ะฐะฟั€ 20:34 /usr/lib/libz.1.2.11.dylib -> libz.1.dylib
lrwxr-xr-x  1 root  wheel      12 27 ะฐะฟั€ 20:34 /usr/lib/libz.1.2.5.dylib -> libz.1.dylib
lrwxr-xr-x  1 root  wheel      12 27 ะฐะฟั€ 20:34 /usr/lib/libz.1.2.8.dylib -> libz.1.dylib
-rwxr-xr-x  1 root  wheel  186480 16 ะฐะฟั€ 07:22 /usr/lib/libz.1.dylib
lrwxr-xr-x  1 root  wheel      12 27 ะฐะฟั€ 20:34 /usr/lib/libz.dylib -> libz.1.dylib

Compile Error๏ผš can not find zdll.lib

Env:
windows 2008 64bit, GCC64, nim-0.13-64bit

Compile Error info:

CC: zip_zipfiles
CC: zip_libzip
CC: libzip_all
c:\users\administrator\.nimble\pkgs\zip-0.1.0\zip\private\libzip_all.c:34:18: fatal error: zlib.h: N
o such file or directory
 #include 
                  ^
compilation terminated.

zipfiles does not work on windows machine.

Problem

On my Windows environment, zipfiles.nim does not work at all.

Situation

When execute nim compiling, compiler shows messages that compiling libzip_all.c is failed.
It seems that zlib.h is not linked.
Sample source code is following as:

import zip/zipfiles
proc main() =
  var fpZip: ZipArchive
  defer: fpZip.close()
  discard fpZip.open(r"C:\Users\puruneko\archive.zip")
  for path in fpZip.walkFiles:
    echo path
when isMainModule:
  main()

Example message of compiling is folloing as:

C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x112): undefined reference to `zError'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x2be0): undefined reference to `crc32'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x2c86): undefined reference to `deflateInit2_'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x2d35): undefined reference to `deflateEnd'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x2da4): undefined reference to `crc32'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x2dce): undefined reference to `deflate'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x2ed6): undefined reference to `deflateEnd'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x37ad): undefined reference to `zError'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x3860): undefined reference to `inflateEnd'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x39bc): undefined reference to `crc32'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x3ab1): undefined reference to `crc32'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x3fff): undefined reference to `inflateInit2_'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x42ec): undefined reference to `crc32'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x69c7): undefined reference to `crc32'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x6a32): undefined reference to `inflate'
C:\Users\puruneko\nimcache\sample_d\libzip_all.c.o:libzip_all.c:(.text+0x6abd): undefined reference to `crc32'

Temporary solution

Compiling only libzip_all.c can succeed. (gcc -shared libzip_all.c -o libzip_all.dll -lz)
It seems that libzip_all.c is correct because of the above, so I checked libzip.nim.
Then, places that seems suspicious were found in the upper when blocks:

when defined(unix) and not defined(useLibzipSrc):
  when defined(macosx):
    {.pragma: mydll, dynlib: "libzip(|2|4).dylib".}
  else:
    {.pragma: mydll, dynlib: "libzip(|2).so(|.4|.2|.1|.0)".}
else:
  when defined(unix):
    {.passl: "-lz".}
  {.compile: "zip/private/libzip_all.c".}
  {.pragma: mydll.}

In the above code, when the case of windows machine, it seems that libzip_all.c is compiled without -lz option.
So, I changed codes following as:

else:
  {.passl: "-lz".}
  {.compile: "zip/private/libzip_all.c".}
  {.pragma: mydll.}

It startrd to move for now...
But, is this a correct solution?

Postscripts

Please pardon my poor English.

GZFileStream atEnd too late

I have a file with 8 lines that I compress with gzip:

bli@naples:~/src/bioinfo_utils/fastq-demultiplexing/Nim$ cat test8lines.txt
1
2
3
4
5
6
7
8
bli@naples:~/src/bioinfo_utils/fastq-demultiplexing/Nim$ gzip -k test8lines.txt

The following program parses the files four lines by four lines and prints something made with the lines:

from streams import newFileStream, Stream, atEnd, readLine
from zip/gzipfiles import newGZFileStream

from strutils import join

proc fourLineParser(stream: Stream): iterator(): tuple[one: string, two: string, three: string, four: string] =
  result = iterator(): tuple[one: string, two: string, three: string, four: string] =
    var
      lineOne: string
      lineTwo: string
      lineThree: string
      lineFour: string
    while not stream.atEnd():
      lineOne = stream.readLine()
      lineTwo = stream.readLine()
      lineThree = stream.readLine()
      lineFour = stream.readLine()
      yield (lineOne, lineTwo, lineThree, lineFour)

let normalInput = fourLineParser(newFileStream("test8lines.txt"))
for l1, l2, l3, l4 in normalInput():
  echo join([l1, l2, l3, l4], " ")

let gzInput = fourLineParser(newGZFileStream("test8lines.txt.gz"))
for l1, l2, l3, l4 in gzInput():
  echo join([l1, l2, l3, l4], " ")

The program outputs an extra empty line in the second case:

bli@naples:~/src/bioinfo_utils/fastq-demultiplexing/Nim$ nim c -r testgz.nim                                                     
Hint: used config file '/home/bli/src/Nim/config/nim.cfg' [Conf]
Hint: system [Processing]
Hint: testgz [Processing]
Hint: streams [Processing]
Hint: gzipfiles [Processing]
Hint: os [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: math [Processing]
Hint: algorithm [Processing]
Hint: times [Processing]
Hint: posix [Processing]
Hint: ospaths [Processing]
Hint: zlib [Processing]
Hint:  [Link]
Hint: operation successful (23642 lines compiled; 0.420 sec total; 54.746MiB peakmem; Debug Build) [SuccessX]
Hint: /home/bli/src/bioinfo_utils/fastq-demultiplexing/Nim/testgz  [Exec]
1 2 3 4
5 6 7 8
1 2 3 4
5 6 7 8
   
bli@naples:~/src/bioinfo_utils/fastq-demultiplexing/Nim$

I expect the output to be the same as when processing a stream made from the non compressed file.

[Feature Request] gzStream / gzReadData similar to readData

It would be nice to have gzStream / gzReadData like what is implemented in @dom96 untar:

type
  GzStream* = ref object of Stream
    handle: GzFilePtr
    pos: int
    isAtEnd: bool

proc gzReadData(s: Stream, buffer: pointer, bufLen: int): int =
  if bufLen == 0: return 0
  var s = GzStream(s)
  let ret = gzread(s.handle, buffer, bufLen.cint)
  checkZlibError ret, s.handle
  s.pos.inc(ret)
  s.isAtEnd = ret == 0

  return ret

addFile StringStream fails on Windows

While this works fine on Linux, calling addFile with a StringStream parameter fails on Windows.
The zip archive is created, but the enclosed file is 200MB+, and the archive cannot be uncompressed.

Here is a minimal example :

{.passl: "-lz".}
import zip/zipfiles
import streams

proc testZip() : void =
    var z : ZipArchive;
    var s = newStringStream("Hello world")
    if open(z, "test.zip", fmWrite):
        try:
            addFile(z, "datafile.txt", s)
        finally:
            close(z)

testZip()

On the other hand, creating zip files from on disk files works on both platforms.

Error: unhandled exception: Failed to create output file

I have implemented:

import zip/zipfiles
const
  fname = "../sundials-master.zip"
    
var
  z:ZipArchive
    
when isMainModule:
  if not z.open(fname):
    echo "Opening zip failed"
    quit(1)
  z.extractAll("./")
  z.close()

but when I run it I get:

$ ./ex01 
/home/jose/src/nimlang/z/ex01.nim(17) ex01
/home/jose/.nimble/pkgs/zip-0.2.1/zip/zipfiles.nim(203) extractAll
/home/jose/.nimble/pkgs/zip-0.2.1/zip/zipfiles.nim(193) extractFile
Error: unhandled exception: Failed to create output file: ./sundials-master [IOError]

I am using archlinux which uses libzip 1.5.1 and

$ nim -version
Nim Compiler Version 0.20.99 [Linux: amd64]
Compiled at 2019-06-19
Copyright (c) 2006-2019 by Andreas Rumpf

git hash: de88fdb86e8df63c657a191d73999890ec712b93
active boot switches: -d:release -d:nativeStackTrace

Am I doing something wrong or is it a bug?

libzip.dylib not found when installed via homebrew on Mac OSX

I use homebrew on Mac OSX as package manager and have libzip installed via that (brew install libzip). However, when compiling a nim project that depends on the zip wrapper/package it doesn't find the libzip.dylib file. I tried adding an explicit path using the "--path" flag but no difference. Relevant excerpt from adding the "-d:nimDebugDlOpen" flag:

...
dlopen(libzip.dylib, 0x0002): tried: 'libzip.dylib' (no such file), '/usr/local/lib/libzip.dylib' (no such file), '/usr/lib/libzip.dylib' (no such file), '/Users/feldt/tmp/nimfm/benchmarks/ml100k/libzip.dylib' (no such file)
...

I also tried copying the libzip.dylib file to the local (build) directory but it keeps asking for other dylib dependencies so I really need to set the right paths. Ideas?

no error reported on file open

The actual error is hidden because the only check is result = z.w != nil
Should report the value of errwhen z.w == nil.

I can open a PR for this. What's the preferred way to do this an exception? Msg to stderr?

windows vs linux inconsistency

If I zip foo/bar.txt on linux or windows and unzip on linux or windows it works as expected with a foo directory created with bar.txt inside it.

However, if I zip foo\bar.txt on windows on linux it unzips as the file 'foo\bar.txt' (with \ part of the filename) and on windows it raises an IOError.

My workaround is to say when defined(windows): filename = filename.replace('\\', '/') but it seems to me that the zip library should handle this.

Incorrect version check in deflateInit, inflateInit, etc.

The inflate/deflateInit group of functions are implemented in C as macros that call the actual functions and tack on extra arguments including the string ZLIB_VERSION.

The Nim equivalents of these are functions that tack on zlibVersion(). That's not the same thing โ€” it's the runtime version, whereas ZLIB_VERSION is the compile-time version. The purpose of this check is to find out what version the client was compiled with, and passing a runtime version defeats that.

Fix is to

  • Add a string constant ZLIB_VERSION whose value is the one from the version of zlib.h that the Nim interface was translated from;
  • Use this instead of zlibVersion() in the init functions.

I'll probably be submitting a PR soon.

zip_open_from_source() & zip_source_buffer_create() not defined in libzip_all.c

Heya,

I'm trying to get this library working when cross-compiling to Windows using the MingW toolchain, this is the Nim code i'm using:

import zip/zipfiles
import strformat
import os

const
    pyzip = slurp"../rsrc/python-3.9.1-embed-amd64.zip"
    tmpdir: string = getEnv("LOCALAPPDATA") / "Temp"

proc extractPython(): bool =
    var z: ZipArchive
    z.fromBuffer(pyzip)
    z.extractAll(tmpdir)
    return true

proc main(): void =
    echo fmt"[*] tmpdir: {tmpdir}"
    if extractPython():
        echo fmt"[*] Python extracted"

when isMainModule:
    main()

I compiled zlib v1.2.11 and made it available to MingW using the instructions from here & here

I then ran the following command to cross-compile the above Nim code and point the linker and compiler to the zlib directory:

nim c -d=useLibzipSrc -d=debug -d=mingw --embedsrc=on --hints=on --app=console --cpu=amd64 --passL:"-L/home/byt3bl33d3r/Devel/zlib-1.2.11 -lzlib1" --passC:"-I/home/byt3bl33d3r/Devel/zlib-1.2.11" --out=bin/embed_rsrc_bin_64.exe src/embed_rsrc_bin.nim

This gives the following error when compiled:

Hint: used config file '/usr/local/nim/config/nim.cfg' [Conf]
Hint: used config file '/usr/local/nim/config/config.nims' [Conf]
........................CC: libzip_all
CC: ../../../.nimble/pkgs/zip-#head/zip/libzip.nim
CC: ../../../.nimble/pkgs/zip-#head/zip/zipfiles.nim

Hint:  [Link]
/usr/bin/x86_64-w64-mingw32-ld: /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/@m..@s..@[email protected]@spkgs@szip-@hhead@[email protected]:@m..@s..@[email protected]@spkgs@szip-@hhead@[email protected]:(.text+0x680): undefined reference to `zip_source_buffer_create'
/usr/bin/x86_64-w64-mingw32-ld: /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/@m..@s..@[email protected]@spkgs@szip-@hhead@[email protected]:@m..@s..@[email protected]@spkgs@szip-@hhead@[email protected]:(.text+0x77c): undefined reference to `zip_open_from_source'
collect2: error: ld returned 1 exit status
Error: execution of an external program failed: '/usr/bin/x86_64-w64-mingw32-gcc   -o /home/byt3bl33d3r/Devel/OffensiveNim/bin/embed_rsrc_bin_64.exe  /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/libzip_all.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_assertions.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_widestrs.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_io.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_system.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_streams.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_parseutils.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_unicode.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_strutils.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_dynlib.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_winlean.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_times.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/@m..@s..@[email protected]@spkgs@szip-@hhead@[email protected] /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_pathnorm.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_os.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/@m..@s..@[email protected]@spkgs@szip-@hhead@[email protected] /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/stdlib_strformat.nim.c.o /home/byt3bl33d3r/.cache/nim/embed_rsrc_bin_d/@membed_rsrc_bin.nim.c.o   -L/home/byt3bl33d3r/Devel/zlib-1.2.11 -lzlib1  '

After some investigation libzip.nim has those two functions defined however they're not actually in the libzip_all.c file. It seems like those two functions are only available in libzip starting from version >= 1.0 (the current libzip_all.c file seems to be based off of libzip 0.9?).

I'm not sure If i'm doing something wrong here, but I think that's the problem.

Thanks.

fixed: zlib version mismatch! [ZlibStreamError]

I was working with zlib, and noticed that when I compiled to 64bit the library threw the error zlib version mismatch! [ZlibStreamError]. However, if I compiled to 32bit the library worked just fine. I discoverd that this is because of the use of in32 to I change the code, and now is working. I don't know how to do a PR so I'll just post the code

zip/zlib.nim :

# Converted from Pascal

## Interface to the zlib http://www.zlib.net/ compression library.

when defined(windows):
  const libz = "zlib1.dll"
elif defined(macosx):
  const libz = "libz.dylib"
else:
  const libz = "libz.so.1"

type
  Uint* = int
  Ulong* = uint
  Ulongf* = uint
  Pulongf* = ptr Ulongf
  ZOffT* = int
  Pbyte* = cstring
  Pbytef* = cstring
  Allocfunc* = proc (p: pointer, items: Uint, size: Uint): pointer{.cdecl.}
  FreeFunc* = proc (p: pointer, address: pointer){.cdecl.}
  InternalState*{.final, pure.} = object
  PInternalState* = ptr InternalState
  ZStream*{.final, pure.} = object
    nextIn*: Pbytef
    availIn*: Uint
    totalIn*: Ulong
    nextOut*: Pbytef
    availOut*: Uint
    totalOut*: Ulong
    msg*: Pbytef
    state*: PInternalState
    zalloc*: Allocfunc
    zfree*: FreeFunc
    opaque*: pointer
    dataType*: int
    adler*: Ulong
    reserved*: Ulong

  ZStreamRec* = ZStream
  PZstream* = ptr ZStream
  GzFile* = pointer
  ZStreamHeader* = enum
    DETECT_STREAM,
    RAW_DEFLATE,
    ZLIB_STREAM,
    GZIP_STREAM

  ZlibStreamError* = object of Exception

{.deprecated: [TInternalState: InternalState, TAllocfunc: Allocfunc,
              TFreeFunc: FreeFunc, TZStream: ZStream, TZStreamRec: ZStreamRec].}

const
  Z_NO_FLUSH* = 0
  Z_PARTIAL_FLUSH* = 1
  Z_SYNC_FLUSH* = 2
  Z_FULL_FLUSH* = 3
  Z_FINISH* = 4
  Z_OK* = 0
  Z_STREAM_END* = 1
  Z_NEED_DICT* = 2
  Z_ERRNO* = -1
  Z_STREAM_ERROR* = -2
  Z_DATA_ERROR* = -3
  Z_MEM_ERROR* = -4
  Z_BUF_ERROR* = -5
  Z_VERSION_ERROR* = -6
  Z_NO_COMPRESSION* = 0
  Z_BEST_SPEED* = 1
  Z_BEST_COMPRESSION* = 9
  Z_DEFAULT_COMPRESSION* = -1
  Z_FILTERED* = 1
  Z_HUFFMAN_ONLY* = 2
  Z_DEFAULT_STRATEGY* = 0
  Z_BINARY* = 0
  Z_ASCII* = 1
  Z_UNKNOWN* = 2
  Z_DEFLATED* = 8
  Z_NULL* = 0
  Z_MEM_LEVEL* = 8
  MAX_WBITS* = 15

proc zlibVersion*(): cstring{.cdecl, dynlib: libz, importc: "zlibVersion".}
proc deflate*(strm: var ZStream, flush: int): int{.cdecl, dynlib: libz,
    importc: "deflate".}
proc deflateEnd*(strm: var ZStream): int{.cdecl, dynlib: libz,
    importc: "deflateEnd".}
proc inflate*(strm: var ZStream, flush: int): int{.cdecl, dynlib: libz,
    importc: "inflate".}
proc inflateEnd*(strm: var ZStream): int{.cdecl, dynlib: libz,
    importc: "inflateEnd".}
proc deflateSetDictionary*(strm: var ZStream, dictionary: Pbytef,
                           dictLength: Uint): int{.cdecl, dynlib: libz,
    importc: "deflateSetDictionary".}
proc deflateCopy*(dest, source: var ZStream): int{.cdecl, dynlib: libz,
    importc: "deflateCopy".}
proc deflateReset*(strm: var ZStream): int{.cdecl, dynlib: libz,
    importc: "deflateReset".}
proc deflateParams*(strm: var ZStream, level: int, strategy: int): int{.
    cdecl, dynlib: libz, importc: "deflateParams".}
proc inflateSetDictionary*(strm: var ZStream, dictionary: Pbytef,
                           dictLength: Uint): int{.cdecl, dynlib: libz,
    importc: "inflateSetDictionary".}
proc inflateSync*(strm: var ZStream): int{.cdecl, dynlib: libz,
    importc: "inflateSync".}
proc inflateReset*(strm: var ZStream): int{.cdecl, dynlib: libz,
    importc: "inflateReset".}
proc compress*(dest: Pbytef, destLen: Pulongf, source: Pbytef, sourceLen: Ulong): cint{.
    cdecl, dynlib: libz, importc: "compress".}
proc compress2*(dest: Pbytef, destLen: Pulongf, source: Pbytef,
                sourceLen: Ulong, level: cint): cint{.cdecl, dynlib: libz,
    importc: "compress2".}
proc uncompress*(dest: Pbytef, destLen: Pulongf, source: Pbytef,
                 sourceLen: Ulong): cint{.cdecl, dynlib: libz,
    importc: "uncompress".}
proc compressBound*(sourceLen: Ulong): Ulong {.cdecl, dynlib: libz, importc.}
proc gzopen*(path: cstring, mode: cstring): GzFile{.cdecl, dynlib: libz,
    importc: "gzopen".}
proc gzdopen*(fd: int, mode: cstring): GzFile{.cdecl, dynlib: libz,
    importc: "gzdopen".}
proc gzsetparams*(thefile: GzFile, level: int, strategy: int): int{.cdecl,
    dynlib: libz, importc: "gzsetparams".}
proc gzread*(thefile: GzFile, buf: pointer, length: int): int{.cdecl,
    dynlib: libz, importc: "gzread".}
proc gzwrite*(thefile: GzFile, buf: pointer, length: int): int{.cdecl,
    dynlib: libz, importc: "gzwrite".}
proc gzprintf*(thefile: GzFile, format: Pbytef): int{.varargs, cdecl,
    dynlib: libz, importc: "gzprintf".}
proc gzputs*(thefile: GzFile, s: Pbytef): int{.cdecl, dynlib: libz,
    importc: "gzputs".}
proc gzgets*(thefile: GzFile, buf: Pbytef, length: int): Pbytef{.cdecl,
    dynlib: libz, importc: "gzgets".}
proc gzputc*(thefile: GzFile, c: int): int {.cdecl, dynlib: libz,
    importc: "gzputc".}
proc gzgetc*(thefile: GzFile): int {.cdecl, dynlib: libz, importc: "gzgetc".}
proc gzungetc*(c: int; thefile: GzFile): int {.cdecl, dynlib: libz, importc: "gzungetc".}
proc gzflush*(thefile: GzFile, flush: int): int{.cdecl, dynlib: libz,
    importc: "gzflush".}
proc gzseek*(thefile: GzFile, offset: ZOffT, whence: int): ZOffT{.cdecl,
    dynlib: libz, importc: "gzseek".}
proc gzrewind*(thefile: GzFile): int{.cdecl, dynlib: libz, importc: "gzrewind".}
proc gztell*(thefile: GzFile): ZOffT{.cdecl, dynlib: libz, importc: "gztell".}
proc gzeof*(thefile: GzFile): int {.cdecl, dynlib: libz, importc: "gzeof".}
proc gzclose*(thefile: GzFile): int{.cdecl, dynlib: libz, importc: "gzclose".}
proc gzerror*(thefile: GzFile, errnum: var int): Pbytef{.cdecl, dynlib: libz,
    importc: "gzerror".}
proc adler32*(adler: Ulong, buf: Pbytef, length: Uint): Ulong{.cdecl,
    dynlib: libz, importc: "adler32".}
  ## **Warning**: Adler-32 requires at least a few hundred bytes to get rolling.
proc crc32*(crc: Ulong, buf: Pbytef, length: Uint): Ulong{.cdecl, dynlib: libz,
    importc: "crc32".}
proc deflateInitu*(strm: var ZStream, level: int, version: cstring,
                   streamSize: int): int{.cdecl, dynlib: libz,
    importc: "deflateInit_".}
proc inflateInitu*(strm: var ZStream, version: cstring,
                   streamSize: int): int {.
    cdecl, dynlib: libz, importc: "inflateInit_".}
proc deflateInit*(strm: var ZStream, level: int): int
proc inflateInit*(strm: var ZStream): int
proc deflateInit2u*(strm: var ZStream, level: int, `method`: int,
                    windowBits: int, memLevel: int, strategy: int,
                    version: cstring, streamSize: int): int {.cdecl,
                    dynlib: libz, importc: "deflateInit2_".}
proc inflateInit2u*(strm: var ZStream, windowBits: int, version: cstring,
                    streamSize: int): int{.cdecl, dynlib: libz,
    importc: "inflateInit2_".}
proc deflateInit2*(strm: var ZStream,
                   level, `method`, windowBits, memLevel,
                   strategy: int): int
proc inflateInit2*(strm: var ZStream, windowBits: int): int
proc zError*(err: int): cstring{.cdecl, dynlib: libz, importc: "zError".}
proc inflateSyncPoint*(z: PZstream): int{.cdecl, dynlib: libz,
    importc: "inflateSyncPoint".}
proc getCrcTable*(): pointer{.cdecl, dynlib: libz, importc: "get_crc_table".}

proc deflateBound*(strm: var ZStream, sourceLen: ULong): ULong {.cdecl,
        dynlib: libz, importc: "deflateBound".}

proc deflateInit(strm: var ZStream, level: int): int =
  result = deflateInitu(strm, level, zlibVersion(), sizeof(ZStream).cint)

proc inflateInit(strm: var ZStream): int =
  result = inflateInitu(strm, zlibVersion(), sizeof(ZStream).cint)

proc deflateInit2(strm: var ZStream,
                  level, `method`, windowBits, memLevel,
                  strategy: int): int =
  result = deflateInit2u(strm, level, `method`, windowBits, memLevel,
                         strategy, zlibVersion(), sizeof(ZStream).cint)

proc inflateInit2(strm: var ZStream, windowBits: int): int =
  result = inflateInit2u(strm, windowBits, zlibVersion(),
                         sizeof(ZStream).cint)

proc zlibAllocMem*(appData: pointer, items, size: int): pointer {.cdecl.} =
  result = alloc(items * size)

proc zlibFreeMem*(appData, `block`: pointer) {.cdecl.} =
  dealloc(`block`)


proc compress*(sourceBuf: cstring; sourceLen: int; level=Z_DEFAULT_COMPRESSION; stream=GZIP_STREAM): string =
  ## Given a cstring, returns its deflated version with an optional header.
  ##
  ## Valid argument for ``stream`` are
  ##   - ``ZLIB_STREAM`` - add a zlib header and footer.
  ##   - ``GZIP_STREAM`` - add a basic gzip header and footer.
  ##   - ``RAW_DEFLATE`` - no header is generated.
  ##
  ## Passing a nil cstring will crash this proc in release mode and assert in
  ## debug mode.
  ##
  ## Compression level can be set with ``level`` argument. Currently
  ## ``Z_DEFAULT_COMPRESSION`` is 6.
  ##
  ## Returns "" on failure.
  assert(not sourceBuf.isNil)
  assert(sourceLen >= 0)

  var z: ZStream
  var windowBits = MAX_WBITS
  case (stream)
  of RAW_DEFLATE: windowBits = -MAX_WBITS
  of GZIP_STREAM: windowBits = MAX_WBITS + 16
  of ZLIB_STREAM, DETECT_STREAM:
    discard # DETECT_STREAM defaults to ZLIB_STREAM

  var status = deflateInit2(z, level.int, Z_DEFLATED.int,
                               windowBits.int, Z_MEM_LEVEL.int,
                               Z_DEFAULT_STRATEGY.int)
  case status
  of Z_OK: discard
  of Z_MEM_ERROR: raise newException(OutOfMemError, "")
  of Z_STREAM_ERROR: raise newException(ZlibStreamError, "invalid zlib stream parameter!")
  of Z_VERSION_ERROR: raise newException(ZlibStreamError, "zlib version mismatch!")
  else: raise newException(ZlibStreamError, "Unkown error(" & $status & ") : " & $z.msg)

  let space = deflateBound(z, sourceLen.Ulong)
  var compressed = newString(space)
  z.next_in = sourceBuf
  z.avail_in = sourceLen.Uint
  z.next_out = addr(compressed[0])
  z.avail_out = space.Uint

  status = deflate(z, Z_FINISH)
  if status != Z_STREAM_END:
    discard deflateEnd(z) # cleanup allocated ressources
    raise newException(ZlibStreamError, "Invalid stream state(" & $status & ") : " & $z.msg)

  status = deflateEnd(z)
  if status != Z_OK: # cleanup allocated ressources
    raise newException(ZlibStreamError, "Invalid stream state(" & $status & ") : " & $z.msg)

  compressed.setLen(z.total_out)
  swap(result, compressed)

proc compress*(input: string; level=Z_DEFAULT_COMPRESSION; stream=GZIP_STREAM): string =
  ## Given a string, returns its deflated version with an optional header.
  ##
  ## Valid arguments for ``stream`` are
  ##  - ``ZLIB_STREAM`` - add a zlib header and footer.
  ##  - ``GZIP_STREAM`` - add a basic gzip header and footer.
  ##  - ``RAW_DEFLATE`` - no header is generated.
  ##
  ## Compression level can be set with ``level`` argument. Currently
  ## ``Z_DEFAULT_COMPRESSION`` is 6.
  ##
  ## Returns "" on failure.
  result = compress(input, input.len, level, stream)

proc uncompress*(sourceBuf: cstring, sourceLen: Natural; stream=DETECT_STREAM): string =
  ## Given a deflated buffer returns its inflated content as a string.
  ##
  ## Valid arguments for ``stream`` are
  ##   - ``DETECT_STREAM`` - detect if zlib or gzip header is present
  ##     and decompress stream. Fail on raw deflate stream.
  ##   - ``ZLIB_STREAM`` - decompress a zlib stream.
  ##   - ``GZIP_STREAM`` - decompress a gzip stream.
  ##   - ``RAW_DEFLATE`` - decompress a raw deflate stream.
  ##
  ## Passing a nil cstring will crash this proc in release mode and assert in
  ## debug mode.
  ##
  ## Returns "" on problems. Failure is a very loose concept, it could be you
  ## passing a non deflated string, or it could mean not having enough memory
  ## for the inflated version.
  ##
  ## The uncompression algorithm is based on http://zlib.net/zpipe.c.
  assert(not sourceBuf.isNil)
  assert(sourceLen >= 0)
  var z: ZStream
  var decompressed: string = ""
  var sbytes = 0
  var wbytes = 0
  ##  allocate inflate state

  z.availIn = 0
  var wbits = case (stream)
  of RAW_DEFLATE:  -MAX_WBITS
  of ZLIB_STREAM:   MAX_WBITS
  of GZIP_STREAM:   MAX_WBITS + 16
  of DETECT_STREAM: MAX_WBITS + 32

  var status = inflateInit2(z, wbits.int)

  case status
  of Z_OK: discard
  of Z_MEM_ERROR: raise newException(OutOfMemError, "")
  of Z_STREAM_ERROR: raise newException(ZlibStreamError, "invalid zlib stream parameter!")
  of Z_VERSION_ERROR: raise newException(ZlibStreamError, "zlib version mismatch!")
  else: raise newException(ZlibStreamError, "Unkown error(" & $status & ") : " & $z.msg)

  # run loop until all input is consumed.
  # handle concatenated deflated stream with header.
  while true:
    z.availIn = (sourceLen - sbytes).int

    # no more input available
    if (sourceLen - sbytes) <= 0: break
    z.nextIn = sourceBuf[sbytes].unsafeaddr

    #  run inflate() on available input until output buffer is full
    while true:
      # if written bytes >= output size : resize output
      if wbytes >= decompressed.len:
        let cur_outlen = decompressed.len
        let new_outlen = if decompressed.len == 0: sourceLen*2 else: decompressed.len*2
        if new_outlen < cur_outlen: # unsigned integer overflow, buffer too large
          discard inflateEnd(z);
          raise newException(OverflowError, "zlib stream decompressed size is too large! (size > " & $int.high & ")")

        decompressed.setLen(new_outlen)

      # available space for decompression
      let space = decompressed.len - wbytes
      z.availOut = space.Uint
      z.nextOut = decompressed[wbytes].addr

      status = inflate(z, Z_NO_FLUSH)
      if status.int8 notin {Z_OK.int8, Z_STREAM_END.int8, Z_BUF_ERROR.int8}:
        discard inflateEnd(z)
        case status
        of Z_MEM_ERROR: raise newException(OutOfMemError, "")
        of Z_DATA_ERROR: raise newException(ZlibStreamError, "invalid zlib stream parameter!")
        else: raise newException(ZlibStreamError, "Unkown error(" & $status & ") : " & $z.msg)

      # add written bytes, if any.
      wbytes += space - z.availOut.int

      # may need more input
      if not (z.availOut == 0): break

    #  inflate() says stream is done
    if (status == Z_STREAM_END):
      # may have another stream concatenated
      if z.availIn != 0:
        sbytes = sourceLen - z.availIn # add consumed bytes
        if inflateReset(z) != Z_OK: # reset zlib struct and try again
          raise newException(ZlibStreamError, "Invalid stream state(" & $status & ") : " & $z.msg)
      else:
        break # end of decompression

  #  clean up and don't care about any error
  discard inflateEnd(z)

  if status != Z_STREAM_END:
    raise newException(ZlibStreamError, "Invalid stream state(" & $status & ") : " & $z.msg)

  decompressed.setLen(wbytes)
  swap(result, decompressed)


proc uncompress*(sourceBuf: string; stream=DETECT_STREAM): string =
  ## Given a GZIP-ed string return its inflated content.
  ##
  ## Valid arguments for ``stream`` are
  ##   - ``DETECT_STREAM`` - detect if zlib or gzip header is present
  ##     and decompress stream. Fail on raw deflate stream.
  ##   - ``ZLIB_STREAM`` - decompress a zlib stream.
  ##   - ``GZIP_STREAM`` - decompress a gzip stream.
  ##   - ``RAW_DEFLATE`` - decompress a raw deflate stream.
  ##
  ## Returns "" on failure.
  result = uncompress(sourceBuf, sourceBuf.len, stream)



proc deflate*(buffer: var string; level=Z_DEFAULT_COMPRESSION; stream=GZIP_STREAM): bool {.discardable.} =
  ## Convenience proc which deflates a string and insert an optional header/footer.
  ##
  ## Valid arguments for ``stream`` are
  ##   - ``ZLIB_STREAM`` - add a zlib header and footer.
  ##   - ``GZIP_STREAM`` - add a basic gzip header and footer.
  ##   - ``RAW_DEFLATE`` - no header is generated.
  ##
  ## Compression level can be set with ``level`` argument. Currently
  ## ``Z_DEFAULT_COMPRESSION`` is 6.
  ##
  ## Returns true if `buffer` was successfully deflated otherwise the buffer is untouched.

  var temp = compress(addr(buffer[0]), buffer.len, level, stream)
  if temp.len != 0:
    swap(buffer, temp)
    result = true

proc inflate*(buffer: var string; stream=DETECT_STREAM): bool {.discardable.} =
  ## Convenience proc which inflates a string containing compressed data
  ## with an optional header.
  ##
  ## Valid argument for ``stream`` are:
  ##   - ``DETECT_STREAM`` - detect if zlib or gzip header is present
  ##     and decompress stream. Fail on raw deflate stream.
  ##   - ``ZLIB_STREAM`` - decompress a zlib stream.
  ##   - ``GZIP_STREAM`` - decompress a gzip stream.
  ##   - ``RAW_DEFLATE`` - decompress a raw deflate stream.
  ##
  ## It is ok to pass a buffer which doesn't contain deflated data,
  ## in this case the proc won't modify the buffer.
  ##
  ## Returns true if `buffer` was successfully inflated.
 
  var temp = uncompress(addr(buffer[0]), buffer.len, stream)
  if temp.len != 0:
    swap(buffer, temp)
    result = true

extractFile segfaults if failed to create file

Example:

import zip.zipfiles

let inFile = "some.zip"
let outFile = "/this/path/doesn't/exist"

var z: ZipArchive
assert z.open(inFile)
z.extractFile("something.txt", outFile)

This crashes at runtime:

Traceback (most recent call last)
test_extract.nim(8)      test_extract
zipfiles.nim(173)        extractFile
zipfiles.nim(165)        extractFile
streams.nim(154)         write
streams.nim(130)         writeData
SIGSEGV: Illegal storage access. (Attempt to read from nil?)

Unable to import zlib

I get a Error: cannot open file: zlib when I try to import zlib.
I'm running Nim v0.18.1 on Linux (Ubuntu 18.04).
EDIT: Nevermind, I learnt that zlib had been removed.

Documentation and examples

The README is as raw as could be and should atleast link to some kind of documentation.

The documentation should include the API exposed and atleast an example of reading a compressed gz file from a FileStream.

Unable to import module

Hello,
I installed the module via nimble install zip (both from macOS and Ubuntu 16.04), and the process gave no error (installed [email protected] and ended with zip installed successfully).

When trying to compile a simple:

import zip/zipfile

i get this error:

/[...]/testarchive.nim(2, 11) Error: cannot open file: zip/zipfile

On Ubuntu I tried downloading the repository and testing manually with nimble task tests, and they pass from the cloned repo.

Can you provide some guidance on this error? Thanks

Directory traversal vulnerability from libzip

Issue

Given a crafted zip file containing a file of filename ../../../../../../../../tmp/evil.txt, zip will extract the file to /tmp/evil.txt, while actually it should be extracted to ./tmp/evil.txt. This vulnerability could allow the attacker to write a file to an arbitrary directory.

How to reproduce

You can try to reproduce this vulnerability using this zip file, note that the symbol nim -d:useLibzipSrc is needed for compilation. You can find the PoC here

could not load: libzip(|2|4).dylib

My Machine:

ProductName:	Mac OS X
ProductVersion: 10.9.5

My Code:

import zip/zipfiles

Results in:

dlopen(libzip.dylib, 2): image not found
dlopen(libzip2.dylib, 2): image not found
dlopen(libzip4.dylib, 2): image not found
could not load: libzip(|2|4).dylib
Error: execution of an external program failed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.