Example #1
0
static int
lload(lua_State *L) {
	struct reader rd;
	rd.source = luaL_checklstring(L,1,&rd.source_sz);
	const char * filename = luaL_checkstring(L, 2);
	struct filter flt = { &rd.stream, inflateEnd, NULL, 0, 0 };
	struct rc4_sbox sbox;
	if (lua_isstring(L, 3)) {
		size_t keysz;
		const char * key = lua_tolstring(L, 3, &keysz);
		if (keysz != 8) {
			return luaL_error(L, "Only support 8 bytes key");
		}
		rc4_init(&sbox, (const uint8_t *)key);
		rd.crypt_sbox = &sbox;
	} else {
		rd.crypt_sbox = NULL;
	}
	rd.flags = Z_NO_FLUSH;
	z_stream *stream = &rd.stream;
	stream->zalloc = Z_NULL;
	stream->zfree = Z_NULL;
	stream->opaque = Z_NULL;
	stream->avail_in = 0;
	stream->avail_out = 0;
	int result = inflateInit(stream);
	lz_assert(L, result, &flt);
	result = lua_load (L, zip_reader, &rd, filename, "bt");
	inflateEnd(stream);
	if (result != LUA_OK) {
		return lua_error(L);
	}
	return 1;
}
Example #2
0
static const char *
zip_reader(lua_State *L, void *data, size_t *size) {
	z_stream *stream;
	struct reader *rd = data;
	if (rd->source == NULL)
		return NULL;
	stream = &rd->stream;
	if (stream->avail_in == 0 && rd->flags != Z_FINISH) {
		if (rd->source_sz <= CHUNK_IN) {
			rd->flags = Z_FINISH;
			stream->avail_in = rd->source_sz;
		} else {
			stream->avail_in = CHUNK_IN;
		}
		if (rd->crypt_sbox) {
			rc4_crypt(rd->crypt_sbox, (const uint8_t *)rd->source, rd->inbuffer, stream->avail_in);
			stream->next_in = (z_const Bytef *)rd->inbuffer;
		} else {
			stream->next_in = (z_const Bytef *)rd->source;
		}
		rd->source += stream->avail_in;
		rd->source_sz -= stream->avail_in;
	}
	stream->next_out = rd->outbuffer;
	stream->avail_out = CHUNK_IN;
	int result = inflate(stream, rd->flags);
	struct filter flt = { &rd->stream, inflateEnd, NULL, 0, 0 };
	lz_assert(L, result, &flt);
	if (rd->flags == Z_FINISH && stream->avail_out != 0) {
		rd->source = NULL;
	}
	*size = CHUNK_IN - stream->avail_out;
	return (const char *)rd->outbuffer;
}
Example #3
0
static int
ldecompress(lua_State *L) {
	z_stream stream;
	stream.zalloc = Z_NULL;
	stream.zfree = Z_NULL;
	stream.opaque = Z_NULL;
	struct filter flt = {
		&stream,
		inflateEnd,
		inflate,
		CRYPT_NONE,
		NULL,
	};
	struct rc4_sbox sbox;
	if (lua_isstring(L, 2)) {
		size_t keysz;
		const char * key = lua_tolstring(L, 2, &keysz);
		if (keysz != 8) {
			return luaL_error(L, "Only support 8 bytes key");
		}
		rc4_init(&sbox, (const uint8_t *)key);
		flt.crypt_type = CRYPT_IN;
		flt.crypt_sbox = &sbox;
	}
	int result = inflateInit(&stream);
	lz_assert(L, result, &flt);
	return execute(L, &flt);
}
Example #4
0
static int
execute(lua_State *L, struct filter *flt) {
	z_stream *stream = flt->stream;
	size_t avail_in;
	const char * source = lua_tolstring(L, 1, &avail_in);
	uint8_t chunk[CHUNK_IN];
	int flags = Z_NO_FLUSH;
	stream->avail_in = 0;
	stream->avail_out = 0;
	luaL_Buffer buff;
	luaL_buffinit(L, &buff);
	int result;
	do {
		if (stream->avail_in == 0 && flags != Z_FINISH) {
			stream->next_in = (z_const Bytef *)chunk;
			if (avail_in <= CHUNK_IN) {
				flags = Z_FINISH;
				stream->avail_in = avail_in;
			} else {
				stream->avail_in = CHUNK_IN;
			}
			if (flt->crypt_type == CRYPT_IN) {
				rc4_crypt(flt->crypt_sbox, (const uint8_t *)source, chunk, stream->avail_in);
				stream->next_in = (z_const Bytef *)chunk;
			} else {
				stream->next_in = (z_const Bytef *)source;
			}
			source += stream->avail_in;
			avail_in -= stream->avail_in;
		}
		void *buffer = luaL_prepbuffer(&buff);
		stream->next_out  = buffer;
		stream->avail_out = LUAL_BUFFERSIZE;
		result = flt->execute(stream, flags);
		lz_assert(L, result, flt);
		if (flt->crypt_type == CRYPT_OUT) {
			rc4_crypt(flt->crypt_sbox, buffer, buffer, LUAL_BUFFERSIZE - stream->avail_out);
		}
		luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out);
	} while ( result != Z_STREAM_END );
	luaL_pushresult(&buff);
	lua_pushinteger(L, stream->adler);
	flt->end(stream);
	return 2;
}
Example #5
0
static int lz_deflate_new(lua_State *L) {
    int level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION);

    /*  Allocate the stream: */
    z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));

    stream->zalloc = Z_NULL;
    stream->zfree  = Z_NULL;
    lz_assert(L, deflateInit(stream, level), stream, __FILE__, __LINE__);

    /*  Don't allow destructor to execute unless deflateInit was successful: */
    luaL_getmetatable(L, "lz.deflate.meta");
    lua_setmetatable(L, -2);

    lua_pushnil(L);
    lua_pushcclosure(L, lz_deflate, 2);
    return 1;
}
Example #6
0
static int lz_inflate_new(lua_State *L) {
    /* Allocate the stream */
    z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));

    /*  By default, we will do gzip header detection w/ max window size */
    int window_size = lua_isnumber(L, 1) ? lua_tointeger(L, 1) : MAX_WBITS + 32;

    stream->zalloc   = Z_NULL;
    stream->zfree    = Z_NULL;
    stream->next_in  = Z_NULL;
    stream->avail_in = 0;

    lz_assert(L, inflateInit2(stream, window_size), stream, __FILE__, __LINE__);

    /*  Don't allow destructor to execute unless deflateInit was successful: */
    luaL_getmetatable(L, "lz.inflate.meta");
    lua_setmetatable(L, -2);

    lua_pushnil(L);
    lua_pushcclosure(L, lz_inflate, 2);
    return 1;
}
Example #7
0
static int lz_deflate_new(lua_State *L) {
    int level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION);
    int window_size = luaL_optint(L, 2, MAX_WBITS);

    /*  Allocate the stream: */
    z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));

    stream->zalloc = Z_NULL;
    stream->zfree  = Z_NULL;

    int result = deflateInit2(stream, level, Z_DEFLATED, window_size,
                              DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);

    lz_assert(L, result, stream, __FILE__, __LINE__);

    /*  Don't allow destructor to execute unless deflateInit2 was successful: */
    luaL_getmetatable(L, "lz.deflate.meta");
    lua_setmetatable(L, -2);

    lua_pushnil(L);
    lua_pushcclosure(L, lz_deflate, 2);
    return 1;
}
Example #8
0
/**
 * @upvalue z_stream - Memory for the z_stream.
 * @upvalue remainder - Any remainder from the last deflate call.
 *
 * @param string - "print" to deflate stream.
 * @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH.
 *
 * if no params, terminates the stream (as if we got empty string and Z_FINISH).
 */
