0
|
1 package nabble.view.web.template;
|
|
2
|
|
3 import fschmidt.util.java.HtmlUtils;
|
|
4 import fschmidt.util.servlet.JtpContext;
|
|
5 import fschmidt.util.servlet.ServletUtils;
|
|
6 import nabble.model.DailyNumber;
|
|
7 import nabble.model.ModelException;
|
|
8 import nabble.model.Node;
|
|
9 import nabble.model.Person;
|
|
10 import nabble.model.Site;
|
|
11 import nabble.model.User;
|
|
12 import nabble.model.ViewCount;
|
|
13 import nabble.naml.compiler.Command;
|
|
14 import nabble.naml.compiler.CommandSpec;
|
|
15 import nabble.naml.compiler.Encoder;
|
|
16 import nabble.naml.compiler.ExitException;
|
|
17 import nabble.naml.compiler.IPrintWriter;
|
|
18 import nabble.naml.compiler.Interpreter;
|
|
19 import nabble.naml.compiler.Namespace;
|
|
20 import nabble.naml.compiler.ScopedInterpreter;
|
|
21 import nabble.naml.namespaces.CommandDoc;
|
|
22 import nabble.naml.namespaces.TemplateException;
|
|
23 import nabble.view.lib.Jtp;
|
|
24 import nabble.view.lib.MyJtpServlet;
|
|
25 import nabble.view.lib.Shared;
|
|
26 import nabble.view.web.user.OnlineStatus;
|
|
27 import nabble.view.lib.Recaptcha;
|
|
28 import org.slf4j.Logger;
|
|
29 import org.slf4j.LoggerFactory;
|
|
30
|
|
31 import javax.servlet.ServletException;
|
|
32 import javax.servlet.http.HttpServletRequest;
|
|
33 import javax.servlet.http.HttpServletResponse;
|
|
34 import java.io.IOException;
|
|
35 import java.io.PrintWriter;
|
|
36 import java.io.StringWriter;
|
|
37 import java.security.NoSuchAlgorithmException;
|
|
38 import java.util.HashMap;
|
|
39 import java.util.Map;
|
|
40 import java.util.Set;
|
|
41 import java.util.HashSet;
|
|
42 import java.util.regex.Matcher;
|
|
43 import java.util.regex.Pattern;
|
|
44
|
|
45
|
|
46 @Namespace (
|
|
47 name = "servlet",
|
|
48 global = true
|
|
49 )
|
|
50 public final class ServletNamespace extends RequestNamespace {
|
|
51 private static final Logger logger = LoggerFactory.getLogger(ServletNamespace.class);
|
|
52
|
|
53 public final HttpServletResponse response;
|
|
54 private final NabbleNamespace nabbleNs;
|
|
55 private UserNamespace visitorNs = null;
|
|
56
|
|
57 public ServletNamespace(HttpServletRequest request, HttpServletResponse response) {
|
|
58 super(request);
|
|
59 this.response = response;
|
|
60 this.nabbleNs = NabbleNamespace.current();
|
|
61 }
|
|
62
|
|
63 public final JtpContext jtpContext() {
|
|
64 return MyJtpServlet.getJtpContext();
|
|
65 }
|
|
66
|
|
67 private Site site() {
|
|
68 return nabbleNs.site();
|
|
69 }
|
|
70
|
|
71 private UserNamespace visitorNamespace()
|
|
72 throws ServletException
|
|
73 {
|
|
74 if( visitorNs == null ) {
|
|
75 if(Jtp.isCached(request,response) )
|
|
76 throw new RuntimeException("can't get visitor on cached page");
|
|
77 Person visitor = Jtp.getVisitor(request, response);
|
|
78 visitorNs = new UserNamespace(visitor);
|
|
79 }
|
|
80 return visitorNs;
|
|
81 }
|
|
82
|
|
83 @Command public void dont_cache(IPrintWriter out,Interpreter interp) {
|
|
84 Jtp.dontCache(response);
|
|
85 }
|
|
86
|
|
87 @Command public void default_host_name(IPrintWriter out,Interpreter interp) {
|
|
88 out.print(Jtp.getDefaultHost());
|
|
89 }
|
|
90
|
|
91 public Person getVisitor()
|
|
92 throws ServletException
|
|
93 {
|
|
94 return visitorNamespace().person();
|
|
95 }
|
|
96
|
|
97 public User getVisitorUser()
|
|
98 throws ServletException
|
|
99 {
|
|
100 Person visitor = getVisitor();
|
|
101 return !(visitor instanceof User) ? null : (User)visitor;
|
|
102 }
|
|
103
|
|
104
|
|
105 public static final CommandSpec visitor = CommandSpec.DO;
|
|
106
|
|
107 @Command public void visitor(IPrintWriter out,ScopedInterpreter<UserNamespace> interp)
|
|
108 throws ServletException
|
|
109 {
|
|
110 out.print( interp.getArg(visitorNamespace(),"do") );
|
|
111 }
|
|
112
|
|
113
|
|
114 private Map<String,FieldNamespace> fields;
|
|
115
|
|
116 public static final CommandSpec field = new CommandSpec.Builder()
|
|
117 .scopedParameters("do")
|
|
118 .dotParameter("do")
|
|
119 .parameters("name")
|
|
120 .build()
|
|
121 ;
|
|
122
|
|
123 @Command public void field(IPrintWriter out,ScopedInterpreter<FieldNamespace> interp) {
|
|
124 String name = interp.getArgString("name");
|
|
125 if (fields == null)
|
|
126 fields = new HashMap<String,FieldNamespace>();
|
|
127 FieldNamespace field = fields.get(name);
|
|
128 if( field == null ) {
|
|
129 field = new FieldNamespace(name);
|
|
130 field.setValue(request);
|
|
131 FieldNamespace f = fields.put(name,field);
|
|
132 if( f != null )
|
|
133 throw new RuntimeException("field named '"+name+"' already defined");
|
|
134 }
|
|
135 out.print( interp.getArg(field,"do") );
|
|
136 }
|
|
137
|
|
138 public static final CommandSpec redirect_to = CommandSpec.NO_OUTPUT()
|
|
139 .dotParameter("url")
|
|
140 .build()
|
|
141 ;
|
|
142
|
|
143 @Command public void redirect_to(IPrintWriter out,Interpreter interp)
|
|
144 throws IOException
|
|
145 {
|
|
146 interp.setEncoder(Encoder.TEXT);
|
|
147 String redirectUrl = interp.getArgString("url").trim();
|
|
148 Jtp.sendRedirect(request,response,redirectUrl);
|
|
149 throw new ExitException();
|
|
150 }
|
|
151
|
|
152 public static final CommandSpec redirect_with_notice = new CommandSpec.Builder()
|
|
153 .parameters("url")
|
|
154 .dotParameter("notice")
|
|
155 .build()
|
|
156 ;
|
|
157
|
|
158 @Command public void redirect_with_notice(IPrintWriter out,Interpreter interp)
|
|
159 throws IOException, ServletException
|
|
160 {
|
|
161 String notice = interp.getArgString("notice").trim();
|
|
162 notice = notice.replaceAll("(\n|\r|\t)","");
|
|
163 notice = HtmlUtils.javascriptStringEncode(notice);
|
|
164 String redirectUrl = interp.getArgString("url").trim();
|
|
165 Shared.javascriptRedirect(request, response, redirectUrl, "Nabble.setVar('notice','" + notice + "');");
|
|
166 throw new ExitException();
|
|
167 }
|
|
168
|
|
169 public static final CommandSpec profile_update_with_redirection_to = CommandSpec.NO_OUTPUT()
|
|
170 .dotParameter("url")
|
|
171 .build()
|
|
172 ;
|
|
173
|
|
174 @Command public void profile_update_with_redirection_to(IPrintWriter out,Interpreter interp)
|
|
175 throws IOException, ServletException
|
|
176 {
|
|
177 StringBuffer js = new StringBuffer();
|
|
178 String userId = ServletUtils.getCookieValue(request,"userId");
|
|
179 if (Jtp.isInteger(userId)) {
|
|
180 Person visitor = site().getUser(Long.valueOf(userId));
|
|
181 if (visitor != null && visitor instanceof User) {
|
|
182 User user = (User) visitor;
|
|
183 String name = user.getName();
|
|
184 String passcookie = user.getPasscookie();
|
|
185 ServletUtils.setCookie(request, response, "username", HtmlUtils.urlEncode(name), true, null);
|
|
186 ServletUtils.setCookie(request, response, "password", HtmlUtils.urlEncode(passcookie), true, null);
|
|
187 js.append("if (parent.nabbleinfo) {");
|
|
188 js.append("Nabble.setCookie('username','").append(HtmlUtils.javascriptStringEncode(HtmlUtils.urlEncode(name))).append("');");
|
|
189 js.append("Nabble.setCookie('password','").append(HtmlUtils.javascriptStringEncode(HtmlUtils.urlEncode(passcookie))).append("');");
|
|
190 js.append("}");
|
|
191 }
|
|
192 }
|
|
193 String redirectUrl = interp.getArgString("url").trim();
|
|
194 Shared.javascriptRedirect(request, response, redirectUrl, js.toString());
|
|
195 throw new ExitException();
|
|
196 }
|
|
197
|
|
198 public static final CommandSpec send_http_error = new CommandSpec.Builder()
|
|
199 .parameters("code")
|
|
200 .dotParameter("text")
|
|
201 .build()
|
|
202 ;
|
|
203
|
|
204 @Command public void send_http_error(IPrintWriter out,Interpreter interp)
|
|
205 throws IOException
|
|
206 {
|
|
207 String text = interp.getArgString("text").trim();
|
|
208 int code = interp.getArgAsInt("code");
|
|
209 response.sendError(code, text);
|
|
210 throw new ExitException();
|
|
211 }
|
|
212
|
|
213
|
|
214 @Command public void set_visitor_online(IPrintWriter out,Interpreter interp)
|
|
215 throws ServletException
|
|
216 {
|
|
217 Person visitor = Jtp.getVisitor(request, response);
|
|
218 OnlineStatus.setOnline(request, visitor, site());
|
|
219 }
|
|
220
|
|
221 public static final CommandSpec author_is_online = new CommandSpec.Builder()
|
|
222 .parameters("search_id")
|
|
223 .build()
|
|
224 ;
|
|
225
|
|
226 @Command public void author_is_online(IPrintWriter out,Interpreter interp) {
|
|
227 String authorId = interp.getArgString("search_id");
|
|
228 out.print( OnlineStatus.isOnline(authorId, site()) );
|
|
229 }
|
|
230
|
|
231
|
|
232 public static final CommandSpec nabble_html = new CommandSpec.Builder()
|
|
233 .scopedParameters("do","output")
|
|
234 .build()
|
|
235 ;
|
|
236 @CommandDoc(
|
|
237 "Commands in \"do\" call \"put_in_head\" and print to the body at the same time. Commands in \"output\" can't do this. The \"output\" is the final output."
|
|
238 )
|
|
239 @Command public void nabble_html(IPrintWriter out,ScopedInterpreter<HtmlNamespace> interp) {
|
|
240 HtmlNamespace ns = new HtmlNamespace(interp);
|
|
241 out.print( interp.getArg(ns,"output") );
|
|
242 }
|
|
243
|
|
244
|
|
245 public static final CommandSpec check_user = new CommandSpec.Builder()
|
|
246 .dotParameter("user_id")
|
|
247 .outputtedParameters()
|
|
248 .build()
|
|
249 ;
|
|
250
|
|
251 @Command public void check_user(IPrintWriter out,Interpreter interp)
|
|
252 throws ServletException
|
|
253 {
|
|
254 String userId = interp.getArgString("user_id");
|
|
255 if( site().getUser(Jtp.parseLong(request,userId)) == null )
|
|
256 throw Jtp.servletException(request,"user not found: "+userId);
|
|
257 }
|
|
258
|
|
259
|
|
260 public static final CommandSpec do_login = new CommandSpec.Builder()
|
|
261 .parameters("email","password")
|
|
262 .optionalParameters("nextUrl")
|
|
263 .build()
|
|
264 ;
|
|
265
|
|
266 @Command public void do_login(IPrintWriter out,Interpreter interp)
|
|
267 throws IOException, ServletException
|
|
268 {
|
|
269 String email = interp.getArgString("email").trim();
|
|
270 String password = interp.getArgString("password");
|
|
271 String nextUrl = interp.getArgString("nextUrl");
|
|
272 if( nextUrl == null )
|
|
273 nextUrl = "/";
|
|
274 User user = site().getUserFromEmail(email);
|
|
275 if( user != null && user.isRegistered() && user.checkPassword(password) ) {
|
|
276 Jtp.doLogin(request,response,user,true);
|
|
277 DailyNumber.logins.inc();
|
|
278
|
|
279 Shared.javascriptRedirect(request,response, nextUrl);
|
|
280 throw new ExitException();
|
|
281 }
|
|
282 }
|
|
283
|
|
284 public static final CommandSpec registration = CommandSpec.DO()
|
|
285 .parameters("email","password","user_name")
|
|
286 .optionalParameters("next_url")
|
|
287 .build()
|
|
288 ;
|
|
289
|
|
290 @Command public void registration(IPrintWriter out,ScopedInterpreter<RegistrationNamespace> interp)
|
|
291 throws IOException, ServletException, ModelException
|
|
292 {
|
|
293 String email = interp.getArgString("email").trim();
|
|
294 String userName = interp.getArgString("user_name");
|
|
295 String password = interp.getArgString("password");
|
|
296 String nextUrl = interp.getArgString("next_url");
|
|
297 if( nextUrl == null )
|
|
298 nextUrl = "/";
|
|
299 out.print( interp.getArg(new RegistrationNamespace(site(), email,password,userName,nextUrl),"do") );
|
|
300 }
|
|
301
|
|
302 public static final CommandSpec check_captcha = CommandSpec.NO_OUTPUT;
|
|
303
|
|
304 @Command public void check_captcha(IPrintWriter out, Interpreter interp)
|
|
305 throws ModelException.InvalidRecaptcha, IOException
|
|
306 {
|
|
307 Recaptcha.check(request);
|
|
308 }
|
|
309
|
|
310 @Command public void do_logout(IPrintWriter out,Interpreter interp) {
|
|
311 Jtp.logout(request,response);
|
|
312 }
|
|
313
|
|
314 public static final CommandSpec set_response_header = new CommandSpec.Builder()
|
|
315 .parameters("name","value")
|
|
316 .outputtedParameters()
|
|
317 .build()
|
|
318 ;
|
|
319
|
|
320 @Command public void set_response_header(IPrintWriter out,Interpreter interp) {
|
|
321 response.setHeader( interp.getArgString("name"), interp.getArgString("value") );
|
|
322 }
|
|
323
|
|
324 @Command public void remote_address(IPrintWriter out,Interpreter interp) {
|
|
325 out.print(Jtp.getClientIpAddr(request));
|
|
326 }
|
|
327
|
|
328 public static final CommandSpec increment_node_view_count = new CommandSpec.Builder()
|
|
329 .parameters("node_id")
|
|
330 .build()
|
|
331 ;
|
|
332
|
|
333 @Command public void increment_node_view_count(IPrintWriter out,Interpreter interp)
|
|
334 throws ServletException
|
|
335 {
|
|
336 Site site = NabbleNamespace.current().site();
|
|
337 long nodeId = interp.getArgAsLong("node_id");
|
|
338 boolean isUser = getVisitor() instanceof User;
|
|
339 ViewCount.inc(site,nodeId,isUser);
|
|
340 }
|
|
341
|
|
342
|
|
343 public static final CommandSpec get_node_from_request_parameter = CommandSpec.DO;
|
|
344
|
|
345 @Command public void get_node_from_request_parameter(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp)
|
|
346 throws IOException, ServletException, TemplateException
|
|
347 {
|
|
348 Node node = site().getNode( Jtp.getLong(request, "node") );
|
|
349 if( node == null ) {
|
|
350 throw TemplateException.newInstance("node_not_found");
|
|
351 }
|
|
352 out.print( interp.getArg(new NodeNamespace(node),"do") );
|
|
353 }
|
|
354
|
|
355 public static final CommandSpec get_user_from_parameter = CommandSpec.DO;
|
|
356
|
|
357 @Command public void get_user_from_parameter(IPrintWriter out,ScopedInterpreter<UserNamespace> interp)
|
|
358 throws IOException, ServletException
|
|
359 {
|
|
360 String userId = Jtp.getString(request,"user");
|
|
361 Person person = site().getPerson(userId);
|
|
362 if( person == null ) {
|
|
363 response.sendError(HttpServletResponse.SC_NOT_FOUND, "User not found.");
|
|
364 throw new ExitException();
|
|
365 }
|
|
366 out.print( interp.getArg(new UserNamespace(person),"do") );
|
|
367 }
|
|
368
|
|
369
|
|
370 Set<String> cacheEvents = null;
|
|
371
|
|
372 public void cache(String event) {
|
|
373 if( cacheEvents != null )
|
|
374 cacheEvents.add(event);
|
|
375 }
|
|
376
|
|
377 public static final CommandSpec uncache_for = CommandSpec.NO_OUTPUT()
|
|
378 .scopedParameters("do")
|
|
379 .dotParameter("do")
|
|
380 .optionalParameters("do")
|
|
381 .build()
|
|
382 ;
|
|
383
|
|
384 @Command public void uncache_for(IPrintWriter out,ScopedInterpreter<CacheNamespace> interp) {
|
|
385 if( visitorNs != null )
|
|
386 throw new RuntimeException("can't cache page that depends on visitor");
|
|
387 CacheNamespace ns = new CacheNamespace();
|
|
388 try {
|
|
389 interp.getArgString(ns,"do");
|
|
390 cacheEvents = ns.events;
|
|
391 request.setAttribute(Jtp.CACHED,"yes");
|
|
392 } catch(CacheNamespace.DontCache e) {}
|
|
393 }
|
|
394
|
|
395 public static final CommandSpec set_anonymous_name = CommandSpec.NO_OUTPUT()
|
|
396 .parameters("name")
|
|
397 .build()
|
|
398 ;
|
|
399
|
|
400 @Command public void set_anonymous_name(IPrintWriter out,Interpreter interp)
|
|
401 throws ServletException
|
|
402 {
|
|
403 Person visitor = getVisitor();
|
|
404 String anonymousName = interp.getArgString("name");
|
|
405 if( visitor instanceof User
|
|
406 || anonymousName == null
|
|
407 || anonymousName.trim().length() == 0
|
|
408 || !"POST".equals(request.getMethod()) // ???
|
|
409 )
|
|
410 return;
|
|
411 try {
|
|
412 visitor.setName(anonymousName);
|
|
413 } catch(ModelException e) {
|
|
414 throw new RuntimeException(e);
|
|
415 }
|
|
416 ServletUtils.setCookie(request, response, "anonymousName", HtmlUtils.urlEncode(anonymousName), true, null);
|
|
417 }
|
|
418
|
|
419
|
|
420 public static final CommandSpec get_registration = CommandSpec.DO()
|
|
421 .parameters("registration_key","email")
|
|
422 .build()
|
|
423 ;
|
|
424
|
|
425 @Command public void get_registration(IPrintWriter out,ScopedInterpreter<UserNamespace> interp)
|
|
426 throws ModelException
|
|
427 {
|
|
428 String key = interp.getArgString("registration_key");
|
|
429 String email = interp.getArgString("email");
|
|
430 User user = site().getRegistration(key);
|
|
431 if (user==null || !user.getEmail().equalsIgnoreCase(email)) {
|
|
432 logger.error("Registration failed: url="+ServletUtils.getCurrentURL(request)+" email="+email+" user="+(user==null?"null":user.getEmail())+" key="+key+" user-agent="+request.getHeader("user-agent"));
|
|
433 out.print((String)null);
|
|
434 return;
|
|
435 }
|
|
436 out.print( interp.getArg(new UserNamespace(user),"do") );
|
|
437 }
|
|
438
|
|
439 public static final CommandSpec get_next_url_from_registration = new CommandSpec.Builder()
|
|
440 .parameters("registration_key")
|
|
441 .build()
|
|
442 ;
|
|
443
|
|
444 @Command public void get_next_url_from_registration(IPrintWriter out,Interpreter interp) {
|
|
445 String key = interp.getArgString("registration_key");
|
|
446 String nextUrl = site().getNextUrl(key);
|
|
447 if( nextUrl==null )
|
|
448 nextUrl = "/";
|
|
449 out.print(nextUrl);
|
|
450 }
|
|
451
|
|
452 @Command public void visitor_ip_address(IPrintWriter out,Interpreter interp) {
|
|
453 out.print(Jtp.getClientIpAddr(request));
|
|
454 }
|
|
455
|
|
456 /** hack for now */
|
|
457
|
|
458 private static final Set<String> testHosts = new HashSet<String>();
|
|
459 static {
|
|
460 testHosts.add("r.789695.n4.nabble.com");
|
|
461 testHosts.add("imagej.1557.x6.nabble.com");
|
|
462 testHosts.add("f.27.me.nabble.com:8081");
|
|
463 }
|
|
464
|
|
465 @Command public void link_test(IPrintWriter out,Interpreter interp) {
|
|
466 Site site = site();
|
|
467 String domain = site.getCustomDomain();
|
|
468 String host = request.getHeader("host");
|
|
469 if( (domain != null || testHosts.contains(host)) && !site.isEmbarrassing() && request.getServletPath().equals("/") ) {
|
|
470 // if( domain != null && !site.isEmbarrassing() && request.getServletPath().equals("/") || testHosts.contains(host) ) {
|
|
471 out.print(" - <a clck href='https://www.super-resume.com/'>Free Resume Builder</a>");
|
|
472 }
|
|
473 }
|
|
474
|
|
475 }
|