1194 lines
36 KiB
Lua
Executable File
1194 lines
36 KiB
Lua
Executable File
-- 打印表格
|
||
function PrintTable(t, indent, done)
|
||
--print ( string.format ('PrintTable type %s', type(keys)) )
|
||
if type(t) ~= "table" then return end
|
||
|
||
done = done or {}
|
||
done[t] = true
|
||
indent = indent or 0
|
||
|
||
local l = {}
|
||
for k, v in pairs(t) do
|
||
table.insert(l, k)
|
||
end
|
||
|
||
table.sort(l)
|
||
for k, v in ipairs(l) do
|
||
-- Ignore FDesc
|
||
if v ~= 'FDesc' then
|
||
local value = t[v]
|
||
|
||
if type(value) == "table" and not done[value] then
|
||
done [value] = true
|
||
print(string.rep ("\t", indent)..tostring(v)..":")
|
||
PrintTable (value, indent + 2, done)
|
||
elseif type(value) == "userdata" and not done[value] then
|
||
done [value] = true
|
||
print(string.rep ("\t", indent)..tostring(v)..": "..tostring(value))
|
||
PrintTable ((getmetatable(value) and getmetatable(value).__index) or getmetatable(value), indent + 2, done)
|
||
else
|
||
if t.FDesc and t.FDesc[v] then
|
||
print(string.rep ("\t", indent)..tostring(t.FDesc[v]))
|
||
else
|
||
print(string.rep ("\t", indent)..tostring(v)..": "..tostring(value))
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
|
||
-- ***** string 功能扩展开始 ******
|
||
|
||
-- RC4
|
||
-- http://en.wikipedia.org/wiki/RC4
|
||
function RC4encrypt(text,key)
|
||
|
||
function KSA(key)
|
||
local key_len = string.len(key)
|
||
local S = {}
|
||
local key_byte = {}
|
||
|
||
for i = 0, 255 do
|
||
S[i] = i
|
||
end
|
||
|
||
for i = 1, key_len do
|
||
key_byte[i-1] = string.byte(key, i, i)
|
||
end
|
||
|
||
local j = 0
|
||
for i = 0, 255 do
|
||
j = (j + S[i] + key_byte[i % key_len]) % 256
|
||
S[i], S[j] = S[j], S[i]
|
||
end
|
||
return S
|
||
end
|
||
|
||
function PRGA(S, text_len)
|
||
local i = 0
|
||
local j = 0
|
||
local K = {}
|
||
|
||
for n = 1, text_len do
|
||
|
||
i = (i + 1) % 256
|
||
j = (j + S[i]) % 256
|
||
|
||
S[i], S[j] = S[j], S[i]
|
||
K[n] = S[(S[i] + S[j]) % 256]
|
||
end
|
||
return K
|
||
end
|
||
|
||
function RC4(key, text)
|
||
local text_len = string.len(text)
|
||
|
||
local S = KSA(key)
|
||
local K = PRGA(S, text_len)
|
||
return output(K, text)
|
||
end
|
||
|
||
function output(S, text)
|
||
local len = string.len(text)
|
||
local c = nil
|
||
local res = {}
|
||
for i = 1, len do
|
||
c = string.byte(text, i, i)
|
||
res[i] = string.char(bxor(S[i], c))
|
||
end
|
||
return table.concat(res)
|
||
end
|
||
|
||
|
||
-------------------------------
|
||
-------------bit wise-----------
|
||
-------------------------------
|
||
|
||
local bit_op = {}
|
||
function bit_op.cond_and(r_a, r_b)
|
||
return (r_a + r_b == 2) and 1 or 0
|
||
end
|
||
|
||
function bit_op.cond_xor(r_a, r_b)
|
||
return (r_a + r_b == 1) and 1 or 0
|
||
end
|
||
|
||
function bit_op.cond_or(r_a, r_b)
|
||
return (r_a + r_b > 0) and 1 or 0
|
||
end
|
||
|
||
function bit_op.base(op_cond, a, b)
|
||
-- bit operation
|
||
if a < b then
|
||
a, b = b, a
|
||
end
|
||
local res = 0
|
||
local shift = 1
|
||
while a ~= 0 do
|
||
r_a = a % 2
|
||
r_b = b % 2
|
||
|
||
res = shift * bit_op[op_cond](r_a, r_b) + res
|
||
shift = shift * 2
|
||
|
||
a = math.modf(a / 2)
|
||
b = math.modf(b / 2)
|
||
end
|
||
return res
|
||
end
|
||
|
||
function bxor(a, b)
|
||
return bit_op.base('cond_xor', a, b)
|
||
end
|
||
|
||
function band(a, b)
|
||
return bit_op.base('cond_and', a, b)
|
||
end
|
||
|
||
function bor(a, b)
|
||
return bit_op.base('cond_or', a, b)
|
||
end
|
||
|
||
local textLen = string.len(text)
|
||
local schedule = KSA(key)
|
||
local k = PRGA(schedule, textLen)
|
||
return output(k, text)
|
||
end
|
||
|
||
|
||
--将字符串按格式转为16进制串
|
||
function string.tohex(str)
|
||
--判断输入类型
|
||
if (type(str)~="string") then
|
||
return nil,"string2hex invalid input type"
|
||
end
|
||
--拼接字符串
|
||
local index=1
|
||
local ret=""
|
||
for index=1,str:len() do
|
||
ret=ret..string.format("%02X",str:sub(index):byte())
|
||
end
|
||
|
||
return ret
|
||
end
|
||
|
||
--将16进制串转换为字符串
|
||
function string.fromhex(hex)
|
||
--判断输入类型
|
||
if (type(hex)~="string") then
|
||
return nil,"hex2string invalid input type"
|
||
end
|
||
--滤掉分隔符
|
||
hex=hex:gsub("[%s%p]",""):upper()
|
||
--检查内容是否合法
|
||
if(hex:find("[^0-9A-Fa-f]")~=nil) then
|
||
return nil,"hex2string invalid input content"
|
||
end
|
||
--检查字符串长度
|
||
if(hex:len()%2~=0) then
|
||
return nil,"hex2string invalid input lenth"
|
||
end
|
||
--拼接字符串
|
||
local index=1
|
||
local ret=""
|
||
for index=1,hex:len(),2 do
|
||
ret=ret..string.char(tonumber(hex:sub(index,index+1),16))
|
||
end
|
||
|
||
return ret
|
||
end
|
||
|
||
|
||
-- 字符串编码
|
||
function string.encode(text, key)
|
||
if text == nil or string.len(text) == 0 then return text end
|
||
return string.tohex(RC4encrypt(text, key))
|
||
end
|
||
|
||
-- 字符串解码
|
||
function string.decode(text, key)
|
||
if text == nil or string.len(text) == 0 then return text end
|
||
local s,e = string.fromhex(text)
|
||
if s == nil then
|
||
return s,e
|
||
else
|
||
return RC4encrypt(s, key)
|
||
end
|
||
end
|
||
|
||
-- 字符串分割,返回分割后子串数组
|
||
function string.split(input, delimiter)
|
||
input = tostring(input)
|
||
delimiter = tostring(delimiter)
|
||
if (delimiter=='') then return false end
|
||
local pos,arr = 0, {}
|
||
for st,sp in function() return string.find(input, delimiter, pos, true) end do
|
||
table.insert(arr, string.sub(input, pos, st - 1))
|
||
pos = sp + 1
|
||
end
|
||
table.insert(arr, string.sub(input, pos))
|
||
return arr
|
||
end
|
||
|
||
-- 字符串输出到文件
|
||
function string.tofile(str, path)
|
||
local out = io.open(path,"w")
|
||
if out then
|
||
out:write(str)
|
||
out:close()
|
||
end
|
||
end
|
||
|
||
-- 超长字符串格式化的方式输出到文件,使用方法 table.concat(t)
|
||
function string.tablefile(str, path)
|
||
local out = io.open(path,"w")
|
||
if out then
|
||
out:write('{\n')
|
||
local len = string.len(str)
|
||
local step = 255
|
||
local n = math.floor(len/step)
|
||
for i=0,n-1 do
|
||
out:write(' "'..string.sub(str, i*step+1, (i+1)*step)..'",\n')
|
||
end
|
||
out:write(' "'..string.sub(str, n*step+1, (n+1)*step)..'"\n}')
|
||
out:close()
|
||
end
|
||
end
|
||
|
||
-- 从kv文件中载入字符串,对应 string.savekvfile 的输出
|
||
function string.loadkvfile(path)
|
||
local t = LoadKeyValues(path)
|
||
if t == nil or t["1"] == nil then return nil end
|
||
|
||
local ret = t["1"]
|
||
local i = 2
|
||
while(t[tostring(i)] ~= nil)
|
||
do
|
||
ret = ret..t[tostring(i)]
|
||
i = i + 1
|
||
end
|
||
t = {}
|
||
return ret
|
||
end
|
||
|
||
--[[
|
||
以字符串内容写入文件,成功返回 true,失败返回 false
|
||
"mode 写入模式" 参数决定 io.writefile() 如何写入内容,可用的值如下:
|
||
- "w+" : 覆盖文件已有内容,如果文件不存在则创建新文件
|
||
- "a+" : 追加内容到文件尾部,如果文件不存在则创建文件
|
||
此外,还可以在 "写入模式" 参数最后追加字符 "b" ,表示以二进制方式写入数据,这样可以避免内容写入不完整。
|
||
- 默认值为 "w+b"
|
||
path 文件完全路径
|
||
content 要写入的内容
|
||
--]]
|
||
function string.writefile(content, path, mode)
|
||
mode = mode or "w+b"
|
||
local file = io.open(path, mode)
|
||
if file then
|
||
if file:write(content) == nil then return false end
|
||
io.close(file)
|
||
return true
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
-- ***** string 功能扩展结束 ******
|
||
|
||
|
||
|
||
-- ***** table 功能扩展开始 ******
|
||
|
||
-- table和string的互转
|
||
function table.tostring(t)
|
||
|
||
function ToStringEx(value)
|
||
if type(value)=='table' then
|
||
return table.tostring(value)
|
||
elseif type(value)=='string' then
|
||
return "\'"..value.."\'"
|
||
else
|
||
return tostring(value)
|
||
end
|
||
end
|
||
|
||
if t == nil then return "" end
|
||
local retstr= "{"
|
||
|
||
local i = 1
|
||
for key,value in pairs(t) do
|
||
local signal = ","
|
||
if i==1 then
|
||
signal = ""
|
||
end
|
||
|
||
if key == i then
|
||
retstr = retstr..signal..ToStringEx(value)
|
||
else
|
||
if type(key)=='number' or type(key) == 'string' then
|
||
retstr = retstr..signal..'['..ToStringEx(key).."]="..ToStringEx(value)
|
||
else
|
||
if type(key)=='userdata' then
|
||
retstr = retstr..signal.."*s"..table.tostring(getmetatable(key)).."*e".."="..ToStringEx(value)
|
||
else
|
||
retstr = retstr..signal..key.."="..ToStringEx(value)
|
||
end
|
||
end
|
||
end
|
||
|
||
i = i+1
|
||
end
|
||
|
||
retstr = retstr.."}"
|
||
return retstr
|
||
end
|
||
|
||
-- table和string的互转
|
||
function table.fromstring(str)
|
||
if str == nil or type(str) ~= "string" then
|
||
return
|
||
end
|
||
print(str)
|
||
-- loadstring在lua5.2中已经被弃用了
|
||
--return loadstring("return " .. str)()
|
||
return load("return " .. str)()
|
||
end
|
||
|
||
-- table按键名排序遍历,默认为升序
|
||
-- t为table, method为排序方式,asc或desc,func为遍历回调
|
||
-- lua中table是按照hash排列的,ipairs可以顺序遍历,但是不一定全部结果都能遍历出来,pairs能够全部遍历,但是遍历出来的结果是随机的,故需使用此方法
|
||
function table.sorteach(t, func, method)
|
||
local tableTemp = {}
|
||
for i in pairs(t) do
|
||
if i ~= nil then
|
||
table.insert(tableTemp, i)
|
||
end
|
||
end
|
||
if method == "desc" or method == "DESC" then
|
||
-- 降序
|
||
table.sort(tableTemp, function(a,b) return (a > b) end)
|
||
else
|
||
-- 升序
|
||
table.sort(tableTemp, function(a,b) return (a < b) end)
|
||
end
|
||
|
||
-- 遍历
|
||
for _, key in pairs(tableTemp) do
|
||
if type(func) == "function" then func(key, t[key]) end
|
||
end
|
||
tableTemp = {}
|
||
end
|
||
|
||
-- 深度复制表
|
||
function table.deepcopy(object)
|
||
local lookup_table = {}
|
||
local function _copy(object)
|
||
if type(object) ~= "table" then
|
||
return object
|
||
elseif lookup_table[object] then
|
||
return lookup_table[object]
|
||
end
|
||
local new_table = {}
|
||
lookup_table[object] = new_table
|
||
for index, value in pairs(object) do
|
||
new_table[_copy(index)] = _copy(value)
|
||
end
|
||
return setmetatable(new_table, getmetatable(object))
|
||
end
|
||
return _copy(object)
|
||
end
|
||
|
||
-- 判断键是否在table中
|
||
function table.haskey(t, key)
|
||
for k,v in pairs(t) do
|
||
if k == key then return true end
|
||
end
|
||
return false
|
||
end
|
||
|
||
-- 判断值是否在table中
|
||
function table.hasvalue(t, value)
|
||
for k,v in pairs(t) do
|
||
if v == value then return true end
|
||
end
|
||
return false
|
||
end
|
||
|
||
-- 从文件中载入数据,来源对应加密数据
|
||
function table.loadkv(path)
|
||
--return table.fromstring(string.decode(string.loadkvfile(path), ""))
|
||
return table.fromstring(string.decode(string.loadkvfile(path), SERVER_KEY))
|
||
end
|
||
|
||
-- 获取表中值元素的长度,不计nil
|
||
function table.count(t)
|
||
if type(t) ~= "table" then
|
||
return 0
|
||
end
|
||
local len = 0
|
||
for k,v in pairs(t) do
|
||
if v ~= nil then
|
||
len = len + 1
|
||
end
|
||
end
|
||
return len
|
||
end
|
||
|
||
-- 获取表按升序排列的第index元素对应的key(排除值为nil的元素),异常返回 nil
|
||
function table.getkey(t, index)
|
||
if type(t) ~= "table" or index == nil then
|
||
return nil
|
||
end
|
||
|
||
local tableTemp = {}
|
||
for k in pairs(t) do
|
||
if k ~= nil then
|
||
table.insert(tableTemp, k)
|
||
end
|
||
end
|
||
-- 降序
|
||
-- table.sort(tableTemp, function(a,b) return (a > b) end)
|
||
-- 升序
|
||
table.sort(tableTemp, function(a,b) return (a < b) end)
|
||
|
||
local key = nil
|
||
local count = 0
|
||
if index >= 1 or index <= #tableTemp then
|
||
key = tableTemp[index]
|
||
end
|
||
tableTemp = {}
|
||
return key
|
||
end
|
||
|
||
-- 按 key 顺序循环,f为可选参数,用于指定排序顺序
|
||
function pairsByKeys(t,f)
|
||
local a = {}
|
||
for n in pairs(t) do a[#a + 1] = n end
|
||
table.sort(a, f)
|
||
local i = 0
|
||
return function()
|
||
i = i + 1
|
||
return a[i], t[a[i]]
|
||
end
|
||
end
|
||
--~ 使用上述迭代器:
|
||
-- for k,v in pairsByKeys(inputTable) do
|
||
-- print(k, v)
|
||
-- end
|
||
|
||
-- 按 key 顺序获取指定key的序号
|
||
function table.keyindex(t, key)
|
||
local index = 0
|
||
for k,v in pairsByKeys(t) do
|
||
index = index + 1
|
||
if k == key then
|
||
return index
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
-- ***** table 功能扩展结束 ******
|
||
|
||
|
||
|
||
-- ***** MD5 功能开始 ******
|
||
|
||
-- 使用 md5.sumhexa(message)
|
||
md5 = {
|
||
_VERSION = "md5.lua 1.1.0",
|
||
_DESCRIPTION = "MD5 computation in Lua (5.1-3, LuaJIT)",
|
||
_URL = "https://github.com/kikito/md5.lua",
|
||
_LICENSE = [[
|
||
MIT LICENSE
|
||
|
||
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
|
||
|
||
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.
|
||
]]
|
||
}
|
||
|
||
-- bit lib implementions
|
||
|
||
local char, byte, format, rep, sub =
|
||
string.char, string.byte, string.format, string.rep, string.sub
|
||
local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift
|
||
|
||
local ok, bit = pcall(require, 'bit')
|
||
if ok then
|
||
bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift = bit.bor, bit.band, bit.bnot, bit.bxor, bit.rshift, bit.lshift
|
||
else
|
||
ok, bit = pcall(require, 'bit32')
|
||
|
||
if ok then
|
||
|
||
bit_not = bit.bnot
|
||
|
||
local tobit = function(n)
|
||
return n <= 0x7fffffff and n or -(bit_not(n) + 1)
|
||
end
|
||
|
||
local normalize = function(f)
|
||
return function(a,b) return tobit(f(tobit(a), tobit(b))) end
|
||
end
|
||
|
||
bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor)
|
||
bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift)
|
||
|
||
else
|
||
|
||
local function tbl2number(tbl)
|
||
local result = 0
|
||
local power = 1
|
||
for i = 1, #tbl do
|
||
result = result + tbl[i] * power
|
||
power = power * 2
|
||
end
|
||
return result
|
||
end
|
||
|
||
local function expand(t1, t2)
|
||
local big, small = t1, t2
|
||
if(#big < #small) then
|
||
big, small = small, big
|
||
end
|
||
-- expand small
|
||
for i = #small + 1, #big do
|
||
small[i] = 0
|
||
end
|
||
end
|
||
|
||
local to_bits -- needs to be declared before bit_not
|
||
|
||
bit_not = function(n)
|
||
local tbl = to_bits(n)
|
||
local size = math.max(#tbl, 32)
|
||
for i = 1, size do
|
||
if(tbl[i] == 1) then
|
||
tbl[i] = 0
|
||
else
|
||
tbl[i] = 1
|
||
end
|
||
end
|
||
return tbl2number(tbl)
|
||
end
|
||
|
||
-- defined as local above
|
||
to_bits = function (n)
|
||
if(n < 0) then
|
||
-- negative
|
||
return to_bits(bit_not(math.abs(n)) + 1)
|
||
end
|
||
-- to bits table
|
||
local tbl = {}
|
||
local cnt = 1
|
||
local last
|
||
while n > 0 do
|
||
last = n % 2
|
||
tbl[cnt] = last
|
||
n = (n-last)/2
|
||
cnt = cnt + 1
|
||
end
|
||
|
||
return tbl
|
||
end
|
||
|
||
bit_or = function(m, n)
|
||
local tbl_m = to_bits(m)
|
||
local tbl_n = to_bits(n)
|
||
expand(tbl_m, tbl_n)
|
||
|
||
local tbl = {}
|
||
for i = 1, #tbl_m do
|
||
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
|
||
tbl[i] = 0
|
||
else
|
||
tbl[i] = 1
|
||
end
|
||
end
|
||
|
||
return tbl2number(tbl)
|
||
end
|
||
|
||
bit_and = function(m, n)
|
||
local tbl_m = to_bits(m)
|
||
local tbl_n = to_bits(n)
|
||
expand(tbl_m, tbl_n)
|
||
|
||
local tbl = {}
|
||
for i = 1, #tbl_m do
|
||
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
|
||
tbl[i] = 0
|
||
else
|
||
tbl[i] = 1
|
||
end
|
||
end
|
||
|
||
return tbl2number(tbl)
|
||
end
|
||
|
||
bit_xor = function(m, n)
|
||
local tbl_m = to_bits(m)
|
||
local tbl_n = to_bits(n)
|
||
expand(tbl_m, tbl_n)
|
||
|
||
local tbl = {}
|
||
for i = 1, #tbl_m do
|
||
if(tbl_m[i] ~= tbl_n[i]) then
|
||
tbl[i] = 1
|
||
else
|
||
tbl[i] = 0
|
||
end
|
||
end
|
||
|
||
return tbl2number(tbl)
|
||
end
|
||
|
||
bit_rshift = function(n, bits)
|
||
local high_bit = 0
|
||
if(n < 0) then
|
||
-- negative
|
||
n = bit_not(math.abs(n)) + 1
|
||
high_bit = 0x80000000
|
||
end
|
||
|
||
local floor = math.floor
|
||
|
||
for i=1, bits do
|
||
n = n/2
|
||
n = bit_or(floor(n), high_bit)
|
||
end
|
||
return floor(n)
|
||
end
|
||
|
||
bit_lshift = function(n, bits)
|
||
if(n < 0) then
|
||
-- negative
|
||
n = bit_not(math.abs(n)) + 1
|
||
end
|
||
|
||
for i=1, bits do
|
||
n = n*2
|
||
end
|
||
return bit_and(n, 0xFFFFFFFF)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- convert little-endian 32-bit int to a 4-char string
|
||
local function lei2str(i)
|
||
local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
|
||
return f(0)..f(8)..f(16)..f(24)
|
||
end
|
||
|
||
-- convert raw string to big-endian int
|
||
local function str2bei(s)
|
||
local v=0
|
||
for i=1, #s do
|
||
v = v * 256 + byte(s, i)
|
||
end
|
||
return v
|
||
end
|
||
|
||
-- convert raw string to little-endian int
|
||
local function str2lei(s)
|
||
local v=0
|
||
for i = #s,1,-1 do
|
||
v = v*256 + byte(s, i)
|
||
end
|
||
return v
|
||
end
|
||
|
||
-- cut up a string in little-endian ints of given size
|
||
local function cut_le_str(s,...)
|
||
local o, r = 1, {}
|
||
local args = {...}
|
||
for i=1, #args do
|
||
table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
|
||
o = o + args[i]
|
||
end
|
||
return r
|
||
end
|
||
|
||
local swap = function (w) return str2bei(lei2str(w)) end
|
||
|
||
-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
|
||
-- 10/02/2001 jcw@equi4.com
|
||
|
||
local CONSTS = {
|
||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
|
||
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
|
||
}
|
||
|
||
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
|
||
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
|
||
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
|
||
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
|
||
local z=function (ff,a,b,c,d,x,s,ac)
|
||
a=bit_and(a+ff(b,c,d)+x+ac,0xFFFFFFFF)
|
||
-- be *very* careful that left shift does not cause rounding!
|
||
return bit_or(bit_lshift(bit_and(a,bit_rshift(0xFFFFFFFF,s)),s),bit_rshift(a,32-s))+b
|
||
end
|
||
|
||
local function transform(A,B,C,D,X)
|
||
local a,b,c,d=A,B,C,D
|
||
local t=CONSTS
|
||
|
||
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
|
||
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
|
||
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
|
||
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
|
||
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
|
||
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
|
||
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
|
||
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
|
||
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
|
||
d=z(f,d,a,b,c,X[ 9],12,t[10])
|
||
c=z(f,c,d,a,b,X[10],17,t[11])
|
||
b=z(f,b,c,d,a,X[11],22,t[12])
|
||
a=z(f,a,b,c,d,X[12], 7,t[13])
|
||
d=z(f,d,a,b,c,X[13],12,t[14])
|
||
c=z(f,c,d,a,b,X[14],17,t[15])
|
||
b=z(f,b,c,d,a,X[15],22,t[16])
|
||
|
||
a=z(g,a,b,c,d,X[ 1], 5,t[17])
|
||
d=z(g,d,a,b,c,X[ 6], 9,t[18])
|
||
c=z(g,c,d,a,b,X[11],14,t[19])
|
||
b=z(g,b,c,d,a,X[ 0],20,t[20])
|
||
a=z(g,a,b,c,d,X[ 5], 5,t[21])
|
||
d=z(g,d,a,b,c,X[10], 9,t[22])
|
||
c=z(g,c,d,a,b,X[15],14,t[23])
|
||
b=z(g,b,c,d,a,X[ 4],20,t[24])
|
||
a=z(g,a,b,c,d,X[ 9], 5,t[25])
|
||
d=z(g,d,a,b,c,X[14], 9,t[26])
|
||
c=z(g,c,d,a,b,X[ 3],14,t[27])
|
||
b=z(g,b,c,d,a,X[ 8],20,t[28])
|
||
a=z(g,a,b,c,d,X[13], 5,t[29])
|
||
d=z(g,d,a,b,c,X[ 2], 9,t[30])
|
||
c=z(g,c,d,a,b,X[ 7],14,t[31])
|
||
b=z(g,b,c,d,a,X[12],20,t[32])
|
||
|
||
a=z(h,a,b,c,d,X[ 5], 4,t[33])
|
||
d=z(h,d,a,b,c,X[ 8],11,t[34])
|
||
c=z(h,c,d,a,b,X[11],16,t[35])
|
||
b=z(h,b,c,d,a,X[14],23,t[36])
|
||
a=z(h,a,b,c,d,X[ 1], 4,t[37])
|
||
d=z(h,d,a,b,c,X[ 4],11,t[38])
|
||
c=z(h,c,d,a,b,X[ 7],16,t[39])
|
||
b=z(h,b,c,d,a,X[10],23,t[40])
|
||
a=z(h,a,b,c,d,X[13], 4,t[41])
|
||
d=z(h,d,a,b,c,X[ 0],11,t[42])
|
||
c=z(h,c,d,a,b,X[ 3],16,t[43])
|
||
b=z(h,b,c,d,a,X[ 6],23,t[44])
|
||
a=z(h,a,b,c,d,X[ 9], 4,t[45])
|
||
d=z(h,d,a,b,c,X[12],11,t[46])
|
||
c=z(h,c,d,a,b,X[15],16,t[47])
|
||
b=z(h,b,c,d,a,X[ 2],23,t[48])
|
||
|
||
a=z(i,a,b,c,d,X[ 0], 6,t[49])
|
||
d=z(i,d,a,b,c,X[ 7],10,t[50])
|
||
c=z(i,c,d,a,b,X[14],15,t[51])
|
||
b=z(i,b,c,d,a,X[ 5],21,t[52])
|
||
a=z(i,a,b,c,d,X[12], 6,t[53])
|
||
d=z(i,d,a,b,c,X[ 3],10,t[54])
|
||
c=z(i,c,d,a,b,X[10],15,t[55])
|
||
b=z(i,b,c,d,a,X[ 1],21,t[56])
|
||
a=z(i,a,b,c,d,X[ 8], 6,t[57])
|
||
d=z(i,d,a,b,c,X[15],10,t[58])
|
||
c=z(i,c,d,a,b,X[ 6],15,t[59])
|
||
b=z(i,b,c,d,a,X[13],21,t[60])
|
||
a=z(i,a,b,c,d,X[ 4], 6,t[61])
|
||
d=z(i,d,a,b,c,X[11],10,t[62])
|
||
c=z(i,c,d,a,b,X[ 2],15,t[63])
|
||
b=z(i,b,c,d,a,X[ 9],21,t[64])
|
||
|
||
return bit_and(A+a,0xFFFFFFFF),bit_and(B+b,0xFFFFFFFF),
|
||
bit_and(C+c,0xFFFFFFFF),bit_and(D+d,0xFFFFFFFF)
|
||
end
|
||
|
||
----------------------------------------------------------------
|
||
|
||
local function md5_update(self, s)
|
||
self.pos = self.pos + #s
|
||
s = self.buf .. s
|
||
for ii = 1, #s - 63, 64 do
|
||
local X = cut_le_str(sub(s,ii,ii+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
|
||
assert(#X == 16)
|
||
X[0] = table.remove(X,1) -- zero based!
|
||
self.a,self.b,self.c,self.d = transform(self.a,self.b,self.c,self.d,X)
|
||
end
|
||
self.buf = sub(s, math.floor(#s/64)*64 + 1, #s)
|
||
return self
|
||
end
|
||
|
||
local function md5_finish(self)
|
||
local msgLen = self.pos
|
||
local padLen = 56 - msgLen % 64
|
||
|
||
if msgLen % 64 > 56 then padLen = padLen + 64 end
|
||
|
||
if padLen == 0 then padLen = 64 end
|
||
|
||
local s = char(128) .. rep(char(0),padLen-1) .. lei2str(bit_and(8*msgLen, 0xFFFFFFFF)) .. lei2str(math.floor(msgLen/0x20000000))
|
||
md5_update(self, s)
|
||
|
||
assert(self.pos % 64 == 0)
|
||
return lei2str(self.a) .. lei2str(self.b) .. lei2str(self.c) .. lei2str(self.d)
|
||
end
|
||
|
||
----------------------------------------------------------------
|
||
|
||
function md5.new()
|
||
return { a = CONSTS[65], b = CONSTS[66], c = CONSTS[67], d = CONSTS[68],
|
||
pos = 0,
|
||
buf = '',
|
||
update = md5_update,
|
||
finish = md5_finish }
|
||
end
|
||
|
||
function md5.tohex(s)
|
||
return format("%08x%08x%08x%08x", str2bei(sub(s, 1, 4)), str2bei(sub(s, 5, 8)), str2bei(sub(s, 9, 12)), str2bei(sub(s, 13, 16)))
|
||
end
|
||
|
||
function md5.sum(s)
|
||
return md5.new():update(s):finish()
|
||
end
|
||
|
||
function md5.sumhexa(s)
|
||
return md5.tohex(md5.sum(s))
|
||
end
|
||
|
||
-- ***** MD5 功能结束 ******
|
||
|
||
|
||
-- ***** datetime 功能开始 ******
|
||
datetime = {}
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 判断是否为闰年
|
||
|=========================================================================
|
||
| @param {int} year
|
||
| @return boolean
|
||
]]
|
||
function datetime.isLeapYear(year)
|
||
return (year%4 == 0 and year%100 ~= 0) or (year%400 == 0)
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 获取UNIX时间戳
|
||
|=========================================================================
|
||
| 以UTC时间为标准
|
||
|
|
||
| @param {string} datetime 只支持格式'2016-10-13 01:01:01'
|
||
| @return int
|
||
]]
|
||
function datetime.toUnixTime(datetimeString)
|
||
local datetimeTable = string.split(datetimeString,' ')
|
||
local datepart = string.split(datetimeTable[1],'-')
|
||
local timepart = string.split(datetimeTable[2],':')
|
||
local sec = tonumber(timepart[3]) + tonumber(timepart[2])*60 + tonumber(timepart[1])*60*60 + (tonumber(datepart[3]) - 1)*86400
|
||
|
||
local year = tonumber(datepart[1])
|
||
local m = tonumber(datepart[2]) - 1
|
||
for i=1,m do
|
||
if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then
|
||
sec = sec + 31 * 86400
|
||
elseif i==4 or i==6 or i==9 or i==11 then
|
||
sec = sec + 30 * 86400
|
||
else
|
||
if datetime.isLeapYear(year) then
|
||
sec = sec + 29 * 86400
|
||
else
|
||
sec = sec + 28 * 86400
|
||
end
|
||
end
|
||
end
|
||
|
||
local day = 0
|
||
for i=1970,year-1 do
|
||
if datetime.isLeapYear(i) then
|
||
day = day + 366
|
||
else
|
||
day = day + 365
|
||
end
|
||
end
|
||
sec = sec + day * 86400
|
||
|
||
return sec
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 把UNIX时间戳转换成日期格式
|
||
|=========================================================================
|
||
| 以UTC时间为标准,输出格式'2016-10-13 01:01:01'
|
||
|
|
||
| @param {int} unixtime
|
||
| @param {boolean} [returnTable] 可选,如果为true返回table
|
||
| @return string|table
|
||
]]
|
||
function datetime.toDatetime(unixtime, returnTable )
|
||
local day = math.floor(unixtime/86400)
|
||
local year = 1970
|
||
while day >= 365 do
|
||
if datetime.isLeapYear(year) then
|
||
day = day - 366
|
||
unixtime = unixtime - 366*86400
|
||
else
|
||
day = day - 365
|
||
unixtime = unixtime - 365*86400
|
||
end
|
||
year = year + 1
|
||
end
|
||
|
||
_day = 0
|
||
local month = 0
|
||
for i=1,12 do
|
||
local d
|
||
if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then
|
||
d = 31
|
||
elseif i==4 or i==6 or i==9 or i==11 then
|
||
d = 30
|
||
else
|
||
if datetime.isLeapYear(year) then
|
||
d = 29
|
||
else
|
||
d = 28
|
||
end
|
||
end
|
||
_day = _day + d
|
||
if day < _day then
|
||
month = i
|
||
unixtime = unixtime - (_day-d)*86400
|
||
break
|
||
end
|
||
end
|
||
|
||
day = math.floor(unixtime/86400)
|
||
unixtime = unixtime - day*86400
|
||
|
||
local h = math.floor(unixtime/3600)
|
||
unixtime = unixtime - h*3600
|
||
local m = math.floor(unixtime/60)
|
||
unixtime = unixtime - m*60
|
||
|
||
if returnTable then
|
||
return {
|
||
year = year,
|
||
month = month,
|
||
day = day+1,
|
||
hour = h,
|
||
min = m,
|
||
second = unixtime,
|
||
}
|
||
end
|
||
|
||
return string.format('%d-%02d-%02d %02d:%02d:%02d',year,month,day+1,h,m,unixtime)
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 获取服务器当前时间,返回标准格式时间,UNIX时间
|
||
|=========================================================================
|
||
| @return string,int
|
||
]]
|
||
function datetime.now()
|
||
local time = math.floor(UTC_TIME + GameRules:GetGameTime())
|
||
return datetime.toDatetime(time),time
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 判断星期几,默认当前时间
|
||
|=========================================================================
|
||
| @param {int} week 区间[1,7]
|
||
| @return boolean
|
||
]]
|
||
function datetime.isWeek(week, datetimeString)
|
||
local date = {}
|
||
if datetimeString == nil then
|
||
date = datetime.toDatetime(math.floor(UTC_TIME + GameRules:GetGameTime()),true)
|
||
else
|
||
date = datetime.toDatetime(datetime.toUnixTime(datetimeString),true)
|
||
end
|
||
local y = date.year
|
||
local m = date.month
|
||
local d = date.day
|
||
if m == 1 or m == 2 then
|
||
m = m + 12
|
||
y = y - 1
|
||
end
|
||
local w = math.floor((d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) % 7)
|
||
if w == 0 then w = 7 end
|
||
-- print(currentWeek)
|
||
return w == week
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 根据日期获取星期几 返回1-7,默认当前时间
|
||
|=========================================================================
|
||
| @param {table} date or string
|
||
| @return int
|
||
]]
|
||
function datetime.getWeek(date)
|
||
if date == nil then
|
||
local time = math.floor(UTC_TIME + GameRules:GetGameTime())
|
||
date = datetime.toDatetime(time,true)
|
||
elseif type(date) == "string" then
|
||
date = datetime.toDatetime(datetime.toUnixTime(date),true)
|
||
end
|
||
local y = date.year
|
||
local m = date.month
|
||
local d = date.day
|
||
|
||
if m == 1 or m == 2 then
|
||
y = y - 1
|
||
m = m + 12
|
||
end
|
||
|
||
local w = (d+2*m+math.floor(3*(m+1)/5)+y+math.floor(y/4)-math.floor(y/100)+math.floor(y/400)) % 7 + 1
|
||
|
||
if w == 0 then
|
||
w = 7
|
||
end
|
||
|
||
return w
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 判断是否当月最后一天
|
||
|=========================================================================
|
||
| @return boolean
|
||
]]
|
||
function datetime.isLastDay(datetimeAny)
|
||
local data
|
||
if type(datetimeAny) == "string" then
|
||
data = datetime.toDatetime(datetime.toUnixTime(datetimeAny), true)
|
||
elseif type(datetimeAny) == "table" then
|
||
data = datetimeAny
|
||
elseif type(datetimeAny) == "number" then
|
||
data = datetime.toDatetime(datetimeAny, true)
|
||
else
|
||
print("Invalid datetime")
|
||
end
|
||
|
||
local i = data.month
|
||
if i > 12 or i < 1 then
|
||
print("Invalid datetime")
|
||
end
|
||
if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then
|
||
return data.day == 31
|
||
elseif i==4 or i==6 or i==9 or i==11 then
|
||
return data.day == 30
|
||
else
|
||
if datetime.isLeapYear(data.year) then
|
||
return data.day == 29
|
||
else
|
||
return data.day == 28
|
||
end
|
||
end
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 获取当月最后一天,传入参数以 yyyy-MM 开头
|
||
|=========================================================================
|
||
| @return boolean
|
||
]]
|
||
function datetime.getLastDay(datetimeString)
|
||
local i = tonumber(string.sub(datetimeString, 6, 7))
|
||
if i==1 or i==3 or i==5 or i==7 or i==8 or i==10 or i==12 then
|
||
return 31
|
||
elseif i==4 or i==6 or i==9 or i==11 then
|
||
return 30
|
||
else
|
||
if datetime.isLeapYear(tonumber(string.sub(datetimeString, 1, 4))) then
|
||
return 29
|
||
else
|
||
return 28
|
||
end
|
||
end
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 获取增加x个月后的时间,一个月按30天计算
|
||
|=========================================================================
|
||
| @return string
|
||
]]
|
||
function datetime.addMonth(datetimeString, month)
|
||
return datetime.toDatetime(datetime.toUnixTime(datetimeString) + month * 30 * 24 * 3600)
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 获取增加x天后的时间
|
||
|=========================================================================
|
||
| @return string
|
||
]]
|
||
function datetime.addDay(datetimeString, day)
|
||
return datetime.toDatetime(datetime.toUnixTime(datetimeString) + day * 24 * 3600)
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 获取两个日期相差多少天,只取日期部分
|
||
|=========================================================================
|
||
| @return number
|
||
]]
|
||
function datetime.getDaysByTwoDate(dateStart, dateEnd)
|
||
local time1 = datetime.toUnixTime(string.sub(dateStart,1,10).." 00:00:00")
|
||
local time2 = datetime.toUnixTime(string.sub(dateEnd,1,10).." 00:00:00")
|
||
return math.floor((time2-time1)/(24*3600))
|
||
end
|
||
|
||
--[[
|
||
|=========================================================================
|
||
| 获取两个日期相差多少秒,结果可用于判定日期前后
|
||
|=========================================================================
|
||
| @return number
|
||
]]
|
||
function datetime.subtracte(dateStart, dateEnd)
|
||
return datetime.toUnixTime(dateEnd) - datetime.toUnixTime(dateStart)
|
||
end
|
||
|
||
-- ***** datetime 功能结束 ******
|