📄 user.java
字号:
/**
* Copyright (C) 2003 Manfred Andres
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package freecs.core;
import freecs.content.*;
import freecs.*;
import freecs.interfaces.*;
import freecs.layout.*;
import java.util.HashMap;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
/**
* the user prototype storing all userdata
*/
public class User implements IUserStates, IMessageDestination {
private static final short LOGGING_IN = 0;
private static final short LOGGED_IN = 1;
private static final short SCHEDULED_FOR_REMOVAL = 2;
private static final short SENDING_QUIT_MESSAGE = 3;
private static final short LOGGING_OUT = 4;
private static final short LOGGED_OUT = 5;
private short state = -1;
public boolean blocked = false, activated = true, isUnregistered = true;
private volatile String name, cookie, colCode, awayMessage, id;
private String customTitle;
private volatile int permissionMap, defaultPermissionMap, defaultMembershipPermissionMap, hashCode=Integer.MIN_VALUE,
flooded=0, questionCounter=0, tooled=0;
private HashMap userProps;
private long sessionStart;
public long lastSentMessage;
public long toolcontrol;
private volatile long lastActive, removeWhen = 0,
lastColChange = 0, awayStart, awayTime=0;
public volatile long lastRecievedMessage;
private volatile transient Group grp = null;
private Vector ignoreList, friendsList;
private volatile transient Group invitedTo;
private volatile transient User invitedBy;
private volatile boolean away = false, isPunished = false, isHTTP11 = true;
private Vector schedMsgs;
private volatile SelectionKey sk;
private TemplateSet ts;
private volatile transient User ownPrivateUser = null, // the last user this user whispered to
foreignPrivateUser = null; // the last user whispering to this user
public Connection conn;
private HashMap memberships = new HashMap();
private Membership defaultMembership = null;
private short friendNotification = 0;
public static final short FN_NONE = 0;
public static final short FN_FRIEND_AGREEMENT = 1;
public static final short FN_ALL = 2;
/**
* constructor for user
*/
public User(String name, String cookie) {
this.colCode = null;
this.name = name;
this.cookie = cookie;
this.userProps = new HashMap();
this.sessionStart = System.currentTimeMillis ();
this.lastRecievedMessage = this.sessionStart;
this.lastActive = this.sessionStart;
this.ignoreList = new Vector ();
this.friendsList = new Vector ();
this.schedMsgs = new Vector ();
this.state = LOGGING_IN;
ts = Server.srv.templatemanager.getTemplateSet("default");
if (Server.TRACE_CREATE_AND_FINALIZE)
Server.log (this, "++++++++++++++++++++++++++++++++++++++++CREATE", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
}
/**
* schedule a message, which will be displayed when the user
* enters the chat (e.g. you have vip-rights)
* @param mpr
*/
public void scheduleMessage (MessageParser mpr) {
if (mpr == null) return;
synchronized (this) {
if (schedMsgs == null)
schedMsgs = new Vector ();
schedMsgs.addElement (mpr);
}
}
/**
* Sends all scheduled messages
*/
public void sendScheduledMessages() {
if (schedMsgs == null) return;
for (Iterator i = schedMsgs.iterator(); i.hasNext(); ) {
MessageParser mpr = (MessageParser) i.next ();
this.implSendMessage(mpr);
i.remove();
}
schedMsgs=null;
}
public boolean isJoining () {
return state == LOGGING_IN;
}
/**
* check if the user is in the removing-process
* @return true if this user is schedulte for removal, false if not
*/
public boolean isRemoving () {
return this.state==SCHEDULED_FOR_REMOVAL;
}
/**
* schedule this user to be removed (if user reconnects, we asume he was accidently disconnected
* and reuse this User-Object. After a deffined time the user get's realy logged out)
*/
public void scheduleToRemove () {
if (this.state>=SCHEDULED_FOR_REMOVAL)
return;
this.state=SCHEDULED_FOR_REMOVAL;
StringBuffer tsb = new StringBuffer ("scheduleToRemove: ");
tsb.append (name);
if (conn != null) {
tsb.append ("@");
tsb.append (conn.toString());
}
Server.log ("[User " + name + "]", tsb.toString (), Server.MSG_AUTH, Server.LVL_VERY_VERBOSE);
this.removeWhen = System.currentTimeMillis () + Server.srv.USER_REMOVE_SCHEDULE_TIME;
if (sk!=null) {
ConnectionBuffer cb = (ConnectionBuffer) sk.attachment();
cb.invalidate();
}
}
public synchronized void sendQuitMessage (boolean b) {
if (state>=SENDING_QUIT_MESSAGE)
return;
state = SENDING_QUIT_MESSAGE;
// if the selectionkey is valid and the channel is open, try
// to send quit message
Group g = grp;
if (grp != null) {
grp = null;
g.removeUser(this);
}
if (g != null && g.size() > 0 && g.isValid()) {
MessageParser mp = new MessageParser ();
mp.setSender (this);
if (b) {
mp.setMessageTemplate ("message.user.leaving.server.kicked");
} else {
if (isAway()){
mp.setMessageTemplate ("message.away.off");
g.sendMessage (mp);
}
mp.setMessageTemplate ("message.user.leaving.server");
}
g.sendMessage (mp);
}
if (sk != null && sk.isValid() && sk.channel().isOpen()) try {
MessageParser mp = new MessageParser ();
mp.setSender (this);
mp.setMessageTemplate (b ? "message.kh.personal" : "message.q");
this.implSendMessage (mp);
Server.log ("[User " + name + "]", "removeNow: sent quit-message", Server.MSG_STATE, Server.LVL_VERBOSE);
} catch (Exception e) {
Server.debug ("[User " + name + "]", "removeNow: ", e, Server.MSG_ERROR, Server.LVL_MINOR);
} else {
CentralSelector.dropKey(sk);
}
removeWhen = System.currentTimeMillis() + 1000;
}
/**
* loggs out the user now. skipps scheduleToRemove or get's called
* because schedule-time has been reached
*/
public synchronized void removeNow () {
if (state>=LOGGING_OUT)
return;
state=LOGGING_OUT;
removeWhen=System.currentTimeMillis() + Server.srv.USER_REMOVE_SCHEDULE_TIME;
UserManager.mgr.removeUser (this);
for (Iterator i = memberships.entrySet().iterator(); i.hasNext(); ) {
Map.Entry entry = (Map.Entry) i.next();
Membership m = (Membership) entry.getValue();
m.remove(this);
}
// if user has a group, send a message to this group to let other users know
// this user has left the server
if (grp != null) {
Group g = grp;
grp = null;
g.removeUser(this);
MessageParser mp = new MessageParser ();
mp.setSender (this);
mp.setMessageTemplate ("message.user.leaving.server");
g.sendMessage (mp);
}
// logout the user
try {
Server.srv.auth.logoutUser (this);
} catch (Exception e) {
Server.debug ("[User " + name + "]", "removeNow: Exception during logout", e, Server.MSG_ERROR, Server.LVL_MAJOR);
}
for (Enumeration e = friendsList.elements (); e.hasMoreElements (); ) {
String fname = (String) e.nextElement ();
UserManager.mgr.removeFriendship (this, fname);
}
StringBuffer tsb = new StringBuffer ("logged out: ");
tsb.append (name);
if (conn != null) {
tsb.append ("@");
tsb.append (conn.toString ());
}
Server.log ("[User " + name + "]", tsb.toString (), Server.MSG_AUTH, Server.LVL_MINOR);
Server.srv.removeToken(cookie);
this.state=LOGGED_OUT;
}
/**
* return the time the user has to be logged out
*/
public long getRemoveWhen () {
return removeWhen;
}
/**
* keeps the lastActive time fresh and checks for flooding
* @return false if the user has flooded or is finalizing
*/
public synchronized boolean wasActive () {
if (state>=LOGGING_OUT)
return false;
if (removeWhen != 0 || state==SCHEDULED_FOR_REMOVAL) {
removeWhen = 0;
state=LOGGED_IN;
}
long currTime = System.currentTimeMillis ();
if ((currTime - this.lastActive) < Server.srv.FLOOD_PROTECT_MILLIS) {
flooded++;
if (flooded > Server.srv.FLOOD_PROTECT_TOLERANC) {
Server.srv.banUser (this, "message.user.flooded", null, Server.srv.FLOOD_BAN_DURATION, "FloodProtection");
return false;
}
} else
flooded = 0;
long difference = toolcontrol- (currTime - this.lastActive);
if (difference <0 ) difference = difference *-1;
if (tooled >0)
Server.log("[User " + name + "]","TOK: " + toolcontrol + " <> " + (currTime - this.lastActive)+ " = " + difference + " Toleranc: " + Server.srv.TOOL_PROTECT_TOLERANC + " Counter: " + tooled , Server.MSG_STATE, Server.LVL_MINOR);
if ((currTime - this.lastActive) * Server.srv.TOOL_PROTECT_MINCOUNTER > Server.srv.TOOL_PROTECT_MINMILLS) {
Server.log("[User " + name + "]","TOK: "+ (currTime - this.lastActive) * Server.srv.TOOL_PROTECT_MINCOUNTER+ " <> " + Server.srv.TOOL_PROTECT_MINMILLS , Server.MSG_STATE, Server.LVL_MINOR);
if (difference <= Server.srv.TOOL_PROTECT_TOLERANC) {
tooled++;
if (tooled >= Server.srv.TOOL_PROTECT_COUNTER) {
Server.srv.banUser (this, "message.user.tooled", null, Server.srv.TOOL_BAN_DURATION, "ToolProtection");
return false;
}
} else
tooled = 0;
}
toolcontrol = currTime - this.lastActive;
this.lastActive = currTime;
return true;
}
/**
* sets the group in which this user joined
* @param newgrp the group this user has joined
*/
public synchronized boolean setGroup (Group newgrp) {
if (newgrp == null)
return false;
if (this.grp != null)
this.grp.removeUser (this);
this.grp = newgrp;
questionCounter = 0;
return true;
}
/**
* gets the group of this user
* @return the group this user is a member from
*/
public Group getGroup () {
return grp;
}
/**
* gets the cookie of this user
* @return this users cookie
*/
public String getCookie () {
return cookie;
}
/**
* gets the last-active-time of this user
* @return last activity as long value
*/
public long lastActive () {
return lastActive;
}
/**
* Sets the SelectionKey of the message-output-frame of this user
* @param sk the SelectionKey for this user's responder
*/
public synchronized void setKey (SelectionKey sk) {
if (!CentralSelector.isSkValid(sk)) {
Server.log (this, "tryed to set invalid key", Server.MSG_STATE, Server.LVL_MINOR);
this.scheduleToRemove();
return;
}
this.sk = sk;
ConnectionBuffer cb = (ConnectionBuffer) sk.attachment ();
cb.setUser (this);
conn = cb.conn;
state=LOGGED_IN;
}
/**
* returns the SelectionKey of this users message-output-frame
* @return SelectionKey of this users message-output-frame
*/
public SelectionKey getKey () {
return sk;
}
/**
* Interface IMessageDestination
*/
/**
* touches this user to keep proxies from closing the connection for this user
*/
public synchronized void touch (long now) {
if (state!=LOGGED_IN) {
return;
}
if (sk == null) {
scheduleToRemove();
return;
}
if (!sk.isValid () || !sk.channel ().isOpen ()) {
Server.log ("[User " + name + "]", "touch: droped key", Server.MSG_STATE, Server.LVL_VERBOSE);
CentralSelector.dropKey (sk);
return;
}
long diff = now - lastRecievedMessage;
if (diff < Server.srv.TOUCH_USER_DELAY) {
return;
}
try {
ByteBuffer clone = ByteBuffer.wrap(UserManager.mgr.TOUCH_CONTENT);
Server.log ("[User " + name + "]", "touch", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
ConnectionBuffer cb = (ConnectionBuffer) sk.attachment();
cb.addToWrite (clone);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -