mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Add zlib binding for NSE. Fixes #532
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#s wa Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE][GH#532] Added zlib library for NSE. This was a leftover project from
|
||||
GSOC 2014, and will be very useful. [Claudiu Perta, Daniel Miller]
|
||||
|
||||
o [NSE][GH#1004] Fixed handling of brute.retries variable. It was being treated
|
||||
as the number of tries, not retries, and a value of 0 would result in
|
||||
infinite retries. Instead, it is now the number of retries, defaulting to 2
|
||||
|
||||
@@ -105,6 +105,11 @@ NSE_SRC+=nse_libssh2.cc
|
||||
NSE_HDRS+=nse_libssh2.h
|
||||
NSE_OBJS+=nse_libssh2.o
|
||||
endif
|
||||
ifneq (@LIBZLIB_LIBS@,)
|
||||
NSE_SRC+=nse_zlib.cc
|
||||
NSE_HDRS+=nse_zlib.h
|
||||
NSE_OBJS+=nse_zlib.o
|
||||
endif
|
||||
endif
|
||||
|
||||
export SRCS = charpool.cc FingerPrintResults.cc FPEngine.cc FPModel.cc idle_scan.cc MACLookup.cc main.cc nmap.cc nmap_dns.cc nmap_error.cc nmap_ftp.cc NmapOps.cc NmapOutputTable.cc nmap_tty.cc osscan2.cc osscan.cc output.cc payload.cc portlist.cc portreasons.cc protocols.cc scan_engine.cc scan_engine_connect.cc scan_engine_raw.cc scan_lists.cc service_scan.cc services.cc Target.cc NewTargets.cc TargetGroup.cc targets.cc tcpip.cc timing.cc traceroute.cc utils.cc xml.cc $(NSE_SRC)
|
||||
|
||||
@@ -166,6 +166,7 @@ xcopy /y /d "$(ProjectDir)..\libssh2\win32\$(Configuration)_dll\*.dll" "$(Proje
|
||||
<ClCompile Include="..\nse_openssl.cc" />
|
||||
<ClCompile Include="..\nse_pcrelib.cc" />
|
||||
<ClCompile Include="..\nse_ssl_cert.cc" />
|
||||
<ClCompile Include="..\nse_zlib.cc" />
|
||||
<ClCompile Include="..\osscan.cc" />
|
||||
<ClCompile Include="..\osscan2.cc" />
|
||||
<ClCompile Include="..\output.cc" />
|
||||
@@ -221,6 +222,7 @@ xcopy /y /d "$(ProjectDir)..\libssh2\win32\$(Configuration)_dll\*.dll" "$(Proje
|
||||
<ClInclude Include="..\nse_openssl.h" />
|
||||
<ClInclude Include="..\nse_pcrelib.h" />
|
||||
<ClInclude Include="..\nse_ssl_cert.h" />
|
||||
<ClInclude Include="..\nse_zlib.h" />
|
||||
<ClInclude Include="..\osscan.h" />
|
||||
<ClInclude Include="..\osscan2.h" />
|
||||
<ClInclude Include="..\output.h" />
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "nse_debug.h"
|
||||
#include "nse_lpeg.h"
|
||||
#include "nse_libssh2.h"
|
||||
#include "nse_zlib.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -551,6 +552,9 @@ static void set_nmap_libraries (lua_State *L)
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL
|
||||
{OPENSSLLIBNAME, luaopen_openssl},
|
||||
#endif
|
||||
#ifdef HAVE_LIBZ
|
||||
{NSE_ZLIBNAME, luaopen_zlib},
|
||||
#endif
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
988
nse_zlib.cc
Normal file
988
nse_zlib.cc
Normal file
@@ -0,0 +1,988 @@
|
||||
/************************************************************************
|
||||
* Author : Tiago Dionizio <tiago.dionizio@gmail.com> *
|
||||
* Library : lzlib - Lua 5 interface to access zlib library functions *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining *
|
||||
* a copy of this software and associated documentation files (the *
|
||||
* "Software"), to deal in the Software without restriction, including *
|
||||
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to *
|
||||
* the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be *
|
||||
* included in all copies or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
/*
|
||||
** =========================================================================
|
||||
** compile time options wich determine available functionality
|
||||
** =========================================================================
|
||||
*/
|
||||
|
||||
/* TODO
|
||||
|
||||
- also call flush on table/userdata when flush function is detected
|
||||
- remove io_cb check inflate_block if condition
|
||||
- only set eos when ZSTREAM_END is reached
|
||||
- check for stream errors to close stream when really needed
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** =========================================================================
|
||||
** zlib stream metamethods
|
||||
** =========================================================================
|
||||
*/
|
||||
#define ZSTREAMMETA "zlib:zstream"
|
||||
|
||||
#define LZ_ANY -1
|
||||
#define LZ_NONE 0
|
||||
#define LZ_DEFLATE 1
|
||||
#define LZ_INFLATE 2
|
||||
|
||||
#if 0
|
||||
#define LZ_BUFFER_SIZE LUAL_BUFFERSIZE
|
||||
#else
|
||||
#define LZ_BUFFER_SIZE 8192
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/* zlib structures */
|
||||
z_stream zstream;
|
||||
/* stream state. LZ_DEFLATE | LZ_INFLATE */
|
||||
int state;
|
||||
int error;
|
||||
int peek;
|
||||
int eos;
|
||||
/* user callback source for reading/writing */
|
||||
int io_cb;
|
||||
/* input buffer */
|
||||
int i_buffer_ref;
|
||||
size_t i_buffer_pos;
|
||||
size_t i_buffer_len;
|
||||
const char *i_buffer;
|
||||
/* output buffer */
|
||||
size_t o_buffer_len;
|
||||
size_t o_buffer_max;
|
||||
char o_buffer[LZ_BUFFER_SIZE];
|
||||
/* dictionary */
|
||||
const Bytef *dictionary;
|
||||
size_t dictionary_len;
|
||||
} lz_stream;
|
||||
|
||||
|
||||
/* forward declarations */
|
||||
static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush);
|
||||
|
||||
|
||||
static lz_stream *lzstream_new(lua_State *L, int src) {
|
||||
lz_stream *s = (lz_stream*)lua_newuserdata(L, sizeof(lz_stream));
|
||||
|
||||
luaL_getmetatable(L, ZSTREAMMETA);
|
||||
lua_setmetatable(L, -2); /* set metatable */
|
||||
|
||||
s->state = LZ_NONE;
|
||||
s->error = Z_OK;
|
||||
s->eos = 0;
|
||||
s->io_cb = LUA_REFNIL;
|
||||
|
||||
s->i_buffer = NULL;
|
||||
s->i_buffer_ref = LUA_REFNIL;
|
||||
s->i_buffer_pos = 0;
|
||||
s->i_buffer_len = 0;
|
||||
|
||||
s->peek = 0;
|
||||
s->o_buffer_len = 0;
|
||||
s->o_buffer_max = sizeof(s->o_buffer) / sizeof(s->o_buffer[0]);
|
||||
|
||||
s->zstream.zalloc = Z_NULL;
|
||||
s->zstream.zfree = Z_NULL;
|
||||
|
||||
/* prepare source */
|
||||
if (lua_isstring(L, src)) {
|
||||
lua_pushvalue(L, src);
|
||||
s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
s->i_buffer = lua_tolstring(L, src, &s->i_buffer_len);
|
||||
} else {
|
||||
/* table | function | userdata */
|
||||
lua_pushvalue(L, src);
|
||||
s->io_cb = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void lzstream_cleanup(lua_State *L, lz_stream *s) {
|
||||
if (s && s->state != LZ_NONE) {
|
||||
if (s->state == LZ_INFLATE) {
|
||||
inflateEnd(&s->zstream);
|
||||
}
|
||||
if (s->state == LZ_DEFLATE) {
|
||||
deflateEnd(&s->zstream);
|
||||
}
|
||||
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, s->io_cb);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
|
||||
s->state = LZ_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static lz_stream *lzstream_get(lua_State *L, int index) {
|
||||
lz_stream *s = (lz_stream*)luaL_checkudata(L, index, ZSTREAMMETA);
|
||||
if (s == NULL) luaL_argerror(L, index, "bad zlib stream");
|
||||
return s;
|
||||
}
|
||||
|
||||
static lz_stream *lzstream_check(lua_State *L, int index, int state) {
|
||||
lz_stream *s = lzstream_get(L, index);
|
||||
if ((state != LZ_ANY && s->state != state) || s->state == LZ_NONE) {
|
||||
luaL_argerror(L, index, "attempt to use invalid zlib stream");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lzstream_tostring(lua_State *L) {
|
||||
lz_stream *s = (lz_stream*)luaL_checkudata(L, 1, ZSTREAMMETA);
|
||||
if (s == NULL) luaL_argerror(L, 1, "bad zlib stream");
|
||||
|
||||
if (s->state == LZ_NONE) {
|
||||
lua_pushstring(L, "zlib stream (closed)");
|
||||
} else if (s->state == LZ_DEFLATE) {
|
||||
lua_pushfstring(L, "zlib deflate stream (%p)", (void*)s);
|
||||
} else if (s->state == LZ_INFLATE) {
|
||||
lua_pushfstring(L, "zlib inflate stream (%p)", (void*)s);
|
||||
} else {
|
||||
lua_pushfstring(L, "%p", (void*)s);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lzstream_gc(lua_State *L) {
|
||||
lz_stream *s = lzstream_get(L, 1);
|
||||
lzstream_cleanup(L, s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lzstream_close(lua_State *L) {
|
||||
lz_stream *s = lzstream_get(L, 1);
|
||||
|
||||
if (s->state == LZ_DEFLATE) {
|
||||
lua_settop(L, 0);
|
||||
lua_pushliteral(L, "");
|
||||
return lzstream_docompress(L, s, 1, 1, Z_FINISH);
|
||||
}
|
||||
|
||||
lzstream_cleanup(L, s);
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lzstream_adler(lua_State *L) {
|
||||
lz_stream *s = lzstream_check(L, 1, LZ_ANY);
|
||||
lua_pushnumber(L, s->zstream.adler);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
/*
|
||||
zlib.deflate(
|
||||
sink: function | { write: function [, close: function, flush: function] },
|
||||
compression level, [Z_DEFAILT_COMPRESSION]
|
||||
method, [Z_DEFLATED]
|
||||
windowBits, [15]
|
||||
memLevel, [8]
|
||||
strategy, [Z_DEFAULT_STRATEGY]
|
||||
dictionary: [""]
|
||||
)
|
||||
*/
|
||||
static int lzlib_deflate(lua_State *L) {
|
||||
int level, method, windowBits, memLevel, strategy;
|
||||
lz_stream *s;
|
||||
const char *dictionary;
|
||||
size_t dictionary_len;
|
||||
|
||||
if (lua_istable(L, 1) || lua_isuserdata(L, 1)) {
|
||||
/* is there a :write function? */
|
||||
lua_getfield(L, 1, "write");
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
luaL_argerror(L, 1, "output parameter does not provide :write function");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else if (!lua_isfunction(L, 1)) {
|
||||
luaL_argerror(L, 1, "output parameter must be a function, table or userdata value");
|
||||
}
|
||||
|
||||
level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
|
||||
method = (int) luaL_optinteger(L, 3, Z_DEFLATED);
|
||||
windowBits = (int) luaL_optinteger(L, 4, 15);
|
||||
memLevel = (int) luaL_optinteger(L, 5, 8);
|
||||
strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY);
|
||||
dictionary = luaL_optlstring(L, 7, NULL, &dictionary_len);
|
||||
|
||||
s = lzstream_new(L, 1);
|
||||
|
||||
if (deflateInit2(&s->zstream, level, method, windowBits, memLevel, strategy) != Z_OK) {
|
||||
lua_pushliteral(L, "call to deflateInit2 failed");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
if (dictionary) {
|
||||
if (deflateSetDictionary(&s->zstream, (const Bytef *) dictionary, dictionary_len) != Z_OK) {
|
||||
lua_pushliteral(L, "call to deflateSetDictionnary failed");
|
||||
lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
s->state = LZ_DEFLATE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
zlib.inflate(
|
||||
source: string | function | { read: function, close: function },
|
||||
windowBits: number, [15]
|
||||
dictionary: [""]
|
||||
)
|
||||
*/
|
||||
static int lzlib_inflate(lua_State *L)
|
||||
{
|
||||
int windowBits;
|
||||
lz_stream *s;
|
||||
int have_peek = 0;
|
||||
const char *dictionary;
|
||||
size_t dictionary_len;
|
||||
|
||||
if (lua_istable(L, 1) || lua_isuserdata(L, 1)) {
|
||||
/* is there a :read function? */
|
||||
lua_getfield(L, 1, "read");
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
luaL_argerror(L, 1, "input parameter does not provide :read function");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
/* check for peek function */
|
||||
lua_getfield(L, 1, "peek");
|
||||
have_peek = lua_isfunction(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else if (!lua_isstring(L, 1) && !lua_isfunction(L, 1)) {
|
||||
luaL_argerror(L, 1, "input parameter must be a string, function, table or userdata value");
|
||||
}
|
||||
|
||||
windowBits = (int) luaL_optinteger(L, 2, 15);
|
||||
dictionary = luaL_optlstring(L, 3, NULL, &dictionary_len);
|
||||
|
||||
s = lzstream_new(L, 1);
|
||||
|
||||
if (windowBits > 0 && windowBits < 16) {
|
||||
windowBits |= 32;
|
||||
}
|
||||
|
||||
if (inflateInit2(&s->zstream, windowBits) != Z_OK) {
|
||||
lua_pushliteral(L, "call to inflateInit2 failed");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
if (dictionary) {
|
||||
s->dictionary = (const Bytef *) dictionary;
|
||||
s->dictionary_len = dictionary_len;
|
||||
}
|
||||
|
||||
s->peek = have_peek;
|
||||
s->state = LZ_INFLATE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lz_pushresult (lua_State *L, lz_stream *s) {
|
||||
if (s->error == Z_OK) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, zError(s->error));
|
||||
lua_pushinteger(L, s->error);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Get block to process:
|
||||
- top of stack gets
|
||||
*/
|
||||
static const char* lzstream_fetch_block(lua_State *L, lz_stream *s, int hint) {
|
||||
if (s->i_buffer_pos >= s->i_buffer_len) {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
|
||||
s->i_buffer_ref = LUA_NOREF;
|
||||
s->i_buffer = NULL;
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
|
||||
if (!lua_isnil(L, -1)) {
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_pushinteger(L, hint);
|
||||
lua_call(L, 1, 1);
|
||||
} else {
|
||||
lua_getfield(L, -1, (s->peek ? "peek" : "read"));
|
||||
lua_insert(L, -2);
|
||||
lua_pushinteger(L, hint);
|
||||
lua_call(L, 2, 1);
|
||||
}
|
||||
|
||||
if (lua_isstring(L, -1)) {
|
||||
s->i_buffer_pos = 0;
|
||||
s->i_buffer = lua_tolstring(L, -1, &s->i_buffer_len);
|
||||
if (s->i_buffer_len > 0) {
|
||||
s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
} else {
|
||||
lua_pushliteral(L, "deflate callback must return string or nil");
|
||||
lua_error(L);
|
||||
}
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return s->i_buffer;
|
||||
}
|
||||
|
||||
static int lzstream_inflate_block(lua_State *L, lz_stream *s) {
|
||||
if (lzstream_fetch_block(L, s, LZ_BUFFER_SIZE) || !s->eos) {
|
||||
int r;
|
||||
|
||||
if (s->i_buffer_len == s->i_buffer_pos) {
|
||||
s->zstream.next_in = NULL;
|
||||
s->zstream.avail_in = 0;
|
||||
} else {
|
||||
s->zstream.next_in = (unsigned char*)(s->i_buffer + s->i_buffer_pos);
|
||||
s->zstream.avail_in = s->i_buffer_len - s->i_buffer_pos;
|
||||
}
|
||||
|
||||
s->zstream.next_out = (unsigned char*)s->o_buffer + s->o_buffer_len;
|
||||
s->zstream.avail_out = s->o_buffer_max - s->o_buffer_len;
|
||||
|
||||
/* munch some more */
|
||||
r = inflate(&s->zstream, Z_SYNC_FLUSH);
|
||||
|
||||
if (r == Z_NEED_DICT) {
|
||||
if (s->dictionary == NULL) {
|
||||
lua_pushliteral(L, "no inflate dictionary provided");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
if (inflateSetDictionary(&s->zstream, s->dictionary, s->dictionary_len) != Z_OK) {
|
||||
lua_pushliteral(L, "call to inflateSetDictionnary failed");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
r = inflate(&s->zstream, Z_SYNC_FLUSH);
|
||||
}
|
||||
|
||||
if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) {
|
||||
lzstream_cleanup(L, s);
|
||||
s->error = r;
|
||||
#if 1
|
||||
lua_pushfstring(L, "failed to decompress [%d]", r);
|
||||
lua_error(L);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (r == Z_STREAM_END) {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
|
||||
s->i_buffer_ref = LUA_NOREF;
|
||||
s->i_buffer = NULL;
|
||||
|
||||
s->eos = 1;
|
||||
}
|
||||
|
||||
/* number of processed bytes */
|
||||
if (s->peek) {
|
||||
size_t processed = s->i_buffer_len - s->i_buffer_pos - s->zstream.avail_in;
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
|
||||
lua_getfield(L, -1, "read");
|
||||
lua_insert(L, -2);
|
||||
lua_pushinteger(L, processed);
|
||||
lua_call(L, 2, 0);
|
||||
}
|
||||
|
||||
s->i_buffer_pos = s->i_buffer_len - s->zstream.avail_in;
|
||||
s->o_buffer_len = s->o_buffer_max - s->zstream.avail_out;
|
||||
}
|
||||
|
||||
return s->o_buffer_len;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove n bytes from the output buffer.
|
||||
*/
|
||||
static void lzstream_remove(lz_stream *s, size_t n) {
|
||||
memmove(s->o_buffer, s->o_buffer + n, s->o_buffer_len - n);
|
||||
s->o_buffer_len -= n;
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy at most n bytes to buffer b and remove them from the
|
||||
** output stream buffer.
|
||||
*/
|
||||
static int lzstream_flush_buffer(lua_State *L, lz_stream *s, size_t n, luaL_Buffer *b) {
|
||||
/* check output */
|
||||
if (n > s->o_buffer_len) {
|
||||
n = s->o_buffer_len;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
lua_pushlstring(L, s->o_buffer, n);
|
||||
luaL_addvalue(b);
|
||||
|
||||
lzstream_remove(s, n);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
z:read(
|
||||
{number | '*l' | '*a'}*
|
||||
)
|
||||
*/
|
||||
static int lz_test_eof(lua_State *L, lz_stream *s) {
|
||||
lua_pushlstring(L, NULL, 0);
|
||||
if (s->o_buffer_len > 0) {
|
||||
return 1;
|
||||
} else if (s->eos) {
|
||||
return 0;
|
||||
} else {
|
||||
return lzstream_inflate_block(L, s);
|
||||
}
|
||||
}
|
||||
|
||||
static int lz_read_line(lua_State *L, lz_stream *s) {
|
||||
luaL_Buffer b;
|
||||
size_t l = 0, n;
|
||||
|
||||
luaL_buffinit(L, &b);
|
||||
|
||||
if (s->o_buffer_len > 0 || !s->eos) do {
|
||||
char *p = s->o_buffer;
|
||||
size_t len = s->o_buffer_len;
|
||||
|
||||
/* find newline in output buffer */
|
||||
for (n = 0; n < len; ++n, ++p) {
|
||||
if (*p == '\n' || *p == '\r') {
|
||||
int eat_nl = *p == '\r';
|
||||
luaL_addlstring(&b, s->o_buffer, n);
|
||||
lzstream_remove(s, n+1);
|
||||
l += n;
|
||||
|
||||
if (eat_nl && lzstream_inflate_block(L, s)) {
|
||||
if (s->o_buffer_len > 0 && *s->o_buffer == '\n') {
|
||||
lzstream_remove(s, 1);
|
||||
}
|
||||
}
|
||||
|
||||
luaL_pushresult(&b);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
luaL_addlstring(&b, s->o_buffer, len);
|
||||
lzstream_remove(s, len);
|
||||
l += len;
|
||||
}
|
||||
} while (lzstream_inflate_block(L, s));
|
||||
|
||||
luaL_pushresult(&b);
|
||||
return l > 0 || !s->eos || s->o_buffer_len > 0;
|
||||
}
|
||||
|
||||
|
||||
static int lz_read_chars(lua_State *L, lz_stream *s, size_t n) {
|
||||
size_t len;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
|
||||
if (s->o_buffer_len > 0 || !s->eos) do {
|
||||
size_t rlen = lzstream_flush_buffer(L, s, n, &b);
|
||||
n -= rlen;
|
||||
} while (n > 0 && lzstream_inflate_block(L, s));
|
||||
|
||||
luaL_pushresult(&b);
|
||||
lua_tolstring(L, -1, &len);
|
||||
return n == 0 || len > 0;
|
||||
}
|
||||
|
||||
static int lzstream_decompress(lua_State *L) {
|
||||
lz_stream *s = lzstream_check(L, 1, LZ_INFLATE);
|
||||
int nargs = lua_gettop(L) - 1;
|
||||
int success;
|
||||
int n;
|
||||
if (nargs == 0) { /* no arguments? */
|
||||
success = lz_read_line(L, s);
|
||||
n = 3; /* to return 1 result */
|
||||
}
|
||||
else { /* ensure stack space for all results and for auxlib's buffer */
|
||||
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
|
||||
success = 1;
|
||||
for (n = 2; nargs-- && success; n++) {
|
||||
if (lua_type(L, n) == LUA_TNUMBER) {
|
||||
size_t l = (size_t)lua_tointeger(L, n);
|
||||
success = (l == 0) ? lz_test_eof(L, s) : lz_read_chars(L, s, l);
|
||||
}
|
||||
else {
|
||||
const char *p = lua_tostring(L, n);
|
||||
luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
|
||||
switch (p[1]) {
|
||||
case 'l': /* line */
|
||||
success = lz_read_line(L, s);
|
||||
break;
|
||||
case 'a': /* file */
|
||||
lz_read_chars(L, s, ~((size_t)0)); /* read MAX_SIZE_T chars */
|
||||
success = 1; /* always success */
|
||||
break;
|
||||
default:
|
||||
return luaL_argerror(L, n, "invalid format");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->error != Z_OK) {
|
||||
return lz_pushresult(L, s);
|
||||
}
|
||||
if (!success) {
|
||||
lua_pop(L, 1); /* remove last result */
|
||||
lua_pushnil(L); /* push nil instead */
|
||||
}
|
||||
return n - 2;
|
||||
}
|
||||
|
||||
|
||||
static int lzstream_readline(lua_State *L) {
|
||||
lz_stream *s;
|
||||
int sucess;
|
||||
|
||||
s = lzstream_check(L, lua_upvalueindex(1), LZ_INFLATE);
|
||||
sucess = lz_read_line(L, s);
|
||||
|
||||
if (s->error != Z_OK) {
|
||||
return lz_pushresult(L, s);
|
||||
}
|
||||
|
||||
if (sucess) {
|
||||
return 1;
|
||||
} else {
|
||||
/* EOF */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int lzstream_lines(lua_State *L) {
|
||||
lzstream_check(L, 1, LZ_INFLATE);
|
||||
lua_settop(L, 1);
|
||||
lua_pushcclosure(L, lzstream_readline, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush) {
|
||||
int r, arg;
|
||||
int self = 0;
|
||||
size_t b_size = s->o_buffer_max;
|
||||
unsigned char *b = (unsigned char *)s->o_buffer;
|
||||
|
||||
/* number of processed bytes */
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
self = 1;
|
||||
lua_getfield(L, -1, "write");
|
||||
}
|
||||
|
||||
for (arg = from; arg <= to; arg++) {
|
||||
s->zstream.next_in = (unsigned char*)luaL_checklstring(L, arg, (size_t*)&s->zstream.avail_in);
|
||||
|
||||
do {
|
||||
s->zstream.next_out = b;
|
||||
s->zstream.avail_out = b_size;
|
||||
|
||||
/* bake some more */
|
||||
r = deflate(&s->zstream, flush);
|
||||
if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) {
|
||||
lzstream_cleanup(L, s);
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushfstring(L, "failed to compress [%d]", r);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (s->zstream.avail_out != b_size) {
|
||||
/* write output */
|
||||
lua_pushvalue(L, -1); /* function */
|
||||
if (self) lua_pushvalue(L, -3); /* self */
|
||||
lua_pushlstring(L, (char*)b, b_size - s->zstream.avail_out); /* data */
|
||||
lua_call(L, (self ? 2 : 1), 0);
|
||||
}
|
||||
|
||||
if (r == Z_STREAM_END) {
|
||||
lzstream_cleanup(L, s);
|
||||
break;
|
||||
}
|
||||
|
||||
/* process all input */
|
||||
} while (s->zstream.avail_in > 0 || s->zstream.avail_out == 0);
|
||||
}
|
||||
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lzstream_compress(lua_State *L) {
|
||||
lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE);
|
||||
return lzstream_docompress(L, s, 2, lua_gettop(L), Z_NO_FLUSH);
|
||||
}
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lzstream_flush(lua_State *L) {
|
||||
static int flush_values[] = { Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH };
|
||||
static const char *const flush_opts[] = { "sync", "full", "finish" };
|
||||
|
||||
lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE);
|
||||
int flush = luaL_checkoption(L, 2, flush_opts[0], flush_opts);
|
||||
|
||||
lua_settop(L, 0);
|
||||
lua_pushliteral(L, "");
|
||||
return lzstream_docompress(L, s, 1, 1, flush_values[flush]);
|
||||
}
|
||||
|
||||
/*
|
||||
** =========================================================================
|
||||
** zlib functions
|
||||
** =========================================================================
|
||||
*/
|
||||
|
||||
static int lzlib_version(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, zlibVersion());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
static int lzlib_adler32(lua_State *L)
|
||||
{
|
||||
if (lua_gettop(L) == 0)
|
||||
{
|
||||
/* adler32 initial value */
|
||||
lua_pushnumber(L, adler32(0L, Z_NULL, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update adler32 checksum */
|
||||
size_t len;
|
||||
int adler = (int) luaL_checkinteger(L, 1);
|
||||
const unsigned char* buf = (unsigned char*)luaL_checklstring(L, 2, &len);
|
||||
|
||||
lua_pushnumber(L, adler32(adler, buf, len));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
static int lzlib_crc32(lua_State *L)
|
||||
{
|
||||
if (lua_gettop(L) == 0)
|
||||
{
|
||||
/* crc32 initial value */
|
||||
lua_pushnumber(L, crc32(0L, Z_NULL, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update crc32 checksum */
|
||||
size_t len;
|
||||
int crc = (int) luaL_checkinteger(L, 1);
|
||||
const unsigned char* buf = (unsigned char*)luaL_checklstring(L, 2, &len);
|
||||
|
||||
lua_pushnumber(L, crc32(crc, buf, len));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
|
||||
static int lzlib_compress(lua_State *L) {
|
||||
size_t avail_in;
|
||||
const char *next_in = luaL_checklstring(L, 1, &avail_in);
|
||||
int level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
|
||||
int method = (int) luaL_optinteger(L, 3, Z_DEFLATED);
|
||||
int windowBits = (int) luaL_optinteger(L, 4, 15);
|
||||
int memLevel = (int) luaL_optinteger(L, 5, 8);
|
||||
int strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY);
|
||||
|
||||
int ret;
|
||||
luaL_Buffer b;
|
||||
z_stream zs;
|
||||
|
||||
luaL_buffinit(L, &b);
|
||||
|
||||
zs.zalloc = Z_NULL;
|
||||
zs.zfree = Z_NULL;
|
||||
|
||||
zs.next_out = Z_NULL;
|
||||
zs.avail_out = 0;
|
||||
zs.next_in = Z_NULL;
|
||||
zs.avail_in = 0;
|
||||
|
||||
ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy);
|
||||
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
lua_pushnumber(L, ret);
|
||||
return 2;
|
||||
}
|
||||
|
||||
zs.next_in = (unsigned char*)next_in;
|
||||
zs.avail_in = avail_in;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
|
||||
zs.avail_out = LUAL_BUFFERSIZE;
|
||||
|
||||
/* munch some more */
|
||||
ret = deflate(&zs, Z_FINISH);
|
||||
|
||||
/* push gathered data */
|
||||
luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
|
||||
|
||||
/* done processing? */
|
||||
if (ret == Z_STREAM_END)
|
||||
break;
|
||||
|
||||
/* error condition? */
|
||||
if (ret != Z_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
deflateEnd(&zs);
|
||||
|
||||
luaL_pushresult(&b);
|
||||
lua_pushnumber(L, ret);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static int lzlib_decompress(lua_State *L)
|
||||
{
|
||||
size_t avail_in;
|
||||
const char *next_in = luaL_checklstring(L, 1, &avail_in);
|
||||
int windowBits = (int) luaL_optinteger(L, 2, 15);
|
||||
|
||||
int ret;
|
||||
luaL_Buffer b;
|
||||
z_stream zs;
|
||||
|
||||
luaL_buffinit(L, &b);
|
||||
|
||||
zs.zalloc = Z_NULL;
|
||||
zs.zfree = Z_NULL;
|
||||
|
||||
zs.next_out = Z_NULL;
|
||||
zs.avail_out = 0;
|
||||
zs.next_in = Z_NULL;
|
||||
zs.avail_in = 0;
|
||||
|
||||
ret = inflateInit2(&zs, windowBits);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
lua_pushliteral(L, "failed to initialize zstream structures");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
zs.next_in = (unsigned char*)next_in;
|
||||
zs.avail_in = avail_in;
|
||||
|
||||
for (;;) {
|
||||
zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
|
||||
zs.avail_out = LUAL_BUFFERSIZE;
|
||||
|
||||
/* bake some more */
|
||||
ret = inflate(&zs, Z_FINISH);
|
||||
|
||||
/* push gathered data */
|
||||
luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
|
||||
|
||||
/* done processing? */
|
||||
if (ret == Z_STREAM_END)
|
||||
break;
|
||||
|
||||
if (ret != Z_OK && ret != Z_BUF_ERROR) {
|
||||
/* cleanup */
|
||||
inflateEnd(&zs);
|
||||
|
||||
lua_pushliteral(L, "failed to process zlib stream");
|
||||
lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
inflateEnd(&zs);
|
||||
|
||||
luaL_pushresult(&b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** =========================================================================
|
||||
** Register functions
|
||||
** =========================================================================
|
||||
*/
|
||||
|
||||
#if (LUA_VERSION_NUM >= 502)
|
||||
|
||||
#define luaL_register(L,n,f) luaL_setfuncs(L,f,0)
|
||||
|
||||
#endif
|
||||
|
||||
LUALIB_API int luaopen_zlib(lua_State *L)
|
||||
{
|
||||
const luaL_Reg lzstream_meta[] =
|
||||
{
|
||||
{"write", lzstream_compress },
|
||||
{"read", lzstream_decompress },
|
||||
{"lines", lzstream_lines },
|
||||
{"flush", lzstream_flush },
|
||||
{"close", lzstream_close },
|
||||
|
||||
{"adler", lzstream_adler },
|
||||
|
||||
{"__tostring", lzstream_tostring },
|
||||
{"__gc", lzstream_gc },
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const luaL_Reg zlib[] =
|
||||
{
|
||||
{"version", lzlib_version },
|
||||
{"adler32", lzlib_adler32 },
|
||||
{"crc32", lzlib_crc32 },
|
||||
|
||||
{"deflate", lzlib_deflate },
|
||||
{"inflate", lzlib_inflate },
|
||||
|
||||
{"compress", lzlib_compress },
|
||||
{"decompress", lzlib_decompress },
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
/* create new metatable for zlib compression structures */
|
||||
luaL_newmetatable(L, ZSTREAMMETA);
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, -2); /* push metatable */
|
||||
lua_rawset(L, -3); /* metatable.__index = metatable */
|
||||
|
||||
/*
|
||||
** Stack: metatable
|
||||
*/
|
||||
luaL_register(L, NULL, lzstream_meta);
|
||||
|
||||
lua_pop(L, 1); /* remove metatable from stack */
|
||||
|
||||
/*
|
||||
** Stack:
|
||||
*/
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushliteral (L, "_COPYRIGHT");
|
||||
lua_pushliteral (L, "Copyright (C) 2003-2010 Tiago Dionizio");
|
||||
lua_settable (L, -3);
|
||||
lua_pushliteral (L, "_DESCRIPTION");
|
||||
lua_pushliteral (L, "Lua 5 interface to access zlib library functions");
|
||||
lua_settable (L, -3);
|
||||
lua_pushliteral (L, "_VERSION");
|
||||
lua_pushliteral (L, "lzlib 0.4-work3");
|
||||
lua_settable (L, -3);
|
||||
|
||||
#define PUSH_LITERAL(name) \
|
||||
lua_pushliteral (L, #name); \
|
||||
lua_pushinteger (L, Z_##name); \
|
||||
lua_settable (L, -3);
|
||||
|
||||
#define PUSH_NUMBER(name, value) \
|
||||
lua_pushliteral (L, #name); \
|
||||
lua_pushinteger (L, value); \
|
||||
lua_settable (L, -3);
|
||||
|
||||
PUSH_LITERAL(NO_COMPRESSION)
|
||||
PUSH_LITERAL(BEST_SPEED)
|
||||
PUSH_LITERAL(BEST_COMPRESSION)
|
||||
PUSH_LITERAL(DEFAULT_COMPRESSION)
|
||||
|
||||
PUSH_LITERAL(FILTERED)
|
||||
PUSH_LITERAL(HUFFMAN_ONLY)
|
||||
PUSH_LITERAL(RLE)
|
||||
PUSH_LITERAL(FIXED)
|
||||
PUSH_LITERAL(DEFAULT_STRATEGY)
|
||||
|
||||
PUSH_NUMBER(MINIMUM_MEMLEVEL, 1)
|
||||
PUSH_NUMBER(MAXIMUM_MEMLEVEL, 9)
|
||||
PUSH_NUMBER(DEFAULT_MEMLEVEL, 8)
|
||||
|
||||
PUSH_NUMBER(DEFAULT_WINDOWBITS, 15)
|
||||
PUSH_NUMBER(MINIMUM_WINDOWBITS, 8)
|
||||
PUSH_NUMBER(MAXIMUM_WINDOWBITS, 15)
|
||||
|
||||
PUSH_NUMBER(GZIP_WINDOWBITS, 16)
|
||||
PUSH_NUMBER(RAW_WINDOWBITS, -1)
|
||||
|
||||
luaL_register(L, NULL, zlib);
|
||||
|
||||
/*
|
||||
** Stack: zlib table
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
9
nse_zlib.h
Normal file
9
nse_zlib.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef ZLIB
|
||||
#define ZLIB
|
||||
|
||||
#define NSE_ZLIBNAME "zlib"
|
||||
|
||||
LUALIB_API int luaopen_zlib(lua_State *L);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -153,6 +153,7 @@ local libs = {
|
||||
"wsdd",
|
||||
"xdmcp",
|
||||
"xmpp",
|
||||
"zlib",
|
||||
}
|
||||
|
||||
-- This script-arg is documented in the unittest script to avoid cluttering
|
||||
|
||||
111
nselib/zlib.luadoc
Normal file
111
nselib/zlib.luadoc
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
-- Zlib compression and decompression library
|
||||
--
|
||||
-- From https://github.com/LuaDist/lzlib
|
||||
-- @author Tiago Dionizio <tiago.dionizio@gmail.com>
|
||||
-- @copyright The MIT License (MIT); Copyright Tiago Dionizio (tiago.dionizio@gmail.com)
|
||||
module "zlib"
|
||||
|
||||
-- NSEdoc derived from lzlib's README
|
||||
|
||||
--- returns zlib version
|
||||
-- @return the zlib version
|
||||
function version()
|
||||
|
||||
--- Compute an adler32 checksum
|
||||
--
|
||||
-- Without any parameters, returns the initial adler32 value.
|
||||
--
|
||||
-- Call to update the adler32 value, adler is the current value, buffer is passed
|
||||
-- to adler32 zlib function and the updated value is returned.
|
||||
-- @param adler An integer, the result of a previous call to <code>adler32</code>
|
||||
-- @param buffer A string, over which to compute the adler32 checksum.
|
||||
-- @return The adler32 checksum result.
|
||||
function adler32(adler, buffer)
|
||||
|
||||
--- Compute a crc32 checksum
|
||||
--
|
||||
-- Without any parameters, returns the initial crc32 value.
|
||||
--
|
||||
-- Call to update the crc32 value, crc is the current value, buffer is passed
|
||||
-- to crc32 zlib function and the updated value is returned.
|
||||
-- @param crc An integer, the result of a previous call to <code>crc32</code>
|
||||
-- @param buffer A string, over which to compute the crc32 checksum.
|
||||
-- @return The crc32 checksum result.
|
||||
function crc32(crc, buffer)
|
||||
|
||||
--- Return a string containing the compressed buffer according to the given parameters.
|
||||
--
|
||||
-- All of the parameters besides buffer are optional. The zlib library sets the
|
||||
-- default values, which are usually equivalent to
|
||||
-- <code>compress(buffer, 6, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY)</code>
|
||||
-- @param buffer String to compress
|
||||
-- @param level Optional integer corresponding to compression level, 0-9
|
||||
-- @param method Optional integer corresponding to compression method
|
||||
-- @param windowBits Optional integer, the base-2 logarithm of the maximum window size. Default: 15
|
||||
-- @param memLevel Optional integer corresponding to memory use and therefore speed
|
||||
-- @param strategy Optional integer corresponding to compression strategy
|
||||
function compress(buffer, level, method, windowBits, memLevel, strategy)
|
||||
|
||||
--- Return the decompressed stream after processing the given buffer.
|
||||
--
|
||||
-- If windowBits is negative, this function decompresses raw deflate data without header.
|
||||
-- @param buffer String containing DEFLATE-compressed data
|
||||
-- @param windowBits Optional integer, the base-2 logarithm of the maximum window size. Default: 15
|
||||
function decompress(buffer, windowBits)
|
||||
|
||||
--- Return a deflate stream.
|
||||
--
|
||||
-- This stream is a file-like object that can be used to write compressed
|
||||
-- (deflated) data to some sink stream. If the sink stream is a table or
|
||||
-- object, it must have a <code>write</code> method. Otherwise, it must be a
|
||||
-- function that will be called with data to write (e.g.
|
||||
-- <code>socket.send</code>).
|
||||
-- @param sink The location where compressed data will be written
|
||||
-- @param level Optional integer corresponding to compression level, 0-9
|
||||
-- @param method Optional integer corresponding to compression method
|
||||
-- @param windowBits Optional integer, the base-2 logarithm of the maximum window size. Default: 15
|
||||
-- @param memLevel Optional integer corresponding to memory use and therefore speed
|
||||
-- @param strategy Optional integer corresponding to compression strategy
|
||||
-- @param dictionary Optional string corresponding to initial compression dictionary
|
||||
function deflate(sink, level, method, windowBits, memLevel, strategy, dictionary)
|
||||
|
||||
--- Read from an inflate stream
|
||||
--
|
||||
-- @param how A number of bytes to read, or "*l" (read until newline), or "*a" (read the whole stream). Default: "*l"
|
||||
-- @return The bytes read, or nil on EOF.
|
||||
function inflate_stream:read(how)
|
||||
|
||||
--- Return iterator that returns a line each time it is called, or nil on end
|
||||
-- of file.
|
||||
-- @return An iterator suitable for use with <code>for</code>
|
||||
function inflate_stream:lines()
|
||||
|
||||
--- Close the stream.
|
||||
--@return True, or false on error
|
||||
--@return An error string
|
||||
function stream:close()
|
||||
|
||||
--- Return an inflate stream.
|
||||
--
|
||||
-- This stream is a file-like object that can be used to read decompressed
|
||||
-- (inflated) data from some source stream. If the source stream is a table or
|
||||
-- object, it must have a <code>read</code> method. Otherwise, it must be a
|
||||
-- function that will be called to get more compressed data.
|
||||
-- @param source The location where compressed data will be read from
|
||||
-- @param windowBits Optional integer, the base-2 logarithm of the maximum window size. Default: 15
|
||||
-- @param dictionary Optional string corresponding to initial compression dictionary
|
||||
-- @return an inflate stream.
|
||||
function inflate(source, windowBits, dictionary)
|
||||
|
||||
--- Write each parameter into the stream
|
||||
-- @param ... any number of strings to write
|
||||
-- @return True, or false on error
|
||||
-- @return Error string on error
|
||||
function deflate_stream:write(...)
|
||||
|
||||
--- Flush output for deflate streams.
|
||||
-- @param value One of 'sync', 'full', or 'finish'
|
||||
-- @return True, or false on error
|
||||
-- @return Error string on error
|
||||
function deflate_stream:flush(value)
|
||||
Reference in New Issue
Block a user