10.10.2018, 11:51
Try this, change IP, port, user and pass as needed. If this works correctly, you should get xml payloads in Logs tab, otherwise errors will go to Alerts tab.
Code:
require('socket')
md5sum = require('encdec').md5
host = '192.168.1.2'
port = 80
user = 'username'
pass = 'password'
uri = '/ISAPI/Event/notification/alertStream'
function getheader(resp, header)
local st, en
header = header .. '="'
st = resp:find(header)
if st then
en = resp:find('"', st + #header)
if en then
return resp:sub(st + #header, en - 1)
end
end
end
function makedigestheader(headers)
local digest = {}
for _, header in ipairs(headers) do
if not header.unquote then
header[ 2 ] = '"' .. header[ 2 ] .. '"'
end
digest[ #digest + 1 ] = header[ 1 ] .. '=' .. header[ 2 ]
end
return 'Digest ' .. table.concat(digest, ', ')
end
function hash(...)
return md5sum(table.concat({...}, ':'))
end
init = {
'GET ' .. uri .. ' HTTP/1.1',
'Host: ' .. host,
'Accept: multipart/x-mixed-replace',
}
sock = socket.tcp()
sock:settimeout(60)
res, err = sock:connect(host, port)
if not res then
alert('init connection failed: ' .. tostring(err))
return
end
sock:send(table.concat(init, '\r\n') .. '\r\n\r\n')
resp, err = sock:receive('*a')
sock:close()
if not resp then
alert('no response: ' .. tostring(err))
return
end
realm = getheader(resp, 'realm')
nonce = getheader(resp, 'nonce')
if not realm or not nonce then
alert('no realm/nonce')
return
end
nc = '00000001'
cnonce = string.format('%08x', os.time())
method = 'GET'
response = hash(
hash(user, realm, pass),
nonce,
nc,
cnonce,
'auth',
hash(method, uri)
)
auth = {
{ 'username', user },
{ 'realm', realm },
{ 'nonce', nonce },
{ 'uri', uri },
{ 'cnonce', cnonce },
{ 'nc', nc, unquote = true },
{ 'qop', 'auth' },
{ 'algorithm', 'MD5' },
{ 'response', response },
}
table.insert(init, 2, 'Authorization: ' .. makedigestheader(auth))
sock = socket.tcp()
sock:settimeout(60)
res, err = sock:connect(host, port)
if not res then
alert('data connection failed: ' .. tostring(err))
return
end
sock:send(table.concat(init, '\r\n') .. '\r\n\r\n')
cl = 'Content-Length:'
while true do
line, err = sock:receive('*l')
if line then
if line:find(cl, 1, true) then
len = tonumber(line:sub(#cl + 1))
if len then
sock:receive('*l') -- skip empty line
data, err = sock:receive(len)
if data then
log(data)
else
alert('data receive failed: ' .. tostring(err))
end
end
end
else
alert('line receive failed: ' .. tostring(err))
break
end
end
sock:close()