Posts: 451
Threads: 94
Joined: Jun 2015
Reputation:
6
Hello,
I have a script that sends an email with attached foscam camera snaphots when my doorbell is pushed.
That works great for months, but after some time it crashed my lm4 as following:
- when my doorbell is pushed i receive an email with size 0 images. every doorbell push i receive that mail with size 0 image
- so i try to find the problem and test my code manual with a resident script (sleepinterval 60), the same code as my event-based script
Code:
1 2
require (
'user.nit_email' )
mail ({
'test@test.nl' },
'Test' ,
'Test message.' ,
'std_camera_2' )
-I receive every 60 seconds an email, thats correct. But when i stop/deactivate this script i also receive every 60 seconds the email, why?
-So i need to restart my lm4 to solve this issue.
Nit_email
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
local from_name =
'HomeLynk'
local settings = {
from =
'test@test.nl' ,
server =
'1.2.3.4' ,
port =
25 ,
}
local escape =
function (
v )
return '<' ..
tostring (
v ) ..
'>'
end
function mail (
to ,
subject ,
message ,
att )
local smtp =
require (
'socket.smtp' )
if att then
local mime =
require (
'mime' )
local ltn12 =
require (
'ltn12' )
bodyAtt =
handleAtt (
att ,
'start' )
else
bodyAtt = {
"" ,
"" }
end
if type (
to ) ~=
'table' then
to = {
to }
end
for index ,
email in ipairs (
to )
do
to [
index ] =
escape (
email )
end
settings.source =
smtp.message ({
headers = {
from =
from_name..escape (
settings.from ),
to =
table.concat (
to ,
', ' ),
subject =
subject ,
},
body = {
{
header = {
[
'Content-type' ] =
'text/html; charset=utf-8' ,
},
body =
mime.eol (
0 ,
message ),
},
bodyAtt [
1 ],
bodyAtt [
2 ],
}
})
bodyAtt =
nil
settings.from =
escape (
settings.from )
settings.rcpt =
to
smtp.send (
settings )
if att then
handleAtt (
att ,
'end' )
end
end
function handleAtt (
att ,
handle )
if handle ==
"start" then
if att ==
"std_camera" then
require (
'user.nit_camera' )
dst =
'/tmp/capture.jpg'
local url =
string.format (
url_cmdFoscam ,
cam_voordeur ,
cam_port ,
'snapPicture2' ,
'' ,
cam_usr2 ,
cam_pwd2 )
local cmd =
string.format (
'wget -O %q %q' ,
dst ,
url )
os.execute (
cmd )
local attachment =
ltn12.source.chain (
ltn12.source.file (
io.open (
dst ,
'r' )),
ltn12.filter.chain (
mime.encode (
'base64' ),
mime.wrap ()) )
return
{
{
headers = {
[
'Content-type' ] =
'image/jpeg; name="image.jpg"' ,
[
'Content-disposition' ] =
'attachment; filename="image.jpg"' ,
[
'Content-transfer-encoding' ] =
'BASE64' ,
},
body =
attachment
}
}
elseif att ==
"std_camera_b" then
require (
'user.nit_camera' )
dst1 =
'/tmp/capture1.jpg'
dst2 =
'/tmp/capture2.jpg'
local url1 =
string.format (
url_cmdFoscam ,
cam_voordeur ,
cam_port ,
'snapPicture2' ,
'' ,
cam_usr2 ,
cam_pwd2 )
local url2 =
string.format (
url_cmdFoscam ,
cam_achterdeur ,
cam_port ,
'snapPicture2' ,
'' ,
cam_usr2 ,
cam_pwd2 )
local cmd1 =
string.format (
'wget -O %q %q' ,
dst1 ,
url1 )
local cmd2 =
string.format (
'wget -O %q %q' ,
dst2 ,
url2 )
os.execute (
cmd1 )
os.execute (
cmd2 )
local attachment1 =
ltn12.source.chain (
ltn12.source.file (
io.open (
dst1 ,
'r' )),
ltn12.filter.chain (
mime.encode (
'base64' ),
mime.wrap ()) )
local attachment2 =
ltn12.source.chain (
ltn12.source.file (
io.open (
dst2 ,
'r' )),
ltn12.filter.chain (
mime.encode (
'base64' ),
mime.wrap ()) )
return
{
{
headers = {
[
'Content-type' ] =
'image/jpeg; name="image1.jpg"' ,
[
'Content-disposition' ] =
'attachment; filename="image1.jpg"' ,
[
'Content-transfer-encoding' ] =
'BASE64' ,
},
body =
attachment1
},
{
headers = {
[
'Content-type' ] =
'image/jpeg; name="image2.jpg"' ,
[
'Content-disposition' ] =
'attachment; filename="image2.jpg"' ,
[
'Content-transfer-encoding' ] =
'BASE64' ,
},
body =
attachment2
}
}
elseif att ==
"std_camera_2" then
require (
'user.nit_camera' )
dst1 =
'/tmp/capture1.jpg'
dst2 =
'/tmp/capture2.jpg'
local url1 =
string.format (
url_cmdFoscam ,
cam_voordeur ,
cam_port ,
'snapPicture2' ,
'' ,
cam_usr2 ,
cam_pwd2 )
local cmd1 =
string.format (
'wget -O %q %q' ,
dst1 ,
url1 )
local cmd2 =
string.format (
'wget -O %q %q' ,
dst2 ,
url1 )
os.execute (
cmd1 )
cmdFoscam (
cam_voordeur ,
cam_port ,
'ptzGotoPresetPoint' ,
'&name=Deur' )
os.sleep (
20 )
os.execute (
cmd2 )
local attachment1 =
ltn12.source.chain (
ltn12.source.file (
io.open (
dst1 ,
'r' )),
ltn12.filter.chain (
mime.encode (
'base64' ),
mime.wrap ()) )
local attachment2 =
ltn12.source.chain (
ltn12.source.file (
io.open (
dst2 ,
'r' )),
ltn12.filter.chain (
mime.encode (
'base64' ),
mime.wrap ()) )
return
{
{
headers = {
[
'Content-type' ] =
'image/jpeg; name="image1.jpg"' ,
[
'Content-disposition' ] =
'attachment; filename="image1.jpg"' ,
[
'Content-transfer-encoding' ] =
'BASE64' ,
},
body =
attachment1
},
{
headers = {
[
'Content-type' ] =
'image/jpeg; name="image2.jpg"' ,
[
'Content-disposition' ] =
'attachment; filename="image2.jpg"' ,
[
'Content-transfer-encoding' ] =
'BASE64' ,
},
body =
attachment2
}
}
end
elseif handle ==
"end" then
if att ==
"std_camera" then
os.remove (
dst )
elseif att ==
"std_camera_b" then
os.remove (
dst1 )
os.remove (
dst2 )
elseif att ==
"std_camera_2" then
os.remove (
dst1 )
os.remove (
dst2 )
end
end
end
Nit_camera
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
cam_voordeur =
'2.2.2.2'
cam_achterdeur =
'2.2.2.3'
cam_port =
80
cam_usr =
'user'
cam_pwd =
'password'
cam_usr2 =
'user2'
cam_pwd2 =
'password2'
url_cmdFoscam =
'http://%s:%s/cgi-bin/CGIProxy.fcgi?cmd=%s%s&usr=%s&pwd=%s'
function cmdFoscam (
iCamera ,
iPort ,
iCmd ,
iParam )
local url ,
response
url =
string.format (
url_cmdFoscam ,
iCamera ,
iPort ,
iCmd ,
iParam ,
cam_usr ,
cam_pwd )
if (
url )
then
require (
'socket.http' )
socket.http.TIMEOUT =
5
response =
socket.http.request (
url_encode (
url ) )
end
return response
end
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
471
You should use LuaSocket to get a snapshot instead of wget. wget will fail if output file already exist so this might cause a problem with 0 sized attachments. There's no need to save snapshot to /tmp, you can use ltn12.source.string.
Posts: 451
Threads: 94
Joined: Jun 2015
Reputation:
6
(26.10.2017, 09:06) admin Wrote: You should use LuaSocket to get a snapshot instead of wget. wget will fail if output file already exist so this might cause a problem with 0 sized attachments. There's no need to save snapshot to /tmp, you can use ltn12.source.string.
can you please give a little example?
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
471
You already have a function for HTTP requests, just get your snapshot by calling cmdFoscam and then pass the result like this:
Code:
1 2
local snapshot =
cmdFoscam (...)
local attachment =
ltn12.source.chain (
ltn12.source.string (
snapshot ),
ltn12.filter.chain (
mime.encode (
'base64' ),
mime.wrap ()) )
Posts: 237
Threads: 31
Joined: May 2018
Reputation:
2
11.07.2018, 10:51
(This post was last modified: 11.07.2018, 10:51 by DGrandes .)
Hello,
I've tried to use this script but I can´t get it to work.
******************************************************************************
function handleAtt(att)
if att == "snapshoot" then
local snapshoot = 'http://IPCAMERA/cgi-bin/snapshot.cgi?'
local attachment = ltn12.source.chain( ltn12.source.string(snapshot), ltn12.filter.chain(mime.encode('base64'), mime.wrap()) )
return
{
{
headers = {
['Content-type'] = 'image/jpeg; name="image.jpg"',
['Content-disposition'] = 'attachment; filename="image.jpg"',
['Content-transfer-encoding'] = 'BASE64',
},
body = attachment
}
}
end
end
The mail function send me a emai with jpg attachment but i can´t see anything.
When I use the link 'http://IPCAMERA/cgi-bin/snapshot.cgi?' i have to log in. How can I automatize with code?
Thanks
Posts: 4938
Threads: 28
Joined: Aug 2017
Reputation:
225
Try like that
'http://user:password@IPCAMERA/cgi-bin/snapshot.cgi?'
------------------------------
Ctrl+F5
Posts: 237
Threads: 31
Joined: May 2018
Reputation:
2
(11.07.2018, 11:02) Daniel. Wrote: Try like that
'http://user:password@IPCAMERA/cgi-bin/snapshot.cgi?'
It doesn´t work.
I´ve tried diferent options and every time ask me user and pass.
https://www.ispyconnect.com/man.aspx?n=Dahua
Posts: 942
Threads: 161
Joined: Jul 2015
Reputation:
33
(11.07.2018, 14:12) DGrandes Wrote: (11.07.2018, 11:02) Daniel. Wrote: Try like that
'http://user:password@IPCAMERA/cgi-bin/snapshot.cgi?'
It doesn´t work.
I´ve tried diferent options and every time ask me user and pass.
https://www.ispyconnect.com/man.aspx?n=Dahua
You can try like here:
https://forum.logicmachine.net/showthrea...38#pid6338
Maybe your camera support such params:
http://IP_address/cgi-bin/snapshot.cgi?c...p=password
Done is better than perfect
Posts: 237
Threads: 31
Joined: May 2018
Reputation:
2
11.07.2018, 15:07
(This post was last modified: 11.07.2018, 15:20 by DGrandes .)
(11.07.2018, 14:20) buuuudzik Wrote: (11.07.2018, 14:12) DGrandes Wrote: (11.07.2018, 11:02) Daniel. Wrote: Try like that
'http://user:password@IPCAMERA/cgi-bin/snapshot.cgi?'
It doesn´t work.
I´ve tried diferent options and every time ask me user and pass.
https://www.ispyconnect.com/man.aspx?n=Dahua
You can try like here:
https://forum.logicmachine.net/showthrea...38#pid6338
Maybe your camera support such params:
http://IP_address/cgi-bin/snapshot.cgi?c...p=password
Don´t work..
My camera is IPC-HDBW1320E of Dahua and I try with both url of 'https://www.ispyconnect.com/man.aspx?n=Dahua':
It do something strange.. the first time I´ve tried the url it work and don´t ask me the user and pass, but once i use this url it doesn´t work..
I´ve tried with:
http://user :pass@CAMERAIP/cgi-bin/snapshot.cgi?1
http://admin :user@CAMERAIP/cgi-bin/snapshot.cgi?loginuse=user&loginpas=pass
http://admin :user@CAMERAIP/cgi-bin/snapshot.cgi?user=user&pass=pass
http://admin :user@CAMERAIP/cgi-bin/snapshot.cgi?user=user&pwd=pass
http://admin :user@CAMERAIP/cgi-bin/snapshot.cgi?u=user&p=pass
Posts: 68
Threads: 3
Joined: Jun 2016
Reputation:
0
Can you try to add a fake parameter in the url like timestamp.
http://user :pass@CAMERAIP/cgi-bin/snapshot.cgi?1&ts=randomnumber
If it worked 1 time, and then fail, maybe there is a caching issue. By adding a parameter that change in the url, it is consider as a new request and will not look in the cache if any.
Posts: 237
Threads: 31
Joined: May 2018
Reputation:
2
12.07.2018, 08:20
(This post was last modified: 12.07.2018, 08:20 by DGrandes .)
(11.07.2018, 18:21) mlaudren Wrote: Can you try to add a fake parameter in the url like timestamp.
http://user :pass@CAMERAIP/cgi-bin/snapshot.cgi?1&ts=randomnumber
If it worked 1 time, and then fail, maybe there is a caching issue. By adding a parameter that change in the url, it is consider as a new request and will not look in the cache if any.
Thanks!! this random number works perfectly. But with the script don´t attach the image correctly.. can you help me with the script?
Event-Based Script:
mail('MyEmail', 'ALERTA', '¡¡¡Alguien en casa!!!', 'captura')
Comon Functions:
function mail (to, subject, message, att)
-- make sure these settings are correct
local settings = {
-- "from" field, only e-mail must be specified here
from = '......',
-- smtp username
user = '.....',
-- smtp password
password = '......',
-- smtp server
server = 'smtp.gmail.com',
-- smtp server port
port = 465,
-- enable tls, required for gmail smtp
secure = 'tlsv1_2',
}
-- make sure these settings are correct
local smtp = require('socket.smtp')
local escape = function(v)
return '<' .. tostring(v) .. '>'
end
local from_name = '.......'
if att then
local mime = require('mime')
local ltn12 = require('ltn12')
-- generate attachements
bodyAtt = handleAtt(att) --bodyAtt = handleAtt(att, 'start')
else
bodyAtt = {"",""}
end
if type(to) ~= 'table' then
to = { to }
end
for index, email in ipairs(to) do
to[ index ] = escape(email)
end
settings.source = smtp.message({
headers = {
from = from_name..escape(settings.from),
to = table.concat(to, ', '),
subject = subject,
},
body = {
--preamble = "Hello Recipient, \r\n" .. "This is your e-mail with a picture attached.",
{
header = {
['Content-type'] = 'text/html; charset=utf-8',
},
body = mime.eol(0, message),
},
bodyAtt[1],bodyAtt[2], -- get attachements if exists (max 2 for now) <---todo:make it dynamic
--epilogue = "That's it folks!
"
}
})
bodyAtt = nil
-- fixup from field
settings.from = escape(settings.from)
settings.rcpt = to
smtp.send(settings)
end
function handleAtt(att)
if att == "captura" then
local snapshot = 'CAMERAIP'--..math.random(0, 1000000000000)
log (snapshot)
local attachment = ltn12.source.chain( ltn12.source.string(snapshot), ltn12.filter.chain(mime.encode('base64'), mime.wrap()) )
return
{
{
headers = {
['Content-type'] = 'image/jpeg; name="Captura.jpg"',
['Content-disposition'] = 'attachment; filename="Captura.jpg"',
['Content-transfer-encoding'] = 'BASE64',
},
body = attachment
}
}
end
end
Thanks!!!
Posts: 237
Threads: 31
Joined: May 2018
Reputation:
2
Hi,
I still don't know how to make a snapshoot from my ip camera and save or send it.
I have created a DNS to share the url in case you want to test it and help me. The camera is covered by privacy reasons...
IP :
http://dnspruebacamara.myqnapcloud.com:5858/
user: admin
pass: 123456789
I have test it from web explorers (chrome or firefox) and it works perfectly from Them:
http://admin:123456789@dnspruebacamara.m...pshot.jpeg
where ts=... is a random number that i must change by code, for the navigator not to ask me again the security credencials
.... But I can not get it work from the following code:
image_type = 'jpeg'
image_name_attachment = 'snapshot'
source_image_url = 'http://admin:123456789@dnspruebacamara.myqnapcloud.com:5858/cgi-bin/snapshot.cgi?1&ts=4561248/snapshot.jpeg'
where ts=... is a random number that i must change by code, for the navigator not to ask me again the security credencials
--Get remote (from HTTP) image and put image file to HL (will be deleted when end of script)
os.execute('wget -O /www/scada/vis/' .. image_name_attachment .. '.' .. image_type .. ' ' .. source_image_url .. '')
or I have also tried this other code, and it did not work either:
image = socket.http.request(source_image_url)
I know that I am doing something wrong, but I dont know what I am missing.
Can anyone help me please???
Best regards
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
471
Your camera uses digest auth mechanism which is not supported by socket.http library.
Use this code to get your snapshot:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
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
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
local sink =
req.sink
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
req.sink =
nil
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
local qop =
ht.qop
if qop and qop ~=
'auth' then
return nil ,
'unsupported qop ' ..
tostring (
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
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
req.sink =
sink
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
url =
'http://admin:123456789@dnspruebacamara.myqnapcloud.com:5858/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
image ,
err ,
hdrs =
request (
url )
Posts: 237
Threads: 31
Joined: May 2018
Reputation:
2
Thanks you!
It works perfectly
Best Regards
Posts: 15
Threads: 2
Joined: Nov 2018
Reputation:
0
25.02.2019, 10:58
(This post was last modified: 25.02.2019, 11:00 by Igori .)
Hello!
I tried to adapt the script from post 13 to my task. But as a result, I get a file with an image, before which there is a piece of HTML code. In the logs we can see:
Code:
1 2 3 4 5 6 7 8
stest 25.02.2019 13 :
44 :
51
*
string : <!
DOCTYPE html >
<
html ><
head ><
title >
Document Error :
Unauthorized </
title ></
head >
<
body ><
h2 >
Access Error :
401
<
p >
Authentication Error </
p >
</
body >
</
html >
����
As we can see, the authorization on the camera does not pass, but I still get the image. In order to view it, I only need to remove the html header.
So, I have to edit the image before sending it by mail. The solution is simple, but I think it is not quite right
Code:
1 2
a1 ,
a2 =
string.find (
image ,
"</html>\r\n" )
image =
string.sub (
image ,
a2 +
1 )
How to solve the problem correctly?
Thanks!
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
471
Your solution is correct, there's nothing else that can be done since the camera response is clearly wrong
Posts: 15
Threads: 2
Joined: Nov 2018
Reputation:
0
Posts: 3
Threads: 1
Joined: Aug 2019
Reputation:
0
(16.08.2018, 12:50) I tried to use this code, hopefully I put it in right. Didn\t flag any errors in the log, so that's hopeful.I can't find the url of where the snapshot is sent to... any help??admin Wrote: Your camera uses digest auth mechanism which is not supported by socket.http library.
Use this code to get your snapshot:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
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
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
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
url =
'http://admin:123456789@dnspruebacamara.myqnapcloud.com:5858/cgi-bin/snapshot.cgi?1&ts=123/snapshot.jpeg'
image ,
err ,
hdrs =
request (
url )
Posts: 8071
Threads: 43
Joined: Jun 2015
Reputation:
471
Log what output the server produces. Add this to the end of the script:
Posts: 38
Threads: 11
Joined: Jul 2017
Reputation:
0
In my case I have a file with a silly header:
<?xml version="1.0" encoding="UTF-8" ?>
<userCheck>
<statusValue>401</statusValue>
<statusString>Unauthorized</statusString>
</userCheck>
so I need to add:
a1, a2 = string.find(image,"</userCheck>\n")
image = string.sub(image, a2+1)
to remove them.
Thanks.