Mercurial Hosting > luan
changeset 1295:9dca1e912658
improve web shell
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 10 Jan 2019 21:42:11 -0700 |
parents | 2555154ad19f |
children | 040c98e1f837 |
files | src/luan/lib/json/JsonToString.java src/luan/modules/Html.luan src/luan/modules/http/tools/Shell.luan |
diffstat | 3 files changed, 91 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
diff -r 2555154ad19f -r 9dca1e912658 src/luan/lib/json/JsonToString.java --- a/src/luan/lib/json/JsonToString.java Thu Jan 10 18:22:52 2019 -0700 +++ b/src/luan/lib/json/JsonToString.java Thu Jan 10 21:42:11 2019 -0700 @@ -29,6 +29,12 @@ return sb.toString(); } + public static String encodeString(String s) { + StringBuilder sb = new StringBuilder(); + encodeString(s,sb); + return sb.toString(); + } + private void toString(Object obj,StringBuilder sb,int indented) throws JsonException { if( obj == null || obj instanceof Boolean || obj instanceof Number ) { sb.append(obj); @@ -49,14 +55,22 @@ throw new JsonException("can't handle type "+obj.getClass().getName()); } - private void toString(final String s,StringBuilder sb) { + private static void toString(final String s,StringBuilder sb) { + sb.append('"'); + encodeString(s,sb); sb.append('"'); + } + + private static void encodeString(final String s,StringBuilder sb) { for( int i=0; i<s.length(); i++ ) { char c = s.charAt(i); switch(c) { case '"': sb.append("\\\""); break; + case '\'': + sb.append("\\'"); + break; case '\\': sb.append("\\\\"); break; @@ -79,7 +93,6 @@ sb.append(c); } } - sb.append('"'); } private void toString(List list,StringBuilder sb,int indented) {
diff -r 2555154ad19f -r 9dca1e912658 src/luan/modules/Html.luan --- a/src/luan/modules/Html.luan Thu Jan 10 18:22:52 2019 -0700 +++ b/src/luan/modules/Html.luan Thu Jan 10 21:42:11 2019 -0700 @@ -2,6 +2,7 @@ local HtmlLuan = require "java:luan.modules.HtmlLuan" local HtmlParser = require "java:luan.modules.parsers.Html" local URLEncoder = require "java:java.net.URLEncoder" +local JsonToString = require "java:luan.lib.json.JsonToString" local Luan = require "luan:Luan.luan" local error = Luan.error local ipairs = Luan.ipairs or error() @@ -14,6 +15,7 @@ local Html = {} Html.encode = HtmlLuan.encode +Html.javascript_encode = JsonToString.encodeString local quote = HtmlLuan.quote Html.quote = quote
diff -r 2555154ad19f -r 9dca1e912658 src/luan/modules/http/tools/Shell.luan --- a/src/luan/modules/http/tools/Shell.luan Thu Jan 10 18:22:52 2019 -0700 +++ b/src/luan/modules/http/tools/Shell.luan Thu Jan 10 21:42:11 2019 -0700 @@ -3,15 +3,17 @@ local load = Luan.load or error() local to_string = Luan.to_string or error() local try = Luan.try or error() -local String = require "luan:String.luan" -local concat = String.concat or error() +local range = Luan.range or error() local Table = require "luan:Table.luan" +local concat = Table.concat or error() local pack = Table.pack or error() local unpack = Table.unpack or error() local Time = require "luan:Time.luan" local Thread = require "luan:Thread.luan" +local Html = require "luan:Html.luan" +local html_encode = Html.encode or error() +local javascript_encode = Html.javascript_encode or error() local Io = require "luan:Io.luan" -local print = Io.print or error() local Http = require "luan:http/Http.luan" local Logging = require "luan:logging/Logging.luan" local logger = Logging.logger "Shell" @@ -26,23 +28,13 @@ return to_string(count) end}).next -local history = "" local env = {} Shell.env = env local fns = {} -function fns.history() - return history -end - function fns.run(cmd) - Io.stdout = {} - Io.stdout.write = function(...) - history = concat(history,...) - end - print( "% "..cmd ) - try { + return try { function() local line try { @@ -53,14 +45,11 @@ line = load(cmd,"<web_shell>",env) end } - local rtn = pack( line() ) - if rtn.n > 0 then - print( unpack(rtn) ) - end + return line() end catch = function(e) - Io.print_to(Io.stderr,e) - print(e) +-- Io.print_to(Io.stderr,e) + return to_string(e) end } end @@ -71,74 +60,91 @@ return Thread.global_callable("shell.session"..session_id,timeout,fns) end -local function remove_session(session_id) - return Thread.remove_global_callable("shell.session"..session_id) -end - function Shell.respond() - local session_id = Http.request.cookies["session"] - if session_id == nil then - session_id = new_session() - Http.response.set_cookie("session",session_id) + Io.stdout = Http.response.text_writer() + local cmd = Http.request.parameters.cmd + if cmd ~= nil then + Http.response.headers["content-type"] = "application/javascript" + local session_id = Http.request.parameters.session or error() + local session = get_session(session_id) + local rtn = pack( session.run(cmd) ) +%> + var pre = document.querySelector('pre'); + pre.innerHTML += '\n> <%=javascript_encode(html_encode(cmd))%>'; +<% + if rtn.n > 0 then + local t = {} + for i in range(1,rtn.n) do + t[#t+1] = javascript_encode(html_encode(to_string(rtn[i]))) + end +%> + pre.innerHTML += '\n<%=concat(t,"\t")%>'; +<% + end + return end - local session = get_session(session_id) - - if Http.request.parameters.clear ~= nil then - remove_session(session_id) - Http.response.send_redirect(Http.request.path) -- reload page - return - else - local cmd = Http.request.parameters.cmd - if cmd ~= nil then - session.run(cmd) - end - end - - Io.stdout = Http.response.text_writer() %> <!doctype html> <html> <head> <title>Luan Shell</title> + <script> + + function ajax(url) { + var request = new XMLHttpRequest(); + request.open( 'GET', url ); + request.onload = function() { + if( request.status !== 200 ) { + console.log( 'ajax failed: ' + request.status ); + return; + } + //console.log( request.responseText ); + eval( request.responseText ); + }; + request.send(); + } + + function submitted() { + var input = document.querySelector('input'); + ajax( '?session=<%=new_session()%>&cmd=' + encodeURIComponent(input.value) ); + input.value = ''; + } + + </script> <style> body { font-family: sans-serif; - margin: 2em 5% 0 5%; } pre { font: inherit; + margin-bottom: 0; } - input[type="text"] { - font: inherit; - padding: .5em .8em; - border-radius: 8px; - border-style: groove; - } - input[type="text"]:focus { - border-color: #66afe9; - outline: none; + table { + width: 100%; + border-collapse: collapse; } - input[type="submit"] { - color: white; - background: #337ab7; - border-color: #337ab7; + td { + padding: 0; + } + td:last-child { + width: 100%; + } + input { + width: 100%; font: inherit; - padding: .5em; - border-radius: 4px; - } - input[type="submit"]:hover { - background: #236aa7 !important; + outline: none; } </style> </head> <body> - <h2>Luan Shell</h2> - <p>This is a command shell. Enter commands below.</p> - <pre><%= session.history() %></pre> - <form method='post'> - % <input type="text" name='cmd' size="80" autofocus> - <input type="submit" value="run"> - <input type="submit" name="clear" value="clear"> + <pre>Luan <%=Luan.VERSION%></pre> + <form autocomplete=off onsubmit="submitted(); return false"> + <table> + <tr> + <td>> </td> + <td><input name=cmd autofocus></td> + </tr> + </table> </form> </body> </html>