001: /*
002: * $Header: /cvsroot/mvnforum/mvnforum/src/com/mvnforum/auth/OnlineUserImpl.java,v 1.76 2008/01/07 10:28:25 tbtrung Exp $
003: * $Author: tbtrung $
004: * $Revision: 1.76 $
005: * $Date: 2008/01/07 10:28:25 $
006: *
007: * ====================================================================
008: *
009: * Copyright (C) 2002-2007 by MyVietnam.net
010: *
011: * All copyright notices regarding mvnForum MUST remain
012: * intact in the scripts and in the outputted HTML.
013: * The "powered by" text/logo with a link back to
014: * http://www.mvnForum.com and http://www.MyVietnam.net in
015: * the footer of the pages MUST remain visible when the pages
016: * are viewed on the internet or intranet.
017: *
018: * This program is free software; you can redistribute it and/or modify
019: * it under the terms of the GNU General Public License as published by
020: * the Free Software Foundation; either version 2 of the License, or
021: * any later version.
022: *
023: * This program is distributed in the hope that it will be useful,
024: * but WITHOUT ANY WARRANTY; without even the implied warranty of
025: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
026: * GNU General Public License for more details.
027: *
028: * You should have received a copy of the GNU General Public License
029: * along with this program; if not, write to the Free Software
030: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
031: *
032: * Support can be obtained from support forums at:
033: * http://www.mvnForum.com/mvnforum/index
034: *
035: * Correspondence and Marketing Questions can be sent to:
036: * info at MyVietnam net
037: *
038: * @author: Minh Nguyen
039: * @author: Mai Nguyen
040: */
041: package com.mvnforum.auth;
042:
043: import java.awt.image.BufferedImage;
044: import java.sql.Timestamp;
045: import java.text.DateFormat;
046: import java.util.*;
047:
048: import javax.servlet.http.HttpServletRequest;
049:
050: import net.myvietnam.mvncore.exception.BadInputException;
051: import net.myvietnam.mvncore.exception.DatabaseException;
052: import net.myvietnam.mvncore.util.DateUtil;
053: import net.myvietnam.mvncore.util.ParamUtil;
054: import net.myvietnam.mvncore.web.GenericRequest;
055: import net.myvietnam.mvncore.web.impl.GenericRequestServletImpl;
056:
057: import org.apache.commons.logging.Log;
058: import org.apache.commons.logging.LogFactory;
059:
060: import com.mvnforum.*;
061: import com.mvnforum.common.MVNCaptchaService;
062: import com.mvnforum.db.*;
063: import com.octo.captcha.image.ImageCaptcha;
064:
065: class OnlineUserImpl implements OnlineUser {
066:
067: private static Log log = LogFactory.getLog(OnlineUserImpl.class);
068:
069: private static long CHECK_NEW_MESSAGE_INTERVAL = 5 * DateUtil.MINUTE;// five minutes
070:
071: private int memberID = MVNForumConstant.MEMBER_ID_OF_GUEST;
072:
073: private String memberName = "";
074:
075: private int authenticationType = AUTHENTICATION_TYPE_UNAUTHENTICATED;
076:
077: private MVNForumPermission permission = null;
078:
079: private OnlineUserAction onlineUserAction = new OnlineUserAction();
080:
081: private int memberPostsPerPage = 10;
082: private int memberMessagesPerPage = 10;
083:
084: private boolean invisible = false;
085:
086: private int newMessageCount = 0;
087:
088: private String memberCssPath = null;
089: private String memberLogoPath = null;
090:
091: private double timezone = 0;
092: /* private DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
093: * Igor: previous line should be: new SimpleDateFormat(..., Locale.US)
094: * Otherwise won't work for users who don't have en/US as default.
095: */
096: private DateFormat timestampFormatter = null;
097: private DateFormat dateFormatter = null;
098:
099: private Timestamp lastLogonTimestamp = null;
100:
101: private boolean passwordExpired = false;
102:
103: private Timestamp lastCheckNewMessageTimestamp = null;
104:
105: private String lastLogonIP = null;
106:
107: private String localeName = "";
108:
109: private Locale locale = null;
110:
111: private boolean gender = true;
112:
113: private ImageCaptcha imageCaptcha = null;
114: private Object conn = null;
115: private Set participants = new HashSet();
116: private Set waitingList = new HashSet();
117:
118: /**
119: * Default access constructor, prevent outsite creation
120: * NOTE: the implementation should init the following:
121: * - Is Guest or not <br/>
122: * - Call initRemoteAddr_UserAgent() <br/>
123: * - The memberCssPath <br/>
124: * - The memberLogoPath <br/>
125: */
126: OnlineUserImpl(HttpServletRequest request, boolean isGuest)
127: throws DatabaseException {
128: GenericRequest genericRequest = new GenericRequestServletImpl(
129: request);
130: init(genericRequest, isGuest);
131: }
132:
133: OnlineUserImpl(GenericRequest request, boolean isGuest)
134: throws DatabaseException {
135: init(request, isGuest);
136: }
137:
138: private void init(GenericRequest request, boolean isGuest)
139: throws DatabaseException {
140: if (isGuest) {
141: setMemberID(MVNForumConstant.MEMBER_ID_OF_GUEST);
142: setMemberName(MVNForumConfig.getDefaultGuestName());
143: }
144: getOnlineUserAction().initRemoteAddr_UserAgent(request);
145: String contextPath = request.getContextPath();
146: memberCssPath = contextPath + MVNForumGlobal.CSS_FULLPATH;
147: memberLogoPath = contextPath + MVNForumGlobal.LOGO_FULLPATH;
148: }
149:
150: public int getMemberID() {
151: return memberID;
152: }
153:
154: public String getMemberName() {
155: return memberName;
156: }
157:
158: public boolean isGuest() {
159: return ((memberID == 0) || (memberID == MVNForumConstant.MEMBER_ID_OF_GUEST));
160: }
161:
162: public boolean isMember() {
163: return !isGuest();
164: }
165:
166: public boolean isInvisibleMember() {
167: // @todo: temp implementation
168: return this .invisible;
169: }
170:
171: public boolean isPasswordExpired() {
172: return passwordExpired;
173: }
174:
175: public int getAuthenticationType() {
176: return authenticationType;
177: }
178:
179: public MVNForumPermission getPermission() {
180: return permission;
181: }
182:
183: public void reloadPermission() {
184: try {
185: if (isGuest()) {
186: permission = MVNForumPermissionFactory
187: .getAnonymousPermission();
188: } else {
189: // Please note that getAuthenticatedPermission only need memberName, so we can get from Cache for better performance
190: MemberBean memberBean = MemberCache.getInstance()
191: .getMember(memberID);
192: permission = MVNForumPermissionFactory
193: .getAuthenticatedPermission(memberBean);
194: }
195: } catch (Exception ex) {
196: log.error(
197: "Error when reload permission in OnlineUserImpl for memberID = "
198: + memberID, ex);
199: }
200: }
201:
202: public void reloadProfile() {
203: try {
204: if (isGuest()) {
205: // currently just do nothing, implement later
206: } else {
207: MemberBean memberBean = DAOFactory.getMemberDAO()
208: .getMember(memberID);
209:
210: double timeZone = memberBean.getMemberTimeZone();
211: localeName = memberBean.getMemberLanguage();
212: int postsPerPage = memberBean.getMemberPostsPerPage();
213:
214: setTimeZone(timeZone);
215: setLocaleName(localeName);
216: setGender(memberBean.getMemberGender() != 0);
217: setPostsPerPage(postsPerPage);
218: setInvisible(memberBean.isInvisible());
219: }
220: } catch (Exception ex) {
221: log.error(
222: "Error when reload profile in OnlineUserImpl for memberID = "
223: + memberID, ex);
224: }
225: }
226:
227: public boolean updateNewMessageCount(boolean forceUpdate) {
228:
229: if (isGuest())
230: return false;
231:
232: int currentMessageCount = newMessageCount;
233: Timestamp now = DateUtil.getCurrentGMTTimestamp();
234: long lastRequest = 0;
235: if (lastCheckNewMessageTimestamp != null) {
236: lastRequest = lastCheckNewMessageTimestamp.getTime();
237: }
238: if ((lastCheckNewMessageTimestamp == null)
239: || forceUpdate
240: || ((lastRequest + CHECK_NEW_MESSAGE_INTERVAL) <= now
241: .getTime())) {
242: try {
243: lastCheckNewMessageTimestamp = now;
244: newMessageCount = DAOFactory
245: .getMessageDAO()
246: .getNumberOfUnreadNonPublicMessages_inMember_inFolder(
247: memberID,
248: MVNForumConstant.MESSAGE_FOLDER_INBOX);
249: if (currentMessageCount < newMessageCount) {
250: return true;
251: }
252: } catch (Exception ex) {
253: log.error(
254: "Error when udpate new message count in OnlineUserImpl for memberID = "
255: + memberID, ex);
256: }
257: }
258: return false;
259: }
260:
261: public OnlineUserAction getOnlineUserAction() {
262: return onlineUserAction;
263: }
264:
265: public java.util.Date convertGMTDate(java.util.Date gmtDate) {
266: return DateUtil.convertGMTDate(gmtDate, timezone);
267: }
268:
269: public Timestamp convertGMTTimestamp(Timestamp gmtTimestamp) {
270: return DateUtil.convertGMTTimestamp(gmtTimestamp, timezone);
271: }
272:
273: public String getGMTDateFormat(java.util.Date gmtDate) {
274: return getGMTDateFormat(gmtDate, true);
275: }
276:
277: public synchronized String getGMTDateFormat(java.util.Date gmtDate,
278: boolean adjustTimeZone) {
279: if (gmtDate == null)
280: return "";
281:
282: java.util.Date date = gmtDate;
283: if (adjustTimeZone) {
284: date = DateUtil.convertGMTDate(gmtDate, timezone);
285: }
286: return dateFormatter.format(date);
287: }
288:
289: public String getGMTTimestampFormat(Timestamp gmtTimestamp) {
290: return getGMTTimestampFormat(gmtTimestamp, true);
291: }
292:
293: public synchronized String getGMTTimestampFormat(
294: Timestamp gmtTimestamp, boolean adjustTimeZone) {
295: if (gmtTimestamp == null)
296: return "";
297:
298: Timestamp timestamp = gmtTimestamp;
299: if (adjustTimeZone) {
300: timestamp = DateUtil.convertGMTTimestamp(gmtTimestamp,
301: timezone);
302: }
303: return timestampFormatter.format(timestamp);
304: }
305:
306: public String getLocaleName() {
307: return localeName;
308: }
309:
310: public void setLocaleName(String localeName) {
311: if (localeName == null) {
312: localeName = "";
313: }
314: this .localeName = localeName;
315:
316: if (localeName.length() == 0) {
317: this .localeName = MVNForumConfig.getDefaultLocaleName();
318: this .locale = MVNForumConfig.getDefaultLocale();
319: } else {
320: locale = MyUtil.getLocale(localeName);
321: }
322:
323: // now init the 2 class variables
324: dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT,
325: locale);
326: timestampFormatter = DateFormat.getDateTimeInstance(
327: DateFormat.DEFAULT, DateFormat.DEFAULT, locale);
328: }
329:
330: public Locale getLocale() {
331: return locale;
332: }
333:
334: public String getLastLogonIP() {
335: if (isGuest()) {
336: return "";
337: }
338: return lastLogonIP;
339: }
340:
341: public Timestamp getLastLogonTimestamp() {
342: return lastLogonTimestamp;
343: }
344:
345: /*
346: public boolean getGender() {
347: return gender;
348: }
349: */
350: public int getPostsPerPage() {
351: return memberPostsPerPage;
352: }
353:
354: public int getMessagesPerPage() {
355: return memberMessagesPerPage;
356: }
357:
358: public int getNewMessageCount() {
359: return newMessageCount;
360: }
361:
362: public String getCssPath() {
363: return memberCssPath;
364: }
365:
366: public String getCssPath(HttpServletRequest request) {
367: String preview = ParamUtil.getParameter(request, "csspreview");
368: if ("yes".equals(preview)) {
369: String contextPath = request.getContextPath();
370: return contextPath + MVNForumGlobal.CSS_PREVIEW_FULLPATH;
371: }
372: return memberCssPath;
373: }
374:
375: public String getLogoPath() {
376: return memberLogoPath;
377: }
378:
379: /**
380: * Build a new captcha, this method must be called before using some
381: * action that need captcha validation.
382: */
383: public void buildNewCaptcha() {
384: destroyCurrentCaptcha();
385:
386: // this line of code could throw Exception in case the captcha image
387: // is small to hold the whole captcha
388: imageCaptcha = MVNCaptchaService.getInstance()
389: .getNextImageCaptcha();
390: }
391:
392: /**
393: * Destroy the current captcha, this method must be called after validate
394: * the captcha
395: */
396: public void destroyCurrentCaptcha() {
397: imageCaptcha = null;
398: }
399:
400: /**
401: * Get the captcha image to challenge the user
402: *
403: * @return BufferedImage the captcha image to challenge the user
404: */
405: public BufferedImage getCurrentCaptchaImage() {
406: if (imageCaptcha == null) {
407: return null;
408: }
409: return (BufferedImage) (imageCaptcha.getChallenge());
410: }
411:
412: /**
413: * Validate the anwser of the captcha from user
414: *
415: * @param anwser String the captcha anwser from user
416: * @return boolean true if the answer is valid, otherwise return false
417: */
418: public boolean validateCaptchaResponse(String anwser) {
419: if (imageCaptcha == null) {
420: log
421: .info("validateCaptchaResponse returned false due to imageCaptcha is null");
422: return false;
423: }
424: anwser = anwser.toUpperCase();//use upper case for easier usage
425: boolean result = (imageCaptcha.validateResponse(anwser))
426: .booleanValue();
427: if (result == false) {
428: // minhnn: I comment the below code because cannot get private variable 'response' from class Gimpy
429: //log.info("validateCaptchaResponse returned false due to wrong answer. The input is '" + anwser + "' but expect '" + imageCaptcha.getQuestion() + "'");
430: }
431: return result;
432: }
433:
434: /**
435: * Check to make sure that the captcha answer is correct
436: *
437: * @param answer String the captcha answer to check
438: * @throws BadInputException in case the captcha answer is not correct
439: */
440: public void ensureCorrectCaptchaResponse(String answer)
441: throws BadInputException {
442:
443: if (validateCaptchaResponse(answer) == false) {
444: throw new BadInputException(
445: MVNForumResourceBundle
446: .getString(locale,
447: "mvncore.exception.BadInputException.wrong_captcha"));
448: }
449: }
450:
451: /*****************************************************************
452: * Default-scope methods, only for internal package usage
453: *****************************************************************/
454: void setMemberID(int memberID) {
455: if (memberID == 0) {
456: this .memberID = MVNForumConstant.MEMBER_ID_OF_GUEST;
457: } else {
458: this .memberID = memberID;
459: }
460: onlineUserAction.setMemberID(this .memberID);
461: }
462:
463: void setPasswordExpired(boolean expired) {
464: this .passwordExpired = expired;
465: }
466:
467: void setMemberName(String memberName) {
468: this .memberName = memberName;
469: onlineUserAction.setMemberName(memberName);
470: }
471:
472: void setInvisible(boolean invisible) {
473: this .invisible = invisible;
474: onlineUserAction.setMemberInvisible(invisible);
475: }
476:
477: void setAuthenticationType(int authType) {
478: authenticationType = authType;
479: }
480:
481: /**
482: * NOTE: this method SHOULD ONLY BE CALLED from OnlineUserFactory
483: */
484: void setPermission(MVNForumPermission permission) {
485: this .permission = permission;
486: }
487:
488: void setTimeZone(double timeZone) {
489: if ((timeZone >= -12) && (timeZone <= 12)) {
490: this .timezone = timeZone;
491: }
492: }
493:
494: void setLastLogonTimestamp(Timestamp lastLogon) {
495: lastLogonTimestamp = lastLogon;
496: }
497:
498: void setLastLogonIP(String lastLogonIP) {
499: this .lastLogonIP = lastLogonIP;
500: }
501:
502: void setGender(boolean gender) {
503: this .gender = gender;
504: }
505:
506: void setPostsPerPage(int postsPerPage) {
507: if (postsPerPage < 5) {
508: postsPerPage = 5;
509: }
510: this .memberPostsPerPage = postsPerPage;
511: }
512:
513: public void setCssPath(String cssPath) {
514: this .memberCssPath = cssPath;
515: }
516:
517: public void setLogoPath(String logoPath) {
518: this .memberLogoPath = logoPath;
519: }
520:
521: // add this method to remove eclipse's warning
522: public boolean getGender() {
523: return gender;
524: }
525:
526: public Object getXMPPConnection() {
527: return conn;
528: }
529:
530: public void setXMPPConnection(Object conn) {
531: this .conn = conn;
532: }
533:
534: public Set getParticipants() {
535: return participants;
536: }
537:
538: public Set getWaitingList() {
539: return waitingList;
540: }
541:
542: public void setParticipants(Object participant) {
543: synchronized (participants) {
544: participants.add(participant);
545: }
546: }
547:
548: public void setWaitingList(Object waiting) {
549: synchronized (waitingList) {
550: waitingList.add(waiting);
551: }
552: }
553:
554: public void removeParticipant(Object participant) {
555: synchronized (participants) {
556: participants.remove(participant);
557: }
558: }
559:
560: public void removeWaiting(Object waiting) {
561: synchronized (waitingList) {
562: waitingList.remove(waiting);
563: }
564: }
565:
566: public double getTimeZone() {
567: return timezone;
568: }
569:
570: public String getTimeZoneFormat() {
571: String returnStr;
572: int nTimezone = (int) timezone;
573: double roundedTimezone = nTimezone;
574: if (timezone > 0) {
575: if (roundedTimezone == timezone) {
576: returnStr = String.valueOf(nTimezone);
577: } else {
578: returnStr = String.valueOf(timezone);
579: }
580: return "+" + returnStr;
581: } else if (timezone == 0) {
582: return "GMT";
583: } else {
584: if (roundedTimezone == timezone) {
585: returnStr = String.valueOf(nTimezone);
586: } else {
587: returnStr = String.valueOf(timezone);
588: }
589: return returnStr;
590: }
591: }
592: }
|