static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), char* name) {
    int flush = Z_NO_FLUSH, result;
    z_stream* stream;
    luaL_Buffer buff;
    size_t avail_in;

    if ( filter == deflate ) {
        const char *const opts[] = { "none", "sync", "full", "finish", NULL };
        flush = luaL_checkoption(L, 2, opts[0], opts);
        if ( flush ) flush++; 
        /* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */

        /* No arguments or nil, we are terminating the stream: */
        if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) {
            flush = Z_FINISH;
        }
    }

    stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1));
    if ( stream == NULL ) {
        if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) {
            lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name);
            lua_error(L);
        }
        lua_pushstring(L, "");
        lua_pushboolean(L, 1);
        return 2; /* Ignore duplicate calls to "close". */
    }

    luaL_buffinit(L, &buff);

    if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1);

    if ( lua_isstring(L, lua_upvalueindex(2)) ) {
        lua_pushvalue(L, lua_upvalueindex(2));
        if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) {
            lua_concat(L, 2);
        }
    }

    /*  Do the actual deflate'ing: */
    stream->next_in = lua_gettop(L) > 0 ?
        (unsigned char*)lua_tolstring(L, -1, &avail_in) :
        NULL;
    stream->avail_in = avail_in;

    if ( ! stream->avail_in && ! flush ) {
        /*  Passed empty string, make it a noop instead of erroring out. */
        lua_pushstring(L, "");
        lua_pushboolean(L, 0);
        lua_pushinteger(L, stream->total_in);
        lua_pushinteger(L, stream->total_out);
        return 4;
    }

    do {
        stream->next_out  = (unsigned char*)luaL_prepbuffer(&buff);
        stream->avail_out = LUAL_BUFFERSIZE;
        result = filter(stream, flush);
        if ( Z_BUF_ERROR != result ) {
            /* Ignore Z_BUF_ERROR since that just indicates that we
             * need a larger buffer in order to proceed.  Thanks to
             * Tobias Markmann for finding this bug!
             */
            lz_assert(L, result, stream, __FILE__, __LINE__);
        }
        luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out);
    } while ( stream->avail_out == 0 );

    /*  Need to do this before we alter the stack: */
    luaL_pushresult(&buff);

    /*  Save remainder in lua_upvalueindex(2): */
    if ( NULL != stream->next_in ) {
        lua_pushlstring(L, (char*)stream->next_in, stream->avail_in);
        lua_replace(L, lua_upvalueindex(2));
    }

    /*  "close" the stream/remove finalizer: */
    if ( result == Z_STREAM_END ) {
        /*  Clear-out the metatable so end is not called twice: */
        lua_pushnil(L);
        lua_setmetatable(L, lua_upvalueindex(1));

        /*  nil the upvalue: */
        lua_pushnil(L);
        lua_replace(L, lua_upvalueindex(1));

        /*  Close the stream: */
        lz_assert(L, end(stream), stream, __FILE__, __LINE__);

        lua_pushboolean(L, 1);
    } else {
        lua_pushboolean(L, 0);
    }
    lua_pushinteger(L, stream->total_in);
    lua_pushinteger(L, stream->total_out);
    return 4;
}