Browse Source

mandatory applicationPath, http error handling and reference library reorg

jrivard 9 years ago
parent
commit
41d74e35e1
38 changed files with 1044 additions and 552 deletions
  1. 18 14
      src/main/java/password/pwm/PwmApplication.java
  2. 13 6
      src/main/java/password/pwm/PwmConstants.java
  3. 1 0
      src/main/java/password/pwm/PwmEnvironment.java
  4. 1 0
      src/main/java/password/pwm/error/PwmError.java
  5. 1 1
      src/main/java/password/pwm/health/LDAPStatusChecker.java
  6. 1 39
      src/main/java/password/pwm/http/ContextManager.java
  7. 1 1
      src/main/java/password/pwm/http/PwmURL.java
  8. 18 8
      src/main/java/password/pwm/http/filter/AbstractPwmFilter.java
  9. 10 1
      src/main/java/password/pwm/http/filter/ApplicationStatusFilter.java
  10. 3 2
      src/main/java/password/pwm/http/filter/RequestInitializationFilter.java
  11. 50 7
      src/main/java/password/pwm/http/servlet/resource/ResourceFileServlet.java
  12. 88 0
      src/main/java/password/pwm/http/tag/JspThrowableHandlerTag.java
  13. 2 8
      src/main/java/password/pwm/http/tag/LocaleOrientationTag.java
  14. 0 6
      src/main/java/password/pwm/http/tag/PwmScriptRefTag.java
  15. 1 0
      src/main/java/password/pwm/i18n/Display.java
  16. 8 4
      src/main/java/password/pwm/util/Helper.java
  17. 11 3
      src/main/java/password/pwm/util/LocaleHelper.java
  18. 1 0
      src/main/java/password/pwm/util/cli/MainClass.java
  19. 1 1
      src/main/resources/password/pwm/PwmConstants.properties
  20. 1 0
      src/main/resources/password/pwm/i18n/Display.properties
  21. 1 0
      src/main/resources/password/pwm/i18n/Error.properties
  22. 14 11
      src/main/webapp/WEB-INF/jsp/application-unavailable.jsp
  23. 2 9
      src/main/webapp/WEB-INF/jsp/error-http.jsp
  24. 1 1
      src/main/webapp/WEB-INF/jsp/fragment/footer.jsp
  25. 7 1
      src/main/webapp/WEB-INF/pwm-taglib.tld
  26. 1 1
      src/main/webapp/WEB-INF/web.xml
  27. 100 0
      src/main/webapp/public/reference/displaystrings.jsp
  28. 131 0
      src/main/webapp/public/reference/environment.jsp
  29. 53 0
      src/main/webapp/public/reference/index.jsp
  30. 3 11
      src/main/webapp/public/reference/license.jsp
  31. 24 0
      src/main/webapp/public/reference/reference-nav.jsp
  32. 2 403
      src/main/webapp/public/reference/referencedoc.jsp
  33. 3 0
      src/main/webapp/public/reference/rest.jsp
  34. 280 0
      src/main/webapp/public/reference/settings.jsp
  35. 152 0
      src/main/webapp/public/reference/tables.jsp
  36. 1 13
      src/main/webapp/public/resources/js/admin.js
  37. 1 1
      src/main/webapp/public/resources/js/configeditor.js
  38. 38 0
      src/main/webapp/public/resources/referenceStyle.css

+ 18 - 14
src/main/java/password/pwm/PwmApplication.java

@@ -219,20 +219,24 @@ public class PwmApplication {
         pwmServiceManager.initAllServices();
         pwmServiceManager.initAllServices();
 
 
         if (!pwmEnvironment.isInternalRuntimeInstance()) {
         if (!pwmEnvironment.isInternalRuntimeInstance()) {
-            final TimeDuration totalTime = TimeDuration.fromCurrent(startTime);
-            LOGGER.info(PwmConstants.PWM_APP_NAME + " " + PwmConstants.SERVLET_VERSION + " open for bidness! (" + totalTime.asCompactString() + ")");
-            StatisticsManager.incrementStat(this,Statistic.PWM_STARTUPS);
-            LOGGER.debug("buildTime=" + PwmConstants.BUILD_TIME + ", javaLocale=" + Locale.getDefault() + ", DefaultLocale=" + PwmConstants.DEFAULT_LOCALE);
-
-            final Thread postInitThread = new Thread() {
-                @Override
-                public void run() {
-                    postInitTasks();
-                }
-            };
-            postInitThread.setDaemon(true);
-            postInitThread.setName(Helper.makeThreadName(this, PwmApplication.class));
-            postInitThread.start();
+            if (pwmEnvironment.getFlags().contains(PwmEnvironment.ApplicationFlag.CommandLineInstance)) {
+                postInitTasks();
+            } else {
+                final TimeDuration totalTime = TimeDuration.fromCurrent(startTime);
+                LOGGER.info(PwmConstants.PWM_APP_NAME + " " + PwmConstants.SERVLET_VERSION + " open for bidness! (" + totalTime.asCompactString() + ")");
+                StatisticsManager.incrementStat(this, Statistic.PWM_STARTUPS);
+                LOGGER.debug("buildTime=" + PwmConstants.BUILD_TIME + ", javaLocale=" + Locale.getDefault() + ", DefaultLocale=" + PwmConstants.DEFAULT_LOCALE);
+
+                final Thread postInitThread = new Thread() {
+                    @Override
+                    public void run() {
+                        postInitTasks();
+                    }
+                };
+                postInitThread.setDaemon(true);
+                postInitThread.setName(Helper.makeThreadName(this, PwmApplication.class));
+                postInitThread.start();
+            }
         }
         }
     }
     }
 
 

+ 13 - 6
src/main/java/password/pwm/PwmConstants.java

@@ -24,16 +24,14 @@ package password.pwm;
 
 
 import org.apache.commons.csv.CSVFormat;
 import org.apache.commons.csv.CSVFormat;
 import password.pwm.bean.SessionLabel;
 import password.pwm.bean.SessionLabel;
+import password.pwm.util.JsonUtil;
 import password.pwm.util.secure.PwmBlockAlgorithm;
 import password.pwm.util.secure.PwmBlockAlgorithm;
 import password.pwm.util.secure.PwmHashAlgorithm;
 import password.pwm.util.secure.PwmHashAlgorithm;
 
 
 import java.nio.charset.Charset;
 import java.nio.charset.Charset;
 import java.text.DateFormat;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.TimeZone;
+import java.util.*;
 
 
 /**
 /**
  * Constant values used throughout the servlet.
  * Constant values used throughout the servlet.
@@ -183,10 +181,19 @@ public abstract class PwmConstants {
     public static final String DOWNLOAD_FILENAME_USER_REPORT_RECORDS_CSV = "UserReportRecords.csv";
     public static final String DOWNLOAD_FILENAME_USER_REPORT_RECORDS_CSV = "UserReportRecords.csv";
     public static final String DOWNLOAD_FILENAME_AUDIT_RECORDS_CSV = "AuditRecords.csv";
     public static final String DOWNLOAD_FILENAME_AUDIT_RECORDS_CSV = "AuditRecords.csv";
 
 
-    public static final String DEFAULT_BUILD_CHECKSUM_FILENAME = "BuildChecksum.properties";
-
     public static final String LOG_REMOVED_VALUE_REPLACEMENT = readPwmConstantsBundle("log.removedValue");
     public static final String LOG_REMOVED_VALUE_REPLACEMENT = readPwmConstantsBundle("log.removedValue");
 
 
+    public static final Collection<Locale> INCLUDED_LOCALES;
+    static {
+        final List<Locale> localeList = new ArrayList<>();
+        final String inputString = readPwmConstantsBundle("includedLocales");
+        final List<String> inputList = JsonUtil.deserializeStringList(inputString);
+        for (final String localeKey : inputList) {
+            localeList.add(new Locale(localeKey));
+        }
+        INCLUDED_LOCALES = Collections.unmodifiableCollection(localeList);
+    }
+
     public enum JSP_URL {
     public enum JSP_URL {
 
 
         INIT("init.jsp"),
         INIT("init.jsp"),

+ 1 - 0
src/main/java/password/pwm/PwmEnvironment.java

@@ -59,6 +59,7 @@ public class PwmEnvironment implements Serializable {
         Appliance,
         Appliance,
         ManageHttps,
         ManageHttps,
         NoFileLock,
         NoFileLock,
+        CommandLineInstance,
 
 
         ;
         ;
 
 

+ 1 - 0
src/main/java/password/pwm/error/PwmError.java

@@ -159,6 +159,7 @@ public enum PwmError {
     ERROR_MACRO_PARSE_ERROR("Error_MacroParseError",5080,true),
     ERROR_MACRO_PARSE_ERROR("Error_MacroParseError",5080,true),
     ERROR_NO_PROFILE_ASSIGNED("Error_NoProfileAssigned",5081,true),
     ERROR_NO_PROFILE_ASSIGNED("Error_NoProfileAssigned",5081,true),
     ERROR_STARTUP_ERROR("Error_StartupError",5082,true),
     ERROR_STARTUP_ERROR("Error_StartupError",5082,true),
+    ERROR_ENVIRONMENT_ERROR("Error_EnvironmentError",5083,true),
 
 
     ERROR_REMOTE_ERROR_VALUE("Error_RemoteErrorValue",6000,true),
     ERROR_REMOTE_ERROR_VALUE("Error_RemoteErrorValue",6000,true),
 
 

+ 1 - 1
src/main/java/password/pwm/health/LDAPStatusChecker.java

@@ -556,7 +556,7 @@ public class LDAPStatusChecker implements HealthChecker {
                         try {
                         try {
                             returnList.addAll(checkUserPermission(pwmApplication, userPermission, pwmSetting));
                             returnList.addAll(checkUserPermission(pwmApplication, userPermission, pwmSetting));
                         } catch (PwmUnrecoverableException e) {
                         } catch (PwmUnrecoverableException e) {
-                            LOGGER.error(e.getMessage(),e);
+                            LOGGER.error("error checking configured permission settings:" + e.getMessage());
                         }
                         }
                     }
                     }
                 }
                 }

+ 1 - 39
src/main/java/password/pwm/http/ContextManager.java

@@ -43,7 +43,6 @@ import javax.servlet.http.HttpSession;
 import java.io.File;
 import java.io.File;
 import java.io.InputStream;
 import java.io.InputStream;
 import java.io.Serializable;
 import java.io.Serializable;
-import java.net.URL;
 import java.util.*;
 import java.util.*;
 
 
 public class ContextManager implements Serializable {
 public class ContextManager implements Serializable {
@@ -148,11 +147,8 @@ public class ContextManager implements Serializable {
         {
         {
             final String applicationPathStr = readApplicationPath();
             final String applicationPathStr = readApplicationPath();
             if (applicationPathStr == null || applicationPathStr.isEmpty()) {
             if (applicationPathStr == null || applicationPathStr.isEmpty()) {
-                applicationPath = locateWebInfFilePath();
-                /*
-                startupErrorInformation = new ErrorInformation(PwmError.ERROR_STARTUP_ERROR,"applicationPath is not specified");
+                startupErrorInformation = new ErrorInformation(PwmError.ERROR_ENVIRONMENT_ERROR,"application path is not specified");
                 return;
                 return;
-                */
             } else {
             } else {
                 applicationPath = new File(applicationPathStr);
                 applicationPath = new File(applicationPathStr);
             }
             }
@@ -434,40 +430,6 @@ public class ContextManager implements Serializable {
         }
         }
     }
     }
 
 
-    public File deriveApplicationPath()
-            throws PwmException
-    {
-        if (this.servletContext == null) {
-            return null;
-        }
-
-        final String realPath = servletContext.getRealPath("/WEB-INF");
-
-        if (realPath != null) {
-            final File servletPath = new File(realPath);
-            if (servletPath.exists()) {
-                return servletPath;
-            }
-        }
-
-        outputError("servlet container unable to return real file system path, will attempt discovery using classloader");
-
-        // for containers which do not return the real path, try to use the class loader to find the path.
-        final String cManagerName = PwmApplication.class.getCanonicalName();
-        final String resourcePathname = "/" + cManagerName.replace(".", "/") + ".class";
-        final URL fileURL = PwmApplication.class.getResource(resourcePathname);
-        if (fileURL != null) {
-            final String newString = fileURL.toString().replace("WEB-INF/classes" + resourcePathname, "");
-            try {
-                return new File(new URL(newString).toURI());
-            } catch (Exception e) {
-                outputError("unable to determine application path using class loader: " + e.getMessage());
-            }
-        }
-
-        throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_APP_UNAVAILABLE,"unable to determine applicationPath working directory"));
-    }
-
     static void outputError(String outputText) {
     static void outputError(String outputText) {
         final String msg = PwmConstants.PWM_APP_NAME + " " + PwmConstants.DEFAULT_DATETIME_FORMAT.format(new Date()) + " " + outputText;
         final String msg = PwmConstants.PWM_APP_NAME + " " + PwmConstants.DEFAULT_DATETIME_FORMAT.format(new Date()) + " " + outputText;
         System.out.println(msg);
         System.out.println(msg);

+ 1 - 1
src/main/java/password/pwm/http/PwmURL.java

@@ -54,7 +54,7 @@ public class PwmURL {
     }
     }
 
 
     public boolean isResourceURL() {
     public boolean isResourceURL() {
-        return checkIfStartsWithURL("/public/resources/");
+        return checkIfStartsWithURL("/public/resources/") || isReferenceURL();
     }
     }
 
 
     public boolean isReferenceURL() {
     public boolean isReferenceURL() {

+ 18 - 8
src/main/java/password/pwm/http/filter/AbstractPwmFilter.java

@@ -23,9 +23,9 @@
 package password.pwm.http.filter;
 package password.pwm.http.filter;
 
 
 
 
-import password.pwm.bean.SessionLabel;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmException;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmRequest;
+import password.pwm.http.PwmURL;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
 import javax.servlet.*;
 import javax.servlet.*;
@@ -53,18 +53,28 @@ public abstract class AbstractPwmFilter implements Filter {
         final HttpServletRequest req = (HttpServletRequest)servletRequest;
         final HttpServletRequest req = (HttpServletRequest)servletRequest;
         final HttpServletResponse resp = (HttpServletResponse)servletResponse;
         final HttpServletResponse resp = (HttpServletResponse)servletResponse;
 
 
-        final PwmFilterChain pwmFilterChain = new PwmFilterChain(servletRequest, servletResponse, filterChain);
-        
-        SessionLabel sessionLabel = null;
+        PwmRequest pwmRequest = null;
         try {
         try {
-            final PwmRequest pwmRequest = PwmRequest.forRequest(req,resp);
-            sessionLabel = pwmRequest.getSessionLabel();
+            pwmRequest = PwmRequest.forRequest(req, resp);
+        } catch (PwmException e) {
+            final PwmURL pwmURL = new PwmURL(req);
+            if (pwmURL.isResourceURL()) {
+                filterChain.doFilter(req,resp);
+                return;
+            }
+
+            LOGGER.error(pwmRequest, "unexpected error processing filter chain: " + e.getMessage(), e);
+        }
+
+        try {
+            final PwmFilterChain pwmFilterChain = new PwmFilterChain(servletRequest, servletResponse, filterChain);
             processFilter(pwmRequest, pwmFilterChain);
             processFilter(pwmRequest, pwmFilterChain);
         } catch (PwmException e) {
         } catch (PwmException e) {
-            LOGGER.error(sessionLabel, "unexpected error processing filter chain: " + e.getMessage(), e);
+            LOGGER.error(pwmRequest, "unexpected error processing filter chain: " + e.getMessage(), e);
         } catch (IOException e) {
         } catch (IOException e) {
-            LOGGER.debug(sessionLabel, "i/o error processing request: " + e.getMessage());
+            LOGGER.debug(pwmRequest, "i/o error processing request: " + e.getMessage());
         }
         }
+
     }
     }
 
 
     abstract void processFilter(
     abstract void processFilter(

+ 10 - 1
src/main/java/password/pwm/http/filter/ApplicationStatusFilter.java

@@ -4,9 +4,11 @@ import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.PwmConstants;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.ErrorInformation;
 import password.pwm.http.ContextManager;
 import password.pwm.http.ContextManager;
+import password.pwm.http.PwmURL;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
 import javax.servlet.*;
 import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.IOException;
 
 
@@ -20,6 +22,7 @@ public class ApplicationStatusFilter implements Filter {
 
 
     @Override
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+
         ErrorInformation startupError = null;
         ErrorInformation startupError = null;
         try {
         try {
             final ServletContext servletContext = servletRequest.getServletContext();
             final ServletContext servletContext = servletRequest.getServletContext();
@@ -34,12 +37,18 @@ public class ApplicationStatusFilter implements Filter {
                 }
                 }
             }
             }
         } catch (Exception e) {
         } catch (Exception e) {
+            final PwmURL pwmURL = new PwmURL((HttpServletRequest)servletRequest);
+            if (pwmURL.isResourceURL()) {
+                filterChain.doFilter(servletRequest, servletResponse);
+                return;
+            }
+
             LOGGER.error("error while trying to detect application status: " + e.getMessage());
             LOGGER.error("error while trying to detect application status: " + e.getMessage());
         }
         }
 
 
         LOGGER.error("unable to satisfy incoming request, application is not available");
         LOGGER.error("unable to satisfy incoming request, application is not available");
         servletRequest.setAttribute(PwmConstants.REQUEST_ATTR.PwmErrorInfo.toString(), startupError);
         servletRequest.setAttribute(PwmConstants.REQUEST_ATTR.PwmErrorInfo.toString(), startupError);
-        ((HttpServletResponse)servletResponse).setStatus(500);
+        ((HttpServletResponse) servletResponse).setStatus(500);
         final String url = PwmConstants.JSP_URL.APP_UNAVAILABLE.getPath();
         final String url = PwmConstants.JSP_URL.APP_UNAVAILABLE.getPath();
         servletRequest.getServletContext().getRequestDispatcher(url).forward(servletRequest, servletResponse);
         servletRequest.getServletContext().getRequestDispatcher(url).forward(servletRequest, servletResponse);
     }
     }

+ 3 - 2
src/main/java/password/pwm/http/filter/RequestInitializationFilter.java

@@ -67,11 +67,12 @@ public class RequestInitializationFilter implements Filter {
         final HttpServletResponse resp = (HttpServletResponse)servletResponse;
         final HttpServletResponse resp = (HttpServletResponse)servletResponse;
 
 
         try {
         try {
-            //if (!(new PwmURL(req).isResourceURL())) {
+            final PwmURL pwmURL = new PwmURL(req);
+            if (!pwmURL.isResourceURL()) {
                 checkAndInitSessionState(req);
                 checkAndInitSessionState(req);
                 final PwmRequest pwmRequest = PwmRequest.forRequest(req,resp);
                 final PwmRequest pwmRequest = PwmRequest.forRequest(req,resp);
                 checkIfSessionRecycleNeeded(pwmRequest);
                 checkIfSessionRecycleNeeded(pwmRequest);
-            //}
+            }
         } catch (Throwable e) {
         } catch (Throwable e) {
             LOGGER.error("can't load application: " + e.getMessage(),e);
             LOGGER.error("can't load application: " + e.getMessage(),e);
             if (!(new PwmURL(req).isResourceURL())) {
             if (!(new PwmURL(req).isResourceURL())) {

+ 50 - 7
src/main/java/password/pwm/http/servlet/resource/ResourceFileServlet.java

@@ -22,7 +22,6 @@
 
 
 package password.pwm.http.servlet.resource;
 package password.pwm.http.servlet.resource;
 
 
-import com.novell.ldapchai.exception.ChaiUnavailableException;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.IOUtils;
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.PwmConstants;
@@ -33,7 +32,7 @@ import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.ServletHelper;
 import password.pwm.http.ServletHelper;
-import password.pwm.http.servlet.AbstractPwmServlet;
+import password.pwm.http.servlet.PwmServlet;
 import password.pwm.svc.stats.EventRateMeter;
 import password.pwm.svc.stats.EventRateMeter;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.StatisticsManager;
 import password.pwm.svc.stats.StatisticsManager;
@@ -43,10 +42,12 @@ import password.pwm.util.logging.PwmLogger;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.io.*;
 import java.util.Arrays;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Matcher;
@@ -60,18 +61,60 @@ import java.util.zip.ZipFile;
                 PwmConstants.URL_PREFIX_PUBLIC + "/resources/*"
                 PwmConstants.URL_PREFIX_PUBLIC + "/resources/*"
         }
         }
 )
 )
-public class ResourceFileServlet extends AbstractPwmServlet {
+public class ResourceFileServlet extends HttpServlet implements PwmServlet {
     private static final PwmLogger LOGGER = PwmLogger.forClass(ResourceFileServlet.class);
     private static final PwmLogger LOGGER = PwmLogger.forClass(ResourceFileServlet.class);
 
 
 
 
     @Override
     @Override
-    protected ProcessAction readProcessAction(PwmRequest request) throws PwmUnrecoverableException {
-        return null;
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException
+    {
+        PwmRequest pwmRequest = null;
+        try {
+            pwmRequest = PwmRequest.forRequest(req, resp);
+        } catch (PwmUnrecoverableException e) {
+            LOGGER.error("unable to satisfy request using standard mechanism, reverting to raw resource server");
+        }
+
+        if (pwmRequest != null) {
+            try {
+                processAction(pwmRequest);
+            } catch (PwmUnrecoverableException e) {
+                LOGGER.error(pwmRequest,"error during resource servlet request processing: " + e.getMessage());
+            }
+        } else {
+            try {
+                rawRequestProcessor(req,resp);
+            } catch (PwmUnrecoverableException e) {
+                LOGGER.error("error serving raw resource request: " + e.getMessage());
+            }
+        }
     }
     }
 
 
-    @Override
+    protected void rawRequestProcessor(final HttpServletRequest req, final HttpServletResponse resp)
+            throws IOException, PwmUnrecoverableException
+    {
+
+        final FileResource file = resolveRequestedFile(
+                req.getServletContext(),
+                req.getRequestURI(),
+                req,
+                Collections.<String, ZipFile>emptyMap(),
+                Collections.<String, FileResource>emptyMap()
+        );
+
+        if (file == null || !file.exists()) {
+            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        handleUncachedResponse(resp, file, false);
+    }
+
+
+
     protected void processAction(PwmRequest pwmRequest)
     protected void processAction(PwmRequest pwmRequest)
-            throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException
+            throws ServletException, IOException, PwmUnrecoverableException
     {
     {
         if (pwmRequest.getMethod() != HttpMethod.GET) {
         if (pwmRequest.getMethod() != HttpMethod.GET) {
             throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_SERVICE_NOT_AVAILABLE,"unable to process resource request for request method " + pwmRequest.getMethod()));
             throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_SERVICE_NOT_AVAILABLE,"unable to process resource request for request method " + pwmRequest.getMethod()));

+ 88 - 0
src/main/java/password/pwm/http/tag/JspThrowableHandlerTag.java

@@ -0,0 +1,88 @@
+/*
+ * Password Management Servlets (PWM)
+ * http://code.google.com/p/pwm/
+ *
+ * Copyright (c) 2006-2009 Novell, Inc.
+ * Copyright (c) 2009-2015 The PWM Project
+ *
+ * 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 password.pwm.http.tag;
+
+import password.pwm.PwmConstants;
+import password.pwm.config.Configuration;
+import password.pwm.http.PwmRequest;
+import password.pwm.i18n.Display;
+import password.pwm.util.Helper;
+import password.pwm.util.LocaleHelper;
+import password.pwm.util.logging.PwmLogger;
+import password.pwm.util.secure.PwmHashAlgorithm;
+import password.pwm.util.secure.SecureEngine;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.tagext.TagSupport;
+import java.io.IOException;
+import java.util.Locale;
+
+public class JspThrowableHandlerTag extends TagSupport {
+    private static final PwmLogger LOGGER = PwmLogger.forClass(JspThrowableHandlerTag.class);
+
+    @Override
+    public int doEndTag()
+            throws javax.servlet.jsp.JspTagException
+    {
+        if (pageContext.getErrorData() == null || pageContext.getErrorData().getThrowable() == null) {
+            return EVAL_PAGE;
+        }
+
+
+        try {
+            final Throwable jspThrowable = pageContext.getErrorData().getThrowable();
+            final String exceptionStr = Helper.throwableToString(jspThrowable);
+            final String errorHash = SecureEngine.hash(exceptionStr, PwmHashAlgorithm.SHA1);
+
+            LOGGER.error("jsp error reference " + errorHash,jspThrowable);
+
+            final String jspOutout = jspOutput(errorHash);
+            pageContext.getOut().write(jspOutout);
+        } catch (Exception e) {
+            try {
+                pageContext.getOut().write("");
+            } catch (IOException e1) {
+                /* ignore */
+            }
+            LOGGER.error("error during pwmFormIDTag output of pwmFormID: " + e.getMessage());
+        }
+        return EVAL_PAGE;
+    }
+
+    private String jspOutput(final String errorReference) {
+        Locale userLocale = PwmConstants.DEFAULT_LOCALE;
+        Configuration configuration = null;
+        try {
+            PwmRequest pwmRequest = PwmRequest.forRequest((HttpServletRequest)pageContext.getRequest(), (HttpServletResponse)pageContext.getResponse());
+            userLocale = pwmRequest.getLocale();
+            configuration = pwmRequest.getConfig();
+        } catch (Exception e) {
+            /* system isn't working enough, so default values will suffice */
+        }
+        final String[] strArgs = new String[] {errorReference};
+        return LocaleHelper.getLocalizedMessage(userLocale, Display.Display_ErrorReference, configuration, strArgs);
+
+    }
+}

+ 2 - 8
src/main/java/password/pwm/http/tag/LocaleOrientationTag.java

@@ -26,7 +26,6 @@ import password.pwm.http.PwmSessionWrapper;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.jsp.JspTagException;
 import java.awt.*;
 import java.awt.*;
 import java.util.Locale;
 import java.util.Locale;
 
 
@@ -36,7 +35,6 @@ public class LocaleOrientationTag extends PwmAbstractTag {
 
 
     private String locale;
     private String locale;
 
 
-// --------------------- GETTER / SETTER METHODS ---------------------
 
 
     public String getLocale() {
     public String getLocale() {
         return locale;
         return locale;
@@ -46,10 +44,6 @@ public class LocaleOrientationTag extends PwmAbstractTag {
         this.locale = locale;
         this.locale = locale;
     }
     }
 
 
-    // ------------------------ INTERFACE METHODS ------------------------
-
-
-// --------------------- Interface Tag ---------------------
 
 
     public int doEndTag()
     public int doEndTag()
             throws javax.servlet.jsp.JspTagException {
             throws javax.servlet.jsp.JspTagException {
@@ -72,8 +66,8 @@ public class LocaleOrientationTag extends PwmAbstractTag {
             }
             }
 
 
         } catch (Exception e) {
         } catch (Exception e) {
-            LOGGER.error("error while executing jsp locale orientation tag: " + e.getMessage(), e);
-            throw new JspTagException(e.getMessage());
+            LOGGER.error("error while executing jsp locale orientation tag: " + e.getMessage());
+            return EVAL_PAGE;
         }
         }
         return EVAL_PAGE;
         return EVAL_PAGE;
     }
     }

+ 0 - 6
src/main/java/password/pwm/http/tag/PwmScriptRefTag.java

@@ -27,7 +27,6 @@ import password.pwm.http.PwmRequest;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
 import javax.servlet.jsp.tagext.TagSupport;
 import javax.servlet.jsp.tagext.TagSupport;
-import java.io.IOException;
 
 
 public class PwmScriptRefTag extends TagSupport {
 public class PwmScriptRefTag extends TagSupport {
 // --------------------- Interface Tag ---------------------
 // --------------------- Interface Tag ---------------------
@@ -58,11 +57,6 @@ public class PwmScriptRefTag extends TagSupport {
             final String output = "<script type=\"text/javascript\" nonce=\"" + cspNonce + "\" src=\"" + url + "\"></script>";
             final String output = "<script type=\"text/javascript\" nonce=\"" + cspNonce + "\" src=\"" + url + "\"></script>";
             pageContext.getOut().write(output);
             pageContext.getOut().write(output);
         } catch (Exception e) {
         } catch (Exception e) {
-            try {
-                pageContext.getOut().write("error-generating-script-ref-tag");
-            } catch (IOException e1) {
-                /* ignore */
-            }
             LOGGER.error("error during scriptRef output of pwmFormID: " + e.getMessage());
             LOGGER.error("error during scriptRef output of pwmFormID: " + e.getMessage());
         }
         }
         return EVAL_PAGE;
         return EVAL_PAGE;

+ 1 - 0
src/main/java/password/pwm/i18n/Display.java

@@ -89,6 +89,7 @@ public enum Display implements PwmDisplayBundle {
     Display_Day,
     Display_Day,
     Display_Days,
     Display_Days,
     Display_ErrorBody,
     Display_ErrorBody,
+    Display_ErrorReference,
     Display_ExpirationDate,
     Display_ExpirationDate,
     Display_FooterInfoText,
     Display_FooterInfoText,
     Display_ForgottenPassword,
     Display_ForgottenPassword,

+ 8 - 4
src/main/java/password/pwm/util/Helper.java

@@ -43,10 +43,7 @@ import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.macro.MacroMachine;
 import password.pwm.util.macro.MacroMachine;
 import password.pwm.util.secure.PwmRandom;
 import password.pwm.util.secure.PwmRandom;
 
 
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
+import java.io.*;
 import java.lang.reflect.Method;
 import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.net.InetAddress;
 import java.net.URI;
 import java.net.URI;
@@ -587,5 +584,12 @@ public class
         };
         };
     }
     }
 
 
+    public static String throwableToString(final Throwable throwable) {
+        final StringWriter sw = new StringWriter();
+        final PrintWriter pw = new PrintWriter(sw);
+        throwable.printStackTrace(pw);
+        pw.flush();
+        return sw.toString();
+    }
 
 
 }
 }

+ 11 - 3
src/main/java/password/pwm/util/LocaleHelper.java

@@ -60,6 +60,10 @@ public class LocaleHelper {
         return getLocalizedMessage(locale, key.getKey(), config, key.getClass());
         return getLocalizedMessage(locale, key.getKey(), config, key.getClass());
     }
     }
 
 
+    public static String getLocalizedMessage(final Locale locale, final PwmDisplayBundle key, final Configuration config, final String[] args) {
+        return getLocalizedMessage(locale, key.getKey(), config, key.getClass(), args);
+    }
+
     public static String getLocalizedMessage(final PwmDisplayBundle key, final PwmRequest pwmRequest, final String... values) {
     public static String getLocalizedMessage(final PwmDisplayBundle key, final PwmRequest pwmRequest, final String... values) {
         return getLocalizedMessage(
         return getLocalizedMessage(
                 pwmRequest == null ? PwmConstants.DEFAULT_LOCALE : pwmRequest.getLocale(),
                 pwmRequest == null ? PwmConstants.DEFAULT_LOCALE : pwmRequest.getLocale(),
@@ -236,17 +240,21 @@ public class LocaleHelper {
     }
     }
 
 
     public static Map<Locale,String> getUniqueLocalizations(
     public static Map<Locale,String> getUniqueLocalizations(
-            final PwmApplication pwmApplication,
+            final Configuration configuration,
             final Class<? extends PwmDisplayBundle> bundleClass,
             final Class<? extends PwmDisplayBundle> bundleClass,
             final String key,
             final String key,
             final Locale defaultLocale
             final Locale defaultLocale
     )
     )
     {
     {
         final Map<Locale, String> returnObj = new LinkedHashMap<>();
         final Map<Locale, String> returnObj = new LinkedHashMap<>();
-        final String defaultValue = getLocalizedMessage(defaultLocale, key, pwmApplication.getConfig(), bundleClass);
+        final Collection<Locale> localeList = configuration == null
+                ? new ArrayList<>(PwmConstants.INCLUDED_LOCALES)
+                : new ArrayList<>(configuration.getKnownLocales());
+
+        final String defaultValue = getLocalizedMessage(defaultLocale, key, configuration, bundleClass);
         returnObj.put(defaultLocale, defaultValue);
         returnObj.put(defaultLocale, defaultValue);
 
 
-        for (final Locale loopLocale : pwmApplication.getConfig().getKnownLocales()) {
+        for (final Locale loopLocale : localeList) {
             final String localizedValue = ResourceBundle.getBundle(bundleClass.getName(), loopLocale).getString(key);
             final String localizedValue = ResourceBundle.getBundle(bundleClass.getName(), loopLocale).getString(key);
             if (!defaultValue.equals(localizedValue)) {
             if (!defaultValue.equals(localizedValue)) {
                 returnObj.put(loopLocale, localizedValue);
                 returnObj.put(loopLocale, localizedValue);

+ 1 - 0
src/main/java/password/pwm/util/cli/MainClass.java

@@ -408,6 +408,7 @@ public class MainClass {
         final Collection<PwmEnvironment.ApplicationFlag> applicationFlags = flags == null
         final Collection<PwmEnvironment.ApplicationFlag> applicationFlags = flags == null
                 ? PwmEnvironment.ParseHelper.readApplicationFlagsFromSystem(null)
                 ? PwmEnvironment.ParseHelper.readApplicationFlagsFromSystem(null)
                 : flags;
                 : flags;
+        applicationFlags.add(PwmEnvironment.ApplicationFlag.CommandLineInstance);
         final PwmEnvironment pwmEnvironment = new PwmEnvironment.Builder(config, applicationPath)
         final PwmEnvironment pwmEnvironment = new PwmEnvironment.Builder(config, applicationPath)
                 .setApplicationMode(mode)
                 .setApplicationMode(mode)
                 .setConfigurationFile(configurationFile)
                 .setConfigurationFile(configurationFile)

+ 1 - 1
src/main/resources/password/pwm/PwmConstants.properties

@@ -47,4 +47,4 @@ enableEulaDisplay=false
 databaseAccessor.keyLength=128
 databaseAccessor.keyLength=128
 missingVersionString=[Version Missing]
 missingVersionString=[Version Missing]
 applicationPathInfoFile=applicationPath.properties
 applicationPathInfoFile=applicationPath.properties
-
+includedLocales=["","cs","de","el","es","fi","fr","hu","it","iw","ja","ko","nl","nn","no","pl","pt","pt_BR","sk","sv","th","tr","zh","zh_TW"]

+ 1 - 0
src/main/resources/password/pwm/i18n/Display.properties

@@ -78,6 +78,7 @@ Display_ConfirmResponses=Be sure your answers and questions are correct.  Check
 Display_Day=day
 Display_Day=day
 Display_Days=days
 Display_Days=days
 Display_ErrorBody=An error has occurred. Please close your browser and try again later.  If this error occurs repeatedly, please contact your help desk.
 Display_ErrorBody=An error has occurred. Please close your browser and try again later.  If this error occurs repeatedly, please contact your help desk.
+Display_ErrorReference=error reference %1%
 Display_ExpirationDate=Account expiration date (maximum %1% days)
 Display_ExpirationDate=Account expiration date (maximum %1% days)
 Display_FooterInfoText=
 Display_FooterInfoText=
 Display_ForgottenPassword=If you have forgotten your password, follow the prompts to reset your password.
 Display_ForgottenPassword=If you have forgotten your password, follow the prompts to reset your password.

+ 1 - 0
src/main/resources/password/pwm/i18n/Error.properties

@@ -155,6 +155,7 @@ Error_LdapDataError=An LDAP data error has occurred.
 Error_MacroParseError=Macro parse error: %1%
 Error_MacroParseError=Macro parse error: %1%
 Error_NoProfileAssigned=No profile is assigned for this operation.
 Error_NoProfileAssigned=No profile is assigned for this operation.
 Error_StartupError=An error occurred while starting the application.  Check the log files for information.
 Error_StartupError=An error occurred while starting the application.  Check the log files for information.
+Error_EnvironmentError=An error with the application environment has prevented the application from starting.
 
 
 Error_RemoteErrorValue=Remote Error: %1%
 Error_RemoteErrorValue=Remote Error: %1%
 
 

+ 14 - 11
src/main/webapp/WEB-INF/jsp/application-unavailable.jsp

@@ -25,35 +25,38 @@
 
 
 <!DOCTYPE html>
 <!DOCTYPE html>
 <%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
 <%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
-<% final ErrorInformation startupError = (ErrorInformation)request.getAttribute(PwmConstants.REQUEST_ATTR.PwmErrorInfo.toString()); %>
+<%
+    final ErrorInformation startupError = request.getAttribute(PwmConstants.REQUEST_ATTR.PwmErrorInfo.toString()) == null
+            ? new ErrorInformation(PwmError.ERROR_APP_UNAVAILABLE)
+            : (ErrorInformation)request.getAttribute(PwmConstants.REQUEST_ATTR.PwmErrorInfo.toString());
+%>
 <html>
 <html>
 <head>
 <head>
-    <meta http-equiv="refresh" content="5">
     <title><%=PwmConstants.PWM_APP_NAME%></title>
     <title><%=PwmConstants.PWM_APP_NAME%></title>
     <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
     <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
     <meta http-equiv="X-UA-Compatible" content="IE=10; IE=9; IE=8; IE=7" />
     <meta http-equiv="X-UA-Compatible" content="IE=10; IE=9; IE=8; IE=7" />
-    <meta http-equiv="refresh" content="30">
+    <meta http-equiv="refresh" content="60">
+    <link href="<%=request.getContextPath()%>/public/resources/style.css" rel="stylesheet" type="text/css" media="screen"/>
 </head>
 </head>
-<body class="nihilo">
+<body class="nihilo" data-jsp-page="application-unavailable.jsp">
 <div id="wrapper">
 <div id="wrapper">
     <div id="centerbody">
     <div id="centerbody">
         <br/>
         <br/>
         <h1><%=PwmConstants.PWM_APP_NAME%></h1>
         <h1><%=PwmConstants.PWM_APP_NAME%></h1>
         <br/>
         <br/>
         <br/>
         <br/>
-        <h2><%=PwmError.ERROR_APP_UNAVAILABLE.toInfo().toDebugStr()%></h2>
+        <h2><%=startupError.toDebugStr()%></h2>
         <br/>
         <br/>
         <br/>
         <br/>
-        <p><%=PwmError.ERROR_APP_UNAVAILABLE.toInfo().toUserStr(request.getLocale(), null)%></p>
-        <% if (startupError != null) { %>
-        <br/>
-        <br/>
-        <p><%=startupError.toDebugStr()%></p>
-        <% } %>
+        <p><%=startupError.toUserStr(request.getLocale(), null)%></p>
         <br/>
         <br/>
         <br/>
         <br/>
         <br/>
         <br/>
         <a href="#">Refresh</a>
         <a href="#">Refresh</a>
+        <% if (startupError.getError() == PwmError.ERROR_ENVIRONMENT_ERROR) { %>
+        <br/><br/><br/>
+        <a href="<%=request.getContextPath()%>/public/reference/environment.jsp">Environment Configuration Reference</a>
+        <% } %>
     </div>
     </div>
     <div class="push"></div>
     <div class="push"></div>
 </div>
 </div>

+ 2 - 9
src/main/webapp/WEB-INF/jsp/error-http.jsp

@@ -1,7 +1,6 @@
 <%@ page import="password.pwm.error.PwmError" %>
 <%@ page import="password.pwm.error.PwmError" %>
 <%@ page import="password.pwm.http.JspUtility" %>
 <%@ page import="password.pwm.http.JspUtility" %>
 <%@ page import="password.pwm.http.servlet.PwmServletDefinition" %>
 <%@ page import="password.pwm.http.servlet.PwmServletDefinition" %>
-<%@ page import="password.pwm.util.StringUtil" %>
 <%--
 <%--
   ~ Password Management Servlets (PWM)
   ~ Password Management Servlets (PWM)
   ~ http://code.google.com/p/pwm/
   ~ http://code.google.com/p/pwm/
@@ -30,6 +29,7 @@
 <%@ page isErrorPage="true" %>
 <%@ page isErrorPage="true" %>
 <% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
 <% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
 <% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_LOCALE); %>
 <% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_LOCALE); %>
+<html>
 <%@ include file="fragment/header.jsp" %>
 <%@ include file="fragment/header.jsp" %>
 <% response.setHeader("Content-Encoding",""); //remove gzip encoding header %>
 <% response.setHeader("Content-Encoding",""); //remove gzip encoding header %>
 <% final int statusCode = pageContext.getErrorData().getStatusCode(); %>
 <% final int statusCode = pageContext.getErrorData().getStatusCode(); %>
@@ -52,14 +52,7 @@
         </span>
         </span>
         <br/>
         <br/>
         <br/>
         <br/>
-        <% if (500 == statusCode) { %>
-        <textarea rows="10" style="width: 98%; font-size:small;" readonly="true">
-            <%=StringUtil.escapeHtml(pageContext.getErrorData().getThrowable().toString())%>
-            <% for (final StackTraceElement stElement : pageContext.getErrorData().getThrowable().getStackTrace()) { %>
-            <%=StringUtil.escapeHtml(stElement.toString())%>
-            <% } %>
-        </textarea>
-        <% } %>
+        <pwm:throwableHandler/>
         <br/>
         <br/>
         <br/>
         <br/>
         <div class="buttonbar">
         <div class="buttonbar">

+ 1 - 1
src/main/webapp/WEB-INF/jsp/fragment/footer.jsp

@@ -81,7 +81,7 @@
     </div>
     </div>
 </div>
 </div>
 <% } %>
 <% } %>
-<% if (footer_pwmRequest.isFlag(PwmRequest.Flag.NO_IDLE_TIMEOUT)) { %>
+<% if (footer_pwmRequest != null && footer_pwmRequest.isFlag(PwmRequest.Flag.NO_IDLE_TIMEOUT)) { %>
 <pwm:script>
 <pwm:script>
     <script type="text/javascript">
     <script type="text/javascript">
         PWM_GLOBAL['idle_suspendTimeout'] = true;
         PWM_GLOBAL['idle_suspendTimeout'] = true;

+ 7 - 1
src/main/webapp/WEB-INF/pwm-taglib.tld

@@ -233,7 +233,13 @@
         <name>current-url</name>
         <name>current-url</name>
         <tag-class>password.pwm.http.tag.CurrentUrlTag</tag-class>
         <tag-class>password.pwm.http.tag.CurrentUrlTag</tag-class>
         <body-content>empty</body-content>
         <body-content>empty</body-content>
-        <description>External Script Reference</description>
+        <description>output the current page url</description>
+    </tag>
+    <tag>
+        <name>throwableHandler</name>
+        <tag-class>password.pwm.http.tag.JspThrowableHandlerTag</tag-class>
+        <body-content>empty</body-content>
+        <description>process jsp level exceptions</description>
     </tag>
     </tag>
 </taglib>
 </taglib>
 
 

+ 1 - 1
src/main/webapp/WEB-INF/web.xml

@@ -31,7 +31,7 @@
     <context-param>
     <context-param>
         <description>
         <description>
             Explicit location of application working directory. If a relative path is specified, it is relative to the
             Explicit location of application working directory. If a relative path is specified, it is relative to the
-            deployed applications base directory.  If the value is "unspecified", the /WEB-INF directory is assumed.
+            deployed applications base directory.
         </description>
         </description>
         <param-name>applicationPath</param-name>
         <param-name>applicationPath</param-name>
         <param-value>unspecified</param-value>
         <param-value>unspecified</param-value>

+ 100 - 0
src/main/webapp/public/reference/displaystrings.jsp

@@ -0,0 +1,100 @@
+<%@ page import="password.pwm.http.JspUtility" %>
+<%@ page import="password.pwm.i18n.PwmLocaleBundle" %>
+<%@ page import="password.pwm.util.LocaleHelper" %>
+<%@ page import="password.pwm.util.StringUtil" %>
+<%@ page import="java.util.Collections" %>
+<%@ page import="java.util.Map" %>
+<%@ page import="java.util.ResourceBundle" %>
+<%@ page import="java.util.TreeSet" %>
+<%--
+  ~ Password Management Servlets (PWM)
+  ~ http://code.google.com/p/pwm/
+  ~
+  ~ Copyright (c) 2006-2009 Novell, Inc.
+  ~ Copyright (c) 2009-2015 The PWM Project
+  ~
+  ~ 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
+  ~
+  --%>
+
+<!DOCTYPE html>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_WARNINGS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_THEME); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_IDLE_TIMEOUT); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_BUTTONS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_FOOTER_TEXT); %>
+<%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
+<%@ taglib uri="pwm" prefix="pwm" %>
+<% final Locale userLocale = JspUtility.locale(request); %>
+<% final PwmRequest pwmRequest = JspUtility.getPwmRequest(pageContext); %>
+<html dir="<pwm:LocaleOrientation/>">
+<%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
+<body class="nihilo">
+<div id="wrapper">
+    <jsp:include page="/WEB-INF/jsp/fragment/header-body.jsp">
+        <jsp:param name="pwm.PageName" value="Display Strings Reference"/>
+    </jsp:include>
+    <div id="centerbody wide">
+        <%@ include file="reference-nav.jsp"%>
+        <ol>
+                <% for (PwmLocaleBundle bundle : PwmLocaleBundle.values()) { %>
+                <li><a href="#displayStrings_<%=bundle.getTheClass().getSimpleName()%>"><%=bundle.getTheClass().getSimpleName()%></a></li>
+                <% } %>
+        </ol>
+        <br/>
+        <% for (PwmLocaleBundle bundle : PwmLocaleBundle.values()) { %>
+        <h2>
+            <a id="displayStrings_<%=bundle.getTheClass().getSimpleName()%>"><%=bundle.getTheClass().getSimpleName()%></a>
+            <% if (bundle.isAdminOnly()) { %> (admin-only) <% } %>
+        </h2>
+        <table>
+            <% final ResourceBundle resourceBundle = ResourceBundle.getBundle(bundle.getTheClass().getName()); %>
+            <% for (final String key : new TreeSet<String>(Collections.list(resourceBundle.getKeys()))) { %>
+            <% final Map<Locale,String> values = LocaleHelper.getUniqueLocalizations(pwmRequest != null ? pwmRequest.getConfig() : null, bundle.getTheClass(), key, PwmConstants.DEFAULT_LOCALE); %>
+            <% for (final Locale locale : values.keySet()) { %>
+            <% if (locale.equals(PwmConstants.DEFAULT_LOCALE)) { %>
+            <tr>
+                <td rowspan="<%=values.size()%>">
+                    <%=key%>
+                </td>
+                <td>
+                    <%= locale.toString()%> - <%=locale.getDisplayName(userLocale)%>
+                </td>
+                <td>
+                    <%= StringUtil.escapeHtml(values.get(locale)) %>
+                </td>
+            </tr>
+            <% } else { %>
+            <tr>
+                <td>
+                    <%= locale.toString()%> - <%=locale.getDisplayName(userLocale)%>
+                </td>
+                <td>
+                    <%= StringUtil.escapeHtml(values.get(locale)) %>
+                </td>
+            </tr>
+            <% } %>
+            <% } %>
+            <% } %>
+        </table>
+        <br/>
+        <% } %>
+        <div class="push"></div>
+    </div>
+</div>
+<%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
+</body>
+</html>

+ 131 - 0
src/main/webapp/public/reference/environment.jsp

@@ -0,0 +1,131 @@
+<%@ page import="password.pwm.http.JspUtility" %>
+<%--
+  ~ Password Management Servlets (PWM)
+  ~ http://code.google.com/p/pwm/
+  ~
+  ~ Copyright (c) 2006-2009 Novell, Inc.
+  ~ Copyright (c) 2009-2015 The PWM Project
+  ~
+  ~ 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
+  --%>
+
+<!DOCTYPE html>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_WARNINGS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_THEME); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_IDLE_TIMEOUT); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_BUTTONS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_FOOTER_TEXT); %>
+<%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
+<%@ taglib uri="pwm" prefix="pwm" %>
+<html dir="<pwm:LocaleOrientation/>">
+<%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
+<body class="nihilo">
+<style nonce="<pwm:value name="cspNonce"/>" type="text/css">
+    <!--
+    .codeExample {
+        background-color: #5d5d5d;
+        color: white;
+        border: 1px white solid;
+        margin: 5px;
+        padding: 10px;
+    }
+    -->
+</style>
+<div id="wrapper">
+    <jsp:include page="/WEB-INF/jsp/fragment/header-body.jsp">
+        <jsp:param name="pwm.PageName" value="Environment Reference"/>
+    </jsp:include>
+    <div id="centerbody">
+        <%@ include file="reference-nav.jsp"%>
+        <h1>About the <%=PwmConstants.PWM_APP_NAME%> Environment</h1>
+        <p>
+            The <%=PwmConstants.PWM_APP_NAME%> application requires environment settings to load and run successfully.  Specifically, an <b>application path</b> setting
+            is required.  The path value is given as a directory on the local file system.  The pwm application must have full permissions to create, modify
+            and delete folders in this directory.
+        </p>
+        <p>
+            Previous versions of <%=PwmConstants.PWM_APP_NAME%> did not require the application path to be set and would automatically use the exploded war directory's
+            <code>WEB-INF</code> directory as the application path.  This is no longer done automatically.
+        </p>
+        <h1>Setting the Application Path</h1>
+        These methods are used in this order until a value is found.  The directory must already exist, and the application must have read and write privileges to that directory.
+        <ol>
+            <li><a href="#webxml">Servlet <code>web.xml</code></a></li>
+            <li><a href="#property">Java System Property</a></li>
+            <li><a href="#envvar">Environment Variable</a></li>
+        </ol>
+        <h2><a id="webxml">Servlet web.xml</a></h2>
+        Modify the servlet <code>WEB-INF/web.xml</code> file.  You will need to modify the application war file to accomplish this method.  This method also accommodates multiple
+        applications on a single application server.  File paths may be absolute or relative to the base of the exploded application directory.
+        <h3>Linux</h3>
+        <div class="codeExample">
+            <code>
+                &lt;context-param&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;description&gt;...&lt;/description&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;param-name&gt;applicationPath&lt;/param-name&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;param-value&gt;/home/user/<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data&lt;/param-value&gt;<br/>
+                &lt;/context-param&gt;<br/>
+            </code>
+        </div>
+        <h3>Windows</h3>
+        <div class="codeExample">
+            <code>
+                &lt;context-param&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;description&gt;...&lt;/description&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;param-name&gt;applicationPath&lt;/param-name&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;param-value&gt;c:\<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data&lt;/param-value&gt;<br/>
+                &lt;/context-param&gt;<br/>
+            </code>
+        </div>
+        <h3>Relative Location</h3>
+        In this example a relative path is specified.  Setting the value to <code>WEB-INF</code> mimics the behavior of older versions of the application.
+        <div class="codeExample">
+            <code>
+                &lt;context-param&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;description&gt;...&lt;/description&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;param-name&gt;applicationPath&lt;/param-name&gt;<br/>
+                &nbsp;&nbsp;&nbsp;&lt;param-value&gt;WEB-INF&lt;/param-value&gt;<br/>
+                &lt;/context-param&gt;<br/>
+            </code>
+        </div>
+        <h2><a id="property">Java System Property</a></h2>
+        <p>The application will read the java system property <b><%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath</b> variable to determine the location of
+            the application path.  Relative paths are not permitted.  These example parameters would be added to the java command
+            line that starts the application server (tomcat) and java process.</p>
+        <h3>Linux</h3>
+        <div class="codeExample">
+            <code>-D<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath='/home/user/<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data'</code>
+        </div>
+        <h3>Windows</h3>
+        <div class="codeExample">
+            <code>-D<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath="c:\<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data"</code>
+        </div>
+        <h2><a id="envvar">Environment Variable</a></h2>
+        <p>The application will read the <b><%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH</b> variable to determine the location of the application path.  Relative paths are not permitted.</p>
+        <h3>Linux</h3>
+        <div class="codeExample">
+            <code>export <%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH='/home/user/<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data'</code>
+        </div>
+        <h3>Windows</h3>
+        <div class="codeExample">
+            <code>set "<%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH=c:\<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data"</code>
+        </div>
+        <br/><br/><br/><br/>
+    </div>
+</div>
+<%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
+</body>
+</html>

+ 53 - 0
src/main/webapp/public/reference/index.jsp

@@ -0,0 +1,53 @@
+<%@ page import="password.pwm.http.JspUtility" %>
+<%--
+  ~ Password Management Servlets (PWM)
+  ~ http://code.google.com/p/pwm/
+  ~
+  ~ Copyright (c) 2006-2009 Novell, Inc.
+  ~ Copyright (c) 2009-2015 The PWM Project
+  ~
+  ~ 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
+  --%>
+
+<!DOCTYPE html>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_WARNINGS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_THEME); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_IDLE_TIMEOUT); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_BUTTONS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_FOOTER_TEXT); %>
+<%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
+<%@ taglib uri="pwm" prefix="pwm" %>
+<html dir="<pwm:LocaleOrientation/>">
+<%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
+<body class="nihilo">
+<div id="wrapper">
+    <jsp:include page="/WEB-INF/jsp/fragment/header-body.jsp">
+        <jsp:param name="pwm.PageName" value="Reference Library"/>
+    </jsp:include>
+    <div id="centerbody">
+        <ul>
+            <li><a href="environment.jsp">Environment</a></li>
+            <li><a href="settings.jsp">Settings</a></li>
+            <li><a href="license.jsp">License</a></li>
+            <li><a href="displaystrings.jsp">Display Strings</a></li>
+            <li><a href="rest.jsp">REST Services</a></li>
+            <li><a href="tables.jsp">Errors, Audit Events and Statistics</a></li>
+        </ul>
+    </div>
+</div>
+<%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
+</body>
+</html>

+ 3 - 11
src/main/webapp/public/reference/license.jsp

@@ -33,22 +33,14 @@
 <html dir="<pwm:LocaleOrientation/>">
 <html dir="<pwm:LocaleOrientation/>">
 <%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
 <%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
 <body class="nihilo">
 <body class="nihilo">
-<style nonce="<pwm:value name="cspNonce"/>" type="text/css">
-    <!--
-    .licenseBlock {
-        background-color: #F5F5F5;
-        border-radius: 5px;
-        box-shadow: 2px 2px 1px 1px #bfbfbf;
-        padding: 5px;
-        margin-bottom: 10px;
-    }
-    -->
-</style>
+<link href="<pwm:url url='/public/resources/referenceStyle.css' addContext="true"/>" rel="stylesheet" type="text/css"/>
 <div id="wrapper">
 <div id="wrapper">
     <jsp:include page="../../WEB-INF/jsp/fragment/header-body.jsp">
     <jsp:include page="../../WEB-INF/jsp/fragment/header-body.jsp">
         <jsp:param name="pwm.PageName" value="Software License Reference"/>
         <jsp:param name="pwm.PageName" value="Software License Reference"/>
     </jsp:include>
     </jsp:include>
     <div id="centerbody">
     <div id="centerbody">
+        <%@ include file="reference-nav.jsp"%>
+
     <p style="font-style: italic; text-align: center; width: 100%">nanos gigantum humeris insidentes</p>
     <p style="font-style: italic; text-align: center; width: 100%">nanos gigantum humeris insidentes</p>
         <div class="licenseBlock">
         <div class="licenseBlock">
             <h1>PWM License</h1>
             <h1>PWM License</h1>

+ 24 - 0
src/main/webapp/public/reference/reference-nav.jsp

@@ -0,0 +1,24 @@
+<%--
+  ~ Password Management Servlets (PWM)
+  ~ http://code.google.com/p/pwm/
+  ~
+  ~ Copyright (c) 2006-2009 Novell, Inc.
+  ~ Copyright (c) 2009-2015 The PWM Project
+  ~
+  ~ 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
+  ~
+  --%>
+
+<pwm:if test="showIcons"><span class="btn-icon fa fa-level-up"></span></pwm:if><a href=".">Reference Library</a>

+ 2 - 403
src/main/webapp/public/reference/referencedoc.jsp

@@ -1,15 +1,3 @@
-<%@ page import="password.pwm.config.PwmSettingCategory" %>
-<%@ page import="password.pwm.config.PwmSettingSyntax" %>
-<%@ page import="password.pwm.config.PwmSettingTemplate" %>
-<%@ page import="password.pwm.error.PwmError" %>
-<%@ page import="password.pwm.error.PwmException" %>
-<%@ page import="password.pwm.http.JspUtility" %>
-<%@ page import="password.pwm.i18n.PwmLocaleBundle" %>
-<%@ page import="password.pwm.svc.event.AuditEvent" %>
-<%@ page import="password.pwm.svc.stats.Statistic" %>
-<%@ page import="password.pwm.util.LocaleHelper" %>
-<%@ page import="password.pwm.util.StringUtil" %>
-<%@ page import="java.util.*" %>
 <%--
 <%--
   ~ Password Management Servlets (PWM)
   ~ Password Management Servlets (PWM)
   ~ http://code.google.com/p/pwm/
   ~ http://code.google.com/p/pwm/
@@ -33,399 +21,10 @@
   --%>
   --%>
 
 
 <!DOCTYPE html>
 <!DOCTYPE html>
-<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_WARNINGS); %>
-<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_THEME); %>
-<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
-<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_IDLE_TIMEOUT); %>
-<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_BUTTONS); %>
-<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_FOOTER_TEXT); %>
-<% final boolean advancedMode = JspUtility.getPwmRequest(pageContext).hasParameter("advanced"); %>
 <%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
 <%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
 <%@ taglib uri="pwm" prefix="pwm" %>
 <%@ taglib uri="pwm" prefix="pwm" %>
-<% final Locale userLocale = JspUtility.locale(request); %>
-<%
-    PwmRequest pwmRequest = null;
-    List<PwmSettingCategory> sortedCategories = new ArrayList();
-    try {
-        pwmRequest = PwmRequest.forRequest(request, response);
-        sortedCategories.addAll(PwmSettingCategory.sortedValues(pwmRequest.getLocale()));
-        for (Iterator<PwmSettingCategory> iterator = sortedCategories.iterator(); iterator.hasNext(); ) {
-            PwmSettingCategory category = iterator.next();
-            if (category.isHidden() || (category.getSettings().isEmpty() && category.getDescription(userLocale).isEmpty())) {
-                iterator.remove();
-            }
-        }
-
-        } catch (PwmException e) {
-            JspUtility.logError(pageContext, "error during page setup: " + e.getMessage());
-        }
-%>
 <html dir="<pwm:LocaleOrientation/>">
 <html dir="<pwm:LocaleOrientation/>">
-<%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
-<body class="nihilo">
-<div id="wrapper">
-    <jsp:include page="/WEB-INF/jsp/fragment/header-body.jsp">
-        <jsp:param name="pwm.PageName" value="Reference"/>
-    </jsp:include>
-    <div id="centerbody" style="width: 800px">
-        <ol>
-            <li><a href="#eventStatistics">Event Statistics</a></li>
-            <li><a href="#auditEvents">Audit Events</a></li>
-            <li><a href="#errors">Errors</a></li>
-            <li><a href="#settings">Settings</a></li>
-            <ol>
-                <% for (final PwmSettingCategory category : sortedCategories) { %>
-                <li><a href="#settings_category_<%=category.toString()%>"><%=category.toMenuLocationDebug(null,userLocale)%></a></li>
-                <% } %>
-            </ol>
-            <% if (advancedMode) { %>
-            <li><a href="#settingStatistics">Setting Statistics</a></li>
-            <li><a href="#appProperties">Application Properties</a></li>
-            <% } %>
-            <li><a href="#displayStrings">Display Strings</a></li>
-            <ol>
-                <% for (PwmLocaleBundle bundle : PwmLocaleBundle.values()) { %>
-                <li><a href="#displayStrings_<%=bundle.getTheClass().getSimpleName()%>"><%=bundle.getTheClass().getSimpleName()%></a></li>
-                <% } %>
-            </ol>
-        </ol>
-        <br/>
-        <h1><a id="eventStatistics">Event Statistics</a></h1>
-        <table>
-            <tr>
-                <td>
-                    <h3>Label</h3>
-                </td>
-                <td>
-                    <h3>Key</h3>
-                </td>
-                <td>
-                    <h3>Description</h3>
-                </td>
-            </tr>
-            <% for (final Statistic statistic : Statistic.sortedValues(userLocale)) { %>
-            <tr>
-                <td>
-                    <%=statistic.getLabel(userLocale)%>
-                </td>
-                <td>
-                    <%=statistic.getKey()%>
-                </td>
-                <td>
-                    <%=statistic.getDescription(userLocale)%>
-                </td>
-            </tr>
-            <% } %>
-        </table>
-        <h1><a id="auditEvents">Audit Events</a></h1>
-        <table>
-            <tr>
-                <td>
-                    <h3>Key</h3>
-                </td>
-                <td>
-                    <h3>Type</h3>
-                </td>
-                <td>
-                    <h3>Resource Key</h3>
-                </td>
-                <td>
-                    <h3>Label</h3>
-                </td>
-            </tr>
-            <% for (AuditEvent auditEvent : AuditEvent.values()) { %>
-            <tr>
-                <td>
-                    <%= auditEvent.toString() %>
-                </td>
-                <td>
-                    <%= auditEvent.getType() %>
-                </td>
-                <td>
-                    <%= auditEvent.getMessage().getKey() %>
-                </td>
-                <td>
-                    <%= auditEvent.getMessage().getLocalizedMessage(userLocale, null) %>
-                </td>
-            </tr>
-            <% } %>
-        </table>
-        <h1><a id="errors">Errors</a></h1>
-        <table class="tablemain">
-            <tr>
-                <td>
-                    <h3>Error Number</h3>
-                </td>
-                <td>
-                    <h3>Key</h3>
-                </td>
-                <td>
-                    <h3>Resource Key</h3>
-                </td>
-                <td>
-                    <h3>Message</h3>
-                </td>
-            </tr>
-            <% for (PwmError error : PwmError.values()) { %>
-            <tr>
-                <td>
-                    <%=error.getErrorCode()%>
-                </td>
-                <td >
-                    <%=error.toString()%>
-                </td>
-                <td>
-                    <%=error.getResourceKey()%>
-                </td>
-                <td>
-                    <%=error.getLocalizedMessage(userLocale, null)%>
-                </td>
-            </tr>
-            <% } %>
-        </table>
-        <h1><a id="settings">Configuration Settings</a></h1>
-        <% for (final PwmSettingCategory category : sortedCategories) { %>
-        <h2><a id="settings_category_<%=category.toString()%>"><%=category.getLabel(userLocale)%></a></h2>
-        <p>
-            <%=category.getDescription(userLocale)%>
-        </p>
-        <% for (final PwmSetting setting : category.getSettings()) { %>
-        <% if (!setting.isHidden()) { %>
-        <a id="setting_key_<%=setting.getKey()%>"  style="font-weight: inherit; text-decoration: none">
-            <table>
-                <tr>
-                    <td class="key" style="width: 100px">
-
-                        <div style="text-align: left">
-                            <a href="#setting_key_<%=setting.getKey()%>" style="text-decoration: inherit">
-                                <span class="btn-icon fa fa-link"></span>
-                            </a>
-                        </div>
-                        Label
-                    </td>
-                    <td>
-                        <%=setting.getLabel(userLocale)%>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Key
-                    </td>
-                    <td>
-                        <%=setting.getKey()%>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Navigation
-                    </td>
-                    <td>
-                        <%=setting.toMenuLocationDebug(null,userLocale)%>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Syntax
-                    </td>
-                    <td>
-                        <%=setting.getSyntax()%>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Level
-                    </td>
-                    <td>
-                        <%=setting.getLevel()%>
-                        <% if (setting.getLevel() == 0) { %>
-                        (Normal)
-                        <% } else if (setting.getLevel() == 1) { %>
-                        (Advanced)
-                        <% } %>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Required
-                    </td>
-                    <td>
-                        <%=setting.isRequired()%>
-                    </td>
-                </tr>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Confidential
-                    </td>
-                    <td>
-                        <%=setting.isConfidential()%>
-                    </td>
-                </tr>
-                <% if (setting.getSyntax() == PwmSettingSyntax.OPTIONLIST || setting.getSyntax() == PwmSettingSyntax.SELECT) { %>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Options
-                    </td>
-                    <td>
-                        <table>
-                            <thead>
-                            <tr><td><b>Stored Value</b></td><td><b>Display</b></td></tr>
-                            </thead>
-                            <tbody>
-                            <% for (final String key : setting.getOptions().keySet()) { %>
-                            <tr>
-                                <td>
-                                    <%=key%>
-                                </td>
-                                <td>
-                                    <%=setting.getOptions().get(key)%>
-                                </td>
-                            </tr>
-                            <% } %>
-                            </tbody>
-                        </table>
-                    </td>
-                </tr>
-                <% } %>
-                <% final Map<PwmSettingTemplate,String> defaultValues = setting.getDefaultValueDebugStrings(userLocale); %>
-                <tr>
-                    <td class="key" style="width: 100px">
-                        Default
-                    </td>
-                    <td style="max-width: 690px; overflow-x: auto">
-                        <% if (defaultValues.size() > 1) { %>
-                        <table>
-                            <thead>
-                            <tr><td><b>Template</b></td><td><b>Value</b></td></tr>
-                            </thead>
-                            <tbody>
-                            <%
-                                for (final PwmSettingTemplate template : defaultValues.keySet()) {
-                                    final String defaultValue = defaultValues.get(template);
-                            %>
-                            <tr><td><%=template.getLabel(userLocale)%></td><td>
-                                <%=defaultValue == null ? "" : StringUtil.escapeHtml(defaultValue)%>
-                            </td></tr>
-                            <% } %>
-                            </tbody>
-                        </table>
-                        <%
-                        } else if (defaultValues.size() == 1) {
-                            final String defaultValue = defaultValues.values().iterator().next();
-                        %>
-                        <pre><%=defaultValue == null ? "" : StringUtil.escapeHtml(defaultValue)%></pre>
-                        <% } %>
-                    </td>
-                </tr>
-                <tr>
-                    <td colspan="2">
-                        <%=setting.getDescription(userLocale)%>
-                    </td>
-                </tr>
-                <% } %>
-            </table>
-        </a>
-        <br/>
-        <% } %>
-        <% } %>
-        <% if (advancedMode) { %>
-        <h2><a id="settingStatistics">Setting Statistics</a></h2>
-        <% Map<PwmSetting.SettingStat,Object> settingStats = PwmSetting.getStats(); %>
-        <table>
-            <tr>
-                <td>
-                    Total Settings
-                </td>
-                <td>
-                    <%= settingStats.get(PwmSetting.SettingStat.Total) %>
-                </td>
-            </tr>
-            <tr>
-                <td>
-                    Settings that are part of a Profile
-                </td>
-                <td>
-                    <%= settingStats.get(PwmSetting.SettingStat.hasProfile) %>
-                </td>
-            </tr>
-            <% Map<PwmSettingSyntax,Integer> syntaxCounts = (Map<PwmSettingSyntax,Integer>)settingStats.get(PwmSetting.SettingStat.syntaxCounts); %>
-            <% for (final PwmSettingSyntax loopSyntax : syntaxCounts.keySet()) { %>
-            <tr>
-                <td>
-                    Settings with syntax type <%= loopSyntax.toString() %>
-                </td>
-                <td>
-                    <%= syntaxCounts.get(loopSyntax) %>
-                </td>
-            </tr>
-            <% } %>
-        </table>
-
-        <h2><a id="appProperties">Application Properties</a></h2>
-        <table>
-            <tr>
-                <td class="key" style="text-align: left">
-                    Key
-                </td>
-                <td class="key" style="text-align: left">
-                    Default Value
-                </td>
-            </tr>
-            <% for (final AppProperty appProperty : AppProperty.values()) { %>
-            <tr>
-                <td style="width: auto; white-space: nowrap; text-align: left">
-                    <%=appProperty.getKey()%>
-                </td>
-                <td>
-                    <%=appProperty.getDefaultValue()%>
-                </td>
-            </tr>
-            <% } %>
-        </table>
-
-
-
-        <% } %>
-        <h1><a id="displayStrings">Display Strings</a></h1>
-        <% for (PwmLocaleBundle bundle : PwmLocaleBundle.values()) { %>
-        <h2>
-            <a id="displayStrings_<%=bundle.getTheClass().getSimpleName()%>"><%=bundle.getTheClass().getSimpleName()%></a>
-            <% if (bundle.isAdminOnly()) { %> (admin-only) <% } %>
-        </h2>
-        <table>
-            <% final ResourceBundle resourceBundle = ResourceBundle.getBundle(bundle.getTheClass().getName()); %>
-            <% for (final String key : new TreeSet<String>(Collections.list(resourceBundle.getKeys()))) { %>
-            <% final Map<Locale,String> values = LocaleHelper.getUniqueLocalizations(pwmRequest.getPwmApplication(), bundle.getTheClass(), key, PwmConstants.DEFAULT_LOCALE); %>
-            <% for (final Locale locale : values.keySet()) { %>
-            <% if (locale.equals(PwmConstants.DEFAULT_LOCALE)) { %>
-            <tr>
-                <td rowspan="<%=values.size()%>">
-                    <%=key%>
-                </td>
-                <td>
-                    <%= locale.toString()%> - <%=locale.getDisplayName(userLocale)%>
-                </td>
-                <td>
-                    <%= values.get(locale) %>
-                </td>
-            </tr>
-            <% } else { %>
-            <tr>
-                <td>
-                    <%= locale.toString()%> - <%=locale.getDisplayName(userLocale)%>
-                </td>
-                <td>
-                    <%= values.get(locale) %>
-                </td>
-            </tr>
-            <% } %>
-            <% } %>
-            <% } %>
-        </table>
-        <br/>
-        <% } %>
-        <div class="push"></div>
-    </div>
-</div>
-<%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
+<body>
+This page has moved to <a href=".">Reference Library</a>.
 </body>
 </body>
 </html>
 </html>

+ 3 - 0
src/main/webapp/public/reference/rest.jsp

@@ -49,6 +49,9 @@
     <jsp:param name="pwm.PageName" value="REST Services Reference"/>
     <jsp:param name="pwm.PageName" value="REST Services Reference"/>
 </jsp:include>
 </jsp:include>
 <div id="centerbody">
 <div id="centerbody">
+    <%@ include file="reference-nav.jsp"%>
+
+    <br/><br/>
 <% if ("true".equals(request.getParameter("forwardedFromRestServer"))) { %>
 <% if ("true".equals(request.getParameter("forwardedFromRestServer"))) { %>
 <div class="message message-info">
 <div class="message message-info">
     It appears you have attempted to request a web service url, however the <i>Accept</i> header was not specified or included a value of <i>html</i>, so you are
     It appears you have attempted to request a web service url, however the <i>Accept</i> header was not specified or included a value of <i>html</i>, so you are

+ 280 - 0
src/main/webapp/public/reference/settings.jsp

@@ -0,0 +1,280 @@
+<%@ page import="password.pwm.config.PwmSettingCategory" %>
+<%@ page import="password.pwm.config.PwmSettingSyntax" %>
+<%@ page import="password.pwm.config.PwmSettingTemplate" %>
+<%@ page import="password.pwm.error.PwmException" %>
+<%@ page import="password.pwm.http.JspUtility" %>
+<%@ page import="password.pwm.util.StringUtil" %>
+<%@ page import="java.util.ArrayList" %>
+<%@ page import="java.util.Iterator" %>
+<%@ page import="java.util.List" %>
+<%@ page import="java.util.Map" %>
+<%--
+  ~ Password Management Servlets (PWM)
+  ~ http://code.google.com/p/pwm/
+  ~
+  ~ Copyright (c) 2006-2009 Novell, Inc.
+  ~ Copyright (c) 2009-2015 The PWM Project
+  ~
+  ~ 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
+  ~
+  --%>
+
+<!DOCTYPE html>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_WARNINGS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_THEME); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_IDLE_TIMEOUT); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_BUTTONS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_FOOTER_TEXT); %>
+<%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
+<%@ taglib uri="pwm" prefix="pwm" %>
+<% final Locale userLocale = JspUtility.locale(request); %>
+<%
+    final PwmRequest pwmRequest = JspUtility.getPwmRequest(pageContext);
+    boolean advancedMode = false;
+    List<PwmSettingCategory> sortedCategories = new ArrayList();
+    try {
+        advancedMode = pwmRequest != null && pwmRequest.hasParameter("advanced");
+        sortedCategories.addAll(PwmSettingCategory.sortedValues(JspUtility.locale(request)));
+        for (Iterator<PwmSettingCategory> iterator = sortedCategories.iterator(); iterator.hasNext(); ) {
+            PwmSettingCategory category = iterator.next();
+            if (category.isHidden() || (category.getSettings().isEmpty() && category.getDescription(userLocale).isEmpty())) {
+                iterator.remove();
+            }
+        }
+
+    } catch (PwmException e) {
+        JspUtility.logError(pageContext, "error during page setup: " + e.getMessage());
+    }
+%>
+<html dir="<pwm:LocaleOrientation/>">
+<%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
+<body class="nihilo">
+<div id="wrapper">
+    <jsp:include page="/WEB-INF/jsp/fragment/header-body.jsp">
+        <jsp:param name="pwm.PageName" value="Setting Reference"/>
+    </jsp:include>
+    <div id="centerbody" style="width: 800px">
+        <%@ include file="reference-nav.jsp"%>
+        <ol>
+            <% for (final PwmSettingCategory category : sortedCategories) { %>
+            <li><a href="#settings_category_<%=category.toString()%>"><%=category.toMenuLocationDebug(null,userLocale)%></a></li>
+            <% } %>
+        </ol>
+        <br/>
+        <% for (final PwmSettingCategory category : sortedCategories) { %>
+        <h2><a id="settings_category_<%=category.toString()%>"><%=category.getLabel(userLocale)%></a></h2>
+        <p>
+            <%=category.getDescription(userLocale)%>
+        </p>
+        <% for (final PwmSetting setting : category.getSettings()) { %>
+        <% if (!setting.isHidden()) { %>
+        <a id="setting_key_<%=setting.getKey()%>"  style="font-weight: inherit; text-decoration: none">
+            <table>
+                <tr>
+                    <td class="key" style="width: 100px">
+
+                        <div style="text-align: left">
+                            <a href="#setting_key_<%=setting.getKey()%>" style="text-decoration: inherit">
+                                <span class="btn-icon fa fa-link"></span>
+                            </a>
+                        </div>
+                        Label
+                    </td>
+                    <td>
+                        <%=setting.getLabel(userLocale)%>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Key
+                    </td>
+                    <td>
+                        <%=setting.getKey()%>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Navigation
+                    </td>
+                    <td>
+                        <%=setting.toMenuLocationDebug(null,userLocale)%>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Syntax
+                    </td>
+                    <td>
+                        <%=setting.getSyntax()%>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Level
+                    </td>
+                    <td>
+                        <%=setting.getLevel()%>
+                        <% if (setting.getLevel() == 0) { %>
+                        (Normal)
+                        <% } else if (setting.getLevel() == 1) { %>
+                        (Advanced)
+                        <% } %>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Required
+                    </td>
+                    <td>
+                        <%=setting.isRequired()%>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Confidential
+                    </td>
+                    <td>
+                        <%=setting.isConfidential()%>
+                    </td>
+                </tr>
+                <% if (setting.getSyntax() == PwmSettingSyntax.OPTIONLIST || setting.getSyntax() == PwmSettingSyntax.SELECT) { %>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Options
+                    </td>
+                    <td>
+                        <table>
+                            <thead>
+                            <tr><td><b>Stored Value</b></td><td><b>Display</b></td></tr>
+                            </thead>
+                            <tbody>
+                            <% for (final String key : setting.getOptions().keySet()) { %>
+                            <tr>
+                                <td>
+                                    <%=key%>
+                                </td>
+                                <td>
+                                    <%=setting.getOptions().get(key)%>
+                                </td>
+                            </tr>
+                            <% } %>
+                            </tbody>
+                        </table>
+                    </td>
+                </tr>
+                <% } %>
+                <% final Map<PwmSettingTemplate,String> defaultValues = setting.getDefaultValueDebugStrings(userLocale); %>
+                <tr>
+                    <td class="key" style="width: 100px">
+                        Default
+                    </td>
+                    <td style="max-width: 690px; overflow-x: auto">
+                        <% if (defaultValues.size() > 1) { %>
+                        <table>
+                            <thead>
+                            <tr><td><b>Template</b></td><td><b>Value</b></td></tr>
+                            </thead>
+                            <tbody>
+                            <%
+                                for (final PwmSettingTemplate template : defaultValues.keySet()) {
+                                    final String defaultValue = defaultValues.get(template);
+                            %>
+                            <tr><td><%=template.getLabel(userLocale)%></td><td>
+                                <%=defaultValue == null ? "" : StringUtil.escapeHtml(defaultValue)%>
+                            </td></tr>
+                            <% } %>
+                            </tbody>
+                        </table>
+                        <%
+                        } else if (defaultValues.size() == 1) {
+                            final String defaultValue = defaultValues.values().iterator().next();
+                        %>
+                        <pre><%=defaultValue == null ? "" : StringUtil.escapeHtml(defaultValue)%></pre>
+                        <% } %>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2">
+                        <%=setting.getDescription(userLocale)%>
+                    </td>
+                </tr>
+                <% } %>
+            </table>
+        </a>
+        <br/>
+        <% } %>
+        <% } %>
+        <% if (advancedMode) { %>
+        <h2><a id="settingStatistics">Setting Statistics</a></h2>
+        <% Map<PwmSetting.SettingStat,Object> settingStats = PwmSetting.getStats(); %>
+        <table>
+            <tr>
+                <td>
+                    Total Settings
+                </td>
+                <td>
+                    <%= settingStats.get(PwmSetting.SettingStat.Total) %>
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    Settings that are part of a Profile
+                </td>
+                <td>
+                    <%= settingStats.get(PwmSetting.SettingStat.hasProfile) %>
+                </td>
+            </tr>
+            <% Map<PwmSettingSyntax,Integer> syntaxCounts = (Map<PwmSettingSyntax,Integer>)settingStats.get(PwmSetting.SettingStat.syntaxCounts); %>
+            <% for (final PwmSettingSyntax loopSyntax : syntaxCounts.keySet()) { %>
+            <tr>
+                <td>
+                    Settings with syntax type <%= loopSyntax.toString() %>
+                </td>
+                <td>
+                    <%= syntaxCounts.get(loopSyntax) %>
+                </td>
+            </tr>
+            <% } %>
+        </table>
+
+        <h2><a id="appProperties">Application Properties</a></h2>
+        <table>
+            <tr>
+                <td class="key" style="text-align: left">
+                    Key
+                </td>
+                <td class="key" style="text-align: left">
+                    Default Value
+                </td>
+            </tr>
+            <% for (final AppProperty appProperty : AppProperty.values()) { %>
+            <tr>
+                <td style="width: auto; white-space: nowrap; text-align: left">
+                    <%=appProperty.getKey()%>
+                </td>
+                <td>
+                    <%=appProperty.getDefaultValue()%>
+                </td>
+            </tr>
+            <% } %>
+        </table>
+        <% } %>
+        <div class="push"></div>
+    </div>
+</div>
+<%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
+</body>
+</html>

+ 152 - 0
src/main/webapp/public/reference/tables.jsp

@@ -0,0 +1,152 @@
+<%@ page import="password.pwm.error.PwmError" %>
+<%@ page import="password.pwm.http.JspUtility" %>
+<%@ page import="password.pwm.svc.event.AuditEvent" %>
+<%@ page import="password.pwm.svc.stats.Statistic" %>
+<%--
+  ~ Password Management Servlets (PWM)
+  ~ http://code.google.com/p/pwm/
+  ~
+  ~ Copyright (c) 2006-2009 Novell, Inc.
+  ~ Copyright (c) 2009-2015 The PWM Project
+  ~
+  ~ 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
+  ~
+  --%>
+
+<!DOCTYPE html>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_WARNINGS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_THEME); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_REQ_COUNTER); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.NO_IDLE_TIMEOUT); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_HEADER_BUTTONS); %>
+<% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_FOOTER_TEXT); %>
+<%@ page language="java" session="true" isThreadSafe="true" contentType="text/html" %>
+<%@ taglib uri="pwm" prefix="pwm" %>
+<% final Locale userLocale = JspUtility.locale(request); %>
+<html dir="<pwm:LocaleOrientation/>">
+<%@ include file="/WEB-INF/jsp/fragment/header.jsp" %>
+<body class="nihilo">
+<div id="wrapper">
+    <jsp:include page="/WEB-INF/jsp/fragment/header-body.jsp">
+        <jsp:param name="pwm.PageName" value="Errors, Audit Events and Statistics"/>
+    </jsp:include>
+    <div id="centerbody" style="width: 800px">
+        <%@ include file="reference-nav.jsp"%>
+
+        <ol>
+            <li><a href="#eventStatistics">Event Statistics</a></li>
+            <li><a href="#auditEvents">Audit Events</a></li>
+            <li><a href="#errors">Errors</a></li>
+        </ol>
+        <br/>
+        <h1><a id="eventStatistics">Event Statistics</a></h1>
+        <table>
+            <tr>
+                <td>
+                    <h3>Label</h3>
+                </td>
+                <td>
+                    <h3>Key</h3>
+                </td>
+                <td>
+                    <h3>Description</h3>
+                </td>
+            </tr>
+            <% for (final Statistic statistic : Statistic.sortedValues(userLocale)) { %>
+            <tr>
+                <td>
+                    <%=statistic.getLabel(userLocale)%>
+                </td>
+                <td>
+                    <%=statistic.getKey()%>
+                </td>
+                <td>
+                    <%=statistic.getDescription(userLocale)%>
+                </td>
+            </tr>
+            <% } %>
+        </table>
+        <h1><a id="auditEvents">Audit Events</a></h1>
+        <table>
+            <tr>
+                <td>
+                    <h3>Key</h3>
+                </td>
+                <td>
+                    <h3>Type</h3>
+                </td>
+                <td>
+                    <h3>Resource Key</h3>
+                </td>
+                <td>
+                    <h3>Label</h3>
+                </td>
+            </tr>
+            <% for (AuditEvent auditEvent : AuditEvent.values()) { %>
+            <tr>
+                <td>
+                    <%= auditEvent.toString() %>
+                </td>
+                <td>
+                    <%= auditEvent.getType() %>
+                </td>
+                <td>
+                    <%= auditEvent.getMessage().getKey() %>
+                </td>
+                <td>
+                    <%= auditEvent.getMessage().getLocalizedMessage(userLocale, null) %>
+                </td>
+            </tr>
+            <% } %>
+        </table>
+        <h1><a id="errors">Errors</a></h1>
+        <table class="tablemain">
+            <tr>
+                <td>
+                    <h3>Error Number</h3>
+                </td>
+                <td>
+                    <h3>Key</h3>
+                </td>
+                <td>
+                    <h3>Resource Key</h3>
+                </td>
+                <td>
+                    <h3>Message</h3>
+                </td>
+            </tr>
+            <% for (PwmError error : PwmError.values()) { %>
+            <tr>
+                <td>
+                    <%=error.getErrorCode()%>
+                </td>
+                <td >
+                    <%=error.toString()%>
+                </td>
+                <td>
+                    <%=error.getResourceKey()%>
+                </td>
+                <td>
+                    <%=error.getLocalizedMessage(userLocale, null)%>
+                </td>
+            </tr>
+            <% } %>
+        </table>
+        <div class="push"></div>
+    </div>
+</div>
+<%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>
+</body>
+</html>

+ 1 - 13
src/main/webapp/public/resources/js/admin.js

@@ -57,22 +57,10 @@ PWM_ADMIN.initAdminNavMenu = function() {
                     }
                     }
                 }));
                 }));
                 pMenu.addChild(new MenuSeparator());
                 pMenu.addChild(new MenuSeparator());
-                pMenu.addChild(new MenuItem({
-                    label: '<span class="fa fa-external-link"></span> Software License Reference',
-                    onClick: function() {
-                        PWM_MAIN.newWindowOpen(PWM_GLOBAL['url-context'] + '/public/reference/license.jsp','license');
-                    }
-                }));
                 pMenu.addChild(new MenuItem({
                 pMenu.addChild(new MenuItem({
                     label: '<span class="fa fa-external-link"></span> Application Reference',
                     label: '<span class="fa fa-external-link"></span> Application Reference',
                     onClick: function() {
                     onClick: function() {
-                        PWM_MAIN.newWindowOpen(PWM_GLOBAL['url-context'] + '/public/reference/referencedoc.jsp','referencedoc');
-                    }
-                }));
-                pMenu.addChild(new MenuItem({
-                    label: '<span class="fa fa-external-link"></span> REST Web Services Reference',
-                    onClick: function() {
-                        PWM_MAIN.newWindowOpen(PWM_GLOBAL['url-context'] + '/public/reference/rest.jsp','restreference');
+                        PWM_MAIN.newWindowOpen(PWM_GLOBAL['url-context'] + '/public/reference','referencedoc');
                     }
                     }
                 }));
                 }));
                 if (PWM_GLOBAL['setting-displayEula'] == true) {
                 if (PWM_GLOBAL['setting-displayEula'] == true) {

+ 1 - 1
src/main/webapp/public/resources/js/configeditor.js

@@ -321,7 +321,7 @@ PWM_CFGEDIT.initConfigEditor = function(nextFunction) {
     PWM_MAIN.addEventHandler('saveButton_icon','click',function(){PWM_CFGEDIT.saveConfiguration()});
     PWM_MAIN.addEventHandler('saveButton_icon','click',function(){PWM_CFGEDIT.saveConfiguration()});
     PWM_MAIN.addEventHandler('setPassword_icon','click',function(){PWM_CFGEDIT.setConfigurationPassword()});
     PWM_MAIN.addEventHandler('setPassword_icon','click',function(){PWM_CFGEDIT.setConfigurationPassword()});
     PWM_MAIN.addEventHandler('referenceDoc_icon','click',function(){
     PWM_MAIN.addEventHandler('referenceDoc_icon','click',function(){
-        PWM_MAIN.newWindowOpen(PWM_GLOBAL['url-context'] + '/public/reference/referencedoc.jsp#settings','referencedoc');
+        PWM_MAIN.newWindowOpen(PWM_GLOBAL['url-context'] + '/public/reference','referencedoc');
     });
     });
     PWM_MAIN.addEventHandler('macroDoc_icon','click',function(){ PWM_CFGEDIT.showMacroHelp(); });
     PWM_MAIN.addEventHandler('macroDoc_icon','click',function(){ PWM_CFGEDIT.showMacroHelp(); });
     PWM_MAIN.addEventHandler('settingFilter_icon','click',function(){ PWM_CFGEDIT.showSettingFilter(); });
     PWM_MAIN.addEventHandler('settingFilter_icon','click',function(){ PWM_CFGEDIT.showSettingFilter(); });

+ 38 - 0
src/main/webapp/public/resources/referenceStyle.css

@@ -0,0 +1,38 @@
+/*
+ * Password Management Servlets (PWM)
+ * http://code.google.com/p/pwm/
+ *
+ * Copyright (c) 2006-2009 Novell, Inc.
+ * Copyright (c) 2009-2015 The PWM Project
+ *
+ * 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
+ *
+ */
+
+.codeExample {
+    background-color: #5d5d5d;
+    color: white;
+    border: 1px white solid;
+    margin: 5px;
+    padding: 10px;
+}
+
+.licenseBlock {
+    background-color: #F5F5F5;
+    border-radius: 5px;
+    box-shadow: 2px 2px 1px 1px #bfbfbf;
+    padding: 5px;
+    margin-bottom: 10px;
+}