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