001: /*
002: Copyright (c) 2003 eInnovation Inc. All rights reserved
003:
004: This library is free software; you can redistribute it and/or modify it under the terms
005: of the GNU Lesser General Public License as published by the Free Software Foundation;
006: either version 2.1 of the License, or (at your option) any later version.
007:
008: This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
009: without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: See the GNU Lesser General Public License for more details.
011: */
012:
013: package com.openedit.modules.admin;
014:
015: import java.util.ArrayList;
016: import java.util.Enumeration;
017: import java.util.Iterator;
018: import java.util.List;
019:
020: import javax.servlet.http.Cookie;
021: import javax.servlet.http.HttpServletRequest;
022: import javax.servlet.http.HttpServletResponse;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026:
027: import com.openedit.OpenEditException;
028: import com.openedit.WebPageRequest;
029: import com.openedit.config.Configuration;
030: import com.openedit.modules.BaseModule;
031: import com.openedit.modules.email.SendMailModule;
032: import com.openedit.page.Page;
033: import com.openedit.page.PageRequestKeys;
034: import com.openedit.users.User;
035: import com.openedit.util.PathUtilities;
036: import com.openedit.util.StringEncryption;
037: import com.openedit.util.URLUtilities;
038: import com.openedit.util.strainer.Filter;
039:
040: /**
041: * This module allows the user to view and administer the site.
042: *
043: * @author Eric Galluzzo
044: * @author Matt Avery, mavery@einnovation.com
045: */
046: public class AdminModule extends BaseModule {
047: protected static final String COOKIE = "openedit.usermanager.autologin";
048:
049: protected String fieldImagesRoot; // used by the imagepicker
050:
051: protected String fieldRootFTPURL;
052:
053: protected static final String UNAME = "username";
054:
055: protected static final String EMAIL = "to";
056:
057: private static final Log log = LogFactory.getLog(AdminModule.class);
058:
059: protected StringEncryption fieldCookieEncryption;
060:
061: protected SendMailModule sendMailModule;
062:
063: public AdminModule() {
064: super ();
065: }
066:
067: /**
068: * Sets the root FTP URL.
069: *
070: * @param rootFTPURL
071: * The root FTP URL to set
072: */
073: public void setRootFTPURL(String rootFTPURL) {
074: if ((rootFTPURL != null) && rootFTPURL.endsWith("/")) {
075: fieldRootFTPURL = rootFTPURL.substring(0, rootFTPURL
076: .length() - 1);
077: } else {
078: fieldRootFTPURL = rootFTPURL;
079: }
080: }
081:
082: /**
083: * Returns the root FTP URL.
084: *
085: * @return A string, which will not end in a slash, or <code>null</code> if
086: * FTP support has not been configured.
087: */
088: public String getRootFTPURL() {
089: return fieldRootFTPURL;
090: }
091:
092: protected PasswordHelper getPasswordHelper(WebPageRequest inReq)
093: throws OpenEditException {
094: PasswordHelper passwordHelper = (PasswordHelper) inReq
095: .getSessionValue("passwordHelper");
096: if (passwordHelper == null) {
097: passwordHelper = new PasswordHelper();
098: passwordHelper.setSendMailModule(sendMailModule);
099: inReq.putSessionValue("passwordHelper", passwordHelper);
100: }
101:
102: return passwordHelper;
103: }
104:
105: public void emailPasswordReminder(WebPageRequest inReq)
106: throws Exception {
107: String e = inReq.getRequestParameter(EMAIL);
108: String u = inReq.getRequestParameter(UNAME);
109: if (e == null && u == null) {
110: inReq.putPageValue("commandSucceeded", "didnotexecute");
111: // log.error("Invalid information");
112: return;
113: }
114:
115: User foundUser = null;
116: String username = null;
117: String email = null;
118: String password = null;
119: // if the user provided an email instead of a username, lookup username
120: String emailaddress = inReq.getRequestParameter(EMAIL);
121: if (emailaddress != null && emailaddress.length() > 0) {
122: foundUser = (User) getUserManager().getUserByEmail(
123: emailaddress);
124: if (foundUser != null) {
125: }
126: }
127:
128: // If the user provided a valid username
129: username = inReq.getRequestParameter(UNAME);
130: if (username != null && foundUser == null) {
131: foundUser = (User) getUserManager().getUser(username);
132: }
133:
134: if (foundUser != null) {
135: email = foundUser.getEmail();
136: if (email == null || email.equals("")) {
137: inReq.putPageValue("error", "noemail");
138: return;
139: }
140: // get the user's current password
141: if (foundUser.getPassword().startsWith("DES:")) {
142: password = getUserManager().getStringEncryption()
143: .decrypt(foundUser.getPassword());
144: } else {
145: password = foundUser.getPassword();
146: }
147: username = foundUser.getUserName();
148: } else {
149: inReq.putPageValue("error", "nouser");
150: return;
151: }
152:
153: // let the passwordHelper send the password
154: PasswordHelper passwordHelper = getPasswordHelper(inReq);
155: passwordHelper.emailPasswordReminder(inReq, getPageManager(),
156: username, password, email);
157:
158: }
159:
160: public void allowEditing(WebPageRequest inReq) throws Exception {
161: boolean value = false;
162: if (inReq.getUser() != null) {
163: Filter filter = inReq.getPage().getEditFilter();
164: value = ((filter == null) || filter.passes(inReq));
165:
166: }
167: inReq.setEditable(value);
168: // Check that we already have a toolbar generator
169: /*
170: * Generator pgen = inReq.getPage().getGenerator(); if (
171: * !pgen.hasGenerator(getToolbarGenerator()) ) { CompositeGenerator
172: * composite = new CompositeGenerator(); composite.addGenerator(pgen);
173: * composite.addGenerator(getToolbarGenerator());
174: * inReq.getPage().setGenerator(composite); }
175: */
176: }
177:
178: public void allowViewing(WebPageRequest inReq)
179: throws OpenEditException {
180: AllowViewing command = new AllowViewing();
181: command.setPageManager(getPageManager());
182:
183: command.configure(inReq.getCurrentAction().getConfig(), inReq
184: .getPage().getPageSettings());
185: command.execute(inReq);
186: }
187:
188: public void enforcePrivilege(WebPageRequest inReq)
189: throws OpenEditException {
190: EnforcePrivilege command = new EnforcePrivilege();
191: command.setPageManager(getPageManager());
192: command.configure(inReq.getCurrentAction().getConfig(), inReq
193: .getPage().getPageSettings());
194: command.execute(inReq);
195: }
196:
197: public void checkForDuplicateByEmail(WebPageRequest inReq)
198: throws Exception {
199: String email = inReq.getRequiredParameter("email");
200:
201: User user = getUserManager().getUserByEmail(email);
202: if (user != null) {
203: String page = inReq.getCurrentAction().getConfig()
204: .getChildValue("redirectpage");
205: if (page == null) {
206: inReq.redirect(page);
207: } else {
208: inReq.putPageValue("oe-exception",
209: "Account already exists with address " + email);
210: }
211: }
212: }
213:
214: /*
215: * public void loginByEmail( WebPageRequest inReq ) throws Exception { String
216: * account = inReq.getRequestParameter("email");
217: *
218: * if ( account != null ) { User user = getUserManager().getUserByEmail(
219: * account ); loginAndRedirect(user,inReq); } else { String referrer =
220: * inReq.getRequest().getHeader("REFERER"); if ( referrer != null ) { //this
221: * is the original page someone might have been on
222: * inReq.putSessionValue("originalEntryPage",referrer ); } } }
223: */
224: public void login(WebPageRequest inReq) throws Exception {
225: String account = inReq.getRequestParameter("accountname");
226: String password = inReq.getRequestParameter("password");
227:
228: if (account != null) {
229: User user = getUserManager().getUser(account);
230: if (user == null) {
231: user = getUserManager().getUserByEmail(account);
232: }
233: if (user == null) // Allow guest user
234: {
235: String groupname = inReq.getPage()
236: .get("autologingroup");
237: if (groupname != null) {
238: user = getUserManager().createGuestUser(account,
239: password, groupname);
240: }
241: }
242:
243: loginAndRedirect(user, password, inReq);
244: }
245: // else
246: // {
247: // String referrer = inReq.getRequest().getHeader("REFERER");
248: // if ( referrer != null )
249: // {
250: // //this is the original page someone might have been on
251: // inReq.putSessionValue("originalEntryPage",referrer );
252: // }
253: // }
254: }
255:
256: /**
257: * @param inUser
258: * @param inReq
259: */
260: protected void loginAndRedirect(User user, String inPassword,
261: WebPageRequest inReq) throws Exception {
262: boolean userok = false;
263: String sendTo = inReq.getRequestParameter("loginokpage");
264:
265: if (user != null) {
266: // Save our logged-in user in the session,
267: // because we use it again later.
268: if (inPassword != null) {
269: userok = getUserManager()
270: .authenticate(user, inPassword);
271: }
272: }
273:
274: if (userok == false) {
275: // System.out.println( "User " + account + " could not be logged in" );
276: inReq.getRequest().setAttribute("oe-exception",
277: "Invalid Logon");
278: inReq.putPageValue("oe-exception", "Invalid Logon");
279: } else {
280: inReq.putSessionValue("user", user);
281: // user is now logged in
282: if (sendTo == null || sendTo.trim().length() == 0) {
283: String sendToOld = (String) inReq
284: .getSessionValue("originalEntryPage");
285: String referrer = inReq.getRequest().getHeader(
286: "REFERER");
287: if (sendToOld != null && !sendToOld.equals(referrer)) {
288: sendTo = sendToOld;
289: }
290: inReq.removeSessionValue("originalEntryPage");
291: }
292: if (sendTo == null) {
293: sendTo = "/index.html";
294: }
295: savePasswordAsCookie(user, inReq);
296: inReq.redirect(sendTo);
297: }
298:
299: }
300:
301: public void savePasswordAsCookie(User user, WebPageRequest inReq)
302: throws OpenEditException {
303: if (user.isVirtual()) {
304: log.debug("User is virtual. Not saving cookie");
305: return;
306: }
307: HttpServletResponse res = inReq.getResponse();
308: if (res != null) {
309: String crypt = getCookieEncryption().encrypt(
310: user.getPassword()); // Double
311: // encrypt
312: // the
313: // password
314: // that
315: // is
316: // already
317: // encrypted
318: // String home = (String)inReq.getPageValue("home");
319: Cookie cookie = new Cookie(createCookieName(inReq), user
320: .getUserName()
321: + "OEWITHOE" + crypt);
322: cookie.setMaxAge(Integer.MAX_VALUE);
323: cookie.setPath("/"); // http://www.unix.org.ua/orelly/java-ent/servlet/ch07_04.htm
324: res.addCookie(cookie);
325: }
326: }
327:
328: public void logout(WebPageRequest inReq) throws OpenEditException {
329: User user = (User) inReq.getSessionValue("user");
330: getUserManager().logout(user);
331:
332: Enumeration enumeration = inReq.getSession()
333: .getAttributeNames();
334: List toremove = new ArrayList();
335: while (enumeration.hasMoreElements()) {
336: String id = (String) enumeration.nextElement();
337: toremove.add(id);
338: }
339: for (Iterator iter = toremove.iterator(); iter.hasNext();) {
340: String id = (String) iter.next();
341: inReq.removeSessionValue(id);
342: }
343:
344: // inReq.removeSessionValue("editMode"); //legacy
345: // inReq.removeSessionValue("username"); //legacy
346: // inReq.removeSessionValue("user");
347: removeCookie(inReq);
348:
349: String referrer = inReq.getRequestParameter("editingPath");
350: if (referrer != null && !referrer.startsWith("http")) {
351: Page epath = getPageManager().getPage(referrer);
352: if (referrer.indexOf("/openedit") >= 0 || !epath.isHtml()
353: || !epath.exists()) {
354: referrer = null;
355: }
356: }
357: if (referrer == null) {
358: referrer = "/index.html";
359: }
360: inReq.redirect(referrer);
361: }
362:
363: protected void removeCookie(WebPageRequest inReq) {
364: HttpServletResponse res = inReq.getResponse();
365: if (res != null) {
366: String home = (String) inReq.getPageValue("home");
367: Cookie cookie = new Cookie(createCookieName(inReq), "none");
368: cookie.setMaxAge(0);
369: cookie.setPath("/"); // http://www.unix.org.ua/orelly/java-ent/servlet/ch07_04.htm
370: res.addCookie(cookie);
371: }
372: }
373:
374: public void autoLogin(WebPageRequest inReq)
375: throws OpenEditException {
376: if (inReq.getUser() != null) {
377: return;
378: }
379: if (!inReq.getPage().isHtml()) {
380: return; // only deal with html requests
381: }
382: if (inReq.getSessionValue("autologindone") == null) {
383: readPasswordFromCookie(inReq);
384: inReq.putSessionValue("autologindone", "true"); // Try only once
385: }
386: }
387:
388: public void autoLoginFromRequest(WebPageRequest inRequest)
389: throws OpenEditException {
390: // Add the currently logged-in user (which may be null).
391: String username = inRequest.getRequest().getRemoteUser();
392: if (username != null) {
393: User user = getUserManager().getUser(username);
394: if (user != null) {
395: inRequest.putProtectedPageValue(PageRequestKeys.USER,
396: user);
397: }
398: }
399: }
400:
401: String createCookieName(WebPageRequest inReq) {
402: String home = (String) inReq.getPageValue("home");
403: return COOKIE + home + "Un1qu3_str1ng";
404: }
405:
406: boolean verifyCookieName(WebPageRequest inReq, Cookie inCookie) {
407: return inCookie.getName().startsWith(createCookieName(inReq));
408: }
409:
410: protected void readPasswordFromCookie(WebPageRequest inReq)
411: throws OpenEditException {
412: // see if we have a coookie for this person with their encrypted password
413: // in it
414: HttpServletRequest req = inReq.getRequest();
415: if (req != null) {
416: Cookie[] cookies = req.getCookies();
417: if (cookies != null) {
418: for (int i = 0; i < cookies.length; i++) {
419: Cookie cook = cookies[i];
420: if (cook.getName() != null
421: && verifyCookieName(inReq, cook)) {
422: String uandpass = cook.getValue();
423: if (uandpass != null) {
424: String[] units = uandpass.split("OEWITHOE");
425: if (units.length == 2) {
426: User user = getUserManager().getUser(
427: units[0]);
428: if (user == null) {
429: log.info("User " + units[0]
430: + " not found.");
431: // removeCookie(inReq);
432: cook.setMaxAge(0); // remove the cookie
433: inReq.getResponse().addCookie(cook);
434: } else {
435: String encoded = units[1];
436: // String password = new String( new
437: // BASE64Decoder().decodeBuffer(encoded) );
438: String password = getCookieEncryption()
439: .decrypt(encoded);
440: boolean ok = getUserManager()
441: .authenticate(user,
442: password);
443: if (ok) {
444: inReq.putSessionValue("user",
445: user);
446: return;
447: } else {
448: log
449: .info("Auto login did not work "
450: + units[0]
451: + " password "
452: + password);
453: cook.setMaxAge(0); // remove the cookie
454: inReq.getResponse().addCookie(
455: cook);
456: }
457: }
458: }
459: }
460: }
461: }
462: }
463: }
464: }
465:
466: // These are deprecated
467: public void wrapDecoration(WebPageRequest inreq) {
468: log
469: .error("Please remove Decorate.wrapDecoration from your _site.xconf");
470: }
471:
472: public void insertDecoration(WebPageRequest inReq) throws Exception {
473: log
474: .error("Please remove Decorate.insertDecoration from your _site.xconf");
475: /*
476: * Page layout = inReq.getPage();
477: *
478: * if (
479: * !layout.getGenerator().hasGenerator(getSearchAndReplaceGenerator()) ) {
480: * //wrap the content with our search generator CompositeGenerator
481: * composite = new CompositeGenerator();
482: * composite.addGenerator(inReq.getPage().getGenerator());
483: * composite.addGenerator(getSearchAndReplaceGenerator());
484: * layout.setGenerator(composite); }
485: */
486: }
487:
488: public void forwardToSecureSocketsLayer(WebPageRequest inReq) {
489: String useSecure = inReq.getPage().get("useshttps");
490:
491: if (Boolean.parseBoolean(useSecure)
492: && inReq.getRequest() != null) {
493: String host = inReq.getPage().get("hostname");
494: if (host == null) {
495: host = inReq.getPage().get("hostName");
496: }
497: if (host != null && !inReq.getRequest().isSecure()) {
498: String path = "https://" + host + inReq.getPathUrl();
499: log.info("Forward to address " + path);
500: inReq.redirect(path);
501: }
502: }
503: }
504:
505: /**
506: * This is deprecated because it can't handle directory redirects and is
507: * buggy and hard to read. Use redirectHost and redirectInternal instead.
508: * @param inReq
509: * @throws OpenEditException
510: * @deprecated
511: */
512: public void redirect(WebPageRequest inReq) throws OpenEditException {
513: String path = inReq.getCurrentAction().getChildValue(
514: "redirectpath");
515: if (path == null) {
516: path = inReq.getPage().get("redirectpath");
517: }
518: if (path != null && inReq.getRequest() != null) {
519: URLUtilities utils = (URLUtilities) inReq
520: .getPageValue(PageRequestKeys.URL_UTILITIES);
521: if (path.endsWith("/")) {
522: path = path.substring(0, path.length() - 1);
523: }
524: List host = inReq.getCurrentAction().getConfig()
525: .getChildren("host");
526: if (host.size() > 0) {
527: String server = utils.buildRoot(); //http://localhost:8080/
528: boolean found = false;
529: for (Iterator iterator = host.iterator(); iterator
530: .hasNext();) {
531: Configuration conf = (Configuration) iterator
532: .next();
533: //verify the host
534: String hostval = conf.getValue();
535: log.debug("Checking [" + server + "] starts with ["
536: + hostval + "]");
537: if (server.startsWith(hostval)) {
538: found = true;
539: break;
540: }
541: }
542: if (!found) {
543: log
544: .info("Host did not match, was [" + server
545: + "]");
546: return;
547: }
548: }
549: int indestpath = path.indexOf("*"); //http://xyz/*
550: if (indestpath > -1) {
551: //this is a dynamic redirect path
552: //http://xyz/* -> http://xyz/somepage.html
553: //take off a part of the path before the *?
554: String begin = path.substring(0, indestpath);
555:
556: String ending = utils
557: .requestPathWithArgumentsNoContext();
558: if (ending.startsWith("/") == true) {
559: ending = ending.substring(1, ending.length());
560: }
561: String server = utils.buildRoot();
562:
563: String redirectPath = null;
564: if (path.startsWith("http")) {
565: redirectPath = begin + "/"
566: + PathUtilities.extractFileName(ending);
567: } else {
568: redirectPath = begin + ending; //this does not handle subdirectory redirects
569: }
570:
571: if (!redirectPath.equals(server)) {
572: inReq.redirectPermanently(redirectPath);
573: } else {
574: throw new OpenEditException(
575: "Infinite loop to forward to "
576: + redirectPath);
577: }
578: } else if (path.startsWith("http")) {
579: // String fixedpath = path;
580: // String domain = utils.siteRoot();
581: // if( domain.startsWith("https://") && !fixedpath.startsWith("https://") )
582: // {
583: // fixedpath = "https://" + path.substring("https://".length()-1, path.length());
584: // }
585: // if( !fixedpath.startsWith(domain) )
586: // {
587: // //see if it exists locally
588: // if ( inReq.getContentPage().exists() )
589: // {
590: // String newurl = fixedpath + utils.requestPathWithArguments();
591: // inReq.redirectPermanently(newurl);
592: // }
593: // else
594: // {
595:
596: //http://localhost:8080/
597: String server = utils.buildRoot();
598: if (!path.startsWith(server)) {
599: inReq.redirectPermanently(path);
600: }
601: // }
602: } else {
603: if (!inReq.getPath().equals(path)) {
604: inReq.redirectPermanently(path);
605: }
606: }
607: }
608: }
609:
610: /**
611: * This is used to direct to a different host. I can be used in conjunction with
612: * redirectInternal().
613: * <path-action name="Admin.redirectHost">
614: * <redirecthost>http://xyz.com/</redirecthost>
615: * </path-action>
616: * @param inReq
617: * @throws OpenEditException
618: */
619: public void redirectHost(WebPageRequest inReq)
620: throws OpenEditException {
621: String host = inReq.getCurrentAction().getChildValue(
622: "redirecthost");
623: URLUtilities utils = (URLUtilities) inReq
624: .getPageValue(PageRequestKeys.URL_UTILITIES);
625: String ending = utils.requestPathWithArgumentsNoContext();
626: String server = utils.buildRoot();
627: if (server.endsWith("/")) {
628: server = server.substring(0, server.length() - 1);
629: }
630: if (host.endsWith("/")) {
631: host = host.substring(0, host.length() - 1);
632: }
633:
634: String redirectPath = host + ending;
635:
636: if (!host.equals(server)) {
637: inReq.redirectPermanently(redirectPath);
638: } else {
639: return;
640: }
641: }
642:
643: /**
644: * This is used to redirect between pages on the same server. It may be used in conjunction with
645: * redirectHost(). This should be used instead of the old Admin.redirect
646: * <path-action name="Admin.redirectInternal">
647: * <!--This is an example of directory substitution-->
648: * <redirectpath>/newpath/</redirectpath>
649: * <redirectroot>/oldpath/</redirectroot>
650: * </path-action>
651: * <path-action name="Admin.redirectInternal">
652: * <!--This is an example of absolute substitution-->
653: * <redirectpath>/newpath/index.html</redirectpath>
654: * <redirectroot>*</redirectroot>
655: * </path-action>
656: * @param inReq
657: * @throws OpenEditException
658: */
659: public void redirectInternal(WebPageRequest inReq)
660: throws OpenEditException {
661: String path = inReq.getCurrentAction().getChildValue(
662: "redirectpath");
663: String rootdir = inReq.getCurrentAction().getChildValue(
664: "redirectroot");
665: URLUtilities utils = (URLUtilities) inReq
666: .getPageValue(PageRequestKeys.URL_UTILITIES);
667: String server = utils.buildRoot();
668: if (server.endsWith("/")) {
669: server = server.substring(0, server.length() - 1);
670: }
671: String ending = utils.requestPathWithArgumentsNoContext();
672: String newEnding;
673:
674: if (rootdir.equals("*")) {
675: newEnding = path;
676: } else {
677: newEnding = ending.replace(rootdir, path);
678: }
679:
680: String redirectPath = server + newEnding;
681:
682: if (!newEnding.equals(ending)) {
683: inReq.redirectPermanently(redirectPath);
684: } else {
685: return;
686: }
687: }
688:
689: public void redirectToOriginal(WebPageRequest inReq) {
690: String editPath = inReq.getRequestParameter("editPath");
691: String orig = inReq.getRequestParameter("origURL");
692: if (orig == null) {
693: orig = inReq.findValue("origURL");
694: }
695: if (orig != null) {
696: if (orig.indexOf("?") == -1 && editPath != null) {
697: inReq.redirect(orig + "?path=" + editPath
698: + "&cache=false");
699: } else {
700: inReq.redirect(orig);
701: }
702: } else {
703: // log.error("No origURL specified");
704: }
705: }
706:
707: public SendMailModule getSendMailModule() {
708: return sendMailModule;
709: }
710:
711: public void setSendMailModule(SendMailModule sendMailModule) {
712: this .sendMailModule = sendMailModule;
713: }
714:
715: public void toogleAdminToolbar(WebPageRequest inReq) {
716: User user = inReq.getUser();
717: if (user != null) {
718: boolean bol = user.getBoolean("openadmintoolbar");
719: if (bol) {
720: user.put("openadmintoolbar", "false");
721: } else {
722: user.put("openadmintoolbar", "true");
723: }
724: if (!user.isVirtual()) {
725: getUserManager().saveUser(user);
726: }
727: }
728: redirectToOriginal(inReq);
729: }
730:
731: public StringEncryption getCookieEncryption() {
732: if (fieldCookieEncryption == null) {
733: fieldCookieEncryption = new StringEncryption();
734: String KEY = "SomeWeirdReallyLongStringYUITYGFNERDF343dfdGDFGSDGGD";
735: fieldCookieEncryption.setEncryptionKey(KEY);
736: }
737: return fieldCookieEncryption;
738: }
739:
740: public void setCookieEncryption(StringEncryption inCookieEncryption) {
741: fieldCookieEncryption = inCookieEncryption;
742: }
743:
744: }
|