nim-lang / zip Goto Github PK
View Code? Open in Web Editor NEWzip wrapper for Nim
License: MIT License
zip wrapper for Nim
License: MIT License
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
.
Current version is 1.6.1, released on February 3, 2020.
I' ve installed this via nimble install zip
and both import zip
and import zlib
fail. Seems like I'm not the only one: http://forum.nim-lang.org/t/1857
zip-0.2.1/zip/libzip.nim(71, 13) Error: ambiguous identifier: 'Time' -- use one of the following:
posix.Time: Time
times.Time: Time
posix
and times
.import posix except Time # On the code that uses zip
๐
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 against a filename with Unicode(multibyte character).
(ex : ใฮฑฮฒฮณโ
ใ.zip)
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.
How to comply with Unicode as a whole ?
Please give me a hand...
At the moment it creates 1-character strings on each iteration:
Lines 163 to 166 in 1843ef1
Thanks for the great work.
๐ธ
Thanks for the great work on the lib tho.
๐ผ
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
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.
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?
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.
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:
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.
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
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.
On my Windows environment, zipfiles.nim
does not work at all.
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'
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?
Please pardon my poor English.
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.
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
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.
The current version(0.9) is too old to support UTF-8
file path, could you kindly update the source update-to-date ?
I download the libzip-1.1.2.tar.gz, there are a lot of files , I can not simplely replace it with new file.
Thank you!
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?
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?
The actual error is hidden because the only check is result = z.w != nil
Should report the value of err
when z.w == nil
.
I can open a PR for this. What's the preferred way to do this an exception? Msg to stderr?
I can't seem to write more than one file using addFile to the same zip. When I attempt to, this is my output:
Error: unhandled exception: File already exists [IOError]
No clue whats going on, Windows 11 pro, zlib.h apparently doesnt exist.
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.
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
ZLIB_VERSION
whose value is the one from the version of zlib.h that the Nim interface was translated from;zlibVersion()
in the init functions.I'll probably be submitting a PR soon.
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.
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
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?)
echo
ing zlibVersion
gives me 1.2.8
.
Running
Nim 0.17.0
Windows 10
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.
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.
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
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.
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
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.