Mercurial Hosting > nabble
view src/nabble/view/web/more/ForumStart.java @ 36:157eac0dee34
whitelist for mailing lists
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 08 Jul 2020 12:22:41 -0600 |
parents | 61800d34be0d |
children | 40e282462f2e |
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.model.Init; 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.Set; 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 <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" ); } static final Set whitelist = (Set)Init.get("whitelist"); 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()) { if( whitelist!=null && !whitelist.contains(email) ) { logger.info("ignoring "+email); return; } 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) ); } }