1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
---
-- Debugging functions for Nmap scripts.
--
-- This module contains various handy functions for debugging. These should
-- never be used for actual results, only during testing.
--
-- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html
local coroutine = require "coroutine"
local debug = require "debug"
local io = require "io"
local math = require "math"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
_ENV = stdnse.module("nsedebug", stdnse.seeall)
local EMPTY = {}; -- Empty constant table
---
-- Converts an arbitrary data type into a string. Will recursively convert
-- tables. This can be very useful for debugging.
--
--@param data The data to convert.
--@param indent (optional) The number of times to indent the line. Default
-- is 0.
--@return A string representation of a data, will be one or more full lines.
function tostr(data, indent)
local str
if(indent == nil) then
indent = 0
end
-- Check the type
local typ = type(data)
if(typ == "nil" or typ == "number" or typ == "boolean" or typ == "function" or typ == "thread" or typ == "userdata") then
str = {(" "):rep(indent), tostring(data), "\n"}
elseif(type(data) == "string") then
str = {(" "):rep(indent), string.format("%q", data), "\n"}
elseif(type(data) == "table") then
local i, v
str = {}
for i, v in pairs(data) do
-- Check for a table in a table
str[#str+1] = (" "):rep(indent)
str[#str+1] = tostring(i)
if(type(v) == "table") then
str[#str+1] = ":\n"
str[#str+1] = tostr(v, indent + 2)
else
str[#str+1] = ": "
str[#str+1] = tostr(v, 0)
end
end
else
stdnse.debug1("Error: unknown data type: %s", type(data))
end
return table.concat(str)
end
--- Print out a string in hex, for debugging.
--
--@param str The data to print in hex.
function print_hex(str)
-- Prints out the full lines
for line=1, #str/16, 1 do
io.write(string.format("%08x ", (line - 1) * 16))
-- Loop through the string, printing the hex
for char=1, 16, 1 do
local ch = string.byte(str, ((line - 1) * 16) + char)
io.write(string.format("%02x ", ch))
end
io.write(" ")
-- Loop through the string again, this time the ascii
for char=1, 16, 1 do
local ch = string.byte(str, ((line - 1) * 16) + char)
if ch < 0x20 or ch > 0x7f then
ch = string.byte(".", 1)
end
io.write(string.format("%c", ch))
end
io.write("\n")
end
-- Prints out the final, partial line
if (#str % 16 ~= 0) then
local line = math.floor((#str/16)) + 1
io.write(string.format("%08x ", (line - 1) * 16))
for char=1, #str % 16, 1 do
local ch = string.byte(str, ((line - 1) * 16) + char)
io.write(string.format("%02x ", ch))
end
io.write(string.rep(" ", 16 - (#str % 16)));
io.write(" ")
for char=1, #str % 16, 1 do
local ch = string.byte(str, ((line - 1) * 16) + char)
if ch < 0x20 or ch > 0x7f then
ch = string.byte(".", 1)
end
io.write(string.format("%c", ch))
end
io.write("\n")
end
-- Print out the length
io.write(string.format(" Length: %d [0x%x]\n", #str, #str))
end
---Print out a stacktrace. The stacktrace will naturally include this function call.
function print_stack()
local thread = coroutine.running()
local trace = debug.traceback(thread);
if trace ~= "stack traceback:" then
print(thread, "\n", trace, "\n");
end
end
return _ENV;
|