0001: /**
0002: * Copyright (C) 2003 Manfred Andres
0003: *
0004: * This program is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU General Public License
0006: * as published by the Free Software Foundation; either version 2
0007: * of the License, or (at your option) any later version.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU General Public License
0015: * along with this program; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0017: *
0018: * FreeCS Server
0019: * This is the main-class which starts the server
0020: */package freecs;
0021:
0022: import freecs.content.*;
0023: import freecs.content.Connection;
0024: import freecs.layout.*;
0025: import freecs.auth.*;
0026: import freecs.core.*;
0027: import freecs.external.XmlRpcManager;
0028: import freecs.interfaces.*;
0029: import freecs.util.*;
0030: import freecs.util.logger.LogWriter;
0031:
0032: import java.util.Calendar;
0033: import java.util.Iterator;
0034: import java.util.Set;
0035: import java.util.TimeZone;
0036: import java.util.Vector;
0037: import java.util.Hashtable;
0038: import java.util.Enumeration;
0039: import java.util.Properties;
0040: import java.text.SimpleDateFormat;
0041:
0042: import java.net.InetAddress;
0043: import java.nio.charset.Charset;
0044: import java.nio.charset.CharsetEncoder;
0045:
0046: import java.io.IOException;
0047: import java.io.File;
0048: import java.io.FileInputStream;
0049: import java.io.FileNotFoundException;
0050: import java.net.UnknownHostException;
0051:
0052: /**
0053: *
0054: * @author Manfred Andres
0055: *
0056: */
0057: public class Server implements IReloadable {
0058: // the versionstring for this release
0059: private static final String VERSION = "1.2.20060102";
0060:
0061: // different request-types may be inserted here (for further use)
0062: public static final int REQUEST_TYPE_HTTP = 1;
0063:
0064: // the home directory will be stored here
0065: public static String BASE_PATH;
0066:
0067: public static final long startupTime = System.currentTimeMillis();
0068:
0069: // these fields are used for the configuration
0070: // default-values may be changed in checkForConfigVals()
0071: public String DEFAULT_CHARSET = "iso-8859-1", COOKIE_DOMAIN,
0072: SERVER_NAME, TIMEZONE, ADMIN_HTTP_ALLOWED,
0073: ADMIN_HTTP_USERNAME, ADMIN_HTTP_PASSWORD,
0074: ADMIN_XMLRPC_ALLOWED;
0075: public long TOUCH_USER_DELAY, READER_MAX_IDLETIME,
0076: FILE_CHECK_INTERVAL, FLOOD_PROTECT_MILLIS, USER_TIMEOUT,
0077: USER_AWAY_TIMEOUT, USER_REMOVE_SCHEDULE_TIME,
0078: HOST_BAN_DURATION, VIP_TIMEOUT, READER_TIMEOUT,
0079: LOGIN_TIMEOUT;
0080: public boolean ALLOW_EXTERNAL, DEBUG_TEMPLATESET, USE_HTTP11,
0081: USE_IP_BAN, THREAD_PER_READ, USE_TOKENSTORE, MD5_PASSWORDS,
0082: USE_MESSAGE_RENDER_CACHE, USE_TRAFFIC_MONITOR,
0083: USE_CENTRAL_REQUESTQUEUE, STRICT_HOST_BINDING;
0084: public int READER_MAX_QUEUE, READER_MAX_QUEUE_USAGE, MAX_READERS,
0085: MAX_BAN_DURATION, DEFAULT_BAN_DURATION,
0086: FLOOD_PROTECT_TOLERANC, FLOOD_BAN_DURATION,
0087: READBUFFER_SIZE, MAX_USERS, COLOR_CHANGE_INTERVAL,
0088: MAX_USERNAME_LENGTH, MAX_DIE_NUMBER, MAX_DIE_EYES,
0089: TCP_RECEIVE_BUFFER_WINDOW, LOG_QUEUE_SIZE,
0090: MAX_REQUESTS_PER_PROXY_IP, MAX_REQUESTS_PER_IP,
0091: MAX_SUUSERS_PER_STARTGROUP, INITIAL_RESPONSE_QUEUE,
0092: MAX_RESPONSE_QUEUE, MAX_GROUPNAME_LENGTH,
0093: MAX_GROUPTHEME_LENGTH, ADMIN_XMLRPC_PORT,
0094: TOOL_PROTECT_COUNTER, TOOL_PROTECT_TOLERANC,
0095: TOOL_BAN_DURATION, TOOL_PROTECT_MINMILLS,
0096: TOOL_PROTECT_MINCOUNTER, JOIN_PUNISHED_COUNTER;
0097:
0098: private Vector adminHosts;
0099: public Vector allowedLoginHosts;
0100: public TemplateManager templatemanager = null;
0101: public AuthManager auth;
0102: public static Server srv = null;
0103: private Hashtable banList;
0104: public InetAddress lh = null;
0105: public Properties props;
0106: public static Calendar cal = Calendar.getInstance();
0107: private volatile boolean isRunning = true;
0108: public Charset defaultCs = Charset.forName(DEFAULT_CHARSET);
0109: public CharsetEncoder defaultCsEnc = defaultCs.newEncoder();
0110:
0111: public static boolean TRACE_CREATE_AND_FINALIZE = false;
0112:
0113: private Hashtable tokenStore = new Hashtable();
0114:
0115: public long KEEP_ALIVE_TIMEOUT;
0116:
0117: public String UNAME_PREFIX_GOD, UNAME_PREFIX_GUEST,
0118: UNAME_PREFIX_MODERATOR, UNAME_PREFIX_PUNISHED,
0119: UNAME_PREFIX_SU, UNAME_PREFIX_VIP, UNAME_SUFFIX_GOD,
0120: UNAME_SUFFIX_GUEST, UNAME_SUFFIX_MODERATOR,
0121: UNAME_SUFFIX_PUNISHED, UNAME_SUFFIX_SU, UNAME_SUFFIX_VIP;
0122:
0123: public short FN_DEFAULT_MODE_FALSE = 0;
0124: public short FN_DEFAULT_MODE_TRUE = 2;
0125:
0126: public Server() {
0127: // this sets the logging to very verbose (just for startup)
0128: LOG_MASK[0] = new Short(LVL_MINOR);
0129: LOG_MASK[1] = new Short(LVL_MINOR);
0130: LOG_MASK[2] = new Short(LVL_MINOR);
0131: LOG_MASK[3] = new Short(LVL_MINOR);
0132: LOG_MASK[4] = new Short(LVL_MINOR);
0133:
0134: try {
0135: lh = InetAddress.getLocalHost();
0136: } catch (UnknownHostException uhe) {
0137: System.out.println("Server: No networkinterface found: "
0138: + uhe.getCause());
0139: uhe.printStackTrace();
0140: System.exit(1);
0141: }
0142: banList = new Hashtable();
0143: props = new Properties();
0144: adminHosts = new Vector();
0145: allowedLoginHosts = new Vector();
0146: }
0147:
0148: /**
0149: * the main-method of server is responsible for:
0150: * .) reading in the configuration
0151: * .) initializing the server
0152: * .) starting the neccessary threads
0153: *
0154: * If this task's are completed this main-thread will
0155: * be used to remove bans which are not valid anymore
0156: * @param args the base-path may be given @commandline. Usage: freecs.Server -b=[path to mainfolder]
0157: */
0158: public static void main(String args[]) {
0159: for (int i = 0; i < args.length; i++) {
0160: if (args[i].startsWith("-b=")) {
0161: BASE_PATH = args[0].substring(3);
0162: } else if (args[i].equals("printcharsets")) {
0163: System.out.println("Available Charsets:");
0164: Set ks = Charset.availableCharsets().keySet();
0165: for (Iterator it = ks.iterator(); it.hasNext();) {
0166: System.out.print(":> ");
0167: System.out.println((String) it.next());
0168: }
0169: System.exit(0);
0170: }
0171: }
0172: if (BASE_PATH == null)
0173: BASE_PATH = "./";
0174: srv = new Server();
0175: srv.readConfig();
0176: srv.initServer();
0177: srv.startThreads();
0178: if (srv.USE_CENTRAL_REQUESTQUEUE)
0179: Server.log("Server",
0180: "starting up with CENTRAL-requestqueue",
0181: Server.MSG_STATE, Server.LVL_MAJOR);
0182: else
0183: Server.log("Server",
0184: "starting up with per RequestReader-requestqueue",
0185: Server.MSG_STATE, Server.LVL_MAJOR);
0186: long lastMessage = 0;
0187: while (srv.isRunning()) {
0188: /* if (Server.DEBUG || lastMessage + 5000 > System.currentTimeMillis()) {
0189: Server.log ("Server", "loopstart", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
0190: lastMessage = System.currentTimeMillis();
0191: } */
0192: try {
0193: long now = System.currentTimeMillis();
0194: long rws[][] = RequestReader.getWorkingSince();
0195: boolean b[] = RequestReader.getAliveState();
0196: StringBuffer sb = new StringBuffer(
0197: "ThreadsWorkingTime:");
0198: for (int i = 0; i < rws.length; i++) {
0199: if (rws[i][0] == 0) {
0200: sb.append(" 0, ");
0201: } else {
0202: sb.append(" ");
0203: sb.append(now - rws[i][0]);
0204: sb.append(", ");
0205: }
0206: if (b[i])
0207: sb.append("alive@");
0208: else
0209: sb.append("dead@");
0210: switch ((short) rws[i][1]) {
0211: case RequestReader.WAITING:
0212: sb.append("waiting");
0213: continue;
0214: case RequestReader.EVAL_GET_MESSAGES_APND2WRITE:
0215: sb.append("appending message to writequeue");
0216: continue;
0217: case RequestReader.EVAL_GET_MESSAGES_SND_MSGS:
0218: sb.append("sending scheduled message");
0219: continue;
0220: case RequestReader.EVAL_GET_MESSAGES:
0221: sb.append("sending messages-frame");
0222: continue;
0223: case RequestReader.EVAL_GET_STATE:
0224: sb.append("retrieving /state");
0225: continue;
0226: case RequestReader.EVAL_GET:
0227: sb.append("evaluating getrequest");
0228: continue;
0229: case RequestReader.EVAL_POST:
0230: sb.append("evaluating postrequest");
0231: continue;
0232: case RequestReader.EVAL_POST_LOGIN:
0233: sb.append("loging in");
0234: continue;
0235: case RequestReader.EVAL_PREP4SEND:
0236: sb.append("perparing for sending");
0237: continue;
0238: case RequestReader.EVAL_SEND:
0239: sb.append("evaluating a /SEND request");
0240: continue;
0241: case RequestReader.EVAL_SENDFINAL:
0242: sb.append("sending content");
0243: continue;
0244: case RequestReader.EVALUATE_COMMAND:
0245: sb.append("evaluating a command");
0246: String cmd = RequestReader.getCurrCommant(i);
0247: if (cmd != null)
0248: sb.append(" (").append(cmd).append(")");
0249: continue;
0250: case RequestReader.EVALUATING:
0251: sb.append("evaluating");
0252: continue;
0253: case RequestReader.PARSE_MSG:
0254: sb.append("parsing message");
0255: continue;
0256: case RequestReader.READING:
0257: sb.append("reading");
0258: continue;
0259: case RequestReader.EVAL_POST_LOGIN_RESULT:
0260: sb.append("evaluating login-result");
0261: continue;
0262: case RequestReader.TRYLOGIN:
0263: sb.append("trylogin");
0264: continue;
0265: case RequestReader.TRYLOGIN_AUTHENTICATE:
0266: sb.append("trylogin authenticate");
0267: continue;
0268: case RequestReader.TRYLOGIN_CHECK_FRIENDS:
0269: sb.append("trylogin check friends");
0270: continue;
0271: case RequestReader.TRYLOGIN_CHECK4PRESENCE:
0272: sb.append("trylogin check for presence");
0273: continue;
0274: case RequestReader.TRYLOGIN_CORRECT_PERMISSION:
0275: sb.append("trylogin correct permission");
0276: continue;
0277: case RequestReader.TRYLOGIN_SCHEDULE_FRIENDMSGS:
0278: sb
0279: .append("trylogin schedule online-friends-messages");
0280: continue;
0281: case RequestReader.TRYLOGIN_SCHEDULE_VIPMSG:
0282: sb.append("trylogin schedule vip-message");
0283: continue;
0284: case RequestReader.TRYLOGIN_SEND_LOGINMSG:
0285: sb.append("trylogin send loginmessages");
0286: continue;
0287: case RequestReader.TRYLOGIN_SET_GROUP:
0288: sb.append("trylogin set group");
0289: continue;
0290: case RequestReader.TRYLOGIN_SET_PERMISSION:
0291: sb.append("trylogin set permission");
0292: continue;
0293: }
0294: }
0295: Server.log("static Server", sb.toString(), MSG_STATE,
0296: LVL_VERBOSE);
0297: Runtime r = Runtime.getRuntime();
0298: long free = r.freeMemory();
0299: long total = r.totalMemory();
0300: long max = r.maxMemory();
0301: long used = r.totalMemory() - r.freeMemory();
0302: sb = new StringBuffer();
0303: sb
0304: .append("Memory-Report (VM-MaxSize/VM-CurrSize/free/used): ");
0305: sb.append(max).append("/");
0306: sb.append(total).append("/");
0307: sb.append(free).append("/");
0308: sb.append(used);
0309: Server.log(null, sb.toString(), MSG_STATE, LVL_MINOR);
0310:
0311: // Cleaning up the banlist is triggered here
0312: long lVal = now + 30001;
0313: for (Enumeration e = srv.banList.keys(); e
0314: .hasMoreElements();) {
0315: Object key = e.nextElement();
0316: BanObject bObj = (BanObject) srv.banList.get(key);
0317: if (bObj == null)
0318: continue;
0319: if (bObj.time < now) {
0320: if (checkLogLvl(Server.MSG_STATE,
0321: Server.LVL_MINOR)) {
0322: sb = new StringBuffer(
0323: "Server: removing ban for ")
0324: .append(key);
0325: Server.log("static Server", sb.toString(),
0326: MSG_STATE, LVL_MINOR);
0327: }
0328: srv.banList.remove(key);
0329: } else if (bObj.time < lVal)
0330: lVal = bObj.time;
0331: }
0332: long slpTime = lVal - now;
0333: if (slpTime < 30)
0334: slpTime = 30;
0335: Thread.sleep(slpTime);
0336: } catch (Exception ie) {
0337: }
0338: }
0339: }
0340:
0341: private void startThreads() {
0342: try {
0343: UserManager.startUserManager();
0344: RequestReader.startRequestReader(true);
0345: RequestReader.startRequestReader(true);
0346: CentralSelector.startCentralSelector();
0347: Responder.startResponder();
0348: Listener.startListener();
0349: } catch (Exception e) {
0350: Server.debug(this , "Exception during starting threads:", e,
0351: MSG_ERROR, LVL_HALT);
0352: }
0353: try {
0354: XmlRpcManager.startManager();
0355: } catch (Exception e) {
0356: Server
0357: .debug(
0358: this ,
0359: "Exception during starting XmlRpcManager (Server will not be reachable via XML-RPC):",
0360: e, MSG_ERROR, LVL_MAJOR);
0361: }
0362: }
0363:
0364: public void readConfig() {
0365: Server.log(this , "FreeCS Startup", MSG_CONFIG, LVL_MINOR);
0366: StringBuffer sb = new StringBuffer(BASE_PATH).append("/config");
0367: File cFile = new File(sb.toString());
0368: if (!cFile.exists()) {
0369: Server.log(this , "config directory missing\r\n" + BASE_PATH
0370: + "/config", MSG_ERROR, LVL_HALT);
0371: }
0372: sb = new StringBuffer(BASE_PATH).append("/config/config.cfg");
0373: cFile = new File(sb.toString());
0374: if (!cFile.exists()) {
0375: Server.log(this , "config file missing\r\n" + sb.toString(),
0376: MSG_ERROR, LVL_HALT);
0377: }
0378:
0379: try {
0380: FileInputStream in = new FileInputStream(cFile);
0381: props.load(in);
0382: in.close();
0383: } catch (FileNotFoundException fnfe) {
0384: // never
0385: } catch (IOException ioe) {
0386: Server.log(this , "unable to read config-files", MSG_ERROR,
0387: LVL_HALT);
0388: }
0389:
0390: // check for port-specification
0391: if (props.getProperty("port") == null)
0392: Server.log(this ,
0393: "No port specified in config: port=[portnumber]",
0394: MSG_ERROR, LVL_HALT);
0395:
0396: checkForConfigValues();
0397: configFile = cFile;
0398: lastModified = cFile.lastModified();
0399: FileMonitor.getFileMonitor().addReloadable(srv);
0400: }
0401:
0402: /**
0403: * checks for properties in the config-file to overrule the default-values
0404: * this has to be "reloadable" meaning that values may be changed on the fly
0405: * @see freecs.util.FileMonitor
0406: * @see freecs.interfaces.IReloadable
0407: */
0408: private synchronized void checkForConfigValues() {
0409: String sgroups = props.getProperty("startgroups");
0410: if (sgroups == null)
0411: Server
0412: .log(
0413: this ,
0414: "No starting-rooms are deffined: startrooms=[room1/TITLE1 [, room2/TITLE2, ...",
0415: MSG_ERROR, LVL_HALT);
0416:
0417: GroupManager.mgr.updateStartingGroups(sgroups.split(","));
0418:
0419: Server.log(this , "updating log-destinations", MSG_CONFIG,
0420: LVL_MINOR);
0421: LOGFILE[MSG_CONFIG] = checkProperty("logfileCfg", "console");
0422: LOGFILE[MSG_AUTH] = checkProperty("logfileAuth", "console");
0423: LOGFILE[MSG_STATE] = checkProperty("logfileState", "console");
0424: LOGFILE[MSG_TRAFFIC] = checkProperty("logfileTraffic",
0425: "console");
0426: LOGFILE[MSG_ERROR] = checkProperty("logfileError", "console");
0427: LOG_QUEUE_SIZE = checkProperty("logQueueSize", 500);
0428: try {
0429: // startup logwriter
0430: LogWriter l = LogWriter.instance;
0431: // l.setLogQueueSize(LOG_QUEUE_SIZE);
0432: } catch (Exception e) {
0433: e.printStackTrace();
0434: }
0435: Server.log(this , "Reading config...", MSG_CONFIG, LVL_MINOR);
0436: READBUFFER_SIZE = checkProperty("readbuffer", 640);
0437: READER_MAX_IDLETIME = checkProperty("threadMaxIdletime", 30000);
0438: READER_MAX_QUEUE = checkProperty("ioQueueSize", 5);
0439: FLOOD_PROTECT_TOLERANC = checkProperty("floodProtectTolerance",
0440: 3);
0441: FLOOD_PROTECT_MILLIS = checkProperty("floodProtectMillis", 500);
0442: FLOOD_BAN_DURATION = checkProperty("floodBanDuration", 30000);
0443: TOOL_PROTECT_TOLERANC = checkProperty("toolProtectTolerance",
0444: 250);
0445: TOOL_PROTECT_COUNTER = checkProperty("toolProtectCounter", 10);
0446: TOOL_BAN_DURATION = checkProperty("toolBanDuration", 600) * 60000;
0447: TOOL_PROTECT_MINMILLS = checkProperty("toolProtectMinmills",
0448: 12000);
0449: TOOL_PROTECT_MINCOUNTER = checkProperty(
0450: "toolProtectMincounter", 10);
0451: JOIN_PUNISHED_COUNTER = checkProperty("joinpunishedcounter", 2);
0452: COLOR_CHANGE_INTERVAL = checkProperty("colorChangeInterval",
0453: 15000);
0454: USER_TIMEOUT = checkProperty("userTimeout", 15) * 60000;
0455: USER_AWAY_TIMEOUT = checkProperty("userAwayTimeout", 30) * 60000;
0456: USER_REMOVE_SCHEDULE_TIME = checkProperty("userRemoveDelay",
0457: 2000);
0458: TCP_RECEIVE_BUFFER_WINDOW = checkProperty("tcpReceiveBuffer",
0459: 4096);
0460: FILE_CHECK_INTERVAL = checkProperty("fileCheckInterval", 10000);
0461: if (FILE_CHECK_INTERVAL < 1000)
0462: FILE_CHECK_INTERVAL = 1000;
0463:
0464: String ndcs = checkProperty("charset", "iso-8859-1");
0465: if (!ndcs.equals(DEFAULT_CHARSET)) {
0466: defaultCs = Charset.forName(ndcs);
0467: defaultCsEnc = defaultCs.newEncoder();
0468: DEFAULT_CHARSET = ndcs;
0469: }
0470:
0471: COOKIE_DOMAIN = checkProperty("cookieDomain", null);
0472: SERVER_NAME = checkProperty("server", null);
0473: ALLOW_EXTERNAL = checkProperty("allowExternalLogin", true);
0474: USE_CENTRAL_REQUESTQUEUE = checkProperty(
0475: "useCentralRequestqueue", false);
0476: DEBUG_TEMPLATESET = checkProperty("debugTemplateset", false);
0477: STRICT_HOST_BINDING = checkProperty("useStrictHostBinding",
0478: true);
0479: MAX_READERS = checkProperty("maxThreads", 100);
0480: USE_HTTP11 = checkProperty("useHTTP1.1", true);
0481: MAX_USERS = checkProperty("maxUsers", 2000);
0482: TOUCH_USER_DELAY = checkProperty("touchUserDelay", 20000);
0483: MAX_BAN_DURATION = checkProperty("maxBanDuration", 120);
0484: USE_IP_BAN = checkProperty("useIpBan", true);
0485: DEFAULT_BAN_DURATION = checkProperty("defaultBanDuration", 10);
0486: INITIAL_RESPONSE_QUEUE = checkProperty("responseQueueSize", 100);
0487: MAX_RESPONSE_QUEUE = checkProperty("maxResponseQueueSize", 1000);
0488: MAX_REQUESTS_PER_PROXY_IP = checkProperty(
0489: "maxRequestsPerProxy", 20000);
0490: MAX_REQUESTS_PER_IP = checkProperty("maxRequestsPerIp", 90);
0491: HOST_BAN_DURATION = checkProperty("floodHostBanDuration",
0492: 3600000);
0493: USE_TRAFFIC_MONITOR = checkProperty("useTrafficMonitor", false);
0494: MAX_DIE_NUMBER = checkProperty("maximumDieNumber", 10);
0495: MAX_DIE_EYES = checkProperty("maximumDieEyes", 20);
0496: MAX_SUUSERS_PER_STARTGROUP = checkProperty(
0497: "maxSuPerStartgroup", 5);
0498: USE_TOKENSTORE = checkProperty("useTokenedLogin", false);
0499: MD5_PASSWORDS = checkProperty("MD5EncodePasswords", false);
0500: MAX_USERNAME_LENGTH = checkProperty("maxUserNameLength", 30);
0501: MAX_GROUPNAME_LENGTH = checkProperty("maxGroupNameLength", -1);
0502: MAX_GROUPTHEME_LENGTH = checkProperty("maxGroupThemeLength", -1);
0503: USE_MESSAGE_RENDER_CACHE = checkProperty(
0504: "useMessageRenderCache", false);
0505: VIP_TIMEOUT = checkProperty("vipTimeout", 0) * 60000;
0506:
0507: ADMIN_HTTP_USERNAME = checkProperty("admin.http.username", null);
0508: ADMIN_HTTP_PASSWORD = checkProperty("admin.http.password", null);
0509: ADMIN_HTTP_ALLOWED = checkProperty("admin.http.allowedClients",
0510: "");
0511: ADMIN_XMLRPC_PORT = checkProperty("admin.xmlrpc.port", 0);
0512: ADMIN_XMLRPC_ALLOWED = checkProperty(
0513: "admin.xmlrpc.allowedClients", "");
0514:
0515: UNAME_PREFIX_GOD = checkProperty("prefix.admin", "<b>");
0516: UNAME_SUFFIX_GOD = checkProperty("suffix.admin", "(A)</b>");
0517: UNAME_PREFIX_GUEST = checkProperty("prefix.guest", "");
0518: UNAME_SUFFIX_GUEST = checkProperty("suffix.guest", "(G)");
0519: UNAME_PREFIX_MODERATOR = checkProperty("prefix.moderator", "");
0520: UNAME_SUFFIX_MODERATOR = checkProperty("suffix.moderator",
0521: "(M)");
0522: UNAME_PREFIX_PUNISHED = checkProperty("prefix.punished", "<s>");
0523: UNAME_SUFFIX_PUNISHED = checkProperty("suffix.punished", "</s>");
0524: UNAME_PREFIX_SU = checkProperty("prefix.su", "<i>");
0525: UNAME_SUFFIX_SU = checkProperty("suffix.su", "</i>");
0526: UNAME_PREFIX_VIP = checkProperty("prefix.vip", "<b>");
0527: UNAME_SUFFIX_VIP = checkProperty("suffix.vip", "</b>");
0528:
0529: READER_TIMEOUT = checkProperty("readerTimeout", 5000);
0530: LOGIN_TIMEOUT = checkProperty("loginTimeout", 20000);
0531:
0532: FN_DEFAULT_MODE_FALSE = (short) checkProperty(
0533: "friendNotificationMode.false", 0);
0534: FN_DEFAULT_MODE_TRUE = (short) checkProperty(
0535: "friendNotificationMode.true", 2);
0536:
0537: KEEP_ALIVE_TIMEOUT = checkProperty("keepAliveTimeout", 30) * 1000;
0538:
0539: TRACE_CREATE_AND_FINALIZE = checkProperty(
0540: "traceCreateAndFinalize", false);
0541:
0542: String val = props.getProperty("moderatedgroups");
0543: if (val != null) {
0544: String values[] = val.split(",");
0545: Vector names = new Vector();
0546: for (int i = 0; i < values.length; i++)
0547: names.add(values[i].trim().toLowerCase());
0548: GroupManager.mgr.updateModeratedGroups(names);
0549: } else {
0550: GroupManager.mgr.updateModeratedGroups(new Vector());
0551: }
0552:
0553: val = props.getProperty("vips");
0554: if (val != null) {
0555: Vector tvl = new Vector();
0556: String values[] = val.split(",");
0557: for (int i = 0; i < values.length; i++) {
0558: tvl.addElement(values[i].trim().toLowerCase());
0559: }
0560: UserManager.mgr.updateVips(tvl);
0561: } else
0562: UserManager.mgr.updateVips(new Vector());
0563:
0564: val = props.getProperty("admins");
0565: if (val != null) {
0566: Vector tvl = new Vector();
0567: String values[] = val.split(",");
0568: for (int i = 0; i < values.length; i++) {
0569: tvl.addElement(values[i].trim().toLowerCase());
0570: }
0571: UserManager.mgr.updateAdmins(tvl);
0572: } else
0573: UserManager.mgr.updateAdmins(new Vector());
0574:
0575: val = props.getProperty("moderators");
0576: if (val != null) {
0577: Vector tvl = new Vector();
0578: String values[] = val.split(",");
0579: for (int i = 0; i < values.length; i++) {
0580: tvl.addElement(values[i].trim().toLowerCase());
0581: }
0582: UserManager.mgr.updateModerators(tvl);
0583: } else
0584: UserManager.mgr.updateModerators(new Vector());
0585:
0586: val = props.getProperty("guests");
0587: if (val != null) {
0588: Vector tvl = new Vector();
0589: String values[] = val.split(",");
0590: for (int i = 0; i < values.length; i++) {
0591: tvl.addElement(values[i].trim().toLowerCase());
0592: }
0593: UserManager.mgr.updateGuests(tvl);
0594: } else
0595: UserManager.mgr.updateGuests(new Vector());
0596:
0597: val = props.getProperty("admin.http.allowedClients");
0598: if (val != null) {
0599: String hsts[] = val.split(",");
0600: Vector newHsts = new Vector();
0601: for (int i = 0; i < hsts.length; i++) {
0602: try {
0603: InetAddress ia = InetAddress.getByName(hsts[i]
0604: .trim());
0605: if (!newHsts.contains(ia))
0606: newHsts.addElement(ia);
0607: } catch (Exception e) {
0608: StringBuffer tsb = new StringBuffer(
0609: "Server.checkForConfigValues: unable to add adminHost ");
0610: tsb.append(hsts[i]);
0611: Server.debug(this , tsb.toString(), e,
0612: Server.MSG_ERROR, Server.LVL_MAJOR);
0613: }
0614: }
0615: Vector remove = (Vector) adminHosts.clone();
0616: remove.removeAll(newHsts);
0617: newHsts.removeAll(adminHosts);
0618: adminHosts.removeAll(remove);
0619: adminHosts.addAll(newHsts);
0620: }
0621:
0622: String oldTimeZone = TIMEZONE;
0623: TIMEZONE = checkProperty("timezone", null);
0624: TimeZone tz = null;
0625: if (TIMEZONE == null || TIMEZONE.length() < 1) {
0626: StringBuffer sb = new StringBuffer(
0627: "checkForConfigValues: setting TimeZone to default-TimeZone (");
0628: tz = TimeZone.getDefault();
0629: sb.append(tz.getID());
0630: sb.append(")");
0631: Server.log(this , sb.toString(), Server.MSG_STATE,
0632: Server.LVL_MINOR);
0633: if (tz.equals(cal.getTimeZone()))
0634: tz = null;
0635: } else if (oldTimeZone == null || !oldTimeZone.equals(TIMEZONE)) {
0636: try {
0637: tz = TimeZone.getTimeZone(TIMEZONE);
0638: if (tz.equals(cal.getTimeZone())) {
0639: Server
0640: .log(
0641: this ,
0642: "checkForConfigVals: TimeZone has not changed",
0643: Server.MSG_ERROR, Server.LVL_MINOR);
0644: tz = null;
0645: } else if (!tz.getID().equals(TIMEZONE)) {
0646: StringBuffer sb = new StringBuffer(
0647: "checkForConfigVals: TimeZone is set to ");
0648: sb.append(tz.getID());
0649: sb
0650: .append(" now. The following TimeZones are available:\r\n");
0651: String[] ids = TimeZone.getAvailableIDs();
0652: for (int i = 0; i < ids.length; i++) {
0653: sb.append(ids[i]);
0654: if (i < ids.length)
0655: sb.append(", ");
0656: }
0657: Server.log(this , sb.toString(), Server.MSG_STATE,
0658: Server.LVL_MINOR);
0659: }
0660: StringBuffer sb = new StringBuffer(
0661: "checkForConfigValues: setting TimeZone to ");
0662: sb.append(tz.getID());
0663: Server.log(this , sb.toString(), Server.MSG_STATE,
0664: Server.LVL_MINOR);
0665: } catch (Exception e) {
0666: Server
0667: .debug(
0668: this ,
0669: "checkForConfigValues: unable to set TimeZone!",
0670: e, Server.MSG_ERROR, Server.LVL_MAJOR);
0671: }
0672: }
0673: if (tz != null) {
0674: cal.setTimeZone(tz);
0675: }
0676:
0677: Listener.updateSscRecieveBuffer(this .TCP_RECEIVE_BUFFER_WINDOW);
0678:
0679: val = checkProperty("allowedLoginHosts", null);
0680: if (val != null) {
0681: String hsts[] = val.split(",");
0682: Vector newHsts = new Vector();
0683: for (int i = 0; i < hsts.length; i++) {
0684: try {
0685: InetAddress ia = InetAddress.getByName(hsts[i]
0686: .trim());
0687: if (!newHsts.contains(ia))
0688: newHsts.addElement(ia);
0689: } catch (Exception e) {
0690: StringBuffer tsb = new StringBuffer(
0691: "Server.checkForConfigValues: unable to add adminHost ");
0692: tsb.append(hsts[i]);
0693: Server.debug(this , tsb.toString(), e,
0694: Server.MSG_ERROR, Server.LVL_MAJOR);
0695: }
0696: }
0697: Vector remove = (Vector) allowedLoginHosts.clone();
0698: remove.removeAll(newHsts);
0699: newHsts.removeAll(allowedLoginHosts);
0700: allowedLoginHosts.removeAll(remove);
0701: allowedLoginHosts.addAll(newHsts);
0702: }
0703:
0704: // set logmask and debug-switch
0705: String logVal = props.getProperty("debug");
0706: if (logVal != null && logVal.equalsIgnoreCase("false"))
0707: DEBUG = false;
0708: else if (logVal != null && logVal.equalsIgnoreCase("true"))
0709: DEBUG = true;
0710:
0711: logVal = props.getProperty("log_config");
0712: if (logVal != null)
0713: LOG_MASK[MSG_CONFIG] = new Short(Short.parseShort(logVal,
0714: 10));
0715: logVal = props.getProperty("log_auth");
0716: if (logVal != null)
0717: LOG_MASK[MSG_AUTH] = new Short(Short.parseShort(logVal, 10));
0718: logVal = props.getProperty("log_state");
0719: if (logVal != null)
0720: LOG_MASK[MSG_STATE] = new Short(Short
0721: .parseShort(logVal, 10));
0722: logVal = props.getProperty("log_traffic");
0723: if (logVal != null)
0724: LOG_MASK[MSG_TRAFFIC] = new Short(Short.parseShort(logVal,
0725: 10));
0726: logVal = props.getProperty("log_error");
0727: if (logVal != null)
0728: LOG_MASK[MSG_ERROR] = new Short(Short
0729: .parseShort(logVal, 10));
0730: }
0731:
0732: /**
0733: * util-method for checking boolean config-values
0734: * @param p
0735: * @param def
0736: * @return
0737: */
0738: private boolean checkProperty(String p, boolean def) {
0739: String pval = props.getProperty(p);
0740: if (pval == null)
0741: return def;
0742: return pval.equalsIgnoreCase("true");
0743: }
0744:
0745: /**
0746: * util-method for checking long config-values
0747: * @param p
0748: * @param def
0749: * @return
0750: */
0751: private long checkProperty(String p, long def) {
0752: String pval = props.getProperty(p);
0753: if (pval == null)
0754: return def;
0755: try {
0756: return Long.parseLong(pval, 10);
0757: } catch (Exception e) {
0758: Server.debug("Server",
0759: "invalid value specified for configuration-parameter "
0760: + pval, e, Server.MSG_ERROR,
0761: Server.LVL_MAJOR);
0762: return def;
0763: }
0764: }
0765:
0766: /**
0767: * util-method for checking int config-values
0768: * @param p
0769: * @param def
0770: * @return
0771: */
0772: private int checkProperty(String p, int def) {
0773: String pval = props.getProperty(p);
0774: if (pval == null)
0775: return def;
0776: try {
0777: return Integer.parseInt(pval, 10);
0778: } catch (Exception e) {
0779: Server.debug("Server",
0780: "invalid value specified for configuration-parameter "
0781: + pval, e, Server.MSG_ERROR,
0782: Server.LVL_MAJOR);
0783: return def;
0784: }
0785: }
0786:
0787: /**
0788: * util-method for checking String config-values
0789: * @param p
0790: * @param def
0791: * @return
0792: */
0793: private String checkProperty(String p, String def) {
0794: String pval = props.getProperty(p);
0795: if (pval == null)
0796: return def;
0797: return pval;
0798: }
0799:
0800: public void initServer() {
0801: try {
0802: if (templatemanager == null)
0803: templatemanager = new TemplateManager();
0804: } catch (IOException ioe) {
0805: Server.debug(this , "unable to load TemplateSet: ", ioe,
0806: MSG_ERROR, LVL_HALT);
0807: }
0808: auth = AuthManager.instance;
0809: auth.init();
0810:
0811: Runtime rt = Runtime.getRuntime();
0812: // register the CleanupClass as shutdown-hook
0813: rt.addShutdownHook(new CleanupClass());
0814: }
0815:
0816: public void removeToken(String cookie) {
0817: if (cookie == null)
0818: return;
0819: tokenStore.remove(cookie);
0820: }
0821:
0822: public boolean isTokenValid(String token, String cookie) {
0823: if (!USE_TOKENSTORE)
0824: return true;
0825: if (token == null || cookie == null)
0826: return false;
0827: String t = (String) tokenStore.get(cookie);
0828: if (t == null || !t.equals(token))
0829: return false;
0830: return true;
0831: }
0832:
0833: public void addToken(String token, String cookie) {
0834: if (!USE_TOKENSTORE || token == null || cookie == null)
0835: return;
0836: tokenStore.put(cookie, token);
0837: }
0838:
0839: /**********************************************************************************************
0840: * QUERY-METHODS (used for retriefing values...)
0841: **********************************************************************************************/
0842: public void startShutdown() {
0843: isRunning = false;
0844: }
0845:
0846: public boolean isRunning() {
0847: return isRunning;
0848: }
0849:
0850: public boolean isAdminHost(InetAddress ia) {
0851: return adminHosts.contains(ia);
0852: }
0853:
0854: public InetAddress getLocalHost() {
0855: return lh;
0856: }
0857:
0858: public String getProperty(String key) {
0859: return props.getProperty(key);
0860: }
0861:
0862: /**
0863: * returns http-url to this server
0864: * @return the http-url to this server
0865: */
0866: public String getUrl() {
0867: StringBuffer sb = new StringBuffer(SERVER_NAME == null ? lh
0868: .getCanonicalHostName() : SERVER_NAME);
0869: String port = props.getProperty("mappedPort");
0870: if (port == null)
0871: port = props.getProperty("port");
0872: if (!"80".equals(port)) {
0873: sb.append(":");
0874: sb.append(port);
0875: }
0876: return (sb.toString());
0877: }
0878:
0879: /**
0880: * returns the version of this server
0881: * @return version of server
0882: */
0883: public static String getVersion() {
0884: return VERSION;
0885: }
0886:
0887: /**********************************************************************************************
0888: * BAN-METHODS (for checking and banning users...
0889: **********************************************************************************************/
0890: /**
0891: * Used to ban a user from the server. Name and cookie are baned
0892: * If the ban-duration is reached, this ban will be removed by the main-thread
0893: * @param u the user object
0894: * @param msgTemplate the message template to use for this ban (eg. user.flood)
0895: * @param millis how long this user will be banned
0896: */
0897: public void banUser(User u, String msgTemplate, String message,
0898: long millis, String bannedBy) {
0899: if (u == null)
0900: return;
0901: MessageParser mp = new MessageParser();
0902: mp.setSender(u);
0903: mp.setUsercontext(u);
0904: Group g = u.getGroup();
0905: if (g != null) {
0906: mp.setMessageTemplate(msgTemplate);
0907: g.removeUser(u);
0908: g.sendMessage(mp);
0909: }
0910: banUser(u, message, millis, bannedBy);
0911: }
0912:
0913: /**
0914: * ban all users contained in given vector
0915: * @param v vector containing users
0916: * @param message reason for the kick
0917: * @param millis milliseconds this user will be banned
0918: * @param bannedBy name of the banner (may be Server in case of floodprotection
0919: */
0920: public void banUser(Vector v, String message, long millis,
0921: String bannedBy) {
0922: for (Enumeration e = v.elements(); e.hasMoreElements();) {
0923: User u = (User) e.nextElement();
0924: this .banUser(u, message, millis, bannedBy);
0925: }
0926: }
0927:
0928: public void banUser(User u, String message, long millis,
0929: String bannedBy) {
0930: if (u == null)
0931: return;
0932: StringBuffer sb = new StringBuffer("banUser: User=");
0933: sb.append(u.getName());
0934: sb.append(" BannedBy=");
0935: sb.append(bannedBy);
0936: sb.append(" Cookie=");
0937: sb.append(u.getCookie());
0938: if (u.conn == null) {
0939: sb.append(" Connection-Object was null");
0940: } else if (u.conn.clientIp != null) {
0941: sb.append(" +IP=");
0942: sb.append(u.conn.clientIp);
0943: } else {
0944: sb.append(" Came over Proxy (Proxy: ");
0945: sb.append(u.conn.peerIp);
0946: sb.append(", ForwardChain: ");
0947: sb.append(u.conn.fwChain);
0948: }
0949: sb.append(" Duration=");
0950: sb.append(millis / 1000);
0951: sb.append("secs Message=");
0952: sb.append(message);
0953: Server.log(this , sb.toString(), Server.MSG_AUTH,
0954: Server.LVL_MAJOR);
0955: BanObject bo = new BanObject(message, bannedBy, System
0956: .currentTimeMillis()
0957: + millis);
0958: bo.cookie = u.getCookie();
0959: bo.usr = u.getName().toLowerCase().trim();
0960: bo.email = (String) u.getProperty("email");
0961: if (bo.email != null) {
0962: bo.email = bo.email.trim().toLowerCase();
0963: banList.put(bo.email, bo);
0964: }
0965: banList.put(bo.usr, bo);
0966: banList.put(bo.cookie, bo);
0967: if (USE_IP_BAN && u.conn != null && u.conn.isBanable()) {
0968: bo.con = u.conn;
0969: banList.put(bo.con.getBanKey(), bo);
0970: }
0971: u.sendQuitMessage(true);
0972: }
0973:
0974: public boolean removeBan(String key) {
0975: BanObject bo = (BanObject) banList.get(key);
0976: if (bo == null)
0977: return false;
0978: if (bo.hostban != null) {
0979: banList.remove(bo.hostban);
0980: } else {
0981: if (bo.usr != null)
0982: banList.remove(bo.usr);
0983: if (bo.cookie != null)
0984: banList.remove(bo.cookie);
0985: if (bo.con != null)
0986: banList.remove(bo.con.getBanKey());
0987: if (bo.email != null)
0988: banList.remove(bo.email);
0989: }
0990: return true;
0991: }
0992:
0993: public BanObject[] getBanList() {
0994: if (banList.size() < 0) {
0995: return new BanObject[0];
0996: }
0997: Vector v = new Vector();
0998: for (Enumeration e = banList.elements(); e.hasMoreElements();) {
0999: Object o = e.nextElement();
1000: if (v.contains(o))
1001: continue;
1002: v.add(o);
1003: }
1004: return (BanObject[]) v.toArray(new BanObject[0]);
1005: }
1006:
1007: public void banHost(InetAddress ia, long millis, String msg) {
1008: BanObject bo = new BanObject(msg, "Server", millis);
1009: bo.hostban = ia.getHostAddress();
1010: banList.put(bo.hostban, bo);
1011: }
1012:
1013: /**
1014: * checks if this Object is associated to a ban
1015: * @param o the Object to check
1016: * @return boolean true if this Object is associated with a ban
1017: */
1018: public boolean isBanned(Object o) {
1019: // null is not ban-able
1020: if (o == null)
1021: return false;
1022:
1023: // get the ban-object if there is one
1024: BanObject b;
1025: if (o instanceof String) {
1026: String s = ((String) o).toLowerCase();
1027: b = (BanObject) banList.get(s);
1028: } else if (o instanceof Connection) {
1029: Connection conn = (Connection) o;
1030: if (!conn.isBanable())
1031: return false;
1032: b = (BanObject) banList.get(conn.getBanKey());
1033: } else if (o instanceof InetAddress) {
1034: InetAddress ia = (InetAddress) o;
1035: b = (BanObject) banList.get(ia.getHostAddress());
1036: } else {
1037: b = (BanObject) banList.get(o);
1038: }
1039:
1040: // not-banned if there is no ban-object
1041: if (b == null)
1042: return false;
1043:
1044: // check if the ban is still fresh
1045: if (b.time < System.currentTimeMillis()) {
1046: banList.remove(o);
1047: return false;
1048: }
1049: return true;
1050: }
1051:
1052: /**********************************************************************************************
1053: * LOGGING (will be moved to an extra object...
1054: **********************************************************************************************/
1055: public static String[] LOGFILE = { "console", "console", "console",
1056: "console", "console" };
1057:
1058: public static final short MSG_CONFIG = 0;
1059: public static final short MSG_AUTH = 1;
1060: public static final short MSG_STATE = 2;
1061: public static final short MSG_TRAFFIC = 3;
1062: public static final short MSG_ERROR = 4;
1063:
1064: public static final short LVL_HALT = 0;
1065: public static final short LVL_MAJOR = 1;
1066: public static final short LVL_MINOR = 2;
1067: public static final short LVL_VERBOSE = 3;
1068: public static final short LVL_VERY_VERBOSE = 4;
1069:
1070: public static boolean DEBUG = false;
1071: public static Short LOG_MASK[] = new Short[5];
1072:
1073: /**
1074: * allows to check for logability of a message in advance of
1075: * performance critical messages
1076: */
1077: public static boolean checkLogLvl(short type, short lvl) {
1078: return (LOG_MASK[type].intValue() >= lvl || DEBUG);
1079: }
1080:
1081: /**
1082: * Logging method configured by the loglevel mechanism
1083: * @param msg the message to log
1084: * @param type the type of message (MSG_ prefixed konstants are used here)
1085: * @param lvl the level of attention to use here (LVL_ prefixed konstants are used here)
1086: */
1087: public static void log(Object o, String msg, short type, short lvl) {
1088: StringBuffer sb = new StringBuffer();
1089: try {
1090: if (LOG_MASK[type].intValue() < lvl && !DEBUG)
1091: return;
1092: sb.append("[");
1093: sb.append(Server.formatDefaultTimeStamp(System
1094: .currentTimeMillis()));
1095: switch (lvl) {
1096: case LVL_MAJOR:
1097: sb.append("] MAJOR-| ");
1098: break;
1099: case LVL_HALT:
1100: sb.append("] HALT -| ");
1101: break;
1102: default:
1103: sb.append("] -| ");
1104: }
1105: if (o != null) {
1106: sb.append(o.toString());
1107: sb.append(": ");
1108: }
1109: sb.append(msg);
1110: sb.append("\r\n");
1111: if ((type == MSG_CONFIG && LOGFILE[MSG_CONFIG]
1112: .equals("console"))
1113: || (type == MSG_AUTH && LOGFILE[MSG_AUTH]
1114: .equals("console"))
1115: || (type == MSG_STATE && LOGFILE[MSG_STATE]
1116: .equals("console"))
1117: || (type == MSG_TRAFFIC && LOGFILE[MSG_TRAFFIC]
1118: .equals("console"))
1119: || (type == MSG_ERROR && LOGFILE[MSG_ERROR]
1120: .equals("console"))) {
1121: System.out.print(sb.toString());
1122: } else {
1123: LogWriter.instance.addLogMessage(type, sb.toString());
1124: }
1125: if (lvl == LVL_HALT)
1126: System.exit(1);
1127: } catch (Exception e) {
1128: System.err
1129: .println("Server.log caused Exception for Message:");
1130: System.err.print(sb.toString());
1131: e.printStackTrace();
1132: }
1133: }
1134:
1135: /**
1136: * Debuging method configured by the loglevel mechanism
1137: * @param prefix to write before other stuff
1138: * @param t is the throwable to print the stacktrace from
1139: * @param type the type of message, konstants with MSG_ prefix are used here
1140: * @param lvl the level of atention to use here, konstants with LVL_ prefix are used here
1141: */
1142: public static void debug(Object o, String prefix, Throwable t,
1143: short type, short lvl) {
1144: if (LOG_MASK[type].intValue() < lvl && !DEBUG)
1145: return;
1146: StringBuffer sb = new StringBuffer();
1147: sb.append(prefix);
1148: sb.append("\r\n");
1149: sb.append(t.toString());
1150: StackTraceElement ste[] = t.getStackTrace();
1151: for (int i = 0; i < ste.length; i++) {
1152: sb.append("\r\n at ");
1153: sb.append(ste[i].getClassName());
1154: sb.append("(");
1155: sb.append(ste[i].getFileName());
1156: sb.append(":");
1157: sb.append(ste[i].getLineNumber());
1158: sb.append(")");
1159: }
1160: log(o, sb.toString(), type, lvl);
1161: }
1162:
1163: /**********************************************************************************************
1164: * INTERFACE RELOADABLE
1165: **********************************************************************************************/
1166: private long lastModified;
1167: private File configFile;
1168:
1169: public long lastModified() {
1170: return lastModified;
1171: }
1172:
1173: public void changed() {
1174: try {
1175: FileInputStream fis = new FileInputStream(configFile);
1176: Properties tprop = new Properties();
1177: tprop.load(fis);
1178: fis.close();
1179: props = tprop;
1180: checkForConfigValues();
1181: lastModified = configFile.lastModified();
1182: Server.log(this , "reload: reloaded configfile",
1183: Server.MSG_STATE, Server.LVL_MINOR);
1184: } catch (Exception e) {
1185: Server.debug(this , "reload: ", e, Server.MSG_ERROR,
1186: Server.LVL_MAJOR);
1187: }
1188: }
1189:
1190: public void removed() {
1191: Server
1192: .log(
1193: this ,
1194: "CRITICAL-WARNING: Config file has been removed!\r\nThe Serverconfiguration of the last configuration-file present will stay in charge, but the server won't start if no config is present!",
1195: Server.MSG_ERROR, Server.LVL_MAJOR);
1196: }
1197:
1198: public File getFile() {
1199: return configFile;
1200: }
1201:
1202: public boolean filePresent() {
1203: return true; // server-config must always be present
1204: }
1205:
1206: public void created() {
1207: changed();
1208: }
1209:
1210: public String getFormatedTime(String pattern) {
1211: return formatTimeStamp(System.currentTimeMillis(), pattern);
1212: }
1213:
1214: public static SimpleDateFormat defaultDateFormat = new SimpleDateFormat(
1215: "yyyy.MM.dd HH:mm:ss");
1216: public static SimpleDateFormat hourSDF = new SimpleDateFormat("HH");
1217: public static SimpleDateFormat minuteSDF = new SimpleDateFormat(
1218: "mm");
1219:
1220: public static String formatDefaultTimeStamp(long ts) {
1221: cal.setTimeInMillis(ts);
1222: return defaultDateFormat.format(cal.getTime());
1223: }
1224:
1225: public String formatTimeStamp(long ts, String pattern) {
1226: SimpleDateFormat sdf = new SimpleDateFormat(pattern);
1227: cal.setTimeInMillis(ts);
1228: return sdf.format(cal.getTime());
1229: }
1230:
1231: public static String formatTimeStamp(long ts, SimpleDateFormat sdf) {
1232: cal.setTimeInMillis(ts);
1233: return sdf.format(cal.getTime());
1234: }
1235:
1236: /**
1237: * returns the directory of the main server config. other classes can
1238: * fetch their configs from there (e.g. the Authenticator-classes.
1239: */
1240: public File getConfigDir() {
1241: return (configFile != null) ? configFile.getParentFile() : null;
1242: }
1243:
1244: public String toString() {
1245: return ("[Server]");
1246: }
1247: }
|