summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-opkg/luasrc
diff options
context:
space:
mode:
Diffstat (limited to 'applications/luci-app-opkg/luasrc')
-rw-r--r--applications/luci-app-opkg/luasrc/controller/opkg.lua100
-rw-r--r--applications/luci-app-opkg/luasrc/view/opkg.htm140
2 files changed, 240 insertions, 0 deletions
diff --git a/applications/luci-app-opkg/luasrc/controller/opkg.lua b/applications/luci-app-opkg/luasrc/controller/opkg.lua
new file mode 100644
index 0000000000..74aa166184
--- /dev/null
+++ b/applications/luci-app-opkg/luasrc/controller/opkg.lua
@@ -0,0 +1,100 @@
+-- Copyright 2018 Jo-Philipp Wich <jo@mein.io>
+-- Licensed to the public under the Apache License 2.0.
+
+module("luci.controller.opkg", package.seeall)
+
+function index()
+ entry({"admin", "system", "opkg"}, template("opkg"), _("Software"), 30)
+ entry({"admin", "system", "opkg", "list"}, call("action_list")).leaf = true
+ entry({"admin", "system", "opkg", "exec"}, post("action_exec")).leaf = true
+ entry({"admin", "system", "opkg", "statvfs"}, call("action_statvfs")).leaf = true
+ entry({"admin", "system", "opkg", "config"}, post_on({ data = true }, "action_config")).leaf = true
+end
+
+function action_list(mode)
+ local cmd
+
+ if mode == "installed" then
+ cmd = { "/bin/cat", "/usr/lib/opkg/status" }
+ else
+ cmd = { "/bin/sh", "-c", [[find /tmp/opkg-lists/ -type f '!' -name '*.sig' | xargs -r gzip -cd]] }
+ end
+
+ luci.http.prepare_content("text/plain; charset=utf-8")
+ luci.sys.process.exec(cmd, luci.http.write)
+end
+
+function action_exec(command, package)
+ local sys = require "luci.sys"
+ local cmd = { "/bin/opkg", "--force-removal-of-dependent-packages", "--force-overwrite" }
+ local pkg = luci.http.formvalue("package")
+
+ if luci.http.formvalue("autoremove") == "true" then
+ cmd[#cmd + 1] = "--autoremove"
+ end
+
+ cmd[#cmd + 1] = command
+
+ if pkg then
+ cmd[#cmd + 1] = pkg
+ end
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(sys.process.exec(cmd, true, true))
+end
+
+function action_statvfs()
+ local fs = require "nixio.fs"
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(fs.statvfs("/") or {})
+end
+
+function action_config()
+ local fs = require "nixio.fs"
+ local js = require "luci.jsonc"
+ local data = luci.http.formvalue("data")
+
+ if data then
+ data = js.parse(data)
+
+ if not data then
+ luci.http.status(400, "Bad Request")
+ return
+ end
+
+ local file, content
+ for file, content in pairs(data) do
+ if type(content) ~= "string" or
+ (file ~= "opkg.conf" and not file:match("^opkg/[^/]+%.conf$"))
+ then
+ luci.http.status(400, "Bad Request")
+ return
+ end
+
+ local path = "/etc/%s" % file
+ if not fs.access(path, "w") then
+ luci.http.status(403, "Permission denied")
+ return
+ end
+
+ fs.writefile(path, content:gsub("\r\n", "\n"))
+ end
+
+ luci.http.status(204, "Saved")
+ else
+ local rv = { ["opkg.conf"] = fs.readfile("/etc/opkg.conf") }
+ local entries = fs.dir("/etc/opkg")
+ if entries then
+ local entry
+ for entry in entries do
+ if entry:match("%.conf$") then
+ rv["opkg/%s" % entry] = fs.readfile("/etc/opkg/%s" % entry)
+ end
+ end
+ end
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(rv)
+ end
+end
diff --git a/applications/luci-app-opkg/luasrc/view/opkg.htm b/applications/luci-app-opkg/luasrc/view/opkg.htm
new file mode 100644
index 0000000000..0d2a4e2920
--- /dev/null
+++ b/applications/luci-app-opkg/luasrc/view/opkg.htm
@@ -0,0 +1,140 @@
+<%#
+ Copyright 2018 Jo-Philipp Wich <jo@mein.io>
+ Licensed to the public under the Apache License 2.0.
+-%>
+
+<%+header%>
+
+<style type="text/css">
+ .controls {
+ display: flex;
+ margin: .5em 0 1em 0;
+ flex-wrap: wrap;
+ justify-content: space-around;
+ }
+
+ .controls > * {
+ padding: .25em;
+ white-space: nowrap;
+ flex: 1 1 33%;
+ box-sizing: border-box;
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ .controls > *:first-child,
+ .controls > * > label {
+ flex-basis: 100%;
+ min-width: 250px;
+ }
+
+ .controls > * > .btn {
+ flex-basis: 20px;
+ text-align: center;
+ }
+
+ .controls > * > * {
+ flex-grow: 1;
+ align-self: center;
+ }
+
+ .controls > div > input {
+ width: auto;
+ }
+
+ .td.version,
+ .td.size {
+ white-space: nowrap;
+ }
+
+ ul.deps, ul.deps ul, ul.errors {
+ margin-left: 1em;
+ }
+
+ ul.deps li, ul.errors li {
+ list-style: none;
+ }
+
+ ul.deps li:before {
+ content: "↳";
+ display: inline-block;
+ width: 1em;
+ margin-left: -1em;
+ }
+
+ ul.deps li > span {
+ white-space: nowrap;
+ }
+
+ ul.errors li {
+ color: #c44;
+ font-size: 90%;
+ font-weight: bold;
+ padding-left: 1.5em;
+ }
+
+ ul.errors li:before {
+ content: "⚠";
+ display: inline-block;
+ width: 1.5em;
+ margin-left: -1.5em;
+ }
+</style>
+
+<h2><%:Software%></h2>
+
+<div class="controls">
+ <div>
+ <label><%:Free space%>:</label>
+ <div class="cbi-progressbar" title="<%:unknown%>">
+ <div>&#160;</div>
+ </div>
+ </div>
+
+ <div>
+ <label><%:Filter%>:</label>
+ <input type="text" name="filter" placeholder="<%:Type to filter…%>"<%=attr("value", luci.http.formvalue("query") or "")%> /><!--
+ --><button class="btn cbi-button" onclick="handleReset(event)"><%:Clear%></button>
+ </div>
+
+ <div>
+ <label><%:Download and install package%>:</label>
+ <input type="text" name="install" placeholder="<%:Package name or URL…%>" onkeydown="if (event.keyCode === 13) handleManualInstall(event)" /><!--
+ --><button class="btn cbi-button cbi-button-action" onclick="handleManualInstall(event)"><%:OK%></button>
+ </div>
+
+ <div>
+ <label><%:Actions%>:</label>
+ <button class="btn cbi-button-positive" data-command="update" onclick="handleOpkg(event)"><%:Update lists…%></button>
+ &#160;
+ <button class="btn cbi-button-neutral" onclick="handleConfig(event)"><%:Configure opkg…%></button>
+ </div>
+</div>
+
+<ul class="cbi-tabmenu mode">
+ <li data-mode="available" class="available cbi-tab"><a href="#"><%:Available%></a></li>
+ <li data-mode="installed" class="installed cbi-tab-disabled"><a href="#"><%:Installed%></a></li>
+ <li data-mode="updates" class="installed cbi-tab-disabled"><a href="#"><%:Updates%></a></li>
+</ul>
+
+<div class="controls" style="display:none">
+ <div id="pager" class="center">
+ <button class="btn cbi-button-neutral prev" aria-label="<%:Previous page%>">«</button>
+ <div class="text">dummy</div>
+ <button class="btn cbi-button-neutral next" aria-label="<%:Next page%>">»</button>
+ </div>
+</div>
+
+<div class="table" id="packages">
+ <div class="tr cbi-section-table-titles">
+ <div class="th col-2 left"><%:Package name%></div>
+ <div class="th col-2 left version"><%:Version%></div>
+ <div class="th col-1 center size"><%:Size (.ipk)%></div>
+ <div class="th col-10 left"><%:Description%></div>
+ <div class="th right">&#160;</div>
+ </div>
+</div>
+
+<script type="text/javascript" src="<%=resource%>/view/opkg.js"></script>
+
+<%+footer%>