/* * Copyright (c) JForum Team. All rights reserved. * * The software in this package is published under the terms of the LGPL * license a copy of which has been included with this distribution in the * license.txt file. * * The JForum Project * http://www.jforum.net */ package net.jforum.entities; import java.io.PrintWriter; import java.io.Serializable; import java.io.StringWriter; import java.io.Writer; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.jforum.security.RoleManager; import net.jforum.util.ConfigKeys; import org.apache.log4j.Logger; import br.com.caelum.vraptor.ioc.Component; import br.com.caelum.vraptor.ioc.SessionScoped; /** * Stores information about an user's session. * @author Rafael Steil */ @Component @SessionScoped public class UserSession implements Serializable { private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(UserSession.class); private User user = new User(null); private RoleManager roleManager; private Map<Integer, Long> topicReadTime = new HashMap<Integer, Long>(); private long lastAccessedTime; private long creationTime; private long lastVisit; private String sessionId; private HttpServletRequest request; private HttpServletResponse response; public void setResponse(HttpServletResponse response) { this.response = response; } /** * Flag a specific topic as "read" by the user * It will be ignored if the user is not logged * @param topicId the id of the topic to mark as read */ public void markTopicAsRead(int topicId) { if (this.isLogged()) { this.topicReadTime.put(topicId, System.currentTimeMillis()); } } public void setRequest(HttpServletRequest request) { this.request = request; } /** * Check if the user has read a specific topic.o * @param topic the topic. Check will be made against <code>topic.lastPost.date</code> * @return true if the topic is read or if the user is not logged. */ public boolean isTopicRead(Topic topic) { if (!this.isLogged()) { return true; } long lastVisit = this.getLastVisit(); long postTime = topic.getLastPost().getDate().getTime(); if (postTime <= lastVisit) { return true; } Long readTime = this.topicReadTime.get(topic.getId()); return readTime != null && postTime <= readTime; } /** * Check if there are unread messages in a specific forum * FIXME this currently only checks for the time of the last message in the forum. * A correct implementation should check all posts in the forum (while not hurting performance) * @param forum the forum to check * @return true if there are no unread messages in the forum, or if the user is not logged */ public boolean isForumRead(Forum forum) { if (!this.isLogged() || forum.getTotalPosts() == 0 || forum.getLastPost() == null) { return true; } long lastVisit = this.getLastVisit(); long postTime = forum.getLastPost().getDate().getTime(); if (postTime <= lastVisit) { return true; } Long readTime = this.topicReadTime.get(forum.getLastPost().getTopic().getId()); return readTime != null && postTime <= readTime; } public void setRoleManager(RoleManager roleManager) { this.roleManager = roleManager; } public RoleManager getRoleManager() { return this.roleManager; } public HttpServletRequest getRequest() { return request; } public String getIp() { /* if(new JForumConfig().getBoolean(ConfigKeys.BLOCK_IP)) { return null; } */ // We look if the request is forwarded // If it is not call the older function. String ip = request.getHeader("X-Pounded-For"); if (ip != null) { return ip; } ip = request.getHeader("x-forwarded-for"); if (ip == null) { return request.getRemoteAddr(); } else { // Process the IP to keep the last IP (real ip of the computer on the net) StringTokenizer tokenizer = new StringTokenizer(ip, ","); // Ignore all tokens, except the last one for (int i = 0; i < tokenizer.countTokens() -1 ; i++) { tokenizer.nextElement(); } ip = tokenizer.nextToken().trim(); if (ip.equals("")) { ip = null; } } // If the ip is still null, we put 0.0.0.0 to avoid null values if (ip == null) { ip = "0.0.0.0"; } return ip; } public User getUser() { return this.user; } public void setUser(User user) { this.user = user; if (user == null) { try { throw new RuntimeException("userSession.setUser with null value. See the stack trace for more information about the call stack. Session ID: " + this.sessionId); } catch (RuntimeException e) { Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); e.printStackTrace(printWriter); logger.warn(writer.toString()); } } } /** * Gets user's session start time * * @return Start time in miliseconds */ public long getCreationTime() { return this.creationTime; } public void setCreationTime(long start) { this.creationTime = start; this.lastAccessedTime = start; this.lastVisit = start; } /** * Gets user's last visit time * * @return Time in miliseconds */ public long getLastAccessedTime() { return this.lastAccessedTime; } public Date getLastAccessedDate() { return new Date(this.getLastAccessedTime()); } /** * @return the lastVisit */ public long getLastVisit() { return this.lastVisit; } /** * @return the lastVisit as a date */ public Date getLastVisitDate() { return new Date(this.lastVisit); } /** * @param lastVisit the lastVisit to set */ public void setLastVisit(long lastVisit) { this.lastVisit = lastVisit; } /** * Updates this instance with the last accessed time of the session */ public void ping() { this.lastAccessedTime = System.currentTimeMillis(); } /** * Gets the session id related to this user session * * @return A string with the session id */ public String getSessionId() { return this.sessionId; } public void setSessionId(String sessionId) { this.sessionId = sessionId; } public boolean isBot() { return false; } /** * Makes the user session anonymous */ public void becomeAnonymous(int anonymousUserId) { User user = new User(); user.setId(anonymousUserId); this.setUser(user); setAttribute(ConfigKeys.LOGGED, "0"); } public void becomeLogged() { this.setAttribute(ConfigKeys.LOGGED, "1"); } public boolean isLogged() { return "1".equals(this.getAttribute(ConfigKeys.LOGGED)); } /** * Gets a cookie by its name. * * @param name The cookie name to retrieve * @return The <code>Cookie</code> object if found, or <code>null</code> oterwhise */ public Cookie getCookie(String name) { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie c : cookies) { if (c.getName().equals(name)) { return c; } } } return null; } /** * Add or update a cookie. This method adds a cookie, serializing its value using XML. * * @param name The cookie name. * @param value The cookie value */ public void addCookie(String name, String value) { int maxAge = 3600 * 24 * 365; if (value == null) { maxAge = 0; value = ""; } Cookie cookie = new Cookie(name, value); cookie.setMaxAge(maxAge); cookie.setPath("/"); response.addCookie(cookie); } /** * Removes a cookie * @param name the name of the cookie to remove */ public void removeCookie(String name) { this.addCookie(name, null); } public void setAttribute(String name, Object value) { request.getSession().setAttribute(name, value); } public Object getAttribute(String name) { return request.getSession().getAttribute(name); } /** * Convert this instance to a {@link Session} * @return */ public Session asSession() { Session session = new Session(); session.setUserId(this.user.getId()); session.setIp(this.getIp()); session.setStart(new Date(this.getCreationTime())); session.setLastAccessed(new Date(this.getLastAccessedTime())); session.setLastVisit(new Date(this.getLastVisit())); return session; } /** * @see java.lang.Object#equals(java.lang.Object) */ //@Override public boolean eequals(Object o) { if (o == this) { return true; } if (!(o instanceof UserSession)) { return false; } return this.getSessionId().equals(((UserSession)o).getSessionId()); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return this.getSessionId().hashCode(); } /** * @param time */ public void setLastAccessedTime(long time) { this.lastAccessedTime = time; } }