Merge pull request #3291 from rs/feature_nextdns
[oweals/luci.git] / applications / luci-app-opkg / luasrc / controller / opkg.lua
1 -- Copyright 2018 Jo-Philipp Wich <jo@mein.io>
2 -- Licensed to the public under the Apache License 2.0.
3
4 module("luci.controller.opkg", package.seeall)
5
6 function index()
7         entry({"admin", "system", "opkg"}, template("opkg"), _("Software"), 30)
8         entry({"admin", "system", "opkg", "list"}, call("action_list")).leaf = true
9         entry({"admin", "system", "opkg", "exec"}, post("action_exec")).leaf = true
10         entry({"admin", "system", "opkg", "statvfs"}, call("action_statvfs")).leaf = true
11         entry({"admin", "system", "opkg", "config"}, post_on({ data = true }, "action_config")).leaf = true
12 end
13
14 function action_list(mode)
15         local util = require "luci.util"
16         local cmd
17
18         if mode == "installed" then
19                 cmd = { "/bin/cat", "/usr/lib/opkg/status" }
20         else
21                 local lists_dir = nil
22
23                 local fd = io.popen([[sed -rne 's#^lists_dir \S+ (\S+)#\1#p' /etc/opkg.conf /etc/opkg/*.conf 2>/dev/null]], "r")
24                 if fd then
25                         lists_dir = fd:read("*l")
26                         fd:close()
27                 end
28
29                 if not lists_dir or #lists_dir == "" then
30                         lists_dir = "/tmp/opkg-lists"
31                 end
32
33                 cmd = { "/bin/sh", "-c", [[find %s -type f '!' -name '*.sig' | xargs -r gzip -cd]] % util.shellquote(lists_dir) }
34         end
35
36         luci.http.prepare_content("text/plain; charset=utf-8")
37         luci.sys.process.exec(cmd, luci.http.write)
38 end
39
40 function action_exec(command, package)
41         local sys = require "luci.sys"
42         local cmd = { "/bin/opkg", "--force-removal-of-dependent-packages" }
43         local pkg = luci.http.formvalue("package")
44
45         if luci.http.formvalue("autoremove") == "true" then
46                 cmd[#cmd + 1] = "--autoremove"
47         end
48
49         if luci.http.formvalue("overwrite") == "true" then
50                 cmd[#cmd + 1] = "--force-overwrite"
51         end
52
53         cmd[#cmd + 1] = command
54
55         if pkg then
56                 cmd[#cmd + 1] = pkg
57         end
58
59         luci.http.prepare_content("application/json")
60         luci.http.write_json(sys.process.exec(cmd, true, true))
61 end
62
63 function action_statvfs()
64         local fs = require "nixio.fs"
65
66         luci.http.prepare_content("application/json")
67         luci.http.write_json(fs.statvfs("/") or {})
68 end
69
70 function action_config()
71         local fs = require "nixio.fs"
72         local js = require "luci.jsonc"
73         local data = luci.http.formvalue("data")
74
75         if data then
76                 data = js.parse(data)
77
78                 if not data then
79                         luci.http.status(400, "Bad Request")
80                         return
81                 end
82
83                 local file, content
84                 for file, content in pairs(data) do
85                         if type(content) ~= "string" or
86                            (file ~= "opkg.conf" and not file:match("^opkg/[^/]+%.conf$"))
87                         then
88                                 luci.http.status(400, "Bad Request")
89                                 return
90                         end
91
92                         local path = "/etc/%s" % file
93                         if not fs.access(path, "w") then
94                                 luci.http.status(403, "Permission denied")
95                                 return
96                         end
97
98                         fs.writefile(path, content:gsub("\r\n", "\n"))
99                 end
100
101                 luci.http.status(204, "Saved")
102         else
103                 local rv = { ["opkg.conf"] = fs.readfile("/etc/opkg.conf") }
104                 local entries = fs.dir("/etc/opkg")
105                 if entries then
106                         local entry
107                         for entry in entries do
108                                 if entry:match("%.conf$") then
109                                         rv["opkg/%s" % entry] = fs.readfile("/etc/opkg/%s" % entry)
110                                 end
111                         end
112                 end
113
114                 luci.http.prepare_content("application/json")
115                 luci.http.write_json(rv)
116         end
117 end