view src/nabble/view/web/template/NodePageNamespace.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line source

package nabble.view.web.template;

import fschmidt.db.DbDatabase;
import nabble.model.FileUpload;
import nabble.model.Message;
import nabble.model.ModelException;
import nabble.model.Node;
import nabble.model.Person;
import nabble.naml.compiler.Command;
import nabble.naml.compiler.CommandSpec;
import nabble.naml.compiler.IPrintWriter;
import nabble.naml.compiler.Interpreter;
import nabble.naml.compiler.Namespace;
import nabble.naml.compiler.ScopedInterpreter;
import nabble.naml.namespaces.TemplateException;
import nabble.view.lib.Jtp;
import nabble.view.lib.Permissions;
import nabble.view.web.forum.NodeEditorNamespace;
import nabble.view.web.forum.SearchNamespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Random;


@Namespace (
	name = "node_page",
	global = true
)
public final class NodePageNamespace {

	private static final Logger logger = LoggerFactory.getLogger(NodePageNamespace.class);

	private NodeNamespace nodeNs;

	public NodePageNamespace(Node node) {
		this(new NodeNamespace(node));
	}

	public NodePageNamespace(NodeNamespace nodeNs) {
		this.nodeNs = nodeNs;
	}

	public final Node node() {
		return nodeNs.node();
	}

	public final NodeNamespace nodeNamespace() {
		return nodeNs;
	}

	private DbDatabase db() {
		return node().getSite().getDb();
	}


	public static final CommandSpec page_node = CommandSpec.DO;

	@Command public void page_node(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		out.print( interp.getArg(nodeNs,"do") );
	}

	public static final CommandSpec search_namespace = CommandSpec.DO()
		.requiredInStack(ServletNamespace.class)
		.build()
	;

	@Command public void search_namespace(IPrintWriter out,ScopedInterpreter<SearchNamespace> interp)
		throws ServletException
	{
		ServletNamespace servletNamespace = interp.getFromStack(ServletNamespace.class);
		out.print( interp.getArg(new SearchNamespace(node(),servletNamespace),"do") );
	}


	public static final CommandSpec edit_page_node = CommandSpec.DO()
		.optionalParameters("commit")
		.requiredInStack(ServletNamespace.class)
		.build()
	;

	@Command public void edit_page_node(IPrintWriter out,ScopedInterpreter<NodeEditorNamespace> interp) {
		ServletNamespace servletNs = interp.getFromStack(ServletNamespace.class);
		boolean commit = interp.getArgAsBoolean("commit",true);
		DbDatabase db = db();
		db.beginTransaction();
		try {
			nodeNs.refreshNode();
			interp.getArgString(new NodeEditorNamespace(node(),servletNs),"do");
			if( commit ) {
				db.commitTransaction();
				nodeNs.refreshNode();
			}
		} finally {
			db.endTransaction();
		}
	}


	public static final CommandSpec create_child_of_page_node = CommandSpec.DO()
		.parameters("subject","message","is_html","kind")
		.optionalParameters("commit","type")
		.restrictedParameter("kind","app","post")
		.requiredInStack(ServletNamespace.class)
		.build()
	;

	@Command public void create_child_of_page_node(IPrintWriter out,ScopedInterpreter<NodeEditorNamespace> interp)
		throws ModelException, ServletException
	{
		ServletNamespace servletNs = interp.getFromStack(ServletNamespace.class);
		HttpServletRequest request = servletNs.request;
		boolean commit = interp.getArgAsBoolean("commit",true);
		String subject = interp.getArgString("subject");
		String message = interp.getArgString("message");
		Message.Format msgFmt = interp.getArgAsBoolean("is_html",false) ? Message.Format.HTML : Message.Format.TEXT;
		String type = interp.getArgString("type");
		Node.Kind kind = "app".equals(interp.getArgString("kind"))? Node.Kind.APP : Node.Kind.POST;
		Person visitor = servletNs.getVisitor();
		DbDatabase db = db();
		db.beginTransaction();
		try {
			nodeNs.refreshNode();
			Node node = node();
			Node newNode = visitor.newChildNode(kind,subject,message,msgFmt,node);
			FileUpload.checkFileTags(newNode.getMessage(), visitor);
			if (type != null)
				newNode.setType(type);
			interp.getArgString(new NodeEditorNamespace(newNode,servletNs),"do");
			if( commit ) {
				db.commitTransaction();
				nodeNs.refreshNode();
			}
		} finally {
			db.endTransaction();
		}
	}

	private static final long TWO_HOURS = 2 * 60 * 60 * 1000;

	@Command public void should_show_creation_notice(IPrintWriter out,Interpreter interp) {
		long created = node().getWhenCreated().getTime();
		out.print( System.currentTimeMillis() - created < TWO_HOURS );
	}


	//
	// Spambot security checker
	//
	private static final byte SUBMIT_POSSIBILITIES = 10;
	private static final long START = new Date().getTime();
	private static final long FIVE_MINUTES = 5 * 60 * 1000;
	private static final Random SECURITY_RND = new Random();

	public static final CommandSpec antispam_submit_button = CommandSpec.DO()
		.parameters("class", "value")
		.requiredInStack(ServletNamespace.class)
		.build()
	;

	@Command public void antispam_submit_button(IPrintWriter out,Interpreter interp) {
		ServletNamespace servletNs = interp.getFromStack(ServletNamespace.class);
		HttpServletRequest request = servletNs.request;

		String className = interp.getArgString("class");
		String value = interp.getArgString("value");

		Byte goodIndex = (byte) SECURITY_RND.nextInt(SUBMIT_POSSIBILITIES);
		request.getSession().setAttribute("sec"+node().getId(), goodIndex);
		for (byte i = 0; i < SUBMIT_POSSIBILITIES; i++) {
			out.print("<input id=\"s" + i + "\" type=\"submit\" class=\""+ className + "\" value=\"" + value + "\" name=\"s" + i + "\" style=\"display:none\"/>");
		}
		String elementId = "s" + goodIndex;
		StringBuilder bufValue = new StringBuilder();
		for (int i = 0; i < elementId.length(); i++) {
			if (bufValue.length() > 0)
				bufValue.append(',');
			bufValue.append((int) elementId.charAt(i));
		}
		out.print("<script type='text/javascript'>");
		out.print("var sv=String.fromCharCode("+ bufValue.toString() +");");
		out.print("document.getElementById(sv).style.display='inline-block';");
		out.print("</script>");
	}

	public static final CommandSpec check_antispam_submit = CommandSpec.DO()
		.optionalParameters("bypass")
		.requiredInStack(ServletNamespace.class)
		.build()
	;

	@Command public void check_antispam_submit(IPrintWriter out,Interpreter interp)
			throws TemplateException
	{
		ServletNamespace servletNs = interp.getFromStack(ServletNamespace.class);
		HttpServletRequest request = servletNs.request;

		String bypass = interp.getArgString("bypass");
		if (bypass != null && request.getParameter(bypass) != null)
			return;

		String attributeName = "sec"+node().getId();
		Byte goodIndex = (Byte) request.getSession().getAttribute(attributeName);
		boolean isSafe = goodIndex != null;
		if (isSafe) {
			for (int i= 0; i < SUBMIT_POSSIBILITIES; i++) {
				String param = request.getParameter("s"+i);
				if (i == goodIndex)
					isSafe = isSafe &&  param != null;
				else
					isSafe = isSafe && param == null;
			}
		}
		request.getSession().removeAttribute(attributeName);
		if (!isSafe) {
			long now = new Date().getTime();
			if (now - START > FIVE_MINUTES) {
				logger.error("suspicious_request - IP: " + Jtp.getClientIpAddr(request));
				throw TemplateException.newInstance("suspicious_request");
			}
		}
	}
}