Posts: 8260
Threads: 44
Joined: Jun 2015
Reputation:
476
You need to modify the fist line of the script and put the correct URL to your camera snapshot.
Posts: 9
Threads: 1
Joined: Jun 2025
Reputation:
0
(25.07.2025, 08:26)admin Wrote: You need to modify the fist line of the script and put the correct URL to your camera snapshot.
The above URL works in Chrome and has the following structure:
Code: http://admin:password@IP/cgi-bin/snapshot.cgi
How should I modify it?
Posts: 5104
Threads: 28
Joined: Aug 2017
Reputation:
232
Code: url = 'http://admin:password@IP/cgi-bin/snapshot.cgi'
res, err, hdrs = require('socket.http').request(url)
log(res, err, h
only use real credentials and IP
------------------------------
Ctrl+F5
Posts: 9
Threads: 1
Joined: Jun 2025
Reputation:
0
25.07.2025, 08:50
(This post was last modified: 25.07.2025, 08:52 by AlphaAI.)
(25.07.2025, 08:44)Daniel Wrote: Code: url = 'http://admin:password@IP/cgi-bin/snapshot.cgi'
res, err, hdrs = require('socket.http').request(url)
log(res, err, h
only use real credentials and IP When I changed the URL structure to the following:
Code: http://admin:pass@192.168.1.108/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg
the result I got was:
Code: * arg: 1
* nil
* arg: 2
* string: host not found
* arg: 3
* nil
I used the actual username, password, and IP of the camera.
Posts: 8260
Threads: 44
Joined: Jun 2015
Reputation:
476
Try without credentials first:
Code: url = 'http://192.168.1.108/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
Posts: 9
Threads: 1
Joined: Jun 2025
Reputation:
0
(25.07.2025, 08:54)admin Wrote: Try without credentials first:
Code: url = 'http://192.168.1.108/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
here is what I got:
Code: * arg: 1
* string:
* arg: 2
* number: 401
* arg: 3
* table:
["content-length"]
* string: 0
["www-authenticate"]
* string: Digest realm="Login to d882f4dfd7e415866755e2f26edb169a", qop="auth", nonce="48452745", opaque="fffc25e85b1cf04564a4329a5d9bf1b13030c745"
["connection"]
* string: close
Posts: 8260
Threads: 44
Joined: Jun 2015
Reputation:
476
There might be a problem if camera admin password contains special characters. Change it so it only contains letters and numbers. Put password into this script and run it.
Code: url = 'http://admin:PASSWORD@192.168.1.108/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
local skthttp = require('socket.http')
local skturl = require('socket.url')
local ltn12 = require('ltn12')
local md5sum = require('encdec').md5
local hash = function(...)
return md5sum(table.concat({...}, ':'))
end
local parse_header = function(header)
local result = {}
for key, value in (header .. ','):gmatch('(%w+)=(.-),') do
if value:sub(1, 1) == '"' then -- strip quotes
result[ key:lower() ] = value:sub(2, -2)
else
result[ key:lower() ] = value
end
end
return result
end
local make_digest_header = function(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
local _request = function(req)
if not req.url then
return nil, 'missing url'
end
local url = skturl.parse(req.url)
local user, password = url.user, url.password
if not user or not password then
return nil, 'missing credentials in url'
end
url.user, url.password, url.authority, url.userinfo = nil, nil, nil, nil
req.url = skturl.build(url)
local source
if req.source then
local chunks = {}
local capture = function(chunk)
if chunk then
chunks[ #chunks + 1 ] = chunk
end
return chunk
end
local chunk_id = 0
source = function()
chunk_id = chunk_id + 1
return chunks[ chunk_id ]
end
req.source = ltn12.source.chain(req.source, capture)
end
local body, code, hdrs = skthttp.request(req)
if code == 401 and hdrs['www-authenticate'] then
local ht = parse_header(hdrs['www-authenticate'])
if not ht.realm or not ht.nonce then
return nil, 'missing realm/nonce from response'
end
if ht.qop ~= 'auth' then
return nil, 'unsupported qop ' .. tostring(ht.qop)
end
if ht.algorithm and ht.algorithm:lower() ~= 'md5' then
return nil, 'unsupported algo ' .. tostring(ht.algorithm)
end
local nc = '00000001'
local cnonce = string.format('%08x', os.time())
local uri = skturl.build({ path = url.path, query = url.query })
local method = req.method or 'GET'
local response = hash(
hash(user, ht.realm, password),
ht.nonce,
nc,
cnonce,
'auth',
hash(method, uri)
)
req.headers = req.headers or {}
local auth = {
{ 'username', user },
{ 'realm', ht.realm },
{ 'nonce', ht.nonce },
{ 'uri', uri },
{ 'cnonce', cnonce },
{ 'nc', nc, unquote = true },
{ 'qop', 'auth' },
{ 'algorithm', 'MD5' },
{ 'response', response },
}
if ht.opaque then
table.insert(auth, { 'opaque', ht.opaque })
end
req.headers.authorization = make_digest_header(auth)
if not req.headers.cookie and hdrs['set-cookie'] then
-- not really correct but enough for httpbin
local cookie = (hdrs['set-cookie'] .. ';'):match('(.-=.-)[;,]')
if cookie then
req.headers.cookie = '$Version: 0; ' .. cookie .. ';'
end
end
if req.source then
req.source = source
end
body, code, hdrs = skthttp.request(req)
end
return body, code, hdrs
end
local request = function(url)
local t = type(url)
if t == 'table' then
return _request(table.clone(url))
elseif t == 'string' then
local req = {}
local _, code, headers = _request({ url = url, sink = ltn12.sink.table(req) })
return table.concat(req), code, headers
end
end
image, err, hdrs = request(url)
log(type(image), err, hdrs)
Posts: 9
Threads: 1
Joined: Jun 2025
Reputation:
0
(25.07.2025, 09:06)admin Wrote: There might be a problem if camera admin password contains special characters. Change it so it only contains letters and numbers. Put password into this script and run it.
Code: url = 'http://admin:PASSWORD@192.168.1.108/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
local skthttp = require('socket.http')
local skturl = require('socket.url')
local ltn12 = require('ltn12')
local md5sum = require('encdec').md5
local hash = function(...)
return md5sum(table.concat({...}, ':'))
end
local parse_header = function(header)
local result = {}
for key, value in (header .. ','):gmatch('(%w+)=(.-),') do
if value:sub(1, 1) == '"' then -- strip quotes
result[ key:lower() ] = value:sub(2, -2)
else
result[ key:lower() ] = value
end
end
return result
end
local make_digest_header = function(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
local _request = function(req)
if not req.url then
return nil, 'missing url'
end
local url = skturl.parse(req.url)
local user, password = url.user, url.password
if not user or not password then
return nil, 'missing credentials in url'
end
url.user, url.password, url.authority, url.userinfo = nil, nil, nil, nil
req.url = skturl.build(url)
local source
if req.source then
local chunks = {}
local capture = function(chunk)
if chunk then
chunks[ #chunks + 1 ] = chunk
end
return chunk
end
local chunk_id = 0
source = function()
chunk_id = chunk_id + 1
return chunks[ chunk_id ]
end
req.source = ltn12.source.chain(req.source, capture)
end
local body, code, hdrs = skthttp.request(req)
if code == 401 and hdrs['www-authenticate'] then
local ht = parse_header(hdrs['www-authenticate'])
if not ht.realm or not ht.nonce then
return nil, 'missing realm/nonce from response'
end
if ht.qop ~= 'auth' then
return nil, 'unsupported qop ' .. tostring(ht.qop)
end
if ht.algorithm and ht.algorithm:lower() ~= 'md5' then
return nil, 'unsupported algo ' .. tostring(ht.algorithm)
end
local nc = '00000001'
local cnonce = string.format('%08x', os.time())
local uri = skturl.build({ path = url.path, query = url.query })
local method = req.method or 'GET'
local response = hash(
hash(user, ht.realm, password),
ht.nonce,
nc,
cnonce,
'auth',
hash(method, uri)
)
req.headers = req.headers or {}
local auth = {
{ 'username', user },
{ 'realm', ht.realm },
{ 'nonce', ht.nonce },
{ 'uri', uri },
{ 'cnonce', cnonce },
{ 'nc', nc, unquote = true },
{ 'qop', 'auth' },
{ 'algorithm', 'MD5' },
{ 'response', response },
}
if ht.opaque then
table.insert(auth, { 'opaque', ht.opaque })
end
req.headers.authorization = make_digest_header(auth)
if not req.headers.cookie and hdrs['set-cookie'] then
-- not really correct but enough for httpbin
local cookie = (hdrs['set-cookie'] .. ';'):match('(.-=.-)[;,]')
if cookie then
req.headers.cookie = '$Version: 0; ' .. cookie .. ';'
end
end
if req.source then
req.source = source
end
body, code, hdrs = skthttp.request(req)
end
return body, code, hdrs
end
local request = function(url)
local t = type(url)
if t == 'table' then
return _request(table.clone(url))
elseif t == 'string' then
local req = {}
local _, code, headers = _request({ url = url, sink = ltn12.sink.table(req) })
return table.concat(req), code, headers
end
end
image, err, hdrs = request(url)
log(type(image), err, hdrs)
Thank you, it works perfectly. The issue was caused by the camera password containing the
character. Once again, thank you very much.
|