1 #include <ctype.h>
2 #include <lauxlib.h>
3 #include <lua.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <zlib.h>
7 
8 /*
9  * ** compatibility with Lua 5.2
10  * */
11 #if (LUA_VERSION_NUM >= 502)
12 #undef luaL_register
13 #define luaL_register(L,n,f) \
14                { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); }
15 
16 #endif
17 
18 #if (LUA_VERSION_NUM >= 503)
19 #undef luaL_optint
20 #define luaL_optint(L,n,d)  ((int)luaL_optinteger(L,(n),(d)))
21 #endif
22 
23 #ifdef LZLIB_COMPAT
24 /**************** lzlib compatibilty **********************************/
25 /* Taken from https://raw.githubusercontent.com/LuaDist/lzlib/93b88e931ffa7cd0a52a972b6b26d37628f479f3/lzlib.c */
26 
27 /************************************************************************
28 * Author    : Tiago Dionizio <tiago.dionizio@gmail.com>                 *
29 * Library   : lzlib - Lua 5 interface to access zlib library functions  *
30 *                                                                       *
31 * Permission is hereby granted, free of charge, to any person obtaining *
32 * a copy of this software and associated documentation files (the       *
33 * "Software"), to deal in the Software without restriction, including   *
34 * without limitation the rights to use, copy, modify, merge, publish,   *
35 * distribute, sublicense, and/or sell copies of the Software, and to    *
36 * permit persons to whom the Software is furnished to do so, subject to *
37 * the following conditions:                                             *
38 *                                                                       *
39 * The above copyright notice and this permission notice shall be        *
40 * included in all copies or substantial portions of the Software.       *
41 *                                                                       *
42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
43 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
44 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
45 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  *
46 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  *
47 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     *
48 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                *
49 ************************************************************************/
50 
51 
52 /*
53 ** =========================================================================
54 ** compile time options wich determine available functionality
55 ** =========================================================================
56 */
57 
58 /* TODO
59 
60 - also call flush on table/userdata when flush function is detected
61 - remove io_cb check inflate_block if condition
62 - only set eos when ZSTREAM_END is reached
63 - check for stream errors to close stream when really needed
64 
65 */
66 
67 
68 /*
69 ** =========================================================================
70 ** zlib stream metamethods
71 ** =========================================================================
72 */
73 #define ZSTREAMMETA "zlib:zstream"
74 
75 #define LZ_ANY     -1
76 #define LZ_NONE    0
77 #define LZ_DEFLATE 1
78 #define LZ_INFLATE 2
79 
80 #if 0
81     #define LZ_BUFFER_SIZE LUAL_BUFFERSIZE
82 #else
83     #define LZ_BUFFER_SIZE 8192
84 #endif
85 
86 typedef struct {
87     /* zlib structures */
88     z_stream zstream;
89     /* stream state. LZ_DEFLATE | LZ_INFLATE */
90     int state;
91     int error;
92     int peek;
93     int eos;
94     /* user callback source for reading/writing */
95     int io_cb;
96     /* input buffer */
97     int i_buffer_ref;
98     size_t i_buffer_pos;
99     size_t i_buffer_len;
100     const char *i_buffer;
101     /* output buffer */
102     size_t o_buffer_len;
103     size_t o_buffer_max;
104     char o_buffer[LZ_BUFFER_SIZE];
105     /* dictionary */
106     const Bytef *dictionary;
107     size_t dictionary_len;
108 } lz_stream;
109 
110 
111 /* forward declarations */
112 static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush);
113 
114 
lzstream_new(lua_State * L,int src)115 static lz_stream *lzstream_new(lua_State *L, int src) {
116     lz_stream *s = (lz_stream*)lua_newuserdata(L, sizeof(lz_stream));
117 
118     luaL_getmetatable(L, ZSTREAMMETA);
119     lua_setmetatable(L, -2);        /* set metatable */
120 
121     s->state = LZ_NONE;
122     s->error = Z_OK;
123     s->eos = 0;
124     s->io_cb = LUA_REFNIL;
125 
126     s->i_buffer = NULL;
127     s->i_buffer_ref = LUA_REFNIL;
128     s->i_buffer_pos = 0;
129     s->i_buffer_len = 0;
130 
131     s->peek = 0;
132     s->o_buffer_len = 0;
133     s->o_buffer_max = sizeof(s->o_buffer) / sizeof(s->o_buffer[0]);
134 
135     s->zstream.zalloc = Z_NULL;
136     s->zstream.zfree = Z_NULL;
137 
138     /* prepare source */
139     if (lua_isstring(L, src)) {
140         lua_pushvalue(L, src);
141         s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX);
142         s->i_buffer = lua_tolstring(L, src, &s->i_buffer_len);
143     } else {
144         /* table | function | userdata */
145         lua_pushvalue(L, src);
146         s->io_cb = luaL_ref(L, LUA_REGISTRYINDEX);
147     }
148     return s;
149 }
150 
lzstream_cleanup(lua_State * L,lz_stream * s)151 static void lzstream_cleanup(lua_State *L, lz_stream *s) {
152     if (s && s->state != LZ_NONE) {
153         if (s->state == LZ_INFLATE) {
154             inflateEnd(&s->zstream);
155         }
156         if (s->state == LZ_DEFLATE) {
157             deflateEnd(&s->zstream);
158         }
159 
160         luaL_unref(L, LUA_REGISTRYINDEX, s->io_cb);
161         luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
162         s->state = LZ_NONE;
163     }
164 }
165 
166 /* ====================================================================== */
167 
lzstream_get(lua_State * L,int index)168 static lz_stream *lzstream_get(lua_State *L, int index) {
169     lz_stream *s = (lz_stream*)luaL_checkudata(L, index, ZSTREAMMETA);
170     if (s == NULL) luaL_argerror(L, index, "bad zlib stream");
171     return s;
172 }
173 
lzstream_check(lua_State * L,int index,int state)174 static lz_stream *lzstream_check(lua_State *L, int index, int state) {
175     lz_stream *s = lzstream_get(L, index);
176     if ((state != LZ_ANY && s->state != state) || s->state == LZ_NONE) {
177         luaL_argerror(L, index, "attempt to use invalid zlib stream");
178     }
179     return s;
180 }
181 
182 /* ====================================================================== */
183 
lzstream_tostring(lua_State * L)184 static int lzstream_tostring(lua_State *L) {
185     lz_stream *s = (lz_stream*)luaL_checkudata(L, 1, ZSTREAMMETA);
186     if (s == NULL) luaL_argerror(L, 1, "bad zlib stream");
187 
188     if (s->state == LZ_NONE) {
189         lua_pushstring(L, "zlib stream (closed)");
190     } else if (s->state == LZ_DEFLATE) {
191         lua_pushfstring(L, "zlib deflate stream (%p)", (void*)s);
192     } else if (s->state == LZ_INFLATE) {
193         lua_pushfstring(L, "zlib inflate stream (%p)", (void*)s);
194     } else {
195         lua_pushfstring(L, "%p", (void*)s);
196     }
197 
198     return 1;
199 }
200 
201 /* ====================================================================== */
202 
lzstream_gc(lua_State * L)203 static int lzstream_gc(lua_State *L) {
204     lz_stream *s = lzstream_get(L, 1);
205     lzstream_cleanup(L, s);
206     return 0;
207 }
208 
209 /* ====================================================================== */
210 
lzstream_close(lua_State * L)211 static int lzstream_close(lua_State *L) {
212     lz_stream *s = lzstream_get(L, 1);
213 
214     if (s->state == LZ_DEFLATE) {
215         lua_settop(L, 0);
216         lua_pushliteral(L, "");
217         return lzstream_docompress(L, s, 1, 1, Z_FINISH);
218     }
219 
220     lzstream_cleanup(L, s);
221     lua_pushboolean(L, 1);
222     return 1;
223 }
224 
225 /* ====================================================================== */
226 
lzstream_adler(lua_State * L)227 static int lzstream_adler(lua_State *L) {
228     lz_stream *s = lzstream_check(L, 1, LZ_ANY);
229     lua_pushnumber(L, s->zstream.adler);
230     return 1;
231 }
232 
233 /* ====================================================================== */
234 
235 /*
236     zlib.deflate(
237         sink: function | { write: function [, close: function, flush: function] },
238         compression level, [Z_DEFAILT_COMPRESSION]
239         method, [Z_DEFLATED]
240         windowBits, [15]
241         memLevel, [8]
242         strategy, [Z_DEFAULT_STRATEGY]
243         dictionary: [""]
244     )
245 */
lzlib_deflate(lua_State * L)246 static int lzlib_deflate(lua_State *L) {
247     int level, method, windowBits, memLevel, strategy;
248     lz_stream *s;
249     const char *dictionary;
250     size_t dictionary_len;
251 
252     if (lua_istable(L, 1) || lua_isuserdata(L, 1)) {
253         /* is there a :write function? */
254         lua_getfield(L, 1, "write");
255         if (!lua_isfunction(L, -1)) {
256             luaL_argerror(L, 1, "output parameter does not provide :write function");
257         }
258         lua_pop(L, 1);
259     }
260     else if (!lua_isfunction(L, 1)) {
261         luaL_argerror(L, 1, "output parameter must be a function, table or userdata value");
262     }
263 
264     level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
265     method = (int) luaL_optinteger(L, 3, Z_DEFLATED);
266     windowBits = (int) luaL_optinteger(L, 4, 15);
267     memLevel = (int) luaL_optinteger(L, 5, 8);
268     strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY);
269     dictionary = luaL_optlstring(L, 7, NULL, &dictionary_len);
270 
271     s = lzstream_new(L, 1);
272 
273     if (deflateInit2(&s->zstream, level, method, windowBits, memLevel, strategy) != Z_OK) {
274         lua_pushliteral(L, "call to deflateInit2 failed");
275         lua_error(L);
276     }
277 
278     if (dictionary) {
279         if (deflateSetDictionary(&s->zstream, (const Bytef *) dictionary, dictionary_len) != Z_OK) {
280             lua_pushliteral(L, "call to deflateSetDictionnary failed");
281             lua_error(L);
282         }
283     }
284 
285     s->state = LZ_DEFLATE;
286     return 1;
287 }
288 
289 /*
290     zlib.inflate(
291         source: string | function | { read: function, close: function },
292         windowBits: number, [15]
293         dictionary: [""]
294     )
295 */
lzlib_inflate(lua_State * L)296 static int lzlib_inflate(lua_State *L)
297 {
298     int windowBits;
299     lz_stream *s;
300     int have_peek = 0;
301     const char *dictionary;
302     size_t dictionary_len;
303 
304     if (lua_istable(L, 1) || lua_isuserdata(L, 1)) {
305         /* is there a :read function? */
306         lua_getfield(L, 1, "read");
307         if (!lua_isfunction(L, -1)) {
308             luaL_argerror(L, 1, "input parameter does not provide :read function");
309         }
310         lua_pop(L, 1);
311         /* check for peek function */
312         lua_getfield(L, 1, "peek");
313         have_peek = lua_isfunction(L, -1);
314         lua_pop(L, 1);
315     }
316     else if (!lua_isstring(L, 1) && !lua_isfunction(L, 1)) {
317         luaL_argerror(L, 1, "input parameter must be a string, function, table or userdata value");
318     }
319 
320     windowBits = (int) luaL_optinteger(L, 2, 15);
321     dictionary = luaL_optlstring(L, 3, NULL, &dictionary_len);
322 
323     s = lzstream_new(L, 1);
324 
325     if (windowBits > 0 && windowBits < 16) {
326         windowBits |= 32;
327     }
328 
329     if (inflateInit2(&s->zstream, windowBits) != Z_OK) {
330         lua_pushliteral(L, "call to inflateInit2 failed");
331         lua_error(L);
332     }
333 
334     if (dictionary) {
335         s->dictionary = (const Bytef *) dictionary;
336         s->dictionary_len = dictionary_len;
337     }
338 
339     s->peek = have_peek;
340     s->state = LZ_INFLATE;
341     return 1;
342 }
343 
344 /* ====================================================================== */
345 
lz_pushresult(lua_State * L,lz_stream * s)346 static int lz_pushresult (lua_State *L, lz_stream *s) {
347     if (s->error == Z_OK) {
348         lua_pushboolean(L, 1);
349         return 1;
350     } else {
351         lua_pushnil(L);
352         lua_pushstring(L, zError(s->error));
353         lua_pushinteger(L, s->error);
354         return 3;
355     }
356 }
357 
358 /*
359     Get block to process:
360         - top of stack gets
361 */
lzstream_fetch_block(lua_State * L,lz_stream * s,int hint)362 static const char* lzstream_fetch_block(lua_State *L, lz_stream *s, int hint) {
363     if (s->i_buffer_pos >= s->i_buffer_len) {
364         luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
365         s->i_buffer_ref = LUA_NOREF;
366         s->i_buffer = NULL;
367 
368         lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
369         if (!lua_isnil(L, -1)) {
370             if (lua_isfunction(L, -1)) {
371                 lua_pushinteger(L, hint);
372                 lua_call(L, 1, 1);
373             } else {
374                 lua_getfield(L, -1, (s->peek ? "peek" : "read"));
375                 lua_insert(L, -2);
376                 lua_pushinteger(L, hint);
377                 lua_call(L, 2, 1);
378             }
379 
380             if (lua_isstring(L, -1)) {
381                 s->i_buffer_pos = 0;
382                 s->i_buffer = lua_tolstring(L, -1, &s->i_buffer_len);
383                 if (s->i_buffer_len > 0) {
384                     s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX);
385                 } else {
386                     lua_pop(L, 1);
387                 }
388             } else if (lua_isnil(L, -1)) {
389                 lua_pop(L, 1);
390             } else {
391                 lua_pushliteral(L, "deflate callback must return string or nil");
392                 lua_error(L);
393             }
394         } else {
395             lua_pop(L, 1);
396         }
397     }
398 
399     return s->i_buffer;
400 }
401 
lzstream_inflate_block(lua_State * L,lz_stream * s)402 static int lzstream_inflate_block(lua_State *L, lz_stream *s) {
403     if (lzstream_fetch_block(L, s, LZ_BUFFER_SIZE) || !s->eos) {
404         int r;
405 
406         if (s->i_buffer_len == s->i_buffer_pos) {
407             s->zstream.next_in = NULL;
408             s->zstream.avail_in = 0;
409         } else {
410             s->zstream.next_in = (unsigned char*)(s->i_buffer + s->i_buffer_pos);
411             s->zstream.avail_in = s->i_buffer_len - s->i_buffer_pos;
412         }
413 
414         s->zstream.next_out = (unsigned char*)s->o_buffer + s->o_buffer_len;
415         s->zstream.avail_out = s->o_buffer_max - s->o_buffer_len;
416 
417         /* munch some more */
418         r = inflate(&s->zstream, Z_SYNC_FLUSH);
419 
420         if (r == Z_NEED_DICT) {
421             if (s->dictionary == NULL) {
422                 lua_pushliteral(L, "no inflate dictionary provided");
423                 lua_error(L);
424             }
425 
426             if (inflateSetDictionary(&s->zstream, s->dictionary, s->dictionary_len) != Z_OK) {
427                 lua_pushliteral(L, "call to inflateSetDictionnary failed");
428                 lua_error(L);
429             }
430 
431             r = inflate(&s->zstream, Z_SYNC_FLUSH);
432         }
433 
434         if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) {
435             lzstream_cleanup(L, s);
436             s->error = r;
437             #if 1
438             lua_pushfstring(L, "failed to decompress [%d]", r);
439             lua_error(L);
440             #endif
441         }
442 
443         if (r == Z_STREAM_END) {
444             luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
445             s->i_buffer_ref = LUA_NOREF;
446             s->i_buffer = NULL;
447 
448             s->eos = 1;
449         }
450 
451         /* number of processed bytes */
452         if (s->peek) {
453             size_t processed = s->i_buffer_len - s->i_buffer_pos - s->zstream.avail_in;
454 
455             lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
456             lua_getfield(L, -1, "read");
457             lua_insert(L, -2);
458             lua_pushinteger(L, processed);
459             lua_call(L, 2, 0);
460         }
461 
462         s->i_buffer_pos = s->i_buffer_len - s->zstream.avail_in;
463         s->o_buffer_len = s->o_buffer_max - s->zstream.avail_out;
464     }
465 
466     return s->o_buffer_len;
467 }
468 
469 /*
470 ** Remove n bytes from the output buffer.
471 */
lzstream_remove(lz_stream * s,size_t n)472 static void lzstream_remove(lz_stream *s, size_t n) {
473     memmove(s->o_buffer, s->o_buffer + n, s->o_buffer_len - n);
474     s->o_buffer_len -= n;
475 }
476 
477 /*
478 ** Copy at most n bytes to buffer b and remove them from the
479 ** output stream buffer.
480 */
lzstream_flush_buffer(lua_State * L,lz_stream * s,size_t n,luaL_Buffer * b)481 static int lzstream_flush_buffer(lua_State *L, lz_stream *s, size_t n, luaL_Buffer *b) {
482     /* check output */
483     if (n > s->o_buffer_len) {
484         n = s->o_buffer_len;
485     }
486 
487     if (n > 0) {
488         lua_pushlstring(L, s->o_buffer, n);
489         luaL_addvalue(b);
490 
491         lzstream_remove(s, n);
492     }
493 
494     return n;
495 }
496 
497 /*
498     z:read(
499         {number | '*l' | '*a'}*
500     )
501 */
lz_test_eof(lua_State * L,lz_stream * s)502 static int lz_test_eof(lua_State *L, lz_stream *s) {
503     lua_pushlstring(L, NULL, 0);
504     if (s->o_buffer_len > 0) {
505         return 1;
506     } else if (s->eos) {
507         return 0;
508     } else {
509         return lzstream_inflate_block(L, s);
510     }
511 }
512 
lz_read_line(lua_State * L,lz_stream * s)513 static int lz_read_line(lua_State *L, lz_stream *s) {
514     luaL_Buffer b;
515     size_t l = 0, n;
516 
517     luaL_buffinit(L, &b);
518 
519     if (s->o_buffer_len > 0 || !s->eos) do {
520         char *p = s->o_buffer;
521         size_t len = s->o_buffer_len;
522 
523         /* find newline in output buffer */
524         for (n = 0; n < len; ++n, ++p) {
525             if (*p == '\n' || *p == '\r') {
526                 int eat_nl = *p == '\r';
527                 luaL_addlstring(&b, s->o_buffer, n);
528                 lzstream_remove(s, n+1);
529                 l += n;
530 
531                 if (eat_nl && lzstream_inflate_block(L, s)) {
532                     if (s->o_buffer_len > 0 && *s->o_buffer == '\n') {
533                         lzstream_remove(s, 1);
534                     }
535                 }
536 
537                 luaL_pushresult(&b);
538                 return 1;
539             }
540         }
541 
542         if (len > 0) {
543             luaL_addlstring(&b, s->o_buffer, len);
544             lzstream_remove(s, len);
545             l += len;
546         }
547     } while (lzstream_inflate_block(L, s));
548 
549     luaL_pushresult(&b);
550     return l > 0 || !s->eos || s->o_buffer_len > 0;
551 }
552 
553 
lz_read_chars(lua_State * L,lz_stream * s,size_t n)554 static int lz_read_chars(lua_State *L, lz_stream *s, size_t n) {
555     size_t len;
556     luaL_Buffer b;
557     luaL_buffinit(L, &b);
558 
559     if (s->o_buffer_len > 0 || !s->eos) do {
560         size_t rlen = lzstream_flush_buffer(L, s, n, &b);
561         n -= rlen;
562     } while (n > 0 && lzstream_inflate_block(L, s));
563 
564     luaL_pushresult(&b);
565     lua_tolstring(L, -1, &len);
566     return n == 0 || len > 0;
567 }
568 
lzstream_decompress(lua_State * L)569 static int lzstream_decompress(lua_State *L) {
570     lz_stream *s = lzstream_check(L, 1, LZ_INFLATE);
571     int nargs = lua_gettop(L) - 1;
572     int success;
573     int n;
574     if (nargs == 0) {  /* no arguments? */
575         success = lz_read_line(L, s);
576         n = 3;  /* to return 1 result */
577     }
578     else {  /* ensure stack space for all results and for auxlib's buffer */
579         luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
580         success = 1;
581         for (n = 2; nargs-- && success; n++) {
582             if (lua_type(L, n) == LUA_TNUMBER) {
583                 size_t l = (size_t)lua_tointeger(L, n);
584                 success = (l == 0) ? lz_test_eof(L, s) : lz_read_chars(L, s, l);
585             }
586             else {
587                 const char *p = lua_tostring(L, n);
588                 luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
589                 switch (p[1]) {
590                     case 'l':  /* line */
591                         success = lz_read_line(L, s);
592                         break;
593                     case 'a':  /* file */
594                         lz_read_chars(L, s, ~((size_t)0));  /* read MAX_SIZE_T chars */
595                         success = 1; /* always success */
596                         break;
597                     default:
598                         return luaL_argerror(L, n, "invalid format");
599                 }
600             }
601         }
602     }
603     if (s->error != Z_OK) {
604         return lz_pushresult(L, s);
605     }
606     if (!success) {
607         lua_pop(L, 1);  /* remove last result */
608         lua_pushnil(L);  /* push nil instead */
609     }
610     return n - 2;
611 }
612 
613 
lzstream_readline(lua_State * L)614 static int lzstream_readline(lua_State *L) {
615     lz_stream *s;
616     int sucess;
617 
618     s = lzstream_check(L, lua_upvalueindex(1), LZ_INFLATE);
619     sucess = lz_read_line(L, s);
620 
621     if (s->error != Z_OK) {
622         return lz_pushresult(L, s);
623     }
624 
625     if (sucess) {
626         return 1;
627     } else {
628         /* EOF */
629         return 0;
630     }
631 }
632 
lzstream_lines(lua_State * L)633 static int lzstream_lines(lua_State *L) {
634     lzstream_check(L, 1, LZ_INFLATE);
635     lua_settop(L, 1);
636     lua_pushcclosure(L, lzstream_readline, 1);
637     return 1;
638 }
639 
640 /* ====================================================================== */
641 
lzstream_docompress(lua_State * L,lz_stream * s,int from,int to,int flush)642 static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush) {
643     int r, arg;
644     int self = 0;
645     size_t b_size = s->o_buffer_max;
646     unsigned char *b = (unsigned char *)s->o_buffer;
647 
648     /* number of processed bytes */
649     lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
650     if (!lua_isfunction(L, -1)) {
651         self = 1;
652         lua_getfield(L, -1, "write");
653     }
654 
655     for (arg = from; arg <= to; arg++) {
656         s->zstream.next_in = (unsigned char*)luaL_checklstring(L, arg, (size_t*)&s->zstream.avail_in);
657 
658         do {
659             s->zstream.next_out = b;
660             s->zstream.avail_out = b_size;
661 
662             /* bake some more */
663             r = deflate(&s->zstream, flush);
664             if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) {
665                 lzstream_cleanup(L, s);
666                 lua_pushboolean(L, 0);
667                 lua_pushfstring(L, "failed to compress [%d]", r);
668                 return 2;
669             }
670 
671             if (s->zstream.avail_out != b_size) {
672                 /* write output */
673                 lua_pushvalue(L, -1); /* function */
674                 if (self) lua_pushvalue(L, -3); /* self */
675                 lua_pushlstring(L, (char*)b, b_size - s->zstream.avail_out); /* data */
676                 lua_call(L, (self ? 2 : 1), 0);
677             }
678 
679             if (r == Z_STREAM_END) {
680                 lzstream_cleanup(L, s);
681                 break;
682             }
683 
684             /* process all input */
685         } while (s->zstream.avail_in > 0 || s->zstream.avail_out == 0);
686     }
687 
688     lua_pushboolean(L, 1);
689     return 1;
690 }
691 
lzstream_compress(lua_State * L)692 static int lzstream_compress(lua_State *L) {
693     lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE);
694     return lzstream_docompress(L, s, 2, lua_gettop(L), Z_NO_FLUSH);
695 }
696 
697 
698 /* ====================================================================== */
699 
lzstream_flush(lua_State * L)700 static int lzstream_flush(lua_State *L) {
701     static int flush_values[] = { Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH };
702     static const char *const flush_opts[] = { "sync", "full", "finish" };
703 
704     lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE);
705     int flush = luaL_checkoption(L, 2, flush_opts[0], flush_opts);
706 
707     lua_settop(L, 0);
708     lua_pushliteral(L, "");
709     return lzstream_docompress(L, s, 1, 1, flush_values[flush]);
710 }
711 
712 /* ====================================================================== */
713 
lzlib_compress(lua_State * L)714 static int lzlib_compress(lua_State *L) {
715     size_t avail_in;
716     const char *next_in = luaL_checklstring(L, 1, &avail_in);
717     int level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
718     int method = (int) luaL_optinteger(L, 3, Z_DEFLATED);
719     int windowBits = (int) luaL_optinteger(L, 4, 15);
720     int memLevel = (int) luaL_optinteger(L, 5, 8);
721     int strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY);
722 
723     int ret;
724     luaL_Buffer b;
725     z_stream zs;
726 
727     luaL_buffinit(L, &b);
728 
729     zs.zalloc = Z_NULL;
730     zs.zfree = Z_NULL;
731 
732     zs.next_out = Z_NULL;
733     zs.avail_out = 0;
734     zs.next_in = Z_NULL;
735     zs.avail_in = 0;
736 
737     ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy);
738 
739     if (ret != Z_OK)
740     {
741         lua_pushnil(L);
742         lua_pushnumber(L, ret);
743         return 2;
744     }
745 
746     zs.next_in = (unsigned char*)next_in;
747     zs.avail_in = avail_in;
748 
749     for(;;)
750     {
751         zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
752         zs.avail_out = LUAL_BUFFERSIZE;
753 
754         /* munch some more */
755         ret = deflate(&zs, Z_FINISH);
756 
757         /* push gathered data */
758         luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
759 
760         /* done processing? */
761         if (ret == Z_STREAM_END)
762             break;
763 
764         /* error condition? */
765         if (ret != Z_OK)
766             break;
767     }
768 
769     /* cleanup */
770     deflateEnd(&zs);
771 
772     luaL_pushresult(&b);
773     lua_pushnumber(L, ret);
774     return 2;
775 }
776 
777 /* ====================================================================== */
778 
lzlib_decompress(lua_State * L)779 static int lzlib_decompress(lua_State *L)
780 {
781     size_t avail_in;
782     const char *next_in = luaL_checklstring(L, 1, &avail_in);
783     int windowBits = (int) luaL_optinteger(L, 2, 15);
784 
785     int ret;
786     luaL_Buffer b;
787     z_stream zs;
788 
789     luaL_buffinit(L, &b);
790 
791     zs.zalloc = Z_NULL;
792     zs.zfree = Z_NULL;
793 
794     zs.next_out = Z_NULL;
795     zs.avail_out = 0;
796     zs.next_in = Z_NULL;
797     zs.avail_in = 0;
798 
799     ret = inflateInit2(&zs, windowBits);
800 
801     if (ret != Z_OK) {
802         lua_pushliteral(L, "failed to initialize zstream structures");
803         lua_error(L);
804     }
805 
806     zs.next_in = (unsigned char*)next_in;
807     zs.avail_in = avail_in;
808 
809     for (;;) {
810         zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
811         zs.avail_out = LUAL_BUFFERSIZE;
812 
813         /* bake some more */
814         ret = inflate(&zs, Z_FINISH);
815 
816         /* push gathered data */
817         luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
818 
819         /* done processing? */
820         if (ret == Z_STREAM_END)
821             break;
822 
823         if (ret != Z_OK && ret != Z_BUF_ERROR) {
824             /* cleanup */
825             inflateEnd(&zs);
826 
827             lua_pushliteral(L, "failed to process zlib stream");
828             lua_error(L);
829         }
830     }
831 
832     /* cleanup */
833     inflateEnd(&zs);
834 
835     luaL_pushresult(&b);
836     return 1;
837 }
838 
839 #endif
840 /**********************************************************************/
841 
842 #define DEF_MEM_LEVEL 8
843 
844 typedef uLong (*checksum_t)        (uLong crc, const Bytef *buf, uInt len);
845 typedef uLong (*checksum_combine_t)(uLong crc1, uLong crc2, z_off_t len2);
846 
847 
848 static int lz_deflate(lua_State *L);
849 static int lz_deflate_delete(lua_State *L);
850 static int lz_inflate_delete(lua_State *L);
851 static int lz_inflate(lua_State *L);
852 static int lz_checksum(lua_State *L);
853 static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine);
854 static int lz_adler32(lua_State *L);
855 static int lz_crc32(lua_State *L);
856 
lz_version(lua_State * L)857 static int lz_version(lua_State *L) {
858     const char* version = zlibVersion();
859     int         count   = strlen(version) + 1;
860     char*       cur     = (char*)memcpy(lua_newuserdata(L, count),
861                                         version, count);
862 
863     count = 0;
864     while ( *cur ) {
865         char* begin = cur;
866         /* Find all digits: */
867         while ( isdigit(*cur) ) cur++;
868         if ( begin != cur ) {
869             int is_end = *cur == '\0';
870             *cur = '\0';
871             lua_pushnumber(L, atoi(begin));
872             count++;
873             if ( is_end ) break;
874             cur++;
875         }
876         while ( *cur && ! isdigit(*cur) ) cur++;
877     }
878 
879     return count;
880 }
881 
lz_assert(lua_State * L,int result,const z_stream * stream,const char * file,int line)882 static int lz_assert(lua_State *L, int result, const z_stream* stream, const char* file, int line) {
883     /* Both of these are "normal" return codes: */
884     if ( result == Z_OK || result == Z_STREAM_END ) return result;
885     switch ( result ) {
886     case Z_NEED_DICT:
887         lua_pushfstring(L, "RequiresDictionary: input stream requires a dictionary to be deflated (%s) at %s line %d",
888                         stream->msg, file, line);
889         break;
890     case Z_STREAM_ERROR:
891         lua_pushfstring(L, "InternalError: inconsistent internal zlib stream (%s) at %s line %d",
892                         stream->msg, file, line);
893         break;
894     case Z_DATA_ERROR:
895         lua_pushfstring(L, "InvalidInput: input string does not conform to zlib format or checksum failed at %s line %d",
896                         file, line);
897         break;
898     case Z_MEM_ERROR:
899         lua_pushfstring(L, "OutOfMemory: not enough memory (%s) at %s line %d",
900                         stream->msg, file, line);
901         break;
902     case Z_BUF_ERROR:
903         lua_pushfstring(L, "InternalError: no progress possible (%s) at %s line %d",
904                         stream->msg, file, line);
905         break;
906     case Z_VERSION_ERROR:
907         lua_pushfstring(L, "IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s) at %s line %d",
908                         ZLIB_VERSION,  zlibVersion(), stream->msg, file, line);
909         break;
910     default:
911         lua_pushfstring(L, "ZLibError: unknown code %d (%s) at %s line %d",
912                         result, stream->msg, file, line);
913     }
914     lua_error(L);
915     return result;
916 }
917 
918 /**
919  * @upvalue z_stream - Memory for the z_stream.
920  * @upvalue remainder - Any remainder from the last deflate call.
921  *
922  * @param string - "print" to deflate stream.
923  * @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH.
924  *
925  * if no params, terminates the stream (as if we got empty string and Z_FINISH).
926  */
lz_filter_impl(lua_State * L,int (* filter)(z_streamp,int),int (* end)(z_streamp),char * name)927 static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), char* name) {
928     int flush = Z_NO_FLUSH, result;
929     z_stream* stream;
930     luaL_Buffer buff;
931     size_t avail_in;
932 
933     if ( filter == deflate ) {
934         const char *const opts[] = { "none", "sync", "full", "finish", NULL };
935         flush = luaL_checkoption(L, 2, opts[0], opts);
936         if ( flush ) flush++;
937         /* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */
938 
939         /* No arguments or nil, we are terminating the stream: */
940         if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) {
941             flush = Z_FINISH;
942         }
943     }
944 
945     stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1));
946     if ( stream == NULL ) {
947         if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) {
948             lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name);
949             lua_error(L);
950         }
951         lua_pushstring(L, "");
952         lua_pushboolean(L, 1);
953         return 2; /* Ignore duplicate calls to "close". */
954     }
955 
956     luaL_buffinit(L, &buff);
957 
958     if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1);
959 
960     if ( lua_isstring(L, lua_upvalueindex(2)) ) {
961         lua_pushvalue(L, lua_upvalueindex(2));
962         if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) {
963             lua_concat(L, 2);
964         }
965     }
966 
967     /*  Do the actual deflate'ing: */
968     if (lua_gettop(L) > 0) {
969         stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in);
970     } else {
971         stream->next_in = NULL;
972         avail_in = 0;
973     }
974     stream->avail_in = avail_in;
975 
976     if ( ! stream->avail_in && ! flush ) {
977         /*  Passed empty string, make it a noop instead of erroring out. */
978         lua_pushstring(L, "");
979         lua_pushboolean(L, 0);
980         lua_pushinteger(L, stream->total_in);
981         lua_pushinteger(L, stream->total_out);
982         return 4;
983     }
984 
985     do {
986         stream->next_out  = (unsigned char*)luaL_prepbuffer(&buff);
987         stream->avail_out = LUAL_BUFFERSIZE;
988         result = filter(stream, flush);
989         if ( Z_BUF_ERROR != result ) {
990             /* Ignore Z_BUF_ERROR since that just indicates that we
991              * need a larger buffer in order to proceed.  Thanks to
992              * Tobias Markmann for finding this bug!
993              */
994             lz_assert(L, result, stream, __FILE__, __LINE__);
995         }
996         luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out);
997     } while ( stream->avail_out == 0 );
998 
999     /*  Need to do this before we alter the stack: */
1000     luaL_pushresult(&buff);
1001 
1002     /*  Save remainder in lua_upvalueindex(2): */
1003     if ( NULL != stream->next_in ) {
1004         lua_pushlstring(L, (char*)stream->next_in, stream->avail_in);
1005         lua_replace(L, lua_upvalueindex(2));
1006     }
1007 
1008     /*  "close" the stream/remove finalizer: */
1009     if ( result == Z_STREAM_END ) {
1010         /*  Clear-out the metatable so end is not called twice: */
1011         lua_pushnil(L);
1012         lua_setmetatable(L, lua_upvalueindex(1));
1013 
1014         /*  nil the upvalue: */
1015         lua_pushnil(L);
1016         lua_replace(L, lua_upvalueindex(1));
1017 
1018         /*  Close the stream: */
1019         lz_assert(L, end(stream), stream, __FILE__, __LINE__);
1020 
1021         lua_pushboolean(L, 1);
1022     } else {
1023         lua_pushboolean(L, 0);
1024     }
1025     lua_pushinteger(L, stream->total_in);
1026     lua_pushinteger(L, stream->total_out);
1027     return 4;
1028 }
1029 
lz_create_deflate_mt(lua_State * L)1030 static void lz_create_deflate_mt(lua_State *L) {
1031     luaL_newmetatable(L, "lz.deflate.meta"); /*  {} */
1032 
1033     lua_pushcfunction(L, lz_deflate_delete);
1034     lua_setfield(L, -2, "__gc");
1035 
1036     lua_pop(L, 1); /*  <empty> */
1037 }
1038 
lz_deflate_new(lua_State * L)1039 static int lz_deflate_new(lua_State *L) {
1040     int level;
1041     int window_size;
1042     int result;
1043 
1044 #ifdef LZLIB_COMPAT
1045     if ( lua_istable(L, 1) || lua_isuserdata(L, 1) || lua_isfunction(L, 1) ) {
1046         return lzlib_deflate(L);
1047     }
1048 #endif
1049 
1050     level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION);
1051     window_size = luaL_optint(L, 2, MAX_WBITS);
1052 
1053     /*  Allocate the stream: */
1054     z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
1055 
1056     stream->zalloc = Z_NULL;
1057     stream->zfree  = Z_NULL;
1058 
1059     result = deflateInit2(stream, level, Z_DEFLATED, window_size,
1060                               DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
1061 
1062     lz_assert(L, result, stream, __FILE__, __LINE__);
1063 
1064     /*  Don't allow destructor to execute unless deflateInit2 was successful: */
1065     luaL_getmetatable(L, "lz.deflate.meta");
1066     lua_setmetatable(L, -2);
1067 
1068     lua_pushnil(L);
1069     lua_pushcclosure(L, lz_deflate, 2);
1070     return 1;
1071 }
1072 
lz_deflate(lua_State * L)1073 static int lz_deflate(lua_State *L) {
1074     return lz_filter_impl(L, deflate, deflateEnd, "deflate");
1075 }
1076 
lz_deflate_delete(lua_State * L)1077 static int lz_deflate_delete(lua_State *L) {
1078     z_stream* stream  = (z_stream*)lua_touserdata(L, 1);
1079 
1080     /*  Ignore errors. */
1081     deflateEnd(stream);
1082 
1083     return 0;
1084 }
1085 
1086 
lz_create_inflate_mt(lua_State * L)1087 static void lz_create_inflate_mt(lua_State *L) {
1088     luaL_newmetatable(L, "lz.inflate.meta"); /*  {} */
1089 
1090     lua_pushcfunction(L, lz_inflate_delete);
1091     lua_setfield(L, -2, "__gc");
1092 
1093     lua_pop(L, 1); /*  <empty> */
1094 }
1095 
lz_inflate_new(lua_State * L)1096 static int lz_inflate_new(lua_State *L) {
1097     /* Allocate the stream */
1098     z_stream* stream;
1099 
1100 #ifdef LZLIB_COMPAT
1101     int type = lua_type(L, 1);
1102     if ( type == LUA_TTABLE || type == LUA_TUSERDATA || type == LUA_TFUNCTION || type == LUA_TSTRING ) {
1103         return lzlib_inflate(L);
1104     }
1105 #endif
1106 
1107     stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
1108 
1109     /*  By default, we will do gzip header detection w/ max window size */
1110     int window_size = lua_isnumber(L, 1) ? lua_tointeger(L, 1) : MAX_WBITS + 32;
1111 
1112     stream->zalloc   = Z_NULL;
1113     stream->zfree    = Z_NULL;
1114     stream->next_in  = Z_NULL;
1115     stream->avail_in = 0;
1116 
1117     lz_assert(L, inflateInit2(stream, window_size), stream, __FILE__, __LINE__);
1118 
1119     /*  Don't allow destructor to execute unless deflateInit was successful: */
1120     luaL_getmetatable(L, "lz.inflate.meta");
1121     lua_setmetatable(L, -2);
1122 
1123     lua_pushnil(L);
1124     lua_pushcclosure(L, lz_inflate, 2);
1125     return 1;
1126 }
1127 
lz_inflate(lua_State * L)1128 static int lz_inflate(lua_State *L) {
1129     return lz_filter_impl(L, inflate, inflateEnd, "inflate");
1130 }
1131 
lz_inflate_delete(lua_State * L)1132 static int lz_inflate_delete(lua_State *L) {
1133     z_stream* stream  = (z_stream*)lua_touserdata(L, 1);
1134 
1135     /*  Ignore errors: */
1136     inflateEnd(stream);
1137 
1138     return 0;
1139 }
1140 
lz_checksum(lua_State * L)1141 static int lz_checksum(lua_State *L) {
1142     if ( lua_gettop(L) <= 0 ) {
1143         lua_pushvalue(L, lua_upvalueindex(3));
1144         lua_pushvalue(L, lua_upvalueindex(4));
1145     } else if ( lua_isfunction(L, 1) ) {
1146         checksum_combine_t combine = (checksum_combine_t)
1147             lua_touserdata(L, lua_upvalueindex(2));
1148 
1149         lua_pushvalue(L, 1);
1150         lua_call(L, 0, 2);
1151         if ( ! lua_isnumber(L, -2) || ! lua_isnumber(L, -1) ) {
1152             luaL_argerror(L, 1, "expected function to return two numbers");
1153         }
1154 
1155         /* Calculate and replace the checksum */
1156         lua_pushnumber(L,
1157                        combine((uLong)lua_tonumber(L, lua_upvalueindex(3)),
1158                                (uLong)lua_tonumber(L, -2),
1159                                (z_off_t)lua_tonumber(L, -1)));
1160         lua_pushvalue(L, -1);
1161         lua_replace(L, lua_upvalueindex(3));
1162 
1163         /* Calculate and replace the length */
1164         lua_pushnumber(L,
1165                        lua_tonumber(L, lua_upvalueindex(4)) + lua_tonumber(L, -2));
1166         lua_pushvalue(L, -1);
1167         lua_replace(L, lua_upvalueindex(4));
1168     } else {
1169         const Bytef* str;
1170         size_t       len;
1171 
1172         checksum_t checksum = (checksum_t)
1173             lua_touserdata(L, lua_upvalueindex(1));
1174         str = (const Bytef*)luaL_checklstring(L, 1, &len);
1175 
1176         /* Calculate and replace the checksum */
1177         lua_pushnumber(L,
1178                        checksum((uLong)lua_tonumber(L, lua_upvalueindex(3)),
1179                                 str,
1180                                 len));
1181         lua_pushvalue(L, -1);
1182         lua_replace(L, lua_upvalueindex(3));
1183 
1184         /* Calculate and replace the length */
1185         lua_pushnumber(L,
1186                        lua_tonumber(L, lua_upvalueindex(4)) + len);
1187         lua_pushvalue(L, -1);
1188         lua_replace(L, lua_upvalueindex(4));
1189     }
1190     return 2;
1191 }
1192 
lz_checksum_new(lua_State * L,checksum_t checksum,checksum_combine_t combine)1193 static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine) {
1194     lua_pushlightuserdata(L, checksum);
1195     lua_pushlightuserdata(L, combine);
1196     lua_pushnumber(L, checksum(0L, Z_NULL, 0));
1197     lua_pushnumber(L, 0);
1198     lua_pushcclosure(L, lz_checksum, 4);
1199     return 1;
1200 }
1201 
lz_adler32(lua_State * L)1202 static int lz_adler32(lua_State *L) {
1203 #ifdef LZLIB_COMPAT
1204     /* lzlib compat*/
1205     if ( lua_gettop(L) != 0 ) {
1206         size_t len;
1207         int adler;
1208         const unsigned char* buf;
1209         if ( lua_isfunction(L, 1) ) {
1210             adler = adler32(0L, Z_NULL, 0);
1211         } else {
1212             adler = (int)luaL_checkinteger(L, 1);
1213         }
1214         buf = (unsigned char*)luaL_checklstring(L, 2, &len);
1215         lua_pushnumber(L, adler32(adler, buf, len));
1216         return 1;
1217     }
1218 #endif
1219     return lz_checksum_new(L, adler32, adler32_combine);
1220 }
1221 
lz_crc32(lua_State * L)1222 static int lz_crc32(lua_State *L) {
1223 #ifdef LZLIB_COMPAT
1224     /* lzlib compat*/
1225     if ( lua_gettop(L) != 0 ) {
1226         size_t len;
1227         int crc;
1228         const unsigned char* buf;
1229         if ( lua_isfunction(L, 1) ) {
1230             crc = crc32(0L, Z_NULL, 0);
1231         } else {
1232             crc = (int)luaL_checkinteger(L, 1);
1233         }
1234         buf = (unsigned char*)luaL_checklstring(L, 2, &len);
1235         lua_pushnumber(L, crc32(crc, buf, len));
1236         return 1;
1237     }
1238 #endif
1239     return lz_checksum_new(L, crc32, crc32_combine);
1240 }
1241 
1242 
1243 static const luaL_Reg zlib_functions[] = {
1244     { "deflate", lz_deflate_new },
1245     { "inflate", lz_inflate_new },
1246     { "adler32", lz_adler32     },
1247     { "crc32",   lz_crc32       },
1248 #ifdef LZLIB_COMPAT
1249     { "compress",   lzlib_compress   },
1250     { "decompress", lzlib_decompress },
1251 #endif
1252     { "version", lz_version     },
1253     { NULL,      NULL           }
1254 };
1255 
1256 #define SETLITERAL(n,v) (lua_pushliteral(L, n), lua_pushliteral(L, v), lua_settable(L, -3))
1257 #define SETINT(n,v) (lua_pushliteral(L, n), lua_pushinteger(L, v), lua_settable(L, -3))
1258 
luaopen_zlib(lua_State * const L)1259 LUALIB_API int luaopen_zlib(lua_State * const L) {
1260     lz_create_deflate_mt(L);
1261     lz_create_inflate_mt(L);
1262 
1263     luaL_register(L, "zlib", zlib_functions);
1264 
1265     SETINT("BEST_SPEED", Z_BEST_SPEED);
1266     SETINT("BEST_COMPRESSION", Z_BEST_COMPRESSION);
1267 
1268     SETLITERAL("_COPYRIGHT", "Copyright (c) 2009-2016 Brian Maher");
1269     SETLITERAL("_DESCRIPTION", "Simple streaming interface to the zlib library");
1270     SETLITERAL("_VERSION", "lua-zlib $Id: da57e91a3a58c7f514e2058feccea7a7b42db5e2 $  (tag: v1.2)");
1271 
1272     /* Expose this to lua so we can do a test: */
1273     SETINT("_TEST_BUFSIZ", LUAL_BUFFERSIZE);
1274 
1275     /* lzlib compatibility */
1276 #ifdef LZLIB_COMPAT
1277     SETINT("NO_COMPRESSION", Z_NO_COMPRESSION);
1278     SETINT("DEFAULT_COMPRESSION", Z_DEFAULT_COMPRESSION);
1279     SETINT("FILTERED", Z_FILTERED);
1280     SETINT("HUFFMAN_ONLY", Z_HUFFMAN_ONLY);
1281     SETINT("RLE", Z_RLE);
1282     SETINT("FIXED", Z_FIXED);
1283     SETINT("DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY);
1284     SETINT("MINIMUM_MEMLEVEL", 1);
1285     SETINT("MAXIMUM_MEMLEVEL", 9);
1286     SETINT("DEFAULT_MEMLEVEL", 8);
1287     SETINT("DEFAULT_WINDOWBITS", 15);
1288     SETINT("MINIMUM_WINDOWBITS", 8);
1289     SETINT("MAXIMUM_WINDOWBITS", 15);
1290     SETINT("GZIP_WINDOWBITS", 16);
1291     SETINT("RAW_WINDOWBITS", -1);
1292 #endif
1293 
1294     return 1;
1295 }
1296