diff --git a/nselib/bin.lua b/nselib/bin.lua
index 41320beb5..ac8290610 100644
--- a/nselib/bin.lua
+++ b/nselib/bin.lua
@@ -78,6 +78,10 @@ local function clamp (args, i, j, mask)
end
end
+local function _fromhex (s)
+ return char(tonumber(s, 16))
+end
+
--- Returns a binary packed string.
--
-- The format string describes how the parameters (p1,
@@ -107,7 +111,7 @@ function _ENV.pack (format, ...)
assert(n > 0, "n cannot be 0") -- original bin library allowed this, it doesn't make sense
local new = "=" -- !! in original bin library, hex strings are always native
for j = i, i+n-1 do
- args[j] = tostring(args[j]):gsub("%s*(%S%S?)%s*", function (s) return char(tonumber(s, 16)) end)
+ args[j] = tostring(args[j]):gsub("%s*(%S%S?)%s*", _fromhex)
new = new .. ("c%d"):format(#args[j])
end
new = new .. endianness -- restore old endianness
@@ -208,15 +212,24 @@ do
assert(_ENV.pack(""00:23:ae:5d:3b:10") to
-- a raw six-byte long.
-- @param str MAC address string.
@@ -453,9 +456,7 @@ function mactobin(str)
if not str then
return nil, "MAC was not specified."
end
- return (str:gsub("(%x%x)[^%x]?", function (x)
- return string.char(tonumber(x, 16))
- end))
+ return (str:gsub("(%x%x)[^%x]?", _hex_str))
end
--- Generate the link-local IPv6 address from the MAC address.
diff --git a/nselib/stringaux.lua b/nselib/stringaux.lua
index 797473f14..96417b19c 100644
--- a/nselib/stringaux.lua
+++ b/nselib/stringaux.lua
@@ -70,6 +70,9 @@ end
-- This pattern must match the percent sign '%' since it is used in
-- escaping.
local FILESYSTEM_UNSAFE = "[^a-zA-Z0-9._-]"
+local function _escape_helper (c)
+ return format("%%%02x", byte(c))
+end
---
-- Escape a string to remove bytes and strings that may have meaning to
-- a filesystem, such as slashes.
@@ -97,9 +100,7 @@ function filename_escape(s)
elseif s == ".." then
return "%2e%2e"
else
- return (gsub(s, FILESYSTEM_UNSAFE, function (c)
- return format("%%%02x", byte(c))
- end))
+ return (gsub(s, FILESYSTEM_UNSAFE, _escape_helper))
end
end
diff --git a/nselib/url.lua b/nselib/url.lua
index 241753842..737a1ea29 100644
--- a/nselib/url.lua
+++ b/nselib/url.lua
@@ -57,12 +57,17 @@ local function make_set(t)
return s
end
+local function hex_esc (c)
+ return string.format("%%%02x", string.byte(c))
+end
+
-- these are allowed within a path segment, along with alphanum
-- other characters must be escaped
local segment_set = make_set {
"-", "_", ".", "!", "~", "*", "'", "(",
")", ":", "@", "&", "=", "+", "$", ",",
}
+setmetatable(segment_set, { __index = hex_esc })
---
-- Protects a path segment, to prevent it from interfering with the
@@ -70,10 +75,7 @@ local segment_set = make_set {
-- @param s Binary string to be encoded.
-- @return Escaped representation of string.
local function protect_segment(s)
- return string.gsub(s, "([^A-Za-z0-9_.~-])", function (c)
- if segment_set[c] then return c
- else return string.format("%%%02x", string.byte(c)) end
- end)
+ return string.gsub(s, "([^A-Za-z0-9_.~-])", segment_set)
end
---
@@ -115,25 +117,26 @@ end
-- @return Escaped representation of string.
-----------------------------------------------------------------------------
function escape(s)
- local ret = string.gsub(s, "([^A-Za-z0-9_.~-])", function(c)
- return string.format("%%%02x", string.byte(c))
- end)
- return ret
+ return (string.gsub(s, "([^A-Za-z0-9_.~-])", hex_esc))
end
+local function hex_unesc (hex)
+ return string.char(base.tonumber(hex, 16))
+end
+
---
-- Decodes an escaped hexadecimal string.
-- @param s Hexadecimal-encoded string.
-- @return Decoded string.
-----------------------------------------------------------------------------
function unescape(s)
- local ret = string.gsub(s, "%%(%x%x)", function(hex)
- return string.char(base.tonumber(hex, 16))
- end)
- return ret
+ return (string.gsub(s, "%%(%x%x)", hex_unesc))
end
+local function normalize_escape (s)
+ return escape(unescape(s))
+end
---
-- Parses a URL and returns a table with all its parts according to RFC 3986.
@@ -171,14 +174,7 @@ function parse(url, default)
-- remove whitespace
-- url = string.gsub(url, "%s", "")
-- Decode unreserved characters
- url = string.gsub(url, "%%(%x%x)", function(hex)
- local char = string.char(base.tonumber(hex, 16))
- if string.match(char, "[a-zA-Z0-9._~-]") then
- return char
- end
- -- Hex encodings that are not unreserved must be preserved.
- return nil
- end)
+ url = string.gsub(url, "%%%x%x", normalize_escape)
-- get fragment
url = string.gsub(url, "#(.*)$", function(f)
parsed.fragment = f
@@ -353,6 +349,11 @@ function build_path(parsed, unsafe)
return table.concat(path)
end
+local entities = {
+ ["amp"] = "&",
+ ["lt"] = "<",
+ ["gt"] = ">"
+}
---
-- Breaks a query string into name/value pairs.
--
@@ -369,9 +370,7 @@ function parse_query(query)
local parsed = {}
local pos = 1
- query = string.gsub(query, "&", "&")
- query = string.gsub(query, "<", "<")
- query = string.gsub(query, ">", ">")
+ query = string.gsub(query, "&([ampltg]+);", entities)
local function ginsert(qstr)
local pos = qstr:find("=", 1, true)