summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-commands/luasrc
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2014-12-03 15:17:05 +0100
committerJo-Philipp Wich <jow@openwrt.org>2015-01-08 16:26:20 +0100
commit1bb4822dca6113f73e3bc89e2acf15935e6f8e92 (patch)
tree35e16f100466e4e00657199b38bb3d87d52bf73f /applications/luci-commands/luasrc
parent9edd0e46c3f880727738ce8ca6ff1c8b85f99ef4 (diff)
Rework LuCI build system
* Rename subdirectories to their repective OpenWrt package names * Make each LuCI module its own standalone package * Deploy a shared luci.mk which is used by each module Makefile Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
Diffstat (limited to 'applications/luci-commands/luasrc')
-rw-r--r--applications/luci-commands/luasrc/controller/commands.lua237
-rw-r--r--applications/luci-commands/luasrc/model/cbi/commands.lua37
-rw-r--r--applications/luci-commands/luasrc/view/commands.htm176
3 files changed, 0 insertions, 450 deletions
diff --git a/applications/luci-commands/luasrc/controller/commands.lua b/applications/luci-commands/luasrc/controller/commands.lua
deleted file mode 100644
index b9f0ce8794..0000000000
--- a/applications/luci-commands/luasrc/controller/commands.lua
+++ /dev/null
@@ -1,237 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-]]--
-
-module("luci.controller.commands", package.seeall)
-
-function index()
- entry({"admin", "system", "commands"}, firstchild(), _("Custom Commands"), 80)
- entry({"admin", "system", "commands", "dashboard"}, template("commands"), _("Dashboard"), 1)
- entry({"admin", "system", "commands", "config"}, cbi("commands"), _("Configure"), 2)
- entry({"admin", "system", "commands", "run"}, call("action_run"), nil, 3).leaf = true
- entry({"admin", "system", "commands", "download"}, call("action_download"), nil, 3).leaf = true
-
- entry({"command"}, call("action_public"), nil, 1).leaf = true
-end
-
---- Decode a given string into arguments following shell quoting rules
---- [[abc \def "foo\"bar" abc'def']] -> [[abc def]] [[foo"bar]] [[abcdef]]
-local function parse_args(str)
- local args = { }
-
- local function isspace(c)
- if c == 9 or c == 10 or c == 11 or c == 12 or c == 13 or c == 32 then
- return c
- end
- end
-
- local function isquote(c)
- if c == 34 or c == 39 or c == 96 then
- return c
- end
- end
-
- local function isescape(c)
- if c == 92 then
- return c
- end
- end
-
- local function ismeta(c)
- if c == 36 or c == 92 or c == 96 then
- return c
- end
- end
-
- --- Convert given table of byte values into a Lua string and append it to
- --- the "args" table. Segment byte value sequence into chunks of 256 values
- --- to not trip over the parameter limit for string.char()
- local function putstr(bytes)
- local chunks = { }
- local csz = 256
- local upk = unpack
- local chr = string.char
- local min = math.min
- local len = #bytes
- local off
-
- for off = 1, len, csz do
- chunks[#chunks+1] = chr(upk(bytes, off, min(off + csz - 1, len)))
- end
-
- args[#args+1] = table.concat(chunks)
- end
-
- --- Scan substring defined by the indexes [s, e] of the string "str",
- --- perform unquoting and de-escaping on the fly and store the result in
- --- a table of byte values which is passed to putstr()
- local function unquote(s, e)
- local off, esc, quote
- local res = { }
-
- for off = s, e do
- local byte = str:byte(off)
- local q = isquote(byte)
- local e = isescape(byte)
- local m = ismeta(byte)
-
- if e then
- esc = true
- elseif esc then
- if m then res[#res+1] = 92 end
- res[#res+1] = byte
- esc = false
- elseif q and quote and q == quote then
- quote = nil
- elseif q and not quote then
- quote = q
- else
- if m then res[#res+1] = 92 end
- res[#res+1] = byte
- end
- end
-
- putstr(res)
- end
-
- --- Find substring boundaries in "str". Ignore escaped or quoted
- --- whitespace, pass found start- and end-index for each substring
- --- to unquote()
- local off, esc, start, quote
- for off = 1, #str + 1 do
- local byte = str:byte(off)
- local q = isquote(byte)
- local s = isspace(byte) or (off > #str)
- local e = isescape(byte)
-
- if esc then
- esc = false
- elseif e then
- esc = true
- elseif q and quote and q == quote then
- quote = nil
- elseif q and not quote then
- start = start or off
- quote = q
- elseif s and not quote then
- if start then
- unquote(start, off - 1)
- start = nil
- end
- else
- start = start or off
- end
- end
-
- --- If the "quote" is still set we encountered an unfinished string
- if quote then
- unquote(start, #str)
- end
-
- return args
-end
-
-local function parse_cmdline(cmdid, args)
- local uci = require "luci.model.uci".cursor()
- if uci:get("luci", cmdid) == "command" then
- local cmd = uci:get_all("luci", cmdid)
- local argv = parse_args(cmd.command)
- local i, v
-
- if cmd.param == "1" and args then
- for i, v in ipairs(parse_args(luci.http.urldecode(args))) do
- argv[#argv+1] = v
- end
- end
-
- for i, v in ipairs(argv) do
- if v:match("[^%w%.%-i/]") then
- argv[i] = '"%s"' % v:gsub('"', '\\"')
- end
- end
-
- return argv
- end
-end
-
-function action_run(...)
- local fs = require "nixio.fs"
- local argv = parse_cmdline(...)
- if argv then
- local outfile = os.tmpname()
- local errfile = os.tmpname()
-
- local rv = os.execute(table.concat(argv, " ") .. " >%s 2>%s" %{ outfile, errfile })
- local stdout = fs.readfile(outfile, 1024 * 512) or ""
- local stderr = fs.readfile(errfile, 1024 * 512) or ""
-
- fs.unlink(outfile)
- fs.unlink(errfile)
-
- local binary = not not (stdout:match("[%z\1-\8\14-\31]"))
-
- luci.http.prepare_content("application/json")
- luci.http.write_json({
- command = table.concat(argv, " "),
- stdout = not binary and stdout,
- stderr = stderr,
- exitcode = rv,
- binary = binary
- })
- else
- luci.http.status(404, "No such command")
- end
-end
-
-function action_download(...)
- local fs = require "nixio.fs"
- local argv = parse_cmdline(...)
- if argv then
- local fd = io.popen(table.concat(argv, " ") .. " 2>/dev/null")
- if fd then
- local chunk = fd:read(4096) or ""
- local name
- if chunk:match("[%z\1-\8\14-\31]") then
- luci.http.header("Content-Disposition", "attachment; filename=%s"
- % fs.basename(argv[1]):gsub("%W+", ".") .. ".bin")
- luci.http.prepare_content("application/octet-stream")
- else
- luci.http.header("Content-Disposition", "attachment; filename=%s"
- % fs.basename(argv[1]):gsub("%W+", ".") .. ".txt")
- luci.http.prepare_content("text/plain")
- end
-
- while chunk do
- luci.http.write(chunk)
- chunk = fd:read(4096)
- end
-
- fd:close()
- else
- luci.http.status(500, "Failed to execute command")
- end
- else
- luci.http.status(404, "No such command")
- end
-end
-
-function action_public(cmdid, args)
- local uci = require "luci.model.uci".cursor()
- if cmdid and
- uci:get("luci", cmdid) == "command" and
- uci:get("luci", cmdid, "public") == "1"
- then
- action_download(cmdid, args)
- else
- luci.http.status(403, "Access to command denied")
- end
-end
diff --git a/applications/luci-commands/luasrc/model/cbi/commands.lua b/applications/luci-commands/luasrc/model/cbi/commands.lua
deleted file mode 100644
index 1359eb2acd..0000000000
--- a/applications/luci-commands/luasrc/model/cbi/commands.lua
+++ /dev/null
@@ -1,37 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-]]--
-
-local m, s
-
-m = Map("luci", translate("Custom Commands"),
- translate("This page allows you to configure custom shell commands which can be easily invoked from the web interface."))
-
-s = m:section(TypedSection, "command", "")
-s.template = "cbi/tblsection"
-s.anonymous = true
-s.addremove = true
-
-
-s:option(Value, "name", translate("Description"),
- translate("A short textual description of the configured command"))
-
-s:option(Value, "command", translate("Command"),
- translate("Command line to execute"))
-
-s:option(Flag, "param", translate("Custom arguments"),
- translate("Allow the user to provide additional command line arguments"))
-
-s:option(Flag, "public", translate("Public access"),
- translate("Allow executing the command and downloading its output without prior authentication"))
-
-return m
diff --git a/applications/luci-commands/luasrc/view/commands.htm b/applications/luci-commands/luasrc/view/commands.htm
deleted file mode 100644
index 83792a91fd..0000000000
--- a/applications/luci-commands/luasrc/view/commands.htm
+++ /dev/null
@@ -1,176 +0,0 @@
-<%#
-LuCI - Lua Configuration Interface
-Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
--%>
-
-<% css = [[
-
-.commandbox {
- height: 12em;
- width: 30%;
- float: left;
- height: 12em;
- margin: 5px;
- position: relative;
-}
-
-.commandbox h3 {
- font-size: 1.5em !important;
- line-height: 2em !important;
- margin: 0 !important;
-}
-
-.commandbox input[type="text"] {
- width: 50% !important;
-}
-
-.commandbox div {
- position: absolute;
- left: 0;
- bottom: 1.5em;
-}
-
-]] -%>
-
-<%+header%>
-
-<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
-<script type="text/javascript">//<![CDATA[
- var stxhr = new XHR();
-
- function command_run(id)
- {
- var args;
- var field = document.getElementById(id);
- if (field)
- args = encodeURIComponent(field.value);
-
- var legend = document.getElementById('command-rc-legend');
- var output = document.getElementById('command-rc-output');
-
- if (legend && output)
- {
- output.innerHTML =
- '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
- '<%:Waiting for command to complete...%>'
- ;
-
- legend.parentNode.style.display = 'block';
- legend.style.display = 'inline';
-
- stxhr.get('<%=luci.dispatcher.build_url("admin", "system", "commands", "run")%>/' + id + (args ? '/' + args : ''), null,
- function(x, st)
- {
- if (st)
- {
- if (st.binary)
- st.stdout = '[<%:Binary data not displayed, download instead.%>]';
-
- legend.style.display = 'none';
- output.innerHTML = String.format(
- '<pre><strong># %h\n</strong>%h<span style="color:red">%h</span></pre>' +
- '<div class="alert-message warning">%s (<%:Code:%> %d)</div>',
- st.command, st.stdout, st.stderr,
- (st.exitcode == 0) ? '<%:Command successful%>' : '<%:Command failed%>',
- st.exitcode);
- }
- else
- {
- legend.style.display = 'none';
- output.innerHTML = '<span class="error"><%:Failed to execute command!%></span>';
- }
-
- location.hash = '#output';
- }
- );
- }
- }
-
- function command_download(id)
- {
- var args;
- var field = document.getElementById(id);
- if (field)
- args = encodeURIComponent(field.value);
-
- location.href = '<%=luci.dispatcher.build_url("admin", "system", "commands", "download")%>/' + id + (args ? '/' + args : '');
- }
-
- function command_link(id)
- {
- var legend = document.getElementById('command-rc-legend');
- var output = document.getElementById('command-rc-output');
-
- var args;
- var field = document.getElementById(id);
- if (field)
- args = encodeURIComponent(field.value);
-
- if (legend && output)
- {
- var link = location.protocol + '//' + location.hostname +
- (location.port ? ':' + location.port : '') +
- location.pathname.split(';')[0] + 'command/' +
- id + (args ? '/' + args : '');
-
- legend.style.display = 'none';
- output.parentNode.style.display = 'block';
- output.innerHTML = String.format(
- '<div class="alert-message"><%:Access command with%> <a href="%s">%s</a></div>',
- link, link
- );
-
- location.hash = '#output';
- }
- }
-
-//]]></script>
-
-<%
- local uci = require "luci.model.uci".cursor()
- local commands = { }
-
- uci:foreach("luci", "command", function(s) commands[#commands+1] = s end)
-%>
-
-<form method="get" action="<%=pcdata(luci.http.getenv("REQUEST_URI"))%>">
- <div class="cbi-map">
- <h2><a id="content" name="content"><%:Custom Commands%></a></h2>
-
- <fieldset class="cbi-section">
- <% local _, command; for _, command in ipairs(commands) do %>
- <div class="commandbox">
- <h3><%=pcdata(command.name)%></h3>
- <p><%:Command:%> <code><%=pcdata(command.command)%></code></p>
- <% if command.param == "1" then %>
- <p><%:Arguments:%> <input type="text" id="<%=command['.name']%>" /></p>
- <% end %>
- <div>
- <input type="button" value="<%:Run%>" class="cbi-button cbi-button-apply" onclick="command_run('<%=command['.name']%>')" />
- <input type="button" value="<%:Download%>" class="cbi-button cbi-button-download" onclick="command_download('<%=command['.name']%>')" />
- <% if command.public == "1" then %>
- <input type="button" value="<%:Link%>" class="cbi-button cbi-button-link" onclick="command_link('<%=command['.name']%>')" />
- <% end %>
- </div>
- </div>
- <% end %>
-
- <br style="clear:both" /><br />
- <a name="output"></a>
- </fieldset>
- </div>
-
- <fieldset class="cbi-section" style="display:none">
- <legend id="command-rc-legend"><%:Collecting data...%></legend>
- <span id="command-rc-output"></span>
- </fieldset>
-</form>
-
-<%+footer%>