luci-base: introduce luci.util.shellquote()
[project/luci.git] / applications / luci-app-upnp / luasrc / controller / upnp.lua
1 -- Copyright 2008 Steven Barth <steven@midlink.org>
2 -- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
3 -- Licensed to the public under the Apache License 2.0.
4
5 module("luci.controller.upnp", package.seeall)
6
7 function index()
8         if not nixio.fs.access("/etc/config/upnpd") then
9                 return
10         end
11
12         local page
13
14         page = entry({"admin", "services", "upnp"}, cbi("upnp/upnp"), _("UPnP"))
15         page.dependent = true
16
17         entry({"admin", "services", "upnp", "status"}, call("act_status")).leaf = true
18         entry({"admin", "services", "upnp", "delete"}, post("act_delete")).leaf = true
19 end
20
21 function act_status()
22         local uci = luci.model.uci.cursor()
23         local lease_file = uci:get("upnpd", "config", "upnp_lease_file")
24         
25         local ipt = io.popen("iptables --line-numbers -t nat -xnvL MINIUPNPD 2>/dev/null")
26         if ipt then
27                 local upnpf = lease_file and io.open(lease_file, "r")
28                 local fwd = { }
29                 while true do
30                         local ln = ipt:read("*l")
31                         if not ln then
32                                 break
33                         elseif ln:match("^%d+") then
34                                 local num, proto, extport, intaddr, intport =
35                                         ln:match("^(%d+).-([a-z]+).-dpt:(%d+) to:(%S-):(%d+)")
36                                 local descr = ""
37
38                                 if num and proto and extport and intaddr and intport then
39                                         num     = tonumber(num)
40                                         extport = tonumber(extport)
41                                         intport = tonumber(intport)
42                                         
43                                         if upnpf then
44                                                 local uln = upnpf:read("*l")
45                                                 if uln then descr = uln:match(string.format("^%s:%d:%s:%d:%%d*:(.*)$", proto:upper(), extport, intaddr, intport)) end
46                                                 if not descr then descr = "" end
47                                         end
48
49                                         fwd[#fwd+1] = {
50                                                 num     = num,
51                                                 proto   = proto:upper(),
52                                                 extport = extport,
53                                                 intaddr = intaddr,
54                                                 intport = intport,
55                                                 descr = descr
56                                         }
57                                 end
58                         end
59                 end
60
61                 if upnpf then upnpf:close() end
62                 ipt:close()
63
64                 luci.http.prepare_content("application/json")
65                 luci.http.write_json(fwd)
66         end
67 end
68
69 function act_delete(num)
70         local idx = tonumber(num)
71         local uci = luci.model.uci.cursor()
72
73         if idx and idx > 0 then
74                 luci.sys.call("iptables -t filter -D MINIUPNPD %d 2>/dev/null" % idx)
75                 luci.sys.call("iptables -t nat -D MINIUPNPD %d 2>/dev/null" % idx)
76
77                 local lease_file = uci:get("upnpd", "config", "upnp_lease_file")
78                 if lease_file and nixio.fs.access(lease_file) then
79                         luci.sys.call("sed -i -e '%dd' %q" %{ idx, lease_file })
80                 end
81
82                 luci.http.status(200, "OK")
83                 return
84         end
85
86         luci.http.status(400, "Bad request")
87 end