changeset 170:7c792a328a83

add web component git-svn-id: https://luan-java.googlecode.com/svn/trunk@171 21e917c8-12df-6dd8-5cb6-c86387c605b9
author fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9>
date Sun, 22 Jun 2014 05:20:30 +0000
parents 9169581dc8fc
children 3dcb0f9bee82
files ext/servlet-api-2.5.jar ext/slf4j-api-1.6.4.jar src/luan/modules/web/HttpLuan.java src/luan/modules/web/web_run.luan src/luan/modules/web/web_shell.luan web/ext/servlet-api-2.5.jar web/ext/slf4j-api-1.6.4.jar web/src/luan/modules/web/HttpLuan.java web/src/luan/modules/web/web_run.luan web/src/luan/modules/web/web_shell.luan
diffstat 10 files changed, 383 insertions(+), 383 deletions(-) [+]
line wrap: on
line diff
diff -r 9169581dc8fc -r 7c792a328a83 ext/servlet-api-2.5.jar
Binary file ext/servlet-api-2.5.jar has changed
diff -r 9169581dc8fc -r 7c792a328a83 ext/slf4j-api-1.6.4.jar
Binary file ext/slf4j-api-1.6.4.jar has changed
diff -r 9169581dc8fc -r 7c792a328a83 src/luan/modules/web/HttpLuan.java
--- a/src/luan/modules/web/HttpLuan.java	Sun Jun 22 04:52:16 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-package luan.modules.web;
-
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-import java.util.Arrays;
-import java.util.Enumeration;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import luan.Luan;
-import luan.LuanState;
-import luan.LuanFunction;
-import luan.LuanElement;
-import luan.LuanException;
-import luan.LuanTable;
-import luan.LuanJavaFunction;
-import luan.LuanExitException;
-import luan.DeepCloner;
-import luan.modules.PackageLuan;
-import luan.modules.IoLuan;
-
-
-public final class HttpLuan {
-
-	public static final LuanFunction LOADER = new LuanFunction() {
-		@Override public Object call(LuanState luan,Object[] args) {
-			return new LuanTable();  // starts empty
-		}
-	};
-
-	public static void service(LuanState luan,HttpServletRequest request,HttpServletResponse response,String modName)
-		throws LuanException
-	{
-		LuanFunction fn;
-		synchronized(luan) {
-			Object mod = PackageLuan.require(luan,modName);
-			if( !(mod instanceof LuanTable) )
-				throw luan.exception( "module '"+modName+"' must return a table" );
-			LuanTable tbl = (LuanTable)mod;
-			if( Luan.toBoolean( tbl.get("per_session") ) ) {
-				HttpSession session = request.getSession();
-				LuanState sessionLuan  = (LuanState)session.getValue("luan");
-				if( sessionLuan!=null ) {
-					luan = sessionLuan;
-				} else {
-					DeepCloner cloner = new DeepCloner();
-					luan = cloner.deepClone(luan);
-					session.putValue("luan",luan);
-				}
-				tbl = (LuanTable)PackageLuan.require(luan,modName);
-				fn = (LuanFunction)tbl.get("page");
-			} else {
-				fn = (LuanFunction)tbl.get("page");
-				if( fn == null )
-					throw luan.exception( "function 'page' is not defined" );
-				DeepCloner cloner = new DeepCloner();
-				luan = cloner.deepClone(luan);
-				fn = cloner.get(fn);
-			}
-		}
-
-		LuanTable module = (LuanTable)luan.loaded().get("Http");
-		if( module == null )
-			throw luan.exception( "module 'Http' not defined" );
-		HttpLuan lib = new HttpLuan(request,response);
-		try {
-			module.put( "request", lib.requestTable() );
-			module.put( "response", lib.responseTable() );
-/*
-			module.put( "write", new LuanJavaFunction(
-				HttpLuan.class.getMethod( "text_write", LuanState.class, new Object[0].getClass() ), lib
-			) );
-*/
-		} catch(NoSuchMethodException e) {
-			throw new RuntimeException(e);
-		}
-
-		luan.call(fn,"<http>");
-	}
-
-
-
-	private final HttpServletRequest request;
-	private final HttpServletResponse response;
-//	private PrintWriter writer = null;
-//	private ServletOutputStream sos = null;
-
-	private HttpLuan(HttpServletRequest request,HttpServletResponse response) {
-		this.request = request;
-		this.response = response;
-	}
-
-	private LuanTable requestTable() throws NoSuchMethodException {
-		LuanTable req = new LuanTable();
-		req.put("java",request);
-		req.put( "get_attribute", new LuanJavaFunction(HttpServletRequest.class.getMethod("getAttribute",String.class),request) );
-		req.put( "set_attribute", new LuanJavaFunction(HttpServletRequest.class.getMethod("setAttribute",String.class,Object.class),request) );
-		req.put( "get_parameter", new LuanJavaFunction(HttpServletRequest.class.getMethod("getParameter",String.class),request) );
-		req.put( "get_parameter_values", new LuanJavaFunction(HttpServletRequest.class.getMethod("getParameterValues",String.class),request) );
-		req.put( "get_header", new LuanJavaFunction(HttpServletRequest.class.getMethod("getHeader",String.class),request) );
-		add( req, "get_cookie_value", String.class );
-		req.put( "method", new LuanJavaFunction(HttpServletRequest.class.getMethod("getMethod"),request) );
-		req.put( "servlet_path", new LuanJavaFunction(HttpServletRequest.class.getMethod("getServletPath"),request) );
-		req.put( "server_name", new LuanJavaFunction(HttpServletRequest.class.getMethod("getServerName"),request) );
-		add( req, "current_url" );
-		req.put( "remote_address", new LuanJavaFunction(HttpServletRequest.class.getMethod("getRemoteAddr"),request) );
-		add( req, "get_session_attribute", String.class );
-		add( req, "set_session_attribute", String.class, Object.class );
-		return req;
-	}
-
-	private LuanTable responseTable() throws NoSuchMethodException {
-		LuanTable resp = new LuanTable();
-		resp.put("java",response);
-		add( resp, "send_redirect", String.class );
-		add( resp, "send_error", Integer.TYPE, String.class );
-		resp.put( "contains_header", new LuanJavaFunction(HttpServletResponse.class.getMethod("containsHeader",String.class),response) );
-		resp.put( "set_header", new LuanJavaFunction(HttpServletResponse.class.getMethod("setHeader",String.class,String.class),response) );
-		add( resp, "set_cookie", String.class, String.class, Boolean.TYPE, String.class );
-		add( resp, "remove_cookie", String.class, String.class );
-		resp.put( "set_content_type", new LuanJavaFunction(HttpServletResponse.class.getMethod("setContentType",String.class),response) );
-		add( resp, "text_writer" );
-		return resp;
-	}
-
-	private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
-		t.put( method, new LuanJavaFunction(HttpLuan.class.getMethod(method,parameterTypes),this) );
-	}
-/*
-	public void text_write(LuanState luan,Object... args) throws LuanException, IOException {
-		if( writer == null )
-			writer = response.getWriter();
-		for( Object obj : args ) {
-			writer.print( luan.toString(obj) );
-		}
-	}
-*/
-	public LuanTable text_writer() throws IOException {
-		return IoLuan.textWriter(response.getWriter());
-	}
-
-	public String get_cookie_value(String name) {
-		return getCookieValue(request, name);
-	}
-
-	public String current_url() {
-		return getCurrentURL(request);
-	}
-
-	public void send_redirect(String redirectUrl)
-		throws IOException
-	{
-		response.sendRedirect(redirectUrl);
-		throw new LuanExitException();
-	}
-
-	public void send_error(int code,String text)
-		throws IOException
-	{
-		response.sendError(code, text);
-		throw new LuanExitException();
-	}
-
-	public void set_cookie(String name,String value,boolean isPersistent, String domain) {
-		setCookie(request,response,name,value,isPersistent,domain);
-	}
-
-	public void remove_cookie(String name, String domain) {
-		removeCookie(request,response,name,domain);
-	}
-
-	public Object get_session_attribute(String name) {
-		return request.getSession().getAttribute(name);
-	}
-
-	public void set_session_attribute(String name,Object value) {
-		request.getSession().setAttribute(name,value);
-	}
-
-
-	// static utils
-
-	public static String getQueryString(HttpServletRequest request) {
-		return getQueryString(request,0);
-	}
-
-	public static String getQueryString(HttpServletRequest request,int maxValueLen) {
-		String method = request.getMethod();
-		if( method.equals("GET") )
-			return request.getQueryString();
-		if( !method.equals("POST") && !method.equals("HEAD") )
-			throw new RuntimeException(method);
-		Enumeration en = request.getParameterNames();
-		StringBuilder queryBuf = new StringBuilder();
-		if( !en.hasMoreElements() )
-			return null;
-		do {
-			String param = (String)en.nextElement();
-			String value = request.getParameter(param);
-			if( maxValueLen > 0 ) {
-				int len = value.length();
-				if( len > maxValueLen )
-					value = value.substring(0,maxValueLen) + "..." + (len-maxValueLen);
-			}
-			queryBuf.append(param);
-			queryBuf.append('=');
-			queryBuf.append(value);
-			queryBuf.append('&');
-		} while( en.hasMoreElements() );
-		queryBuf.deleteCharAt(queryBuf.length() - 1);
-		return queryBuf.toString();
-	}
-
-	public static String getCurrentURL(HttpServletRequest request) {
-		return getCurrentURL(request,0);
-	}
-
-	public static String getCurrentURL(HttpServletRequest request,int maxValueLen) {
-//		StringBuffer buf = HttpUtils.getRequestURL(request);
-		StringBuffer buf = request.getRequestURL();
-		String qStr = getQueryString(request,maxValueLen);
-		if(qStr != null && qStr.length() > 0) {
-			buf.append('?');
-			buf.append(qStr);
-		}
-		return buf.toString();
-	}
-
-	private static String escape(String value) {
-		return value.replaceAll(";", "%3B");
-	}
-
-	private static String unescape(String value) {
-		return value.replaceAll("%3B", ";");
-	}
-
-	private static Cookie getCookie(HttpServletRequest request,String name) {
-		Cookie[] cookies = request.getCookies();
-		if( cookies == null )
-			return null;
-		for (Cookie cookie : cookies) {
-			if (cookie.getName().equals(name))
-				return cookie;
-		}
-		return null;
-	}
-
-	public static String getCookieValue(HttpServletRequest request,String name) {
-		Cookie cookie = getCookie(request,name);
-		return cookie==null ? null : unescape(cookie.getValue());
-	}
-
-	public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,boolean isPersistent, String domain) {
-		Cookie cookie = getCookie(request,name);
-		if( cookie==null || !cookie.getValue().equals(value) ) {
-			cookie = new Cookie(name, escape(value));
-			cookie.setPath("/");
-			if (domain != null && domain.length() > 0)
-				cookie.setDomain(domain);
-			if( isPersistent )
-				cookie.setMaxAge(10000000);
-			response.addCookie(cookie);
-		}
-	}
-
-	public static void removeCookie(HttpServletRequest request,
-									HttpServletResponse response,
-									String name,
-									String domain
-
-	) {
-		Cookie cookie = getCookie(request, name);
-		if(cookie != null) {
-			Cookie delCookie = new Cookie(name, "delete");
-			delCookie.setPath("/");
-			delCookie.setMaxAge(0);
-			if (domain != null && domain.length() > 0)
-				delCookie.setDomain(domain);
-			response.addCookie(delCookie);
-		}
-	}
-
-}
diff -r 9169581dc8fc -r 7c792a328a83 src/luan/modules/web/web_run.luan
--- a/src/luan/modules/web/web_run.luan	Sun Jun 22 04:52:16 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-import "Http"
-
-local function lines(s)
-	local matcher = String.gmatch(s,"([^\n]*)\n|([^\n])+$")
-	return function()
-		local m1, m2 = matcher()
-		return m1 or m2
-	end
-end
-
-local function print_with_line_numbers(s)
-	i = 1
-	for line in lines(s) do
-		print(i,line)
-		i = i + 1
-	end
-end
-
-function page()
-	local content_type = Http.request.get_parameter("content_type")
-	if content_type ~= nil then
-		Http.response.set_content_type(content_type)
-	end
-	Io.stdout = Http.response.text_writer()
-	local code = Http.request.get_parameter "code"
-	local env = {
-		request = Http.request;
-		response = Http.response;
-	}
-	try
-		local run = load(code,"<web_run>",env)
-		run()
-	catch e do
-		Http.response.set_content_type "text/plain"
-		print(e)
-		print()
-		print()
-		print_with_line_numbers(code)
-	end
-end
diff -r 9169581dc8fc -r 7c792a328a83 src/luan/modules/web/web_shell.luan
--- a/src/luan/modules/web/web_shell.luan	Sun Jun 22 04:52:16 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-import "Http"
-
-per_session = true
-
-local history = {}
-local env = {}
-
-Io.stdout = {}
-function Io.stdout.write(...)
-	for _,v in Basic.values(...) do
-		history[#history+1] = v
-	end
-end
-
-function page()
-	if Http.request.get_parameter("clear") ~= nil then
-		history = {}
-	else
-		local cmd = Http.request.get_parameter("cmd")
-		if cmd ~= nil then
-			print( "% "..cmd )
-			try
-				local line = load(cmd,"<web_shell>",env,true);
-				Debug.print_if_something( line() )
-			catch e do
-				Io.print_to(Io.stderr,e)
-				print(e)
-			end
-		end
-	end
-
-	local write = Http.response.text_writer().write
-	write %>
-<html>
-<title>Luan Shell</title>
-	<body>
-		<p>This is a command shell.  Enter commands below.
-		<pre><%
-		for _,v in ipairs(history) do
-			write(v)
-		end
-		write %></pre>
-		<form name='theForm' method='post'>
-			% <input name='cmd' size=60>
-			<input type=submit value=run>
-			<input type=submit name=clear value=clear>
-		</form>
-		
-		<script>document.theForm.cmd.focus();</script>
-		
-		<p/>
-	</body>
-</html>
-<%
-
-end
diff -r 9169581dc8fc -r 7c792a328a83 web/ext/servlet-api-2.5.jar
Binary file web/ext/servlet-api-2.5.jar has changed
diff -r 9169581dc8fc -r 7c792a328a83 web/ext/slf4j-api-1.6.4.jar
Binary file web/ext/slf4j-api-1.6.4.jar has changed
diff -r 9169581dc8fc -r 7c792a328a83 web/src/luan/modules/web/HttpLuan.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/src/luan/modules/web/HttpLuan.java	Sun Jun 22 05:20:30 2014 +0000
@@ -0,0 +1,287 @@
+package luan.modules.web;
+
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import java.util.Arrays;
+import java.util.Enumeration;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import luan.Luan;
+import luan.LuanState;
+import luan.LuanFunction;
+import luan.LuanElement;
+import luan.LuanException;
+import luan.LuanTable;
+import luan.LuanJavaFunction;
+import luan.LuanExitException;
+import luan.DeepCloner;
+import luan.modules.PackageLuan;
+import luan.modules.IoLuan;
+
+
+public final class HttpLuan {
+
+	public static final LuanFunction LOADER = new LuanFunction() {
+		@Override public Object call(LuanState luan,Object[] args) {
+			return new LuanTable();  // starts empty
+		}
+	};
+
+	public static void service(LuanState luan,HttpServletRequest request,HttpServletResponse response,String modName)
+		throws LuanException
+	{
+		LuanFunction fn;
+		synchronized(luan) {
+			Object mod = PackageLuan.require(luan,modName);
+			if( !(mod instanceof LuanTable) )
+				throw luan.exception( "module '"+modName+"' must return a table" );
+			LuanTable tbl = (LuanTable)mod;
+			if( Luan.toBoolean( tbl.get("per_session") ) ) {
+				HttpSession session = request.getSession();
+				LuanState sessionLuan  = (LuanState)session.getValue("luan");
+				if( sessionLuan!=null ) {
+					luan = sessionLuan;
+				} else {
+					DeepCloner cloner = new DeepCloner();
+					luan = cloner.deepClone(luan);
+					session.putValue("luan",luan);
+				}
+				tbl = (LuanTable)PackageLuan.require(luan,modName);
+				fn = (LuanFunction)tbl.get("page");
+			} else {
+				fn = (LuanFunction)tbl.get("page");
+				if( fn == null )
+					throw luan.exception( "function 'page' is not defined" );
+				DeepCloner cloner = new DeepCloner();
+				luan = cloner.deepClone(luan);
+				fn = cloner.get(fn);
+			}
+		}
+
+		LuanTable module = (LuanTable)luan.loaded().get("Http");
+		if( module == null )
+			throw luan.exception( "module 'Http' not defined" );
+		HttpLuan lib = new HttpLuan(request,response);
+		try {
+			module.put( "request", lib.requestTable() );
+			module.put( "response", lib.responseTable() );
+/*
+			module.put( "write", new LuanJavaFunction(
+				HttpLuan.class.getMethod( "text_write", LuanState.class, new Object[0].getClass() ), lib
+			) );
+*/
+		} catch(NoSuchMethodException e) {
+			throw new RuntimeException(e);
+		}
+
+		luan.call(fn,"<http>");
+	}
+
+
+
+	private final HttpServletRequest request;
+	private final HttpServletResponse response;
+//	private PrintWriter writer = null;
+//	private ServletOutputStream sos = null;
+
+	private HttpLuan(HttpServletRequest request,HttpServletResponse response) {
+		this.request = request;
+		this.response = response;
+	}
+
+	private LuanTable requestTable() throws NoSuchMethodException {
+		LuanTable req = new LuanTable();
+		req.put("java",request);
+		req.put( "get_attribute", new LuanJavaFunction(HttpServletRequest.class.getMethod("getAttribute",String.class),request) );
+		req.put( "set_attribute", new LuanJavaFunction(HttpServletRequest.class.getMethod("setAttribute",String.class,Object.class),request) );
+		req.put( "get_parameter", new LuanJavaFunction(HttpServletRequest.class.getMethod("getParameter",String.class),request) );
+		req.put( "get_parameter_values", new LuanJavaFunction(HttpServletRequest.class.getMethod("getParameterValues",String.class),request) );
+		req.put( "get_header", new LuanJavaFunction(HttpServletRequest.class.getMethod("getHeader",String.class),request) );
+		add( req, "get_cookie_value", String.class );
+		req.put( "method", new LuanJavaFunction(HttpServletRequest.class.getMethod("getMethod"),request) );
+		req.put( "servlet_path", new LuanJavaFunction(HttpServletRequest.class.getMethod("getServletPath"),request) );
+		req.put( "server_name", new LuanJavaFunction(HttpServletRequest.class.getMethod("getServerName"),request) );
+		add( req, "current_url" );
+		req.put( "remote_address", new LuanJavaFunction(HttpServletRequest.class.getMethod("getRemoteAddr"),request) );
+		add( req, "get_session_attribute", String.class );
+		add( req, "set_session_attribute", String.class, Object.class );
+		return req;
+	}
+
+	private LuanTable responseTable() throws NoSuchMethodException {
+		LuanTable resp = new LuanTable();
+		resp.put("java",response);
+		add( resp, "send_redirect", String.class );
+		add( resp, "send_error", Integer.TYPE, String.class );
+		resp.put( "contains_header", new LuanJavaFunction(HttpServletResponse.class.getMethod("containsHeader",String.class),response) );
+		resp.put( "set_header", new LuanJavaFunction(HttpServletResponse.class.getMethod("setHeader",String.class,String.class),response) );
+		add( resp, "set_cookie", String.class, String.class, Boolean.TYPE, String.class );
+		add( resp, "remove_cookie", String.class, String.class );
+		resp.put( "set_content_type", new LuanJavaFunction(HttpServletResponse.class.getMethod("setContentType",String.class),response) );
+		add( resp, "text_writer" );
+		return resp;
+	}
+
+	private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException {
+		t.put( method, new LuanJavaFunction(HttpLuan.class.getMethod(method,parameterTypes),this) );
+	}
+/*
+	public void text_write(LuanState luan,Object... args) throws LuanException, IOException {
+		if( writer == null )
+			writer = response.getWriter();
+		for( Object obj : args ) {
+			writer.print( luan.toString(obj) );
+		}
+	}
+*/
+	public LuanTable text_writer() throws IOException {
+		return IoLuan.textWriter(response.getWriter());
+	}
+
+	public String get_cookie_value(String name) {
+		return getCookieValue(request, name);
+	}
+
+	public String current_url() {
+		return getCurrentURL(request);
+	}
+
+	public void send_redirect(String redirectUrl)
+		throws IOException
+	{
+		response.sendRedirect(redirectUrl);
+		throw new LuanExitException();
+	}
+
+	public void send_error(int code,String text)
+		throws IOException
+	{
+		response.sendError(code, text);
+		throw new LuanExitException();
+	}
+
+	public void set_cookie(String name,String value,boolean isPersistent, String domain) {
+		setCookie(request,response,name,value,isPersistent,domain);
+	}
+
+	public void remove_cookie(String name, String domain) {
+		removeCookie(request,response,name,domain);
+	}
+
+	public Object get_session_attribute(String name) {
+		return request.getSession().getAttribute(name);
+	}
+
+	public void set_session_attribute(String name,Object value) {
+		request.getSession().setAttribute(name,value);
+	}
+
+
+	// static utils
+
+	public static String getQueryString(HttpServletRequest request) {
+		return getQueryString(request,0);
+	}
+
+	public static String getQueryString(HttpServletRequest request,int maxValueLen) {
+		String method = request.getMethod();
+		if( method.equals("GET") )
+			return request.getQueryString();
+		if( !method.equals("POST") && !method.equals("HEAD") )
+			throw new RuntimeException(method);
+		Enumeration en = request.getParameterNames();
+		StringBuilder queryBuf = new StringBuilder();
+		if( !en.hasMoreElements() )
+			return null;
+		do {
+			String param = (String)en.nextElement();
+			String value = request.getParameter(param);
+			if( maxValueLen > 0 ) {
+				int len = value.length();
+				if( len > maxValueLen )
+					value = value.substring(0,maxValueLen) + "..." + (len-maxValueLen);
+			}
+			queryBuf.append(param);
+			queryBuf.append('=');
+			queryBuf.append(value);
+			queryBuf.append('&');
+		} while( en.hasMoreElements() );
+		queryBuf.deleteCharAt(queryBuf.length() - 1);
+		return queryBuf.toString();
+	}
+
+	public static String getCurrentURL(HttpServletRequest request) {
+		return getCurrentURL(request,0);
+	}
+
+	public static String getCurrentURL(HttpServletRequest request,int maxValueLen) {
+//		StringBuffer buf = HttpUtils.getRequestURL(request);
+		StringBuffer buf = request.getRequestURL();
+		String qStr = getQueryString(request,maxValueLen);
+		if(qStr != null && qStr.length() > 0) {
+			buf.append('?');
+			buf.append(qStr);
+		}
+		return buf.toString();
+	}
+
+	private static String escape(String value) {
+		return value.replaceAll(";", "%3B");
+	}
+
+	private static String unescape(String value) {
+		return value.replaceAll("%3B", ";");
+	}
+
+	private static Cookie getCookie(HttpServletRequest request,String name) {
+		Cookie[] cookies = request.getCookies();
+		if( cookies == null )
+			return null;
+		for (Cookie cookie : cookies) {
+			if (cookie.getName().equals(name))
+				return cookie;
+		}
+		return null;
+	}
+
+	public static String getCookieValue(HttpServletRequest request,String name) {
+		Cookie cookie = getCookie(request,name);
+		return cookie==null ? null : unescape(cookie.getValue());
+	}
+
+	public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,boolean isPersistent, String domain) {
+		Cookie cookie = getCookie(request,name);
+		if( cookie==null || !cookie.getValue().equals(value) ) {
+			cookie = new Cookie(name, escape(value));
+			cookie.setPath("/");
+			if (domain != null && domain.length() > 0)
+				cookie.setDomain(domain);
+			if( isPersistent )
+				cookie.setMaxAge(10000000);
+			response.addCookie(cookie);
+		}
+	}
+
+	public static void removeCookie(HttpServletRequest request,
+									HttpServletResponse response,
+									String name,
+									String domain
+
+	) {
+		Cookie cookie = getCookie(request, name);
+		if(cookie != null) {
+			Cookie delCookie = new Cookie(name, "delete");
+			delCookie.setPath("/");
+			delCookie.setMaxAge(0);
+			if (domain != null && domain.length() > 0)
+				delCookie.setDomain(domain);
+			response.addCookie(delCookie);
+		}
+	}
+
+}
diff -r 9169581dc8fc -r 7c792a328a83 web/src/luan/modules/web/web_run.luan
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/src/luan/modules/web/web_run.luan	Sun Jun 22 05:20:30 2014 +0000
@@ -0,0 +1,40 @@
+import "Http"
+
+local function lines(s)
+	local matcher = String.gmatch(s,"([^\n]*)\n|([^\n])+$")
+	return function()
+		local m1, m2 = matcher()
+		return m1 or m2
+	end
+end
+
+local function print_with_line_numbers(s)
+	i = 1
+	for line in lines(s) do
+		print(i,line)
+		i = i + 1
+	end
+end
+
+function page()
+	local content_type = Http.request.get_parameter("content_type")
+	if content_type ~= nil then
+		Http.response.set_content_type(content_type)
+	end
+	Io.stdout = Http.response.text_writer()
+	local code = Http.request.get_parameter "code"
+	local env = {
+		request = Http.request;
+		response = Http.response;
+	}
+	try
+		local run = load(code,"<web_run>",env)
+		run()
+	catch e do
+		Http.response.set_content_type "text/plain"
+		print(e)
+		print()
+		print()
+		print_with_line_numbers(code)
+	end
+end
diff -r 9169581dc8fc -r 7c792a328a83 web/src/luan/modules/web/web_shell.luan
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/src/luan/modules/web/web_shell.luan	Sun Jun 22 05:20:30 2014 +0000
@@ -0,0 +1,56 @@
+import "Http"
+
+per_session = true
+
+local history = {}
+local env = {}
+
+Io.stdout = {}
+function Io.stdout.write(...)
+	for _,v in Basic.values(...) do
+		history[#history+1] = v
+	end
+end
+
+function page()
+	if Http.request.get_parameter("clear") ~= nil then
+		history = {}
+	else
+		local cmd = Http.request.get_parameter("cmd")
+		if cmd ~= nil then
+			print( "% "..cmd )
+			try
+				local line = load(cmd,"<web_shell>",env,true);
+				Debug.print_if_something( line() )
+			catch e do
+				Io.print_to(Io.stderr,e)
+				print(e)
+			end
+		end
+	end
+
+	local write = Http.response.text_writer().write
+	write %>
+<html>
+<title>Luan Shell</title>
+	<body>
+		<p>This is a command shell.  Enter commands below.
+		<pre><%
+		for _,v in ipairs(history) do
+			write(v)
+		end
+		write %></pre>
+		<form name='theForm' method='post'>
+			% <input name='cmd' size=60>
+			<input type=submit value=run>
+			<input type=submit name=clear value=clear>
+		</form>
+		
+		<script>document.theForm.cmd.focus();</script>
+		
+		<p/>
+	</body>
+</html>
+<%
+
+end