diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2014-12-03 15:17:05 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2015-01-08 16:26:20 +0100 |
commit | 1bb4822dca6113f73e3bc89e2acf15935e6f8e92 (patch) | |
tree | 35e16f100466e4e00657199b38bb3d87d52bf73f /applications/luci-commands/luasrc | |
parent | 9edd0e46c3f880727738ce8ca6ff1c8b85f99ef4 (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')
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%> |