You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.1 KiB
Lua

local bit = require("bit")
local cbson = require("cbson")
local md5 = ngx and ngx.md5 or function(str) return require("crypto").digest("md5", str) end
local hmac_sha1 = ngx and ngx.hmac_sha1 or function(str, key) return require("crypto").hmac.digest("sha1", key, str, true) end
local hasposix , posix = pcall(require, "posix")
local machineid
if hasposix then
machineid = posix.uname("%n")
else
machineid = assert(io.popen("uname -n")):read("*l")
end
machineid = md5(machineid):sub(1, 6)
local function uint_to_hex(num, len, be)
local len = len or 4
local be = be or 0
local num = cbson.uint(num)
local raw = cbson.uint_to_raw(num, len, be)
local out = ''
for i = 1, #raw do
out = out .. string.format("%02x", raw:byte(i,i))
end
return out
end
local counter = 0
if not ngx then
math.randomseed(os.time())
counter = math.random(100)
else
local resty_random = require "resty.random"
local resty_string = require "resty.string"
local strong_random = resty_random.bytes(4,true)
while strong_random == nil do
strong_random = resty_random.bytes(4,true)
end
counter = tonumber(resty_string.to_hex(strong_random), 16)
end
local function generate_oid()
local pid = ngx and ngx.worker.pid() or nil
if not pid then
if hasposix then
pid = posix.getpid("pid")
else
pid = 1
end
end
pid = uint_to_hex(pid,2)
counter = counter + 1
local time = os.time()
return uint_to_hex(time, 4, 1) .. machineid .. pid .. uint_to_hex(counter, 4, 1):sub(3,8)
end
local function print_r(t, indent)
local indent=indent or ''
if #indent > 5 then return end
if type(t) ~= "table" then
print(t)
return
end
for key,value in pairs(t) do
io.write(indent,'[',tostring(key),']')
if type(value)=="table" then io.write(':\n') print_r(value,indent..'\t')
else io.write(' = ',tostring(value),'\n') end
end
end
local function parse_uri(url)
-- initialize default parameters
local parsed = {}
-- empty url is parsed to nil
if not url or url == "" then return nil, "invalid url" end
-- remove whitespace
url = string.gsub(url, "%s", "")
-- get fragment
url = string.gsub(url, "#(.*)$", function(f)
parsed.fragment = f
return ""
end)
-- get scheme
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
function(s) parsed.scheme = s; return "" end)
-- get authority
local location
url = string.gsub(url, "^//([^/]*)", function(n)
location = n
return ""
end)
-- get query stringing
url = string.gsub(url, "%?(.*)", function(q)
parsed.query_string = q
return ""
end)
-- get params
url = string.gsub(url, "%;(.*)", function(p)
parsed.params = p
return ""
end)
-- path is whatever was left
if url ~= "" then parsed.database = string.gsub(url,"^/([^/]*).*","%1") end
if not parsed.database or #parsed.database == 0 then parsed.database = "admin" end
if not location then return parsed end
location = string.gsub(location,"^([^@]*)@",
function(u) parsed.userinfo = u; return "" end)
parsed.hosts = {}
string.gsub(location, "([^,]+)", function(u)
local pr = { host = "localhost", port = 27017 }
u = string.gsub(u, ":([^:]*)$",
function(p) pr.port = p; return "" end)
if u ~= "" then pr.host = u end
table.insert(parsed.hosts, pr)
end)
if #parsed.hosts == 0 then parsed.hosts = {{ host = "localhost", port = 27017 }} end
parsed.query = {}
if parsed.query_string then
string.gsub(parsed.query_string, "([^&]+)", function(u)
u = string.gsub(u, "([^=]*)=([^=]*)$",
function(k,v) parsed.query[k] = v; return "" end)
end)
end
local userinfo = parsed.userinfo
if not userinfo then return parsed end
userinfo = string.gsub(userinfo, ":([^:]*)$",
function(p) parsed.password = p; return "" end)
parsed.user = userinfo
return parsed
end
local function xor_bytestr( a, b )
local res = ""
for i=1,#a do
res = res .. string.char(bit.bxor(string.byte(a,i,i), string.byte(b, i, i)))
end
return res
end
local function xor_bytestr( a, b )
local res = ""
for i=1,#a do
res = res .. string.char(bit.bxor(string.byte(a,i,i), string.byte(b, i, i)))
end
return res
end
-- A simple implementation of PBKDF2_HMAC_SHA1
local function pbkdf2_hmac_sha1( pbkdf2_key, iterations, salt, len )
local u1 = hmac_sha1(pbkdf2_key, salt .. "\0\0\0\1")
local ui = u1
for i=1,iterations-1 do
u1 = hmac_sha1(pbkdf2_key, u1)
ui = xor_bytestr(ui, u1)
end
if #ui < len then
for i=1,len-(#ui) do
ui = string.char(0) .. ui
end
end
return ui
end
-- not full implementation, but oh well
local function saslprep(username)
return string.gsub(string.gsub(username, '=', '=3D'), ',' , '=2C')
end
local function pass_digest ( username , password )
return md5(username .. ":mongo:" .. password)
end
return {
parse_uri = parse_uri;
print_r = print_r;
pbkdf2_hmac_sha1 = pbkdf2_hmac_sha1;
saslprep = saslprep;
pass_digest = pass_digest;
xor_bytestr = xor_bytestr;
generate_oid = generate_oid;
}