1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-08 21:51:28 +00:00

Remove more bin.lua packings.

This commit is contained in:
dmiller
2018-09-22 05:19:24 +00:00
parent e9addd756f
commit ff6b5b65a8
4 changed files with 116 additions and 184 deletions

View File

@@ -1,4 +1,3 @@
local bin = require "bin"
local comm = require "comm"
local json = require "json"
local lpeg = require "lpeg"
@@ -329,22 +328,23 @@ COAP.header.build = function(options)
code = COAP.header.codes.build(code)
-- Build the fixed portion of the header.
local pkt = ""
ver = ver << 6
mtype = mtype << 4
pkt = pkt .. bin.pack("C", ver | mtype | tkl)
pkt = pkt .. code
pkt = pkt .. bin.pack(">S", id)
pkt = pkt .. token
local pkt = {
string.pack("B", ver | mtype | tkl),
code,
string.pack(">I2", id),
token,
}
-- Include optional portions of the header.
if options["options"] then
pkt = pkt .. COAP.header.options.build(options.options)
pkt[#pkt+1] = COAP.header.options.build(options.options)
end
return pkt
return table.concat(pkt)
end
--- Parses a CoAP message header.
@@ -361,9 +361,6 @@ end
-- string containing the error message on failure.
COAP.header.parse = function(buf, pos)
assert(type(buf) == "string")
if #buf < 4 then
return false, "Cannot parse a string of less than four bytes."
end
if not pos or pos == 0 then
pos = 1
@@ -371,14 +368,11 @@ COAP.header.parse = function(buf, pos)
assert(type(pos) == "number")
assert(pos <= #buf)
if pos + 4 - 1 > #buf then
if #buf - pos + 1 < 4 then
return false, "Fixed header extends past end of buffer."
end
local pos, ver_type_tkl, code, id = bin.unpack("CA>S", buf, pos)
if not pos then
return false, "Failed to parse fixed header."
end
local ver_type_tkl, code, id, pos = string.unpack(">Bc1I2", buf, pos)
-- Parse the fixed header.
local hdr = {}
@@ -486,7 +480,7 @@ COAP.header.codes.build = function(name)
class = class << 5
return bin.pack("C", class | detail)
return string.pack("B", class | detail)
end
--- Parses a CoAP request or response code.
@@ -511,7 +505,7 @@ COAP.header.codes.parse = function(buf, pos)
assert(type(pos) == "number")
assert(pos <= #buf)
local pos, id = bin.unpack("C", buf, pos)
local id, pos = string.unpack("B", buf, pos)
if not pos then
return false, id
end
@@ -1462,20 +1456,8 @@ COAP.header.options.value.uint.build = function(val)
if val == 0 then
return ""
end
if val <= 255 then
return bin.pack("C", val)
end
if val <= 65535 then
return bin.pack(">S", val)
end
if val <= 16777215 then
return bin.pack(">I", val):sub(2, 5)
end
return bin.pack(">I", val)
-- strip leading null bytes to use smallest space
return string.pack(">I16", val):gsub("^\0*","")
end
--- Parses a CoAP message Uint header option value.
@@ -1490,25 +1472,15 @@ end
COAP.header.options.value.uint.parse = function(buf)
assert(type(buf) == "string")
assert(#buf >= 0)
assert(#buf <= 4)
assert(#buf <= 16)
if #buf == 0 then
return 0
end
local val, pos
if #buf == 1 then
pos, val = bin.unpack("C", buf)
elseif #buf == 2 then
pos, val = bin.unpack(">S", buf)
elseif #buf == 3 then
pos, val = bin.unpack(">I", string.char(0x00) .. buf)
else
pos, val = bin.unpack(">I", buf)
end
local val = string.unpack(">I" .. #buf, buf)
-- There should be no way for this to fail.
assert(pos)
assert(val)
assert(type(val) == "number")
@@ -1567,19 +1539,18 @@ COAP.header.options.delta_length.build = function(delta, length)
end
if num <= 268 then
return 13, bin.pack("C", num - 13)
return 13, string.pack("B", num - 13)
end
return 14, bin.pack(">S", num - 269)
return 14, string.pack(">I2", num - 269)
end
local d1, d2 = build(delta)
local l1, l2 = build(length)
d1 = d1 << 4
bin.pack("C", d1 | l1)
return bin.pack("C", d1 | l1) .. d2 .. l2
return string.pack("B", d1 | l1) .. d2 .. l2
end
--- Parse the variable-length option delta and length field.
@@ -1613,7 +1584,7 @@ COAP.header.options.delta_length.parse = function(buf, pos)
assert(type(pos) == "number")
assert(pos <= #buf)
local pos, delta_and_length = bin.unpack("C", buf, pos)
local delta_and_length, pos = string.unpack("B", buf, pos)
if not pos then
return false, nil, nil, delta_and_length
end
@@ -1636,20 +1607,20 @@ COAP.header.options.delta_length.parse = function(buf, pos)
if delta == 13 then
required_bytes = required_bytes + 1
dspec = "C"
dspec = "B"
elseif delta == 14 then
required_bytes = required_bytes + 2
delta = 269
dspec = ">S"
dspec = ">I2"
end
if length == 13 then
required_bytes = required_bytes + 1
lspec = "C"
lspec = "B"
elseif length == 14 then
required_bytes = required_bytes + 2
length = 269
lspec = ">S"
lspec = ">I2"
end
if pos + required_bytes - 1 > #buf then
@@ -1659,7 +1630,7 @@ COAP.header.options.delta_length.parse = function(buf, pos)
-- Extract the remaining bytes of each field.
if dspec then
local num
pos, num = bin.unpack(dspec, buf, pos)
num, pos = string.unpack(dspec, buf, pos)
if not pos then
return false, nil, nil, num
end
@@ -1668,7 +1639,7 @@ COAP.header.options.delta_length.parse = function(buf, pos)
if lspec then
local num
pos, num = bin.unpack(lspec, buf, pos)
num, pos = string.unpack(lspec, buf, pos)
if not pos then
return false, nil, nil, num
end
@@ -2426,7 +2397,7 @@ local tests = {
{
{["name"] = "etag", ["value"] = "ETAGETAG"},
},
bin.pack("CA", 0x48, "ETAGETAG")
"\x48ETAGETAG"
},
{
-- Before
@@ -2450,7 +2421,7 @@ local tests = {
{["name"] = "uri_path", ["value"] = "foo"},
{["name"] = "max_age", ["value"] = 0},
},
bin.pack("CAC", 0xB3, "foo", 0x30)
"\xB3foo\x30"
},
{
-- Before
@@ -2463,7 +2434,7 @@ local tests = {
{["name"] = "uri_path", ["value"] = ".well-known"},
{["name"] = "uri_path", ["value"] = "core"},
},
bin.pack("CACA", 0xBB, ".well-known", 0x04, "core")
"\xBB.well-known\x04core"
},
{
-- Before
@@ -2482,14 +2453,7 @@ local tests = {
{["name"] = "uri_path", ["value"] = "core"},
{["name"] = "max_age", ["value"] = 0},
},
bin.pack(
"CACCACAC",
0x48, "ETAGETAG", -- ID: 4, Delta: 4
0x10, -- ID: 5, Delta: 1
0x6B, ".well-known", -- ID: 11, Delta: 6
0x04, "core", -- ID: 11, Delta: 0
0x30 -- ID: 14, Delta: 3
)
"\x48ETAGETAG\x10\x6B.well-known\x04core\x30"
},
}
@@ -2537,15 +2501,7 @@ local tests = {
{["name"] = "uri_path", ["value"] = "core"},
},
},
bin.pack(
"CC>SACACA",
0x48,
0x01,
0x1234,
"nmapcoap",
0xBB, ".well-known",
0x04, "core"
)
"\x48\x01\x12\x34nmapcoap\xBB.well-known\x04core"
},
}

View File

@@ -14,7 +14,6 @@
-- o Added possibility to override transaction id
-- o Added WPAD action
local bin = require "bin"
local datetime = require "datetime"
local ipOps = require "ipOps"
local math = require "math"
@@ -67,7 +66,7 @@ local function read_ip(data, pos, length)
local results = {}
for i=1, length, 4 do
local value
pos, value = bin.unpack(">I", data, pos)
value, pos = string.unpack(">I4", data, pos)
table.insert(results, ipOps.fromdword(value))
end
@@ -75,7 +74,7 @@ local function read_ip(data, pos, length)
end
else
local value
pos, value = bin.unpack(">I", data, pos)
value, pos = string.unpack(">I4", data, pos)
return pos, ipOps.fromdword(value)
end
@@ -89,7 +88,8 @@ end
--@return The new position (will always be pos + length, no matter what we think it should be)
--@return The value of the field, or nil if the field length was wrong.
local function read_string(data, pos, length)
return bin.unpack(string.format("A%d", length), data, pos)
local value, pos = string.unpack(("c%d"):format(length), data, pos)
return pos, value
end
---Read a single byte. Print an error if the length isn't 1.
@@ -105,7 +105,8 @@ local function read_1_byte(data, pos, length)
pos = pos + length
return pos, nil
end
return bin.unpack("C", data, pos)
local value, pos = string.unpack("B", data, pos)
return pos, value
end
---Read a message type. This is a single-byte value that's looked up in the <code>request_types_str</code>
@@ -163,7 +164,8 @@ local function read_2_bytes(data, pos, length)
pos = pos + length
return pos, nil
end
return bin.unpack(">S", data, pos)
local value, pos = string.unpack(">I2", data, pos)
return pos, value
end
@@ -185,7 +187,7 @@ local function read_2_bytes_list(data, pos, length)
local results = {}
for i=1, length, 2 do
local value
pos, value = bin.unpack(">S", data, pos)
value, pos = string.unpack(">I2", data, pos)
table.insert(results, value)
end
@@ -207,7 +209,8 @@ local function read_4_bytes(data, pos, length)
pos = pos + length
return pos, nil
end
return bin.unpack(">I", data, pos)
local value, pos = string.unpack(">I4", data, pos)
return pos, value
end
---Read a 4-byte unsigned little endian value, and interpret it as a time offset value. Print an
@@ -225,7 +228,7 @@ local function read_time(data, pos, length)
pos = pos + length
return pos, nil
end
pos, result = bin.unpack(">I", data, pos)
result, pos = string.unpack(">I4", data, pos)
return pos, datetime.format_time(result)
end
@@ -426,34 +429,32 @@ function dhcp_build(request_type, ip_address, mac_address, options, request_opti
end
-- Header
packet = packet .. bin.pack(">CCCC", overrides['op'] or 1, overrides['htype'] or 1, overrides['hlen'] or 6, overrides['hops'] or 0) -- BOOTREQUEST, 10mb ethernet, 6 bytes long, 0 hops
packet = packet .. string.pack(">BBBB", overrides['op'] or 1, overrides['htype'] or 1, overrides['hlen'] or 6, overrides['hops'] or 0) -- BOOTREQUEST, 10mb ethernet, 6 bytes long, 0 hops
packet = packet .. ( overrides['xid'] or transaction_id ) -- Transaction ID =
packet = packet .. bin.pack(">SS", overrides['secs'] or 0, overrides['flags'] or 0x0000) -- Secs, flags
packet = packet .. string.pack(">I2I2", overrides['secs'] or 0, overrides['flags'] or 0x0000) -- Secs, flags
packet = packet .. ip_address -- Client address
packet = packet .. bin.pack("<I", overrides['yiaddr'] or 0) -- yiaddr
packet = packet .. bin.pack("<I", overrides['siaddr'] or 0) -- siaddr
packet = packet .. bin.pack("<I", overrides['giaddr'] or 0) -- giaddr
packet = packet .. string.pack("<I4I4I4", overrides['yiaddr'] or 0,
overrides['siaddr'] or 0,
overrides['giaddr'] or 0)
packet = packet .. mac_address .. string.rep('\0', 16 - #mac_address) -- chaddr (MAC address)
packet = packet .. (overrides['sname'] or string.rep('\0', 64)) -- sname
packet = packet .. (overrides['file'] or string.rep('\0', 128)) -- file
packet = packet .. bin.pack(">I", overrides['cookie'] or 0x63825363) -- Magic cookie
packet = packet .. string.pack(">I4", overrides['cookie'] or 0x63825363) -- Magic cookie
-- Options
packet = packet .. bin.pack(">CCC", 0x35, 1, request_type) -- Request type
packet = packet .. string.pack(">BBB", 0x35, 1, request_type) -- Request type
for _, option in ipairs(options or {}) do
packet = packet .. bin.pack(">C", option.number)
if ( "string" == option.type ) then
packet = packet .. bin.pack("p", option.value)
elseif( "ip" == option.type ) then
packet = packet .. bin.pack(">CI", 4, option.value)
packet = packet .. string.pack(">B", option.number)
if ( "string" == option.type or "ip" == option.type ) then
packet = packet .. string.pack("s1", option.value)
end
end
packet = packet .. bin.pack(">CCA", 0x37, #request_options, request_options) -- Request options
packet = packet .. bin.pack(">CCI", 0x33, 4, lease_time or 1) -- Lease time
packet = packet .. string.pack(">Bs1", 0x37, request_options) -- Request options
packet = packet .. string.pack(">BBI4", 0x33, 4, lease_time or 1) -- Lease time
packet = packet .. bin.pack(">C", 0xFF) -- Termination
packet = packet .. "\xFF" -- Termination
return true, strbuf.dump(packet)
end
@@ -473,26 +474,26 @@ function dhcp_parse(data, transaction_id)
local result = {}
-- Receive the first bit and make sure we got the correct operation back
pos, result['op'], result['htype'], result['hlen'], result['hops'] = bin.unpack(">CCCC", data, pos)
result.op, result.htype, result.hlen, result.hops, pos = string.unpack(">BBBB", data, pos)
if(result['op'] ~= 2) then
return false, string.format("DHCP server returned invalid reply ('op' wasn't BOOTREPLY (it was 0x%02x))", result['op'])
end
-- Confirm the transaction id
pos, result['xid'] = bin.unpack("A4", data, pos)
result.xid, pos = string.unpack("c4", data, pos)
if(result['xid'] ~= transaction_id) then
return false, string.format("DHCP server returned invalid reply (transaction id didn't match (%s != %s))", result['xid'], transaction_id)
end
-- Unpack the secs, flags, addresses, sname, and file
pos, result['secs'], result['flags'] = bin.unpack(">SS", data, pos)
pos, result['ciaddr'] = bin.unpack(">I", data, pos)
pos, result['yiaddr'] = bin.unpack(">I", data, pos)
pos, result['siaddr'] = bin.unpack(">I", data, pos)
pos, result['giaddr'] = bin.unpack(">I", data, pos)
pos, result['chaddr'] = bin.unpack("A16", data, pos)
pos, result['sname'] = bin.unpack("A64", data, pos)
pos, result['file'] = bin.unpack("A128", data, pos)
result.secs, result.flags,
result.ciaddr,
result.yiaddr,
result.siaddr,
result.giaddr,
result.chaddr,
result.sname,
result.file, pos = string.unpack(">I2I2 I4I4I4I4 c16 c64 c128", data, pos)
-- Convert the addresses to strings
result['ciaddr_str'] = ipOps.fromdword(result['ciaddr'])
@@ -501,7 +502,7 @@ function dhcp_parse(data, transaction_id)
result['giaddr_str'] = ipOps.fromdword(result['giaddr'])
-- Confirm the cookie
pos, result['cookie'] = bin.unpack(">I", data, pos)
result.cookie, pos = string.unpack(">I4", data, pos)
if(result['cookie'] ~= 0x63825363) then
return false, "DHCP server returned invalid reply (the magic cookie was invalid)"
end
@@ -515,7 +516,7 @@ function dhcp_parse(data, transaction_id)
end
local option, length
pos, option, length = bin.unpack(">CC", data, pos)
option, length, pos = string.unpack(">BB", data, pos)
-- Check for termination condition
if(option == 0xFF) then
@@ -611,10 +612,10 @@ end
--@return The parsed response, as a table.
function make_request(target, request_type, ip_address, mac_address, options, request_options, overrides, lease_time)
-- A unique id that identifies this particular session (and lets us filter out what we don't want to see)
local transaction_id = overrides and overrides['xid'] or bin.pack("<I", math.random(0, 0x7FFFFFFF))
local transaction_id = overrides and overrides['xid'] or string.pack("<I4", math.random(0, 0x7FFFFFFF))
-- Generate the packet
local status, packet = dhcp_build(request_type, bin.pack(">I", ipOps.todword(ip_address)), mac_address, options, request_options, overrides, lease_time, transaction_id)
local status, packet = dhcp_build(request_type, ipOps.ip_to_str(ip_address), mac_address, options, request_options, overrides, lease_time, transaction_id)
if(not(status)) then
stdnse.debug1("dhcp: Couldn't build packet: " .. packet)
return false, "Couldn't build packet: " .. packet

View File

@@ -920,7 +920,8 @@ MQTT.utf8_parse = function(buf, pos)
return false, ("Buffer at position %d has no space for a %d-byte UTF-8 string."):format(pos, str_length)
end
return string.unpack(">s2", buf, pos)
local value, pos = string.unpack(">s2", buf, pos)
return pos, value
end
--- Prefix the body of an MQTT packet with a fixed header.

View File

@@ -7,7 +7,6 @@
--
-- @author Patrik Karlsson <patrik@cqure.net>
local bin = require "bin"
local nmap = require "nmap"
local stdnse = require "stdnse"
local string = require "string"
@@ -91,7 +90,7 @@ local function decodeHeader( data, pos )
local response = {}
local pos, tmp = pos or 1, 0
pos, tmp = bin.unpack( "<I", data, pos )
tmp, pos = string.unpack( "<I4", data, pos )
response.len = ( tmp & 255 )
response.number = ( tmp >> 24 )
@@ -121,42 +120,38 @@ function receiveGreeting( socket )
end
local is_error
pos, is_error = bin.unpack( "C", data, pos )
is_error, pos = string.unpack("B", data, pos)
if ( is_error == 0xff ) then
pos, response.errorcode = bin.unpack( "<S", data, pos )
pos, response.errormsg = bin.unpack("A" .. (#data - pos + 1), data, pos )
response.errorcode, pos = string.unpack( "<I2", data, pos )
response.errormsg = data:sub(pos)
return false, response.errormsg
end
response.proto = is_error
pos, response.version = bin.unpack( "z", data, pos )
pos, response.threadid = bin.unpack( "<I", data, pos )
response.version, response.threadid, pos = string.unpack( "<zI4", data, pos )
if response.proto == 10 then
pos, response.salt, _ = bin.unpack( "A8C", data, pos )
pos, response.capabilities = bin.unpack( "<S", data, pos )
if pos < #data then
pos, response.charset = bin.unpack( "C", data, pos )
pos, response.status = bin.unpack( "<S", data, pos )
pos, response.extcapabilities = bin.unpack( "<S", data, pos) -- capabilities, upper 2 bytes
response.salt, response.capabilities, pos = string.unpack("<c8xI2", data, pos)
local auth_plugin_len
pos, auth_plugin_len = bin.unpack("C", data, pos)
pos, tmp = bin.unpack( "A10", data, pos )
if pos < #data then
response.charset, response.status,
response.extcapabilities, -- capabilities, upper 2 bytes
auth_plugin_len, tmp, pos = string.unpack( "<BI2 I2 Bc10", data, pos )
if tmp ~= "\0\0\0\0\0\0\0\0\0\0" then
stdnse.debug2("reserved bytes are not nulls")
end
if response.capabilities & Capabilities.Support41Auth > 0 then
pos, tmp, _ = bin.unpack("A" .. (math.max(13, auth_plugin_len - 8) - 1) .. "x", data, pos)
tmp, pos = string.unpack("c" .. (math.max(13, auth_plugin_len - 8) - 1) .. "x", data, pos)
response.salt = response.salt .. tmp
end
if response.extcapabilities & ExtCapabilities.SupportsAuthPlugins > 0 then
response.auth_plugin_name = bin.unpack("z", data, pos)
response.auth_plugin_name = string.unpack("z", data, pos)
end
end
elseif response.proto == 9 then
pos, response.auth_plugin_data = bin.unpack( "z", data, pos )
response.auth_plugin_data, pos = string.unpack( "z", data, pos )
else
stdnse.debug2("Unknown MySQL protocol version: %d", response.proto)
end
@@ -189,8 +184,8 @@ local function createLoginHash(pass, salt)
hash_stage3 = openssl.sha1( salt .. hash_stage2 )
for pos=1, hash_stage1:len() do
_, b1 = bin.unpack( "C", hash_stage1, pos )
_, b2 = bin.unpack( "C", hash_stage3, pos )
b1 = string.unpack( "B", hash_stage1, pos )
b2 = string.unpack( "B", hash_stage3, pos )
reply[pos] = string.char( b2 ~ b1 )
end
@@ -244,7 +239,7 @@ function loginRequest( socket, params, username, password, salt )
hash = createLoginHash( password, salt )
end
local packet = bin.pack( "<SSICAzp",
local packet = string.pack( "<I2I2I4B c23 zs1",
clicap,
extcapabilities,
MAXPACKET,
@@ -256,7 +251,7 @@ function loginRequest( socket, params, username, password, salt )
local tmp = packet:len() + ( packetno << 24 )
packet = bin.pack( "<I", tmp ) .. packet
packet = string.pack( "<I4", tmp ) .. packet
try( socket:send(packet) )
packet = try( socket:receive_bytes(HEADER_SIZE) )
@@ -270,26 +265,24 @@ function loginRequest( socket, params, username, password, salt )
local is_error
pos, is_error = bin.unpack( "C", packet, pos )
is_error, pos = string.unpack( "B", packet, pos )
if is_error > 0 then
pos, response.errorcode = bin.unpack( "<S", packet, pos )
local has_sqlstate
pos, has_sqlstate = bin.unpack( "C", packet, pos )
response.errorcode, has_sqlstate, pos = string.unpack( "<I2B", packet, pos )
if has_sqlstate == 35 then
pos, response.sqlstate = bin.unpack( "A5", packet, pos )
response.sqlstate, pos = string.unpack( "c5", packet, pos )
end
pos, response.errormessage = bin.unpack( "z", packet, pos )
response.errormessage, pos = string.unpack( "z", packet, pos )
return false, response.errormessage
else
response.errorcode = 0
pos, response.affectedrows = bin.unpack( "C", packet, pos )
pos, response.serverstatus = bin.unpack( "<S", packet, pos )
pos, response.warnings = bin.unpack( "<S", packet, pos )
response.affectedrows,
response.serverstatus,
response.warnings, pos = string.unpack( "<BI2I2", packet, pos )
end
return true, response
@@ -309,36 +302,19 @@ end
-- <code>length</code> and <code>type</code>
function decodeField( data, pos )
local header, len
local def, _
local _
local field = {}
pos, len = bin.unpack( "C", data, pos )
pos, field.catalog = bin.unpack( "A" .. len, data, pos )
pos, len = bin.unpack( "C", data, pos )
pos, field.database = bin.unpack( "A" .. len, data, pos )
pos, len = bin.unpack( "C", data, pos )
pos, field.table = bin.unpack( "A" .. len, data, pos )
pos, len = bin.unpack( "C", data, pos )
pos, field.orig_table = bin.unpack( "A" .. len, data, pos )
pos, len = bin.unpack( "C", data, pos )
pos, field.name = bin.unpack( "A" .. len, data, pos )
pos, len = bin.unpack( "C", data, pos )
pos, field.orig_name = bin.unpack( "A" .. len, data, pos )
-- should be 0x0C
pos, _ = bin.unpack( "C", data, pos )
-- charset, in my case 0x0800
pos, _ = bin.unpack( "<S", data, pos )
pos, field.length = bin.unpack( "<I", data, pos )
pos, field.type = bin.unpack( "A6", data, pos )
field.catalog,
field.database,
field.table,
field.orig_table,
field.name,
field.orig_name,
_, -- should be 0x0C
_, -- charset, in my case 0x0800
field.length,
field.type, pos = string.unpack( "<s1s1s1s1s1s1BI2I4c6", data, pos )
return pos, field
@@ -403,7 +379,7 @@ function decodeQueryResponse( socket )
end
if header.len > 0 then
local _, b = bin.unpack("C", data, pos )
local b = string.unpack("B", data, pos )
-- Is this the EOF packet?
if b == EOF_MARKER then
@@ -465,13 +441,11 @@ end
-- @return number containing the amount of fields
function decodeResultSetHeader( data )
local _, fields
if data:len() ~= HEADER_SIZE + 1 then
return false, "Result set header was incorrect"
end
_, fields = bin.unpack( "C", data, HEADER_SIZE + 1 )
local fields = string.unpack( "B", data, HEADER_SIZE + 1 )
return true, fields
end
@@ -486,16 +460,16 @@ end
-- @return rows table containing row tables
function decodeDataPackets( data, count )
local len, pos = 0, 1, 1
local header, row, rows = {}, {}, {}
local pos = 1
local rows = {}
while pos < data:len() do
row = {}
while pos <= data:len() do
local row = {}
local header
pos, header = decodeHeader( data, pos )
for i=1, count do
pos, len = bin.unpack("C", data, pos )
pos, row[i] = bin.unpack("A" .. len, data, pos)
row[i], pos = string.unpack("s1", data, pos)
end
table.insert( rows, row )
@@ -521,7 +495,7 @@ function sqlQuery( socket, query )
local packet, packet_len, pos, header
local status, fields, field_count, rows, rs
packet = bin.pack("<ICA", querylen, Command.Query, query )
packet = string.pack("<I4B", querylen, Command.Query) .. query
--
-- http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Result_Set_Header_Packet