📄 usermanager.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.*;
import freecs.auth.AuthManager;
import freecs.interfaces.*;
import freecs.layout.TemplateSet;
import freecs.util.EntityDecoder;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Iterator;
public class UserManager extends Thread implements IUserStates, IMessageDestination {
public static final UserManager mgr = new UserManager();
public static int highWaterMark = 0;
public final byte[] TOUCH_CONTENT;
public UserStore ustr = new UserStore();
private HashMap fshipList;
private Vector schedule, onlineVips, notListedAsOnlineVips, guests, moderators, vips, admins, loggingIn;
private volatile long lastModified=0;
public String ustrState() {
return ustr.state();
}
private UserManager () {
try {
CharBuffer cb = CharBuffer.wrap ("<!-- ping -->");
TOUCH_CONTENT = Charset.forName (Server.srv.DEFAULT_CHARSET).newEncoder ().encode (cb).array();
} catch (Exception e) {
Server.debug("static UserManager", "touch_content-construction failed", e, Server.MSG_ERROR, Server.LVL_HALT);
throw new RuntimeException ("failed to initialize UserManager");
}
fshipList = new HashMap ();
onlineVips = new Vector();
notListedAsOnlineVips = new Vector ();
vips=new Vector();
admins=new Vector();
moderators=new Vector();
guests=new Vector ();
this.setName ("UserManager");
schedule = new Vector ();
loggingIn = new Vector();
}
public static void startUserManager() {
mgr.setName("UserManager");
mgr.setPriority(Thread.MAX_PRIORITY-1);
mgr.start();
}
/**
* returns the number of active users
*/
public int getActiveUserCount () {
return ustr.size();
}
public static final short LOGIN_OK = 0,
LOGIN_MISSING = 1,
LOGIN_COOKIE_MISSING = 2,
LOGIN_GROUP_MISSING = 3,
LOGIN_GROUP_NOSTART = 4,
LOGIN_GROUP_BAN = 5,
LOGIN_GROUP_LOCK = 6,
LOGIN_COOKIE_DUPLICATE = 7,
LOGIN_PRESENT = 8,
LOGIN_RELOAD = 9,
LOGIN_FAILED =10,
TECHNICAL_ERROR =11,
MAX_USERS =12,
LOGIN_BLOCKED =13,
USERNAME_TOO_LONG =14,
USERNAME_INVALID =15,
USERNAME_NOT_ACTIVATED =16,
USEREMAIL_BANED =17,
LOGIN_CANCELED =18;
/**
* try to login this user. returns integer containing 0 for ok or any other number (treated as error-code)
* @return short 0 = ok, erverything else is an errorcode
*/
public short tryLogin (String uname, String pwd, String grp, TemplateSet ts, RequestReader req, User u) {
String ltUname = uname == null ? null : uname.toLowerCase().trim();
if ((uname != null && loggingIn.contains(ltUname))
|| (uname == null && pwd == null && grp == null
&& req.currentRequest.getCookie() != null && u != null && u.getCookie().equals(req.currentRequest.getCookie()) && u.check(System.currentTimeMillis())))
return LOGIN_RELOAD;
if (uname == null)
return LOGIN_MISSING;
if (uname.length() > Server.srv.MAX_USERNAME_LENGTH)
return USERNAME_TOO_LONG;
if (!AuthManager.instance.isValidName(uname))
return USERNAME_INVALID;
loggingIn.add(ltUname);
short result = execTryLogin (uname, pwd, grp, ts, req);
loggingIn.remove(ltUname);
return result;
}
private short execTryLogin (String uname, String pwd, String grp, TemplateSet ts, RequestReader req) {
req.currPosition = RequestReader.TRYLOGIN;
if (req.currentRequest.getCookie() == null || req.currentRequest.getCookie().length () < 1)
return LOGIN_COOKIE_MISSING;
if (grp == null || grp.length () < 1)
return LOGIN_GROUP_MISSING;
req.currPosition = RequestReader.TRYLOGIN_CHECK4PRESENCE;
User un, uc;
un = (User) ustr.getUserName(uname.toLowerCase ());
uc = (User) ustr.getUserCookie(req.currentRequest.getCookie());
if (un != null && uc == null)
return LOGIN_PRESENT;
if (un == null && uc != null)
return LOGIN_COOKIE_DUPLICATE;
if (un != null && uc != null && un.equals (uc))
return LOGIN_RELOAD;
if (un != null && uc != null)
return LOGIN_FAILED;
User nu;
req.currPosition = RequestReader.TRYLOGIN_AUTHENTICATE;
try {
nu = Server.srv.auth.loginUser (uname, pwd, req.currentRequest.getCookie(), req.currentRequest);
} catch (NullPointerException npe) {
Server.debug (this, "Catched NPE!", npe, Server.MSG_ERROR, Server.LVL_MAJOR);
return TECHNICAL_ERROR;
} catch (CanceledRequestException cre) {
Server.log (this, "Canceled login due to "
+ (cre.timedOut ?
"request timeout" : "connection loss to client"),
Server.MSG_AUTH, Server.LVL_VERBOSE);
return LOGIN_CANCELED;
} catch (Exception e) {
Server.debug (this, "tryLogin:", e, Server.MSG_ERROR, Server.LVL_MAJOR);
return TECHNICAL_ERROR;
}
if (nu == null)
return LOGIN_FAILED;
if (Server.srv.isBanned(nu.getProperty("email"))) {
return USEREMAIL_BANED;
}
req.currPosition = RequestReader.TRYLOGIN_CORRECT_PERMISSION;
// check user-rights here. If user-rights equal 0, the rights will
// be corrected to the IUserRights.ROLE_USER.
if (nu.hasRole(0) || nu.hasRole(Integer.MIN_VALUE))
nu.setPermission(IUserStates.ROLE_USER);
// if the user has IUserRights.ROLE_USER, the config will be checked
// for the user-rights
if (nu.hasRole(IUserStates.ROLE_USER)) {
String tname = nu.getName().trim().toLowerCase();
if (guests.contains (tname)) {
nu.givePermission (IUserStates.IS_GUEST);
}else if (admins.contains (tname)) {
nu.setPermission (IUserStates.ROLE_GOD);
} else if (moderators.contains (tname)) {
nu.setPermission (IUserStates.IS_MODERATOR);
} else if (vips.contains (tname)) {
nu.setPermission (IUserStates.ROLE_VIP);
}
}
if (ustr.size () >= Server.srv.MAX_USERS
&& !nu.hasDefaultRight(IUserStates.ROLE_VIP))
return MAX_USERS;
req.currPosition = RequestReader.TRYLOGIN_SET_GROUP;
if (nu.blocked)
return LOGIN_BLOCKED;
if (!nu.activated)
return USERNAME_NOT_ACTIVATED;
if (!GroupManager.mgr.isStartingGroup(grp))
return LOGIN_GROUP_NOSTART;
Group g = GroupManager.mgr.getStartingGroup (grp);
if (g != null) {
if (!g.hasState(IGroupState.ENTRANCE))
return LOGIN_GROUP_NOSTART;
if (g.usrIsBaned(uname))
return LOGIN_GROUP_BAN;
if (!g.hasState(IGroupState.OPEN) && !nu.hasRight(IUserStates.MAY_JOIN_LOCKED_GROUP))
return LOGIN_GROUP_LOCK;
req.currPosition = RequestReader.TRYLOGIN_SEND_LOGINMSG;
} else {
if (!GroupManager.mgr.isStartingGroup(grp))
return LOGIN_GROUP_NOSTART;
g = GroupManager.mgr.openGroup(grp, (String) GroupManager.mgr.startGroupThemes.get(grp.trim().toLowerCase()), nu);
if (g==null)
return LOGIN_GROUP_NOSTART;
}
MessageParser mprj = new MessageParser();
mprj.setSender (nu);
mprj.setMessageTemplate ("message.user.join.server");
g.sendMessage (mprj);
try {
this.addUser (nu);
g.addLoginUser (nu);
} catch (Exception e) {
Server.debug(this, "Exception during addUser: ", e, Server.MSG_ERROR, Server.LVL_MAJOR);
return TECHNICAL_ERROR;
}
List fn;
switch (nu.notifyFriends()) {
case User.FN_ALL:
fn = (List) fshipList.get (nu.getName ().toLowerCase());
break;
case User.FN_FRIEND_AGREEMENT:
// check for strong-friend-relationship
// if login-user and the friend have marked each other
// as friends, a notification will be sent
List allFriends = (List) fshipList.get (nu.getName ().toLowerCase());
if (allFriends == null) {
fn=null;
break;
}
fn = new ArrayList();
for (Iterator i = allFriends.iterator(); i.hasNext(); ) {
User fu = (User) i.next();
if (nu.isFriend(fu)) {
fn.add(fu);
}
}
break;
default:
fn = null;
}
sendFriendNotification (nu, g, fn);
req.currPosition = RequestReader.TRYLOGIN_SET_PERMISSION;
nu.setTemplateSet (ts);
req.currPosition = RequestReader.TRYLOGIN_SCHEDULE_VIPMSG;
Membership defaultMembership = nu.getDefaultMembership();
boolean listedAsOnlinevip = true;
if (defaultMembership != null)
listedAsOnlinevip = defaultMembership.listedAsOnlinevip();
if (nu.hasRight(IUserStates.ROLE_VIP) || nu.hasDefaultRight(ROLE_VIP)) {
MessageParser mpr = new MessageParser();
mpr.setUsercontext(nu) ;
mpr.setMessageTemplate ("message.user.vip");
nu.scheduleMessage (mpr);
if (listedAsOnlinevip) {
onlineVips.add(nu);
} else notListedAsOnlineVips.add(nu);
}
req.currPosition = RequestReader.TRYLOGIN_SCHEDULE_FRIENDMSGS;
Vector onlineFriends = new Vector();
for (Enumeration e = nu.friends (); e.hasMoreElements (); ) {
String fname = (String) e.nextElement ();
User cu = getUserByName (fname);
if (cu == null)
continue;
onlineFriends.add(cu);
}
if (onlineFriends.size()>0) {
MessageParser mpr = new MessageParser();
mpr.setMessageTemplate ("message.f.headline");
mpr.setParam(String.valueOf(onlineFriends.size()));
nu.scheduleMessage (mpr);
for (Enumeration e = onlineFriends.elements(); e.hasMoreElements(); ) {
User cu = (User) e.nextElement();
mpr = new MessageParser ();
mpr.setUsercontext (cu);
Group gg = cu.getGroup ();
mpr.setTargetGroup (gg);
mpr.setMessageTemplate ("message.f.isOnline");
nu.scheduleMessage (mpr);
}
}
MessageParser mpr = new MessageParser();
mpr.setMessageTemplate ("message.user.join.server.personal");
mpr.setSender(nu);
nu.scheduleMessage (mpr);
return LOGIN_OK;
}
/**
* adds a user to the lists
* @param u The user to add
*/
public void addUser (User u) throws Exception {
ustr.addUser(u);
lastModified=System.currentTimeMillis();
if (ustr.size() > highWaterMark)
highWaterMark = ustr.size();
}
/**
* removes a user from the userlists
* @param u the user to remove
*/
public void removeUser (User u) {
ustr.removeUser(u);
lastModified=System.currentTimeMillis();
Membership defaultMembership = u.getDefaultMembership();
boolean listedAsOnlinevip = true;
if (defaultMembership != null)
listedAsOnlinevip = defaultMembership.listedAsOnlinevip();
if ((u.hasRight(IUserStates.ROLE_VIP) || u.hasDefaultRight(IUserStates.ROLE_VIP)) && listedAsOnlinevip) {
onlineVips.removeElement(u);
} else if ((u.hasRight(IUserStates.ROLE_VIP) || u.hasDefaultRight(IUserStates.ROLE_VIP)) && !listedAsOnlinevip) {
notListedAsOnlineVips.removeElement(u);
}
}
/**
* returns the user identifyed by the give cookie-value
* @param c the cookie-value
* @return User the user identified by this cookie-value
*/
public User getUserByCookie (String c) {
return ustr.getUserCookie(c);
}
/**
* returns the user identifyed by the give name
* @param n the name
* @return User the user identified by this name
*/
public User getUserByName (String n) {
if (n.indexOf("&") > -1)
n = EntityDecoder.htmlToChar (n);
return ustr.getUserName(n);
}
/**
* schedules this user to be removed
public void scheduleToRemove (User u) {
if (u.getRemoveWhen() == 0)
return;
removableUsers.addElement (u);
}
*/
/**
* adds a friendship-relation
* @param u The user which has registered fname as friend
* @param fname the name of the user which will be registered with u
*/
public void addFriendship (User u, String fname) {
Vector f = (Vector) fshipList.get (fname);
if (f == null) {
f = new Vector ();
fshipList.put (fname, f);
}
f.addElement (u);
}
/**
* removes a friendship-relation
* @param u The user which wants to unregister fname as friend
* @param fname the name of the user which will be unregisterd with u
*/
public synchronized void removeFriendship (User u, String fname) {
Vector f = (Vector) fshipList.get (fname);
if (f == null)
return;
f.remove (u);
if (f.size()==0)
fshipList.remove(f);
}
/**
* cleanup the userspace. if a user times out, we have to remove
* this user from all lists and also unregister his key
* The touching of users connected via proxy-servers will also be done within here
* Also the ScheduledActions will be triggered here
*/
public void run () {
long lastMessage = 0;
while (Server.srv.isRunning ()) try {
if (Server.DEBUG || lastMessage + 5000 > System.currentTimeMillis()) {
Server.log (this, "loopstart", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
lastMessage = System.currentTimeMillis();
}
long currTime = System.currentTimeMillis ();
long lowestValue = currTime + Math.min(Server.srv.USER_REMOVE_SCHEDULE_TIME, Server.srv.TOUCH_USER_DELAY);
lowestValue = checkUsers (currTime, lowestValue);
// checking the ScheduledActions
for (Enumeration e = schedule.elements (); e.hasMoreElements (); ) {
ScheduledAction sa = (ScheduledAction) e.nextElement ();
if (!ustr.contains(sa.getUser())) {
schedule.removeElement (sa);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -