octonet/octoserve/var/www/channelscan.lua

366 lines
9.2 KiB
Lua

#!/usr/bin/lua
local host = os.getenv("HTTP_HOST")
local proto = os.getenv("SERVER_PROTOCOL")
local query = os.getenv("QUERY_STRING")
local method = os.getenv("REQUEST_METHOD")
local clength = os.getenv("CONTENT_LENGTH")
local ctype = os.getenv("CONTENT_TYPE")
function http_print(s)
if s then
io.stdout:write(tostring(s).."\r\n")
else
io.stdout:write("\r\n")
end
end
if #arg> 0 then
method="GET"
query=arg[1]
proto = "HTTP/1.0"
end
function SendError(err,desc)
http_print(proto.." "..err)
http_print("Content-Type: text/html")
http_print()
local file = io.open("e404.html")
if file then
local tmp = file:read("*a")
tmp = string.gsub(tmp,"404 Not Found",err .. " " .. desc)
http_print(tmp)
file:close()
end
end
function perr(s)
io.stderr:write(tostring(s).."\n")
end
--
local newdecoder = require("lunajson.decoder")
local newencoder = require("lunajson.encoder")
local function LoadTransponderList()
local tl = nil
local f = nil
f = io.open("/config/TransponderList.json","r")
if not f then
f = io.open("/var/channels/TransponderList.json","r")
end
if f then
local t = f:read("*a")
f:close()
local decode = newdecoder()
tl = decode(t)
end
return tl
end
local function CheckTransponderList(tl)
local i,Source
for i,Source in ipairs(tl.SourceList) do
if not Source.Title then
error("SourceList["..i.."].Title missing",0)
end
if not Source.Key then
error("SourceList["..i.."].Key missing",0)
end
if not Source.DVBType then
error("SourceList["..i.."].DVBType missing",0)
end
if not Source.TransponderList then
error("SourceList["..i.."].TransponderList missing",0)
end
local j,Transponder
for j,Transponder in ipairs(Source.TransponderList) do
if not Transponder.Request then
error("SourceList["..i.."].TransponderList["..j.."].Request missing",0)
end
end
end
if tl.CIMapList then
local CIMap
for i,CIMap in ipairs(tl.CIMapList) do
if not CIMap.Slot then
error("CIMapList["..i.."].Slot missing",0)
end
end
end
if tl.ChannelOverwriteList then
local ChannelOverwrite
for i,ChannelOverwrite in ipairs(tl.ChannelOverwriteList) do
if not ChannelOverwrite.ID then
error("ChannelOverwriteList["..i.."].ID missing",0)
end
end
end
if tl.GroupList then
local Group
for i,Group in ipairs(tl.GroupList) do
if not Group.Title then
error("GroupList["..i.."].Title missing",0)
end
end
end
return "TransponderList.json"
end
local function CheckChannelList(cl)
local i,Group
for i,Group in ipairs(cl.GroupList) do
if not Group.Title then
error("GroupList["..i.."].Title missing",0)
end
local j,Channel
for j,Channel in ipairs(Group.ChannelList) do
if not Channel.Title then
error("GroupList["..i.."].ChannelList["..j.."].Title missing",0)
end
if not Channel.Request then
error("GroupList["..i.."].ChannelList["..j.."].Request missing",0)
end
end
end
return "ChannelList.json"
end
local function GetCMD(s)
local q,v
local params = ""
local cmd = ""
for q,v in s:gmatch("(%a+)=([%w%.]+)") do
if q == "select" then
cmd = v
elseif q ~= "t" then
params = params.." "..q.."="..v
end
end
return cmd,params
end
local function Keys()
local data = nil
local tl = LoadTransponderList()
if tl then
local kl = { KeyList = { } }
local s
for _,s in ipairs(tl.SourceList) do
table.insert(kl.KeyList, { Key=s.Key,Title=s.Title,DVBType=s.DVBType })
end
kl.KeyList[0] = #kl.KeyList
local encode = newencoder()
data = encode(kl)
end
return data
end
local function Scan(cmd,params)
local data = nil
local rc = os.execute("mkdir /tmp/doscan.lock")
if rc ~= 0 then
data = '{"status":"busy"}'
else
data = '{"status":"retry"}'
local f = io.open("/tmp/doscan.msg","w+")
if f then
f:write("Scanning")
f:close()
end
os.execute("/var/channels/do"..cmd..".lua "..params.." >/tmp/doscan.log 2>&1 &")
end
return data
end
local function Status()
local data = nil
local js = { }
local f = io.open("/tmp/doscan.lock/doscan.msg")
if f then
js.status = "active"
local m = f:read("*l")
local count,msg = m:match("(%d+):(.*)")
js.count = count
js.msg = msg
f:close()
else
f = io.open("/tmp/doscan.msg")
if f then
local m = f:read("*l")
local count,msg = m:match("(%d+):(.*)")
if count and msg then
js.count = count
js.msg = msg
js.status = "done"
else
if m == "Scanning" then
js.status = "retry"
else
js.status = nil
end
end
f:close()
else
js.status = ""
end
end
local encode = newencoder()
data = encode(js)
return data
end
local function Delete(params)
local data = nil
local rc = os.execute("mkdir /tmp/doscan.lock")
if rc ~= 0 then
data = '{"status":"busy"}'
else
data = '{"status":"deleted"}'
os.execute("rm /config/ChannelList.json");
if params == " all=true" then
os.execute("rm /config/TransponderList.json");
end
os.execute("rm /tmp/doscan.msg");
os.execute("rm -rf /tmp/doscan.lock");
end
return data
end
local function Restore()
local data = nil
local rc = os.execute("mkdir /tmp/doscan.lock")
if rc ~= 0 then
data = '{"status":"busy"}'
else
local rc = os.execute("mv /config/ChannelList.bak /config/ChannelList.json");
if rc == 0 then
data = '{"status":"restored", "count":1}'
else
data = '{"status":"restored", "count":0}'
end
os.execute("rm /tmp/doscan.msg");
os.execute("rm -rf /tmp/doscan.lock");
end
return data
end
local function Upload()
local data = nil
local rc = os.execute("mkdir /tmp/doscan.lock")
if rc ~= 0 then
data = '{"status":"busy"}'
else
local boundary = string.match(ctype,"boundary=(.*)")
if boundary then
while true do
local line = io.stdin:read()
line = string.gsub(line,"\r","")
if line == "" then break end
end
local filedata = io.stdin:read("*a")
local i = filedata:find("--"..boundary,1,true)
if i then
filedata = filedata:sub(1,i-1)
else
filedata = "{}"
end
local decode = newdecoder()
local rc,json = pcall(decode,filedata)
if rc then
rc = false
local msg = "invalid list"
if json.SourceList then
rc,msg = pcall(CheckTransponderList,json)
data = '{"status":"updated", "msg":"Transponder list"}'
elseif json.GroupList then
rc,msg = pcall(CheckChannelList,json)
end
if rc then
local f = io.open("/config/"..msg,"w+")
if f then
f:write(filedata)
f:close()
data = '{"status":"updated", "msg":"'..msg..'"}'
else
data = '{"status":"error", "msg":"'..msg..' not saved"}'
end
else
data = '{"status":"error", "msg":"'..msg..'"}'
end
else
local msg = "unknown error"
if json then
msg = json:match(".-: (.*)")
end
data = '{"status":"error", "msg":"'..msg..'"}'
end
else
data = '{"status":"error","msg":"malformed request"}'
end
os.execute("rm /tmp/doscan.msg");
os.execute("rm -rf /tmp/doscan.lock");
end
return data
end
local filename = nil
local contenttype = "application/json; charset=utf-8"
local data = nil
local cmd = ""
local params
if method == "GET" then
cmd,params = GetCMD(query)
elseif method == "POST" and clength and ctype then
if ctype:match("application/x%-www%-form%-urlencoded") then
local query = io.read(tonumber(clength))
query = string.gsub(query,"\r","")
cmd,params = GetCMD(query)
elseif ctype:match("multipart/form%-data") then
cmd = "upload"
end
else
SendError("500","What")
return
end
if cmd == "keys" then
data = Keys()
elseif cmd == "scan" then
data = Scan("scan",params)
elseif cmd == "epg" then
data = Scan("epgscan",params)
elseif cmd == "status" then
data = Status()
elseif cmd == "delete" then
data = Delete(params)
elseif cmd == "restore" then
data = Restore()
elseif cmd == "upload" then
data = Upload()
end
if data then
http_print(proto.." 200" )
http_print("Pragma: no-cache")
http_print("Cache-Control: no-cache")
http_print("Content-Type: "..contenttype)
if filename then
http_print('Content-Disposition: filename="'..filename..'"')
end
http_print(string.format("Content-Length: %d",#data))
http_print()
http_print(data)
else
SendError("404","not found")
end