view src/nabble/view/web/more/ForumStart.java @ 32:1016a9f81684

minor
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 06 Jul 2020 21:43:38 -0600
parents ab41a84898a9
children 61800d34be0d
line wrap: on
line source


package nabble.view.web.more;

import fschmidt.db.DbDatabase;
import fschmidt.util.mail.MailAddress;
import fschmidt.util.servlet.CanonicalUrl;
import nabble.model.Db;
import nabble.model.Message;
import nabble.model.ModelException;
import nabble.model.ModelHome;
import nabble.model.Site;
import nabble.model.User;
import nabble.naml.compiler.Template;
import nabble.naml.compiler.TemplatePrintWriter;
import nabble.naml.namespaces.BasicNamespace;
import nabble.view.lib.Jtp;
import nabble.view.lib.NewSiteMail;
import nabble.view.lib.Permissions;
import nabble.view.lib.Shared;
import nabble.view.lib.UrlMappable;
import nabble.view.lib.Recaptcha;
import nabble.view.web.app.Languages;
import nabble.view.web.template.NabbleNamespace;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public final class ForumStart extends HttpServlet implements UrlMappable, CanonicalUrl {
	private static final Logger logger = LoggerFactory.getLogger(ForumStart.class);

	private static final Pattern URL_PATTERN = Pattern.compile("/free-(forum|gallery|newspaper|blog|mailing-list)\\.html$");

	public static String url(String what) {
		return Jtp.defaultContextUrl() + path(what);
	}

	public static String path(String what) {
		return "/free-" + what + ".html";
	}

	public String getCanonicalUrl(HttpServletRequest request) {
		return url( request.getParameter("what") );
	}

	public Map<String,String[]> getParameterMapFromUrl(HttpServletRequest request,String mappedUrl) {
		Matcher m = URL_PATTERN.matcher(mappedUrl);
		if( !m.find() )
			throw new RuntimeException();
		Map<String,String[]> params = new HashMap<String,String[]>();
		String what = m.group(1);
		params.put("what",new String[]{what});
		return params;
	}

	public Pattern getUrlPattern() {
		return URL_PATTERN;
	}

	protected void service(HttpServletRequest request,HttpServletResponse response)
		throws ServletException, IOException
	{
		build(request, response, Collections.<String,String>emptyMap(), Collections.<String,String>emptyMap());
	}

	private static void build(HttpServletRequest request,HttpServletResponse response, Map<String,String> values, Map<String,String> errors)
		throws ServletException, IOException
	{
		PrintWriter out = response.getWriter();
		String what = request.getParameter("what");
		if (what == null)
			what = "Forum";
		else if ("mailing-list".equals(what))
			what = "Mailing List";
		else
			what = Jtp.capitalize(what);

		String imgName = what.toLowerCase();
		if ("Mailing List".equals(what))
			imgName = "mailing-list";

		
		out.print( "\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n	<head>\r\n		" );
 Shared.head(request,response); 
		out.print( "\r\n		<title>Nabble - Free " );
		out.print( (what) );
		out.print( " Setup</title>\r\n		<meta name=\"robots\" content=\"noindex\"/>\r\n		<META NAME=\"description\" CONTENT=\"Setting up a free " );
		out.print( (what.toLowerCase()) );
		out.print( " on Nabble is quick and easy. Fill in one simple form and you are done.\">\r\n		<META NAME=\"keywords\" CONTENT=\"free " );
		out.print( (what.toLowerCase()) );
		out.print( ", hosted " );
		out.print( (what.toLowerCase()) );
		out.print( ", simple, embeddable " );
		out.print( (what.toLowerCase()) );
		out.print( ", customizable\">\r\n		<style type=\"text/css\">\r\n			div.center-content {\r\n				margin: 0px auto;\r\n				margin-bottom: 3em;\r\n			}\r\n			td.column1 {\r\n				text-align: right;\r\n				width: 7em;\r\n				white-space: nowrap;\r\n			}\r\n			input[type=text],input[type=password] {\r\n				padding: .4em 0;\r\n			}\r\n			div.field-title {\r\n				margin-top: .3em;\r\n			}\r\n			.important {\r\n				font-weight: bold;\r\n			}\r\n			label {\r\n				vertical-align: -15%;\r\n			}\r\n			#submit-btn {\r\n				padding: .5em .8em;\r\n				font-size: 110%;\r\n				font-weight: bold;\r\n			}\r\n		</style>\r\n		<script type=\"text/javascript\">\r\n\r\n			function singleFormSubmit(f) {\r\n				if (f.done)\r\n					return false;\r\n				f.done = true;\r\n				$('#submit-btn').hide();\r\n				var $div = $('#wait-message');\r\n				function loading1() { $div.fadeTo(300,0.3,loading2);  };\r\n				function loading2() { $div.fadeTo(300,1,loading1);  };\r\n				loading1();\r\n				return true;\r\n			};\r\n\r\n		</script>\r\n		" );
		out.print( ( Recaptcha.JS ) );
		out.print( "\r\n	</head>\r\n	<body style=\"text-align:center\">\r\n		" );
 Shared.minHeaderGlobal(request,response); 
		out.print( "\r\n\r\n		<div class=\"center-content\">\r\n			<img src=\"/images/logo_nabble_home.png\" border=\"0\" alt=\"Nabble - free forums for everyone\"/><br />\r\n			<h1 style=\"color:#979797\">Start Your " );
		out.print( (what) );
		out.print( "</h1>\r\n\r\n			" );
 if (errors.size() > 0) { 
		out.print( "\r\n				<div class=\"error-message important\" style=\"margin:1em;padding:.5em 0\">\r\n					" );
 String generic = errors.get("generic"); 
		out.print( "\r\n					" );
		out.print( (generic != null? generic : errors.size() > 0? "Please check the errors below" : "") );
		out.print( "\r\n				</div>\r\n			" );
 } 
		out.print( "\r\n\r\n			<form action=\"/more/ForumStart$Save.jtp\" method=\"post\" accept-charset=\"UTF-8\" onsubmit=\"return singleFormSubmit(this)\">\r\n				<input type=\"hidden\" name=\"type\" value=\"" );
		out.print( (what.toLowerCase().replace(" ","")) );
		out.print( "\" />\r\n				<input type=\"hidden\" name=\"what\" value=\"" );
		out.print( (what) );
		out.print( "\" />\r\n\r\n				<div style=\"text-align:left;width:50em;margin:0 auto\">\r\n					<div style=\"border-bottom:2px solid #eeeeee;padding:1em\">\r\n						<div class=\"weak-color\" style=\"width:12em;text-align:center;float:left\">\r\n							<div style=\"font-weight:bold\">Account</div>\r\n							<img src=\"/images/account.png\" width=\"84\" height=\"45\"/>\r\n							<div style=\"margin-top:1em;font-size:80%\">\r\n								You will receive an email with a link to activate your account\r\n							</div>\r\n						</div>\r\n						<table>\r\n							<tr>\r\n								<td class=\"column1\"><div class=\"second-font field-title\">User Name</div></td>\r\n								<td><input type=\"text\" autofocus size=\"35\" maxlength=\"30\" name=\"username\" value=\"" );
		out.print( (Jtp.hideNull(values.get("username"))) );
		out.print( "\" /></td>\r\n								<td class=\"important\">" );
		out.print( (errors.containsKey("username")? errors.get("username"):"") );
		out.print( "</td>\r\n							</tr>\r\n							<tr>\r\n								<td class=\"column1\"><div class=\"second-font field-title\">Email</div></td>\r\n								<td><input type=\"text\" size=\"35\" maxlength=\"60\" name=\"email\" value=\"" );
		out.print( (Jtp.hideNull(values.get("email"))) );
		out.print( "\"/></td>\r\n								<td class=\"important\">" );
		out.print( (errors.containsKey("email")? errors.get("email"):"") );
		out.print( "</td>\r\n							</tr>\r\n							<tr>\r\n								<td class=\"column1\"><div class=\"second-font field-title\">Password</div></td>\r\n								<td><input type=\"password\" size=\"35\" maxlength=\"15\" name=\"password\" value=\"" );
		out.print( (Jtp.hideNull(values.get("password"))) );
		out.print( "\"/></td>\r\n								<td class=\"important\">" );
		out.print( (errors.containsKey("password")? errors.get("password"):"") );
		out.print( "</td>\r\n							</tr>\r\n							<tr>\r\n								<td class=\"column1\"><input type=\"checkbox\" id=\"terms\" name=\"terms\" value=\"y\" " );
		out.print( ("y".equals(values.get("terms"))?"checked":"") );
		out.print( " /></td>\r\n								<td colspan=2><label for=\"terms\">I have read and I agree to Nabble's <a href=\"" );
		out.print( (Jtp.termsUrl(true)) );
		out.print( "\">Terms of Use</a>.</label></td>\r\n							</tr>\r\n						</table>\r\n					</div>\r\n\r\n					<div style=\"padding:1em;overflow:hidden\">\r\n						<div class=\"weak-color\" style=\"width:12em;text-align:center;float:left;height:15em\">\r\n							<div style=\"font-weight:bold\">" );
		out.print( (what) );
		out.print( "</div>\r\n							<img src=\"/images/homepage/" );
		out.print( (imgName) );
		out.print( ".png\" alt=\"Free " );
		out.print( (what.toLowerCase()) );
		out.print( "\">\r\n						</div>\r\n						<table>\r\n							<tr>\r\n								<td class=\"column1\"><div class=\"second-font field-title\">Language</div></td>\r\n								<td>\r\n									<select name=\"lang\">\r\n										" );
 for( Map.Entry<String,String> entry : Languages.languages.entrySet() ) { 
		out.print( "\r\n										" );
 String lang = request.getParameter("lang"); 
		out.print( "\r\n										" );
 boolean isEnglish = entry.getKey().equals("none"); 
		out.print( "\r\n										" );
 boolean isSelected = (lang == null && isEnglish) || entry.getKey().equals(lang); 
		out.print( "\r\n										<option value=\"" );
		out.print( (entry.getKey()) );
		out.print( "\" " );
		out.print( (isSelected?"selected=\"true\"":"") );
		out.print( ">" );
		out.print( (entry.getValue()) );
		out.print( "</option>\r\n										" );
 } 
		out.print( "\r\n									</select>\r\n								</td>\r\n								<td></td>\r\n							</tr>\r\n							<tr>\r\n								<td colspan=\"3\" style=\"height:.6em\"></td>\r\n							</tr>\r\n							<tr>\r\n								<td class=\"column1\"><div class=\"second-font field-title\">" );
		out.print( (what) );
		out.print( " Name</div></td>\r\n								<td><input type=\"text\" name=\"subject\" size=\"30\" maxlength=\"80\" value=\"" );
		out.print( (Jtp.hideNull(values.get("subject"))) );
		out.print( "\"/></td>\r\n								<td class=\"important\">" );
		out.print( (errors.containsKey("subject")? errors.get("subject"):"") );
		out.print( "</td>\r\n							</tr>\r\n							<tr>\r\n								<td colspan=3 style=\"padding:.4em 0 0 .6em\">\r\n									<div class=\"second-font field-title\">Description &nbsp;<span class=\"weak-color\" style=\"font-weight:normal;\">(optional)</span></div>\r\n									<textarea rows=\"7\" name=\"message\" wrap=\"SOFT\" style=\"width:28em\">" );
		out.print( (Jtp.hideNull(values.get("message"))) );
		out.print( "</textarea>\r\n									<br>" );
		out.print( ( Recaptcha.DIV ) );
		out.print( "\r\n								</td>\r\n							</tr>\r\n						</table>\r\n					</div>\r\n					<div class=\"weak-color\" style=\"margin-top:.5em;text-align:center;\">\r\n						<input id=\"submit-btn\" type=\"submit\" value=\"Create " );
		out.print( (what) );
		out.print( "\" />\r\n						<div id=\"wait-message\" class=\"important invisible\" style=\"margin:.1em 0\">Creating " );
		out.print( (what) );
		out.print( "... Please wait</div>\r\n					</div>\r\n				</div>\r\n                    </form>\r\n		</div>\r\n\r\n		" );
 Shared.footer(request,response); 
		out.print( "\r\n		" );
 Shared.analytics(request,response); 
		out.print( "\r\n	</body>\r\n</html>\r\n" );

	}


	public static class Save extends HttpServlet {

		private static String get(String name, HttpServletRequest request) {
			String s = request.getParameter(name);
			return s == null ? null : s.trim();
		}

		protected void service(HttpServletRequest request, HttpServletResponse response)
				throws ServletException, IOException
		{
			String username = get("username", request);
			String email = get("email", request);
			String password = get("password", request);
			boolean agreed = "y".equals(get("terms", request));
			String subject = get("subject", request);
			String message = get("message", request);

			Map<String,String> errors = new HashMap<String,String>();
			if (username == null || username.trim().length() == 0)
				errors.put("username", "required");
			if (email == null || email.length() == 0)
				errors.put("email", "required");
			else if (!new MailAddress(email).isValid())
				errors.put("email", "invalid email");
			if (password == null || password.length() < 4)
				errors.put("password", "too short");
			if (!agreed)
				errors.put("generic", "You must agree to the Terms and Conditions");
			if (subject == null || subject.length() == 0)
				errors.put("subject", "required");

			String type = get("type", request);
			type = "newspaper".equals(type)? "news" : type;

			String extraMessage = "";
			if ("mailinglist".equals(type)) {
				type = "forum";
				StringBuilder m = new StringBuilder();
				m.append("\n\nMailing List Options\n");
				m.append("Click \"Options > Subscribe via email\" to subscribe to this mailing list;\n");
				m.append("Click \"Options > Post by email...\" to get the email address of this mailing list;\n");
				m.append("You can post messages via email or through the forum interface below;\n");
				m.append("All web posts and emails are archived here.");
				extraMessage = m.toString();
			}

			if (errors.isEmpty()) {
				DbDatabase db = Db.dbGlobal();
				db.beginTransaction();
				try {
					Recaptcha.check(request);
					Site site = ModelHome.newSite(type,subject, message + extraMessage, Message.Format.TEXT, email, username);
					Permissions.addToGroup( (User)site.getRootNode().getOwner(), Permissions.ADMINISTRATORS_GROUP );
					String key = site.newRegistration(email,password,username,"/");
					db.commitTransaction();

					// Track spam activities by IP
					ModelHome.setRemoteAddr(site, Jtp.getClientIpAddr(request));

					site = site.getGoodCopy();

					String lang = request.getParameter("lang");
					if (!"none".equals(lang)) {
						site.setModuleEnabled(lang, true);
						site = site.getGoodCopy();
					}

					sendRegisterMail(site, email, key);
					NewSiteMail.send(site, request, response);
					response.sendRedirect(site.getBaseUrl()+"/more/ForumStart$Redirection.jtp");
					return;
				} catch(ModelException e) {
					errors.put("generic", e.getMessage());
				} finally {
					db.endTransaction();
				}
			}

			Map<String,String> values = new HashMap<String,String>();
			values.put("username", username);
			values.put("email", email);
			values.put("password", password);
			values.put("terms", agreed?"y":"");
			values.put("subject", subject);
			values.put("message", message);
			build(request, response, values, errors);
		}
	}

	/** Sets cookies in the site domain  */
	public static class Redirection extends HttpServlet {

		protected void service(HttpServletRequest request, HttpServletResponse response)
				throws ServletException, IOException
		{
			Site site = Jtp.getSite(request);
			Shared.javascriptRedirect(request, response, Jtp.url(site.getRootNode()), "Nabble.setVar('appnotice','true');");
		}
	}

	public static void sendRegisterMail(Site site, String email, String key) {
		Map<String,Object> args = new HashMap<String,Object>();
		args.put("email",email);
		args.put("next_url","/");
		args.put("key",key);
		Template template = site.getTemplate( "send_registration_email",
			BasicNamespace.class, NabbleNamespace.class
		);
		template.run( TemplatePrintWriter.NULL, args,
			new BasicNamespace(template), new NabbleNamespace(site)
		);
	}
}