Browse Source

configeditor bug fixes

jrivard 10 years ago
parent
commit
c2162b9893
39 changed files with 524 additions and 421 deletions
  1. 1 1
      pwm/servlet/src/password/pwm/config/FormUtility.java
  2. 7 6
      pwm/servlet/src/password/pwm/config/PwmSetting.java
  3. 10 2
      pwm/servlet/src/password/pwm/config/PwmSetting.xml
  4. 4 2
      pwm/servlet/src/password/pwm/config/PwmSettingCategory.java
  5. 12 0
      pwm/servlet/src/password/pwm/config/StoredConfiguration.java
  6. 0 2
      pwm/servlet/src/password/pwm/http/servlet/ConfigEditorServlet.java
  7. 1 1
      pwm/servlet/src/password/pwm/http/servlet/ConfigGuideServlet.java
  8. 8 1
      pwm/servlet/src/password/pwm/http/servlet/ConfigManagerServlet.java
  9. 14 1
      pwm/servlet/src/password/pwm/http/servlet/ForgottenPasswordServlet.java
  10. 21 16
      pwm/servlet/src/password/pwm/http/servlet/ForgottenUsernameServlet.java
  11. 4 4
      pwm/servlet/src/password/pwm/http/servlet/NewUserServlet.java
  12. 1 0
      pwm/servlet/src/password/pwm/i18n/Config.java
  13. 1 0
      pwm/servlet/src/password/pwm/i18n/Config.properties
  14. 2 2
      pwm/servlet/src/password/pwm/ldap/UserSearchEngine.java
  15. 47 1
      pwm/servlet/src/password/pwm/util/StringUtil.java
  16. 14 1
      pwm/servlet/src/password/pwm/util/cli/AbstractCliCommand.java
  17. 2 9
      pwm/servlet/src/password/pwm/util/cli/ClearResponsesCommand.java
  18. 57 0
      pwm/servlet/src/password/pwm/util/cli/ConfigDeleteCommand.java
  19. 1 0
      pwm/servlet/src/password/pwm/util/cli/MainClass.java
  20. 1 1
      pwm/servlet/src/password/pwm/wordlist/AbstractWordlist.java
  21. 18 5
      pwm/servlet/web/WEB-INF/jsp/configeditor.jsp
  22. 12 9
      pwm/servlet/web/WEB-INF/jsp/configguide-template.jsp
  23. 1 1
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-actionchoice.jsp
  24. 9 24
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-attributes.jsp
  25. 1 1
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-enterotp.jsp
  26. 1 1
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-entertoken.jsp
  27. 1 11
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-method.jsp
  28. 2 27
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-responses.jsp
  29. 1 1
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-search.jsp
  30. 1 8
      pwm/servlet/web/WEB-INF/jsp/forgottenpassword-tokenchoice.jsp
  31. 0 8
      pwm/servlet/web/WEB-INF/jsp/forgottenusername-search.jsp
  32. 38 0
      pwm/servlet/web/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp
  33. 1 1
      pwm/servlet/web/WEB-INF/jsp/login.jsp
  34. 11 3
      pwm/servlet/web/public/resources/configStyle.css
  35. 0 1
      pwm/servlet/web/public/resources/js/changepassword.js
  36. 193 258
      pwm/servlet/web/public/resources/js/configeditor-settings.js
  37. 24 11
      pwm/servlet/web/public/resources/js/main.js
  38. 1 1
      pwm/servlet/web/public/resources/js/responses.js
  39. 1 0
      pwm/servlet/web/public/resources/style.css

+ 1 - 1
pwm/servlet/src/password/pwm/config/FormUtility.java

@@ -156,7 +156,7 @@ public class FormUtility {
             filter.append("(|");
             for (final String name : filterClauses.keySet()) {
                 final String value = filterClauses.get(name);
-                filter.append("(").append(name).append("=").append(StringUtil.escapeLdap(value)).append(")");
+                filter.append("(").append(name).append("=").append(StringUtil.escapeLdapFilter(value)).append(")");
             }
             filter.append(")");
 

+ 7 - 6
pwm/servlet/src/password/pwm/config/PwmSetting.java

@@ -129,13 +129,13 @@ public enum PwmSetting {
     PASSWORD_SYNC_ENABLE_REPLICA_CHECK(
             "passwordSync.enableReplicaCheck", PwmSettingSyntax.SELECT, PwmSettingCategory.CHANGE_PASSWORD),
     PASSWORD_SYNC_MIN_WAIT_TIME(
-            "passwordSyncMinWaitTime", PwmSettingSyntax.NUMERIC, PwmSettingCategory.CHANGE_PASSWORD),
+            "passwordSyncMinWaitTime", PwmSettingSyntax.DURATION, PwmSettingCategory.CHANGE_PASSWORD),
     PASSWORD_SYNC_MAX_WAIT_TIME(
-            "passwordSyncMaxWaitTime", PwmSettingSyntax.NUMERIC, PwmSettingCategory.CHANGE_PASSWORD),
+            "passwordSyncMaxWaitTime", PwmSettingSyntax.DURATION, PwmSettingCategory.CHANGE_PASSWORD),
     PASSWORD_EXPIRE_PRE_TIME(
-            "expirePreTime", PwmSettingSyntax.NUMERIC, PwmSettingCategory.CHANGE_PASSWORD),
+            "expirePreTime", PwmSettingSyntax.DURATION, PwmSettingCategory.CHANGE_PASSWORD),
     PASSWORD_EXPIRE_WARN_TIME(
-            "expireWarnTime", PwmSettingSyntax.NUMERIC, PwmSettingCategory.CHANGE_PASSWORD),
+            "expireWarnTime", PwmSettingSyntax.DURATION, PwmSettingCategory.CHANGE_PASSWORD),
     EXPIRE_CHECK_DURING_AUTH(
             "expireCheckDuringAuth", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.CHANGE_PASSWORD),
     SEEDLIST_FILENAME(
@@ -203,8 +203,6 @@ public enum PwmSetting {
             "ldap.defaultObjectClasses", PwmSettingSyntax.STRING_ARRAY, PwmSettingCategory.LDAP_GLOBAL),
     LDAP_FOLLOW_REFERRALS(
             "ldap.followReferrals", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.LDAP_GLOBAL),
-    QUERY_MATCH_PWM_ADMIN(
-            "pwmAdmin.queryMatch", PwmSettingSyntax.USER_PERMISSION, PwmSettingCategory.LDAP_GLOBAL),
     LDAP_DUPLICATE_MODE(
             "ldap.duplicateMode", PwmSettingSyntax.SELECT, PwmSettingCategory.LDAP_GLOBAL),
     LDAP_SELECTABLE_CONTEXT_MODE(
@@ -966,6 +964,9 @@ public enum PwmSetting {
     SSO_AUTH_HEADER_NAME(
             "security.sso.authHeaderName", PwmSettingSyntax.STRING, PwmSettingCategory.HTTP_SSO),
 
+    // administration
+    QUERY_MATCH_PWM_ADMIN(
+            "pwmAdmin.queryMatch", PwmSettingSyntax.USER_PERMISSION, PwmSettingCategory.ADMINISTRATION),
 
 
     ENABLE_EXTERNAL_WEBSERVICES(

+ 10 - 2
pwm/servlet/src/password/pwm/config/PwmSetting.xml

@@ -517,7 +517,7 @@
         <regex>^.+:::.+$</regex>
         <default />
     </setting>
-    <setting key="ldap.testuser.username" level="1">
+    <setting key="ldap.testuser.username" level="0">
         <label>LDAP Test User</label>
         <description><![CDATA[The LDAP test user is used to test functionality and access to the ldap directory. This user should be configured similar to a normal user account with normal access privileges. This account will periodically be used to perform a health check, including changing the password of the account. <br/><br/><b>Using a test user account will greatly increase the ability to detect and alert configuration and health issues.</b><br/><br/>The following functionality (if enabled) will be tested using the test user account.<ul><li>Authentication</li><li>Password policy reading</li><li>Set password</li><li>Set challenge/responses</li><li>Load challenge/responses</li></ul>]]></description>
         <default>
@@ -3618,6 +3618,10 @@
         <default>
             <value>-1</value>
         </default>
+        <options>
+            <option value="min">-1</option>
+            <option value="max">10000</option>
+        </options>
     </setting>
     <setting key="reporting.ldap.maxQuerySize" level="2">
         <label>Maximum LDAP Query Size</label>
@@ -4242,6 +4246,10 @@
         <description><![CDATA[Policies for forgotten password configuration.]]></description>
         <profile setting="recovery.profile.list"/>
     </category>
+    <category key="ADMINISTRATION">
+        <label>Administration</label>
+        <description></description>
+    </category>
     <category key="FORGOTTEN_USERNAME">
         <label>Forgotten Username</label>
         <description><![CDATA[Allow a user to search for a forgotten username using a configurable search filter and attributes.]]></description>
@@ -4280,7 +4288,7 @@
         <description>The people search module provides basic white pages or directory lookup functionality to your users.  Customizations alow easy searching and display quick detailed information about your user's colleagues.</description>
     </category>
     <category key="HELPDESK_PROFILE">
-        <label>Helpdesk Profile</label>
+        <label>Helpdesk</label>
         <description><![CDATA[Profile for helpdesk activities.]]></description>
         <profile setting="helpdesk.profile.list"/>
     </category>

+ 4 - 2
pwm/servlet/src/password/pwm/config/PwmSettingCategory.java

@@ -89,8 +89,10 @@ public enum PwmSettingCategory {
     CHALLENGE                   (PROFILES),
     CHALLENGE_POLICY            (PROFILES),
 
-    CHANGE_PASSWORD             (MODULES),
+    ADMINISTRATION              (MODULES),
+
     ACCOUNT_INFO                (MODULES),
+    CHANGE_PASSWORD             (MODULES),
     RECOVERY                    (MODULES),
     RECOVERY_SETTINGS           (RECOVERY),
     RECOVERY_PROFILE            (RECOVERY),
@@ -153,7 +155,7 @@ public enum PwmSettingCategory {
     public String getDescription(final Locale locale) {
         Element categoryElement = PwmSettingXml.readCategoryXml(this);
         Element description = categoryElement.getChild("description");
-        return description.getText();
+        return description == null ? "" : description.getText();
     }
 
     public int getLevel() {

+ 12 - 0
pwm/servlet/src/password/pwm/config/StoredConfiguration.java

@@ -908,6 +908,7 @@ public class StoredConfiguration implements Serializable {
 
     private static class ConfigurationCleaner {
         private static void cleanup(final StoredConfiguration configuration) {
+            updateProperitiesWithoutType(configuration);
             updateMandatoryElements(configuration.document);
             profilizeNonProfiledSettings(configuration);
             stripOrphanedProfileSettings(configuration);
@@ -1020,6 +1021,17 @@ public class StoredConfiguration implements Serializable {
             }
         }
 
+        private static void updateProperitiesWithoutType(final StoredConfiguration storedConfiguration) {
+            final Document document = storedConfiguration.document;
+            final String xpathString = "//properties[not(@type)]";
+            final XPathFactory xpfac = XPathFactory.instance();
+            final XPathExpression xp = xpfac.compile(xpathString);
+            final List<Element> propertiesElements = (List<Element>)xp.evaluate(document);
+            for (final Element propertiesElement : propertiesElements) {
+                propertiesElement.setAttribute(XML_ATTRIBUTE_TYPE,XML_ATTRIBUTE_VALUE_CONFIG);
+            }
+        }
+
         private static void stripOrphanedProfileSettings(final StoredConfiguration storedConfiguration) {
             final Document document = storedConfiguration.document;
             final XPathFactory xpfac = XPathFactory.instance();

+ 0 - 2
pwm/servlet/src/password/pwm/http/servlet/ConfigEditorServlet.java

@@ -59,8 +59,6 @@ public class ConfigEditorServlet extends PwmServlet {
 
     private static final PwmLogger LOGGER = PwmLogger.forClass(ConfigEditorServlet.class);
 
-    private static final String COOKIE_NAME_PREFERENCES = "ConfigEditor_preferences";
-
     public enum ConfigEditorAction implements PwmServlet.ProcessAction {
         readSetting(HttpMethod.POST),
         writeSetting(HttpMethod.POST),

+ 1 - 1
pwm/servlet/src/password/pwm/http/servlet/ConfigGuideServlet.java

@@ -158,7 +158,7 @@ public class ConfigGuideServlet extends PwmServlet {
             defaultLdapForm.put(PARAM_LDAP_SECURE, "ldaps".equalsIgnoreCase(uri.getScheme()) ? "true" : "false");
 
             defaultLdapForm.put(PARAM_LDAP_ADMIN_DN, (String)PwmSetting.LDAP_PROXY_USER_DN.getDefaultValue(template).toNativeObject());
-            defaultLdapForm.put(PARAM_LDAP_ADMIN_PW, (String)PwmSetting.LDAP_PROXY_USER_PASSWORD.getDefaultValue(template).toNativeObject());
+            defaultLdapForm.put(PARAM_LDAP_ADMIN_PW, "");
 
             defaultLdapForm.put(PARAM_LDAP2_CONTEXT, ((List<String>)PwmSetting.LDAP_CONTEXTLESS_ROOT.getDefaultValue(template).toNativeObject()).get(0));
             defaultLdapForm.put(PARAM_LDAP2_TEST_USER, (String)PwmSetting.LDAP_TEST_USER_DN.getDefaultValue(template).toNativeObject());

+ 8 - 1
pwm/servlet/src/password/pwm/http/servlet/ConfigManagerServlet.java

@@ -40,6 +40,7 @@ import password.pwm.http.PwmResponse;
 import password.pwm.http.PwmSession;
 import password.pwm.http.bean.ConfigManagerBean;
 import password.pwm.i18n.Config;
+import password.pwm.i18n.Display;
 import password.pwm.i18n.LocaleHelper;
 import password.pwm.i18n.Message;
 import password.pwm.ldap.auth.AuthenticationType;
@@ -165,7 +166,13 @@ public class ConfigManagerServlet extends PwmServlet {
         final ConfigurationReader configurationReader = pwmRequest.getContextManager().getConfigReader();
         pwmRequest.setAttribute(PwmConstants.REQUEST_ATTR.PageTitle,LocaleHelper.getLocalizedMessage(Config.Title_ConfigManager, pwmRequest));
         pwmRequest.setAttribute(PwmConstants.REQUEST_ATTR.ConfigFilename, configurationReader.getConfigFile().getAbsolutePath());
-        pwmRequest.setAttribute(PwmConstants.REQUEST_ATTR.ConfigLastModified, PwmConstants.DEFAULT_DATETIME_FORMAT.format(configurationReader.getStoredConfiguration().modifyTime()));
+        {
+            final Date lastModifyTime = configurationReader.getStoredConfiguration().modifyTime();
+            final String output = lastModifyTime == null
+                    ? LocaleHelper.getLocalizedMessage(Display.Value_NotApplicable,pwmRequest)
+                    : PwmConstants.DEFAULT_DATETIME_FORMAT.format(lastModifyTime);
+            pwmRequest.setAttribute(PwmConstants.REQUEST_ATTR.ConfigLastModified, output);
+        }
         pwmRequest.setAttribute(PwmConstants.REQUEST_ATTR.ConfigHasPassword, LocaleHelper.booleanString(configurationReader.getStoredConfiguration().hasPassword(),pwmRequest.getLocale(),pwmRequest.getConfig()));
     }
 

+ 14 - 1
pwm/servlet/src/password/pwm/http/servlet/ForgottenPasswordServlet.java

@@ -188,7 +188,7 @@ public class ForgottenPasswordServlet extends PwmServlet {
                     break;
 
                 case reset:
-                    pwmSession.clearSessionBean(ForgottenPasswordBean.class);
+                    this.processReset(pwmRequest);
                     break;
 
                 case actionChoice:
@@ -228,6 +228,19 @@ public class ForgottenPasswordServlet extends PwmServlet {
         }
     }
 
+    private void processReset(final PwmRequest pwmRequest)
+            throws IOException, PwmUnrecoverableException
+    {
+        final ForgottenPasswordBean forgottenPasswordBean = pwmRequest.getPwmSession().getForgottenPasswordBean();
+
+        pwmRequest.getPwmSession().clearSessionBean(ForgottenPasswordBean.class);
+
+        if (forgottenPasswordBean.getUserInfo() == null) {
+            pwmRequest.sendRedirectToContinue();
+            return;
+        }
+    }
+
     private void processTokenChoice(final PwmRequest pwmRequest)
             throws PwmUnrecoverableException, ServletException, IOException, ChaiUnavailableException
     {

+ 21 - 16
pwm/servlet/src/password/pwm/http/servlet/ForgottenUsernameServlet.java

@@ -93,7 +93,7 @@ public class ForgottenUsernameServlet extends PwmServlet {
             }
         }
 
-        pwmRequest.forwardToJsp(PwmConstants.JSP_URL.FORGOTTEN_USERNAME);
+        forwardToFormJsp(pwmRequest);
     }
 
     public void handleSearchRequest(
@@ -145,29 +145,33 @@ public class ForgottenUsernameServlet extends PwmServlet {
                 pwmApplication.getIntruderManager().convenience().markAddressAndSession(pwmSession);
                 pwmApplication.getStatisticsManager().incrementValue(Statistic.FORGOTTEN_USERNAME_FAILURES);
                 pwmRequest.setResponseError(PwmError.ERROR_CANT_MATCH_USER.toInfo());
-                pwmRequest.forwardToJsp(PwmConstants.JSP_URL.FORGOTTEN_USERNAME);
+                forwardToFormJsp(pwmRequest);
                 return;
             }
 
             // make sure the user isn't locked.
             pwmApplication.getIntruderManager().convenience().checkUserIdentity(userIdentity);
 
+
+            final UserInfoBean forgottenUserInfo = new UserInfoBean();
+            final UserStatusReader userStatusReader = new UserStatusReader(pwmApplication, pwmSession.getLabel());
+            userStatusReader.populateUserInfoBean(forgottenUserInfo, pwmRequest.getLocale(), userIdentity);
+
+
             // send username
-            sendUsername(pwmApplication, pwmSession, userIdentity);
+            sendUsername(pwmApplication, pwmSession, forgottenUserInfo);
 
             // redirect user to success page.
             LOGGER.info(pwmSession, "found user " + userIdentity.getUserDN());
             try {
-                final String usernameAttribute = pwmApplication.getConfig().readSettingAsString(PwmSetting.FORGOTTEN_USERNAME_USERNAME_ATTRIBUTE);
-                final UserDataReader userDataReader = LdapUserDataReader.appProxiedReader(pwmApplication, userIdentity);
-                final String username = userDataReader.readStringAttribute(usernameAttribute);
-                LOGGER.trace(pwmSession, "read username attribute '" + usernameAttribute + "' value=" + username);
+                final String username = forgottenUserInfo.getUsername();
+                LOGGER.trace(pwmSession, "read username value=" + username);
 
                 pwmApplication.getIntruderManager().convenience().clearAddressAndSession(pwmSession);
                 pwmApplication.getIntruderManager().convenience().clearAttributes(formValues);
 
                 pwmApplication.getStatisticsManager().incrementValue(Statistic.FORGOTTEN_USERNAME_SUCCESSES);
-                pwmRequest.forwardToSuccessPage(Message.Success_ForgottenUsername);
+                pwmRequest.forwardToSuccessPage(Message.Success_ForgottenUsername, username);
                 return;
             } catch (Exception e) {
                 LOGGER.error("error reading username value for " + userIdentity + ", " + e.getMessage());
@@ -185,14 +189,14 @@ public class ForgottenUsernameServlet extends PwmServlet {
         }
 
         pwmApplication.getStatisticsManager().incrementValue(Statistic.FORGOTTEN_USERNAME_FAILURES);
-        pwmRequest.forwardToJsp(PwmConstants.JSP_URL.FORGOTTEN_USERNAME);
+        forwardToFormJsp(pwmRequest);
     }
 
 
     private void sendUsername(
             final PwmApplication pwmApplication,
             final PwmSession pwmSession,
-            final UserIdentity userIdentity
+            final UserInfoBean forgottenUserInfo
     )
             throws PwmOperationalException, PwmUnrecoverableException
     {
@@ -206,10 +210,6 @@ public class ForgottenUsernameServlet extends PwmServlet {
             return;
         }
 
-        final UserInfoBean forgottenUserInfo = new UserInfoBean();
-        final UserStatusReader userStatusReader = new UserStatusReader(pwmApplication, pwmSession.getLabel());
-        userStatusReader.populateUserInfoBean(forgottenUserInfo, userLocale, userIdentity);
-
         sendMessageViaMethod(
                 pwmApplication,
                 forgottenUserInfo,
@@ -288,8 +288,6 @@ public class ForgottenUsernameServlet extends PwmServlet {
     )
             throws PwmOperationalException, PwmUnrecoverableException
     {
-        final Configuration config = pwmApplication.getConfig();
-
         final String toNumber = userInfoBean.getUserSmsNumber();
         if (toNumber == null || toNumber.length() < 1) {
             final String errorMsg = String.format("unable to send new password email for '%s'; no SMS number available in ldap", userInfoBean.getUserIdentity());
@@ -324,4 +322,11 @@ public class ForgottenUsernameServlet extends PwmServlet {
         return null;
     }
 
+    private void forwardToFormJsp(final PwmRequest pwmRequest)
+            throws ServletException, PwmUnrecoverableException, IOException
+    {
+        pwmRequest.addFormInfoToRequestAttr(PwmSetting.FORGOTTEN_USERNAME_FORM,false,false);
+        pwmRequest.forwardToJsp(PwmConstants.JSP_URL.FORGOTTEN_USERNAME);
+    }
+
 }

+ 4 - 4
pwm/servlet/src/password/pwm/http/servlet/NewUserServlet.java

@@ -279,12 +279,12 @@ public class NewUserServlet extends PwmServlet {
             newUserBean.setCreateStartTime(new Date());
             pwmRequest.forwardToJsp(PwmConstants.JSP_URL.NEW_USER_WAIT);
         } catch (PwmOperationalException e) {
+            LOGGER.error(pwmRequest, "error during user creation: " + e.getMessage());
             if (newUserProfile.readSettingAsBoolean(PwmSetting.NEWUSER_DELETE_ON_FAIL)) {
                 deleteUserAccount(newUserDN, pwmSession, pwmApplication);
             }
             LOGGER.error(pwmSession, e.getErrorInformation().toDebugStr());
-            pwmRequest.setResponseError(e.getErrorInformation());
-            forwardToFormPage(pwmRequest);
+            pwmRequest.respondWithError(e.getErrorInformation());
         }
     }
 
@@ -671,7 +671,7 @@ public class NewUserServlet extends PwmServlet {
                 throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_NEW_USER_FAILURE,
                         "username definition not set, and naming attribute is not present in form"));
             }
-            final String escapedName = StringUtil.escapeLdap(namingValue);
+            final String escapedName = StringUtil.escapeLdapDN(namingValue);
             final String generatedDN = namingAttribute + "=" + escapedName + "," + expandedContext;
             LOGGER.debug(pwmRequest, "generated dn for new user: " + generatedDN);
             return generatedDN;
@@ -690,7 +690,7 @@ public class NewUserServlet extends PwmServlet {
                 if (!testIfEntryNameExists(pwmRequest, expandedName)) {
                     LOGGER.trace(pwmRequest, "generated entry name for new user is unique: " + expandedName);
                     final String namingAttribute = pwmRequest.getConfig().getDefaultLdapProfile().readSettingAsString(PwmSetting.LDAP_NAMING_ATTRIBUTE);
-                    final String escapedName = StringUtil.escapeLdap(expandedName);
+                    final String escapedName = StringUtil.escapeLdapDN(expandedName);
                     generatedDN = namingAttribute + "=" + escapedName + "," + expandedContext;
                     LOGGER.debug(pwmRequest, "generated dn for new user: " + generatedDN);
                     return generatedDN;

+ 1 - 0
pwm/servlet/src/password/pwm/i18n/Config.java

@@ -48,6 +48,7 @@ public enum Config implements PwmDisplayBundle {
     Display_ConfigManagerNew,
     Display_ConfigManagerRunning,
     Display_ConfigManagerRunningEditor,
+    Display_ConfigOpenInfo,
     MenuDisplay_AlternateNewConfig,
     MenuDisplay_AlternateUnlockConfig,
     MenuDisplay_AlternateUpload,

+ 1 - 0
pwm/servlet/src/password/pwm/i18n/Config.properties

@@ -46,6 +46,7 @@ Display_ConfigManagerRunningEditor=Your modified configuration is currently in m
 Display_SettingFilter_Level_0=Required
 Display_SettingFilter_Level_1=Standard / Common
 Display_SettingFilter_Level_2=Advanced
+Display_ConfigOpenInfo=<p>While the configuration status is <i>open</i> any user can access this configuration without authenticating to LDAP.</p><p>Please close the configuration using the <a id="link-configManager">ConfigurationManager</a> when the configuration is completed enough to authenticate administrative users.</p>
 MenuDisplay_AlternateNewConfig=Edit a new configuration in memory by selecting a new configuration template. After editing the configuration, you can download the <em>%1%</em> file.  This option will not modify the running configuration.
 MenuDisplay_AlternateUnlockConfig=The closing of the <em>%1%</em> file is controlled by the property "configIsEditable" within the file.  Set this property to "true" to return to the online configuration mode. Be aware that while this property is set to true anyone accessing this site can make modifications to the live configuration without authentication.
 MenuDisplay_AlternateUpload=Alternatively, you may upload a previously saved configuration file. The uploaded file will be saved as the new configuration.

+ 2 - 2
pwm/servlet/src/password/pwm/ldap/UserSearchEngine.java

@@ -89,7 +89,7 @@ public class UserSearchEngine {
             final String attrName = "%" + formItem.getName() + "%";
             String value = formValues.get(formItem);
             if (enableValueEscaping) {
-                value = StringUtil.escapeLdap(value);
+                value = StringUtil.escapeLdapFilter(value);
             }
             newSearchFilter = newSearchFilter.replace(attrName, value);
         }
@@ -291,7 +291,7 @@ public class UserSearchEngine {
         final String searchFilter;
         if (searchConfiguration.getUsername() != null) {
             final String inputQuery = searchConfiguration.isEnableValueEscaping()
-                    ? StringUtil.escapeLdap(searchConfiguration.getUsername())
+                    ? StringUtil.escapeLdapFilter(searchConfiguration.getUsername())
                     : searchConfiguration.getUsername();
 
             if (searchConfiguration.getUsername().split("\\s").length > 1) { // split on all whitespace chars

+ 47 - 1
pwm/servlet/src/password/pwm/util/StringUtil.java

@@ -43,7 +43,7 @@ public abstract class StringUtil {
      * @return ldap escaped script
      *
      */
-    public static String escapeLdap(final String input) {
+    public static String escapeLdapFilter(final String input) {
         final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < input.length(); i++) {
             char curChar = input.charAt(i);
@@ -70,6 +70,52 @@ public abstract class StringUtil {
         return sb.toString();
     }
 
+    /**
+     * Based on http://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java.
+     *
+     * @param input string to have escaped
+     * @return ldap escaped script
+     *
+     */
+    public static String escapeLdapDN(final String input) {
+        StringBuilder sb = new StringBuilder(); // If using JDK >= 1.5 consider using StringBuilder
+        if ((input.length() > 0) && ((input.charAt(0) == ' ') || (input.charAt(0) == '#'))) {
+            sb.append('\\'); // add the leading backslash if needed
+        }
+        for (int i = 0; i < input.length(); i++) {
+            char curChar = input.charAt(i);
+            switch (curChar) {
+                case '\\':
+                    sb.append("\\\\");
+                    break;
+                case ',':
+                    sb.append("\\,");
+                    break;
+                case '+':
+                    sb.append("\\+");
+                    break;
+                case '"':
+                    sb.append("\\\"");
+                    break;
+                case '<':
+                    sb.append("\\<");
+                    break;
+                case '>':
+                    sb.append("\\>");
+                    break;
+                case ';':
+                    sb.append("\\;");
+                    break;
+                default:
+                    sb.append(curChar);
+            }
+        }
+        if ((input.length() > 1) && (input.charAt(input.length() - 1) == ' ')) {
+            sb.insert(sb.length() - 1, '\\'); // add the trailing backslash if needed
+        }
+        return sb.toString();
+    }
+
     public static Map<String, String> convertStringListToNameValuePair(final Collection<String> input, final String separator) {
         if (input == null) {
             return Collections.emptyMap();

+ 14 - 1
pwm/servlet/src/password/pwm/util/cli/AbstractCliCommand.java

@@ -3,7 +3,7 @@
  * http://code.google.com/p/pwm/
  *
  * Copyright (c) 2006-2009 Novell, Inc.
- * Copyright (c) 2009-2014 The PWM Project
+ * 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
@@ -23,6 +23,7 @@
 package password.pwm.util.cli;
 
 import java.io.IOException;
+import java.util.Scanner;
 
 public abstract class AbstractCliCommand implements CliCommand  {
     protected CliEnvironment cliEnvironment;
@@ -60,5 +61,17 @@ public abstract class AbstractCliCommand implements CliCommand  {
         }
     }
 
+    boolean promptForContinue() {
+        out("To proceed, type 'continue'");
+        final Scanner scanner = new Scanner(System.in);
+        final String input = scanner.nextLine();
+
+        if (!"continue".equalsIgnoreCase(input)) {
+            out("exiting...");
+            return false;
+        }
+        return true;
+    }
+
     abstract void doCommand() throws Exception;
 }

+ 2 - 9
pwm/servlet/src/password/pwm/util/cli/ClearResponsesCommand.java

@@ -3,7 +3,7 @@
  * http://code.google.com/p/pwm/
  *
  * Copyright (c) 2006-2009 Novell, Inc.
- * Copyright (c) 2009-2014 The PWM Project
+ * 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
@@ -24,8 +24,6 @@ package password.pwm.util.cli;
 
 import password.pwm.util.localdb.LocalDB;
 
-import java.util.Scanner;
-
 public class ClearResponsesCommand extends AbstractCliCommand {
 
     @Override
@@ -37,12 +35,7 @@ public class ClearResponsesCommand extends AbstractCliCommand {
         out("");
         out("The application must be stopped for this operation to succeed.");
         out("");
-        out("To proceed, type 'continue'");
-        final Scanner scanner = new Scanner(System.in);
-        final String input = scanner.nextLine();
-
-        if (!"continue".equalsIgnoreCase(input)) {
-            out("exiting...");
+        if (!promptForContinue()) {
             return;
         }
 

+ 57 - 0
pwm/servlet/src/password/pwm/util/cli/ConfigDeleteCommand.java

@@ -0,0 +1,57 @@
+/*
+ * 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.util.cli;
+
+import java.io.File;
+
+public class ConfigDeleteCommand extends AbstractCliCommand {
+    public void doCommand()
+            throws Exception
+    {
+        final File configurationFile = cliEnvironment.configurationFile;
+        if (configurationFile == null || !configurationFile.exists()) {
+            out("configuration file is not present");
+            return;
+        }
+
+
+        if (!promptForContinue()) {
+            return;
+        }
+
+        configurationFile.delete();
+        out("success");
+    }
+
+    @Override
+    public CliParameters getCliParameters()
+    {
+        CliParameters cliParameters = new CliParameters();
+        cliParameters.commandName = "ConfigDelete";
+        cliParameters.description = "Unlock a configuration, allows config to be edited without LDAP authentication.";
+        cliParameters.needsPwmApplication = false;
+        cliParameters.readOnly = true;
+        return cliParameters;
+    }
+
+}

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

@@ -62,6 +62,7 @@ public class MainClass {
         commandList.add(new ConfigNewCommand());
         commandList.add(new VersionCommand());
         commandList.add(new LdapSchemaExtendCommand());
+        commandList.add(new ConfigDeleteCommand());
 
         final Map<String,CliCommand> sortedMap = new TreeMap<>();
         for (CliCommand command : commandList) {

+ 1 - 1
pwm/servlet/src/password/pwm/wordlist/AbstractWordlist.java

@@ -129,7 +129,7 @@ abstract class AbstractWordlist implements Wordlist, PwmService {
         try {
             final String storedSizeStr = localDB.get(META_DB, KEY_SIZE);
             storedSize = Integer.valueOf(storedSizeStr);
-        } catch (LocalDBException e) {
+        } catch (NumberFormatException | LocalDBException e) {
             final String errorMsg = DEBUG_LABEL + " error reading stored size, closing, " + e.getMessage();
             LOGGER.warn(errorMsg);
             lastError = new ErrorInformation(PwmError.ERROR_SERVICE_NOT_AVAILABLE,errorMsg);

+ 18 - 5
pwm/servlet/web/WEB-INF/jsp/configeditor.jsp

@@ -34,6 +34,7 @@
 <%@ include file="fragment/header.jsp" %>
 <% final PwmRequest configeditor_pwmRequest = PwmRequest.forRequest(request, response); %>
 <% final ConfigManagerBean configManagerBean = configeditor_pwmRequest.getPwmSession().getConfigManagerBean(); %>
+<% final boolean configUnlocked = configeditor_pwmRequest.getPwmApplication().getApplicationMode() == PwmApplication.MODE.CONFIGURATION && !PwmConstants.TRIAL_MODE; %>
 <% final String configNotes = configManagerBean.getStoredConfiguration().readConfigProperty(StoredConfiguration.ConfigProperty.PROPERTY_KEY_NOTES);%>
 <body class="nihilo">
 <style>
@@ -46,6 +47,9 @@
             <div id="header-title">
                 <%=PwmConstants.PWM_APP_NAME%> Configuration Editor <span id="currentPageDisplay"></span>
                 <span style="visibility: hidden" id="working_icon" class="headerIcon fa fa-cog fa-spin"></span>
+                <span id="idle_status" class="editorIdleStatus">
+                    <%--idle timeout text --%>
+                </span>
                 <div class="headerIcon" id="cancelButton_icon">
                     <span class="fa fa-times"></span>
                 </div>
@@ -61,9 +65,6 @@
                 <div class="headerIcon" id="macroDoc_icon">
                     <span class="fa fa-magic"></span>
                 </div>
-            <div id="idle_status" class="editorIdleStatus">
-                <%--idle timeout text --%>
-            </div>
             </div>
         </div>
     </div>
@@ -121,8 +122,8 @@
 </div>
 <pwm:script>
     <script type="text/javascript">
-        PWM_GLOBAL['setting_alwaysFloatMessages'] = true;
         var PWM_VAR = PWM_VAR || {};
+        PWM_GLOBAL['setting_alwaysFloatMessages'] = true;
         PWM_VAR['currentTemplate'] = '<%=configManagerBean.getStoredConfiguration().getTemplate()%>';
         PWM_VAR['configurationNotes'] = '<%=configNotes==null?"":StringUtil.escapeJS(configNotes)%>';
         PWM_VAR['ldapProfileIds'] = [];
@@ -132,8 +133,20 @@
 
         PWM_GLOBAL['startupFunctions'].push(function(){
             PWM_CFGEDIT.initConfigEditor();
-        });
 
+            <% if (configUnlocked) { %>
+            PWM_MAIN.showDialog({
+                title:'Notice - Configuration Status: Open',
+                text:PWM_CONFIG.showString('Display_ConfigOpenInfo'),
+                loadFunction:function(){
+                    PWM_MAIN.addEventHandler('link-configManager','click',function(){
+                        PWM_MAIN.goto('/private/config/ConfigManager');
+                    });
+                }
+            });
+
+            <% } %>
+        });
     </script>
 </pwm:script>
 <% JspUtility.setFlag(pageContext, PwmRequest.Flag.HIDE_LOCALE); %>

+ 12 - 9
pwm/servlet/web/WEB-INF/jsp/configguide-template.jsp

@@ -46,7 +46,7 @@
         <%@ include file="/WEB-INF/jsp/fragment/message.jsp" %>
         <pwm:display key="Display_ConfigGuideSelectTemplate" bundle="Config"/>
         <br/>
-        <form id="configForm" data-dojo-type="dijit/form/Form">
+        <form id="configForm">
             <select id="<%=ConfigGuideServlet.PARAM_TEMPLATE_NAME%>" name="<%=ConfigGuideServlet.PARAM_TEMPLATE_NAME%>" style="width:300px">
                 <% if (selectedTemplate == null) { %>
                 <option value="NOTSELECTED" selected="selected">-- Please select a template --</option>
@@ -79,9 +79,7 @@
     <script type="text/javascript">
         function formHandler() {
             var startTemplate = '<%=selectedTemplate == null ? "" : selectedTemplate.toString()%>';
-
-            var configForm = dojo.formToObject('configForm');
-            var newTemplate = configForm['<%=ConfigGuideServlet.PARAM_TEMPLATE_NAME%>'];
+            var newTemplate = getSelectedValue();
             if (startTemplate && startTemplate.length > 0 && startTemplate != newTemplate) {
                 PWM_MAIN.showConfirmDialog({
                     text:'Changing the template will cause existing guide settings to be cleared.  Are you sure you wish to continue?',
@@ -99,18 +97,23 @@
             }
         }
 
+        function getSelectedValue() {
+            var selectedIndex = PWM_MAIN.getObject('<%=ConfigGuideServlet.PARAM_TEMPLATE_NAME%>').selectedIndex;
+            var newTemplate = PWM_MAIN.getObject('<%=ConfigGuideServlet.PARAM_TEMPLATE_NAME%>').options[selectedIndex];
+            return newTemplate.value;
+        }
+
         function updateNextButton() {
-            require(["dojo"],function(dojo) {
-                var configForm = dojo.formToObject('configForm');
-                var notSelected = configForm['<%=ConfigGuideServlet.PARAM_TEMPLATE_NAME%>'] == 'NOTSELECTED';
-                PWM_MAIN.getObject('button_next').disabled = notSelected;
-            });
+            var newTemplate = getSelectedValue();
+            var notSelected = newTemplate == 'NOTSELECTED';
+            PWM_MAIN.getObject('button_next').disabled = notSelected;
         }
 
         PWM_GLOBAL['startupFunctions'].push(function(){
             PWM_MAIN.addEventHandler('button_previous','click',function(){PWM_GUIDE.gotoStep('PREVIOUS')});
             PWM_MAIN.addEventHandler('button_next','click',function(){PWM_GUIDE.gotoStep('NEXT')});
             PWM_MAIN.addEventHandler('<%=ConfigGuideServlet.PARAM_TEMPLATE_NAME%>','change',function(){formHandler()});
+            updateNextButton();
         });
     </script>
 </pwm:script>

+ 1 - 1
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-actionchoice.jsp

@@ -81,7 +81,7 @@
             </tr>
             <tr>
                 <td>
-                    <%@ include file="/WEB-INF/jsp/fragment/button-cancel.jsp" %>
+                    <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
                 </td>
                 <td>
                     &nbsp;

+ 9 - 24
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-attributes.jsp

@@ -65,39 +65,24 @@ this is handled this way so on browsers where hiding fields is not possible, the
                     <pwm:display key="Button_RecoverPassword"/>
                 </button>
                 <%@ include file="/WEB-INF/jsp/fragment/button-reset.jsp" %>
-                <pwm:if test="showCancel">
-                    <button style="visibility:hidden;" type="button" name="button" class="btn" id="button_cancel" onclick="handleCancelClick()">
-                        <pwm:if test="showIcons"><span class="btn-icon fa fa-times"></span></pwm:if>
-                        <pwm:display key="Button_Cancel"/>
-                    </button>
-                </pwm:if>
+                <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
                 <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
             </div>
         </form>
     </div>
     <div class="push"></div>
 </div>
-<form name="responseResetForm" id="responseResetForm" action="<pwm:url url='ForgottenPassword'/>" method="post"
-      enctype="application/x-www-form-urlencoded">
-    <input type="hidden" name="processAction" value="reset"/>
-    <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
-</form>
 <pwm:script>
-<script type="text/javascript">
-    PWM_GLOBAL['startupFunctions'].push(function(){
-        PWM_RESPONSES.startupResponsesPage();
-    });
-
-    function handleCancelClick() {
-        PWM_MAIN.showWaitDialog({
-            loadFunction:function(){
-                PWM_MAIN.getObject('responseResetForm').submit();
-            }
+    <script type="text/javascript">
+        PWM_GLOBAL['startupFunctions'].push(function(){
+            PWM_RESPONSES.startupResponsesPage();
+            PWM_MAIN.addEventHandler('button_cancel', 'click', function(event){
+                PWM_MAIN.handleFormSubmit(PWM_MAIN.getObject('button_cancel'),event);
+            });
         });
-    }
-</script>
+    </script>
 </pwm:script>
-<script type="text/javascript" src="<pwm:context/><pwm:url url='/public/resources/js/responses.js'/>"></script>
+<script nonce="<pwm:value name="cspNonce"/>" type="text/javascript" src="<pwm:context/><pwm:url url='/public/resources/js/responses.js'/>"></script>
 <%@ include file="fragment/footer.jsp" %>
 </body>
 </html>

+ 1 - 1
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-enterotp.jsp

@@ -54,8 +54,8 @@
                     <pwm:display key="Button_CheckCode"/>
                 </button>
                 <%@ include file="/WEB-INF/jsp/fragment/button-reset.jsp" %>
+                <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
                 <input type="hidden" id="processAction" name="processAction" value="enterOtp"/>
-                <%@ include file="/WEB-INF/jsp/fragment/button-cancel.jsp" %>
                 <input type="hidden" id="pwmFormID" name="pwmFormID" value="<pwm:FormID/>"/>
             </div>
         </form>

+ 1 - 1
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-entertoken.jsp

@@ -50,8 +50,8 @@
                 </button>
                 <%@ include file="/WEB-INF/jsp/fragment/button-reset.jsp" %>
                 <input type="hidden" id="processAction" name="processAction" value="<%=ForgottenPasswordServlet.ForgottenPasswordAction.enterCode%>"/>
-                <%@ include file="/WEB-INF/jsp/fragment/button-cancel.jsp" %>
                 <input type="hidden" id="pwmFormID" name="pwmFormID" value="<pwm:FormID/>"/>
+                <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
             </div>
         </form>
     </div>

+ 1 - 11
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-method.jsp

@@ -67,17 +67,7 @@
         </table>
         <br/>
         <div style="text-align:center;">
-            <% if (ContextManager.getPwmApplication(session).getConfig().readSettingAsBoolean(password.pwm.config.PwmSetting.DISPLAY_CANCEL_BUTTON)) { %>
-            <form action="<pwm:url url='ForgottenPassword'/>" method="post"
-                  enctype="application/x-www-form-urlencoded" name="search">
-                <button class="btn" type="submit" name="submitBtn">
-                    <pwm:if test="showIcons"><span class="btn-icon fa fa-times"></span></pwm:if>
-                    <pwm:display key="Button_Cancel"/>
-                </button>
-                <input type="hidden" name="processAction" value="<%=ForgottenPasswordServlet.ForgottenPasswordAction.reset%>"/>
-                <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
-            </form>
-            <% } %>
+            <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
         </div>
     </div>
     <div class="push"></div>

+ 2 - 27
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-responses.jsp

@@ -62,39 +62,14 @@ this is handled this way so on browsers where hiding fields is not possible, the
                     <pwm:display key="Button_RecoverPassword"/>
                 </button>
                 <%@ include file="/WEB-INF/jsp/fragment/button-reset.jsp" %>
-                <pwm:if test="showCancel">
-                    <button style="visibility:hidden;" type="button" name="button" class="btn" id="button_cancel" onclick="handleCancelClick()">
-                        <pwm:if test="showIcons"><span class="btn-icon fa fa-times"></span></pwm:if>
-                        <pwm:display key="Button_Cancel"/>
-                    </button>
-                </pwm:if>
+                <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
                 <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
             </div>
         </form>
     </div>
     <div class="push"></div>
 </div>
-<form name="responseResetForm" id="responseResetForm" action="<pwm:url url='ForgottenPassword'/>" method="post"
-      enctype="application/x-www-form-urlencoded">
-    <input type="hidden" name="processAction" value="reset"/>
-    <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
-</form>
-<pwm:script>
-<script type="text/javascript">
-    PWM_GLOBAL['startupFunctions'].push(function(){
-        PWM_RESPONSES.startupResponsesPage();
-    });
-
-    function handleCancelClick() {
-        PWM_MAIN.showWaitDialog({
-            loadFunction:function(){
-                PWM_MAIN.getObject('responseResetForm').submit();
-            }
-        });
-    }
-</script>
-</pwm:script>
-<script type="text/javascript" src="<pwm:context/><pwm:url url='/public/resources/js/responses.js'/>"></script>
+<script nonce="<pwm:value name="cspNonce"/>" type="text/javascript" src="<pwm:context/><pwm:url url='/public/resources/js/responses.js'/>"></script>
 <%@ include file="fragment/footer.jsp" %>
 </body>
 </html>

+ 1 - 1
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-search.jsp

@@ -46,7 +46,7 @@
                     <pwm:display key="Button_Search"/>
                 </button>
                 <%@ include file="/WEB-INF/jsp/fragment/button-reset.jsp" %>
-                <%@ include file="/WEB-INF/jsp/fragment/button-cancel.jsp" %>
+                <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
                 <input type="hidden" name="pwmFormID" value="<pwm:FormID/>"/>
             </div>
         </form>

+ 1 - 8
pwm/servlet/web/WEB-INF/jsp/forgottenpassword-tokenchoice.jsp

@@ -81,7 +81,7 @@
             </tr>
             <tr>
                 <td>
-                    <%@ include file="/WEB-INF/jsp/fragment/button-cancel.jsp" %>
+                    <%@ include file="/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp" %>
                 </td>
                 <td>
                     &nbsp;
@@ -96,13 +96,6 @@
     </div>
     <div class="push"></div>
 </div>
-<pwm:script>
-<script type="text/javascript">
-    PWM_GLOBAL['startupFunctions'].push(function(){
-        PWM_MAIN.getObject('username').focus();
-    });
-</script>
-</pwm:script>
 <%@ include file="fragment/footer.jsp" %>
 </body>
 </html>

+ 0 - 8
pwm/servlet/web/WEB-INF/jsp/forgottenusername-search.jsp

@@ -37,7 +37,6 @@
         <form action="<pwm:url url='ForgottenUsername'/>" method="post" enctype="application/x-www-form-urlencoded"
               name="searchForm" class="pwm-form" id="searchForm">
             <%@ include file="/WEB-INF/jsp/fragment/ldap-selector.jsp" %>
-            <% request.setAttribute("form",PwmSetting.FORGOTTEN_USERNAME_FORM); %>
             <jsp:include page="fragment/form.jsp"/>
             <div class="buttonbar">
                 <input type="hidden" name="processAction" value="search"/>
@@ -53,13 +52,6 @@
     </div>
     <div class="push"></div>
 </div>
-<pwm:script>
-<script type="text/javascript">
-    PWM_GLOBAL['startupFunctions'].push(function(){
-        document.forms.searchForm.elements[0].focus();
-    });
-</script>
-</pwm:script>
 <%@ include file="fragment/footer.jsp" %>
 </body>
 </html>

+ 38 - 0
pwm/servlet/web/WEB-INF/jsp/fragment/forgottenpassword-cancel.jsp

@@ -0,0 +1,38 @@
+<%@ page import="password.pwm.http.servlet.ForgottenPasswordServlet" %>
+<%@ page language="java" session="true" isThreadSafe="true" contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="pwm" prefix="pwm" %>
+<%--
+  ~ 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="showCancel">
+    <button type="button" name="button" class="btn" id="button-sendReset">
+        <pwm:if test="showIcons"><span class="btn-icon fa fa-times"></span></pwm:if>
+        <pwm:display key="Button_Cancel"/>
+    </button>
+    <pwm:script>
+        <script type="text/javascript">
+            PWM_GLOBAL['startupFunctions'].push(function(){
+                PWM_MAIN.submitPostAction('button-sendReset','ForgottenPassword','<%=ForgottenPasswordServlet.ForgottenPasswordAction.reset%>');
+            });
+        </script>
+    </pwm:script>
+</pwm:if>

+ 1 - 1
pwm/servlet/web/WEB-INF/jsp/login.jsp

@@ -120,7 +120,7 @@
 <pwm:script>
     <script type="text/javascript">
         PWM_GLOBAL['startupFunctions'].push(function(){
-            PWM_MAIN.addEventHandler('login','submit',function(){
+            PWM_MAIN.addEventHandler('login','submit',function(event){
                 PWM_MAIN.handleLoginFormSubmit(PWM_MAIN.getObject('login'),event);
             });
         });

+ 11 - 3
pwm/servlet/web/public/resources/configStyle.css

@@ -430,11 +430,19 @@ table {
 }
 
 .editorIdleStatus {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+    font-size: 10px;
+    font-family: "Courier New", Courier, monospace;
+    /*
+    display: table;
+    margin: 0 auto;
+    top: 0;
+    position: absolute;
     margin-left: 40%;
     margin-right: 40%;
-    position: absolute;
-    top: 0;
     text-align: center;
-    font-size: 10px;
     width:20%;
+    */
 }

+ 0 - 1
pwm/servlet/web/public/resources/js/changepassword.js

@@ -64,7 +64,6 @@ PWM_CHANGEPW.validatePasswords = function(userDN)
         }
     };
 
-    debugger;
     PWM_MAIN.pwmFormValidator(validationProps);
 };
 

+ 193 - 258
pwm/servlet/web/public/resources/js/configeditor-settings.js

@@ -527,9 +527,9 @@ MultiLocaleTableHandler.draw = function(keyName) {
             }
         }
 
-        var addLocaleFunction = function() {
+        var addLocaleFunction = function(value) {
             require(["dijit/registry"],function(registry){
-                MultiLocaleTableHandler.writeMultiLocaleSetting(keyName, registry.byId(keyName + "-addLocaleValue").value, 0, '', regExPattern);
+                MultiLocaleTableHandler.writeMultiLocaleSetting(keyName, value, 0, '', regExPattern);
             });
         };
 
@@ -623,7 +623,7 @@ FormTableHandler.drawRow = function(parentDiv, settingKey, iteration, value) {
             optionList = JSON.parse(options['types']);
         }
         if (!PWM_MAIN.isEmpty(optionList)) {
-        htmlRow += '<select id="' + inputID + 'type">';
+            htmlRow += '<select id="' + inputID + 'type">';
             for (var optionItem in optionList) {
                 if (optionList[optionItem] != 'userDN' || userDNtypeAllowed) {
                     var optionName = optionList[optionItem];
@@ -651,11 +651,9 @@ FormTableHandler.drawRow = function(parentDiv, settingKey, iteration, value) {
             htmlRow += '<span id="' + inputID + '-moveUp" class="action-icon fa fa-chevron-up"></span>';
         }
         htmlRow += '</td>';
-
-        htmlRow += '<td><span class="delete-row-icon action-icon fa fa-times" id="' + inputID + 'deleteRowButton"></span></td>';
+        htmlRow += '<td><span class="delete-row-icon action-icon fa fa-times" id="' + inputID + '-deleteRowButton"></span></td>';
 
         newTableRow.innerHTML = htmlRow;
-
         var parentDivElement = PWM_MAIN.getObject(parentDiv);
         parentDivElement.appendChild(newTableRow);
 
@@ -665,7 +663,7 @@ FormTableHandler.drawRow = function(parentDiv, settingKey, iteration, value) {
         PWM_MAIN.addEventHandler(inputID + "-moveDown", 'click', function () {
             FormTableHandler.move(settingKey, false, iteration);
         });
-        PWM_MAIN.addEventHandler(inputID + "deleteRowButton", 'click', function () {
+        PWM_MAIN.addEventHandler(inputID + "-deleteRowButton", 'click', function () {
             FormTableHandler.removeRow(settingKey, iteration);
         });
         PWM_MAIN.addEventHandler(inputID + "label", 'click, keypress', function () {
@@ -1000,7 +998,7 @@ FormTableHandler.multiLocaleStringDialog = function(keyName, iteration, settingT
                             PWM_VAR['clientSettingCache'][keyName][iteration][settingType][localeName] = value;
                             FormTableHandler.writeFormSetting(keyName);
                         });
-                        PWM_MAIN.addEventHandler(localeID + 'removeLocaleButton', 'click', function () {
+                        PWM_MAIN.addEventHandler(localeID + '-removeLocaleButton', 'click', function () {
                             delete PWM_VAR['clientSettingCache'][keyName][iteration]['labels'][localeName];
                             FormTableHandler.writeFormSetting(keyName);
                             FormTableHandler.multiLocaleStringDialog(keyName, iteration, settingType, finishAction, titleText);
@@ -1337,6 +1335,23 @@ ChangePasswordHandler.changePasswordPopup = function(settingKey) {
 // -------------------------- action handler ------------------------------------
 
 var ActionHandler = {};
+ActionHandler.defaultValue = {
+    name:"",
+    description:"",
+    type:"webservice",
+    method:"get",
+    url:"",
+    body:"",
+    headers:{},
+    attributeName:"",
+    attributeValue:""
+};
+ActionHandler.httpMethodOptions = [
+    { label: "Delete", value: "delete" },
+    { label: "Get", value: "get" },
+    { label: "Post", value: "post" },
+    { label: "Put", value: "put" }
+];
 
 ActionHandler.init = function(keyName) {
     console.log('ActionHandler init for ' + keyName);
@@ -1385,8 +1400,8 @@ ActionHandler.redraw = function(keyName) {
 
     var addItemButton = document.createElement("button");
     addItemButton.setAttribute("type", "button");
-    addItemButton.setAttribute("onclick", "ActionHandler.addMultiSetting('" + keyName + "','" + parentDiv + "');");
     addItemButton.setAttribute("class", "btn");
+    addItemButton.setAttribute("id", "button-" + keyName + "-addValue");
     addItemButton.innerHTML = '<span class="btn-icon fa fa-plus-square"></span>Add Value';
     newTableData.appendChild(addItemButton);
 
@@ -1396,93 +1411,58 @@ ActionHandler.redraw = function(keyName) {
     require(["dojo/parser","dijit/form/Button","dijit/form/Select","dijit/form/Textarea"],function(dojoParser){
         dojoParser.parse(parentDiv);
     });
+
+    PWM_MAIN.addEventHandler('button-' + keyName + '-addValue','click',function(){
+        ActionHandler.addRow(keyName);
+    });
 };
 
 ActionHandler.drawRow = function(parentDiv, settingKey, iteration, value) {
     var inputID = 'value_' + settingKey + '_' + iteration + "_";
-
-    // clear the old dijit node (if it exists)
-    PWM_MAIN.clearDijitWidget(inputID + "name");
-    PWM_MAIN.clearDijitWidget(inputID + "description");
-    PWM_MAIN.clearDijitWidget(inputID + "type");
-    PWM_MAIN.clearDijitWidget(inputID + "optionsButton");
+    var optionList = PWM_GLOBAL['actionTypeOptions'];
 
     var newTableRow = document.createElement("tr");
     newTableRow.setAttribute("style", "border-width: 0");
-    {
-        {
-            var td1 = document.createElement("td");
-            td1.setAttribute("style", "border-width: 0; width:50px");
-            var nameInput = document.createElement("input");
-            nameInput.setAttribute("id", inputID + "name");
-            nameInput.setAttribute("value", value['name']);
-            nameInput.setAttribute("onchange","PWM_VAR['clientSettingCache']['" + settingKey + "'][" + iteration + "]['name'] = this.value;ActionHandler.writeFormSetting('" + settingKey + "')");
-            nameInput.setAttribute("data-dojo-type", "dijit.form.ValidationTextBox");
-            nameInput.setAttribute("data-dojo-props", "required: true");
-
-            td1.appendChild(nameInput);
-            newTableRow.appendChild(td1);
-        }
-
-        {
-            var td2 = document.createElement("td");
-            td2.setAttribute("style", "border-width: 0");
-            var descriptionInput = document.createElement("input");
-            descriptionInput.setAttribute("id", inputID + "description");
-            descriptionInput.setAttribute("value", value['description']);
-            descriptionInput.setAttribute("onchange","PWM_VAR['clientSettingCache']['" + settingKey + "'][" + iteration + "]['description'] = this.value;ActionHandler.writeFormSetting('" + settingKey + "')");
-            descriptionInput.setAttribute("data-dojo-type", "dijit.form.ValidationTextBox");
-            td2.appendChild(descriptionInput);
-            newTableRow.appendChild(td2);
-        }
 
-        {
-            var td3 = document.createElement("td");
-            td3.setAttribute("style", "border-width: 0");
-            var optionList = PWM_GLOBAL['actionTypeOptions'];
-            var typeSelect = document.createElement("select");
-            typeSelect.setAttribute("data-dojo-type", "dijit.form.Select");
-            typeSelect.setAttribute("id", inputID + "type");
-            typeSelect.setAttribute("style","width: 90px");
-            typeSelect.setAttribute("onchange","PWM_VAR['clientSettingCache']['" + settingKey + "'][" + iteration + "]['type'] = this.value;ActionHandler.writeFormSetting('" + settingKey + "')");
-            for (var optionItem in optionList) {
-                var optionElement = document.createElement("option");
-                optionElement.value = optionList[optionItem];
-                optionElement.innerHTML = optionList[optionItem];
-                if (optionList[optionItem] == PWM_VAR['clientSettingCache'][settingKey][iteration]['type']) {
-                    optionElement.setAttribute("selected","true");
-                }
-                typeSelect.appendChild(optionElement);
-            }
-
-            td3.appendChild(typeSelect);
-            newTableRow.appendChild(td3);
-        }
-
-        {
-            var td4 = document.createElement("td");
-            td4.setAttribute("style", "border-width: 0");
-            var labelButton = document.createElement("button");
-            labelButton.setAttribute("id", inputID + "optionsButton");
-            labelButton.setAttribute("data-dojo-type", "dijit.form.Button");
-            labelButton.setAttribute("onclick","ActionHandler.showOptionsDialog('" + settingKey + "'," + iteration + ")");
-            labelButton.innerHTML = "Options";
-            td4.appendChild(labelButton);
-            newTableRow.appendChild(td4);
-        }
+    var htmlRow = '';
+    htmlRow += '<td>';
+    htmlRow += '<input id="input-' + inputID + '-name" class="configStringInput" style="width:180px" value="' + value['name'] + '"/>';
+    htmlRow += '</td><td>';
+    htmlRow += '<input id="input-' + inputID + '-description" class="configStringInput" style="width:180px" value="' + value['description'] + '"/>';
+    htmlRow += '</td><td>';
+    htmlRow += '<select id="select-' + inputID + '-type">';
+    for (var optionItem in optionList) {
+        var selected = optionList[optionItem] == PWM_VAR['clientSettingCache'][settingKey][iteration]['type'];
+        htmlRow += '<option value="' + optionList[optionItem] + '"' + (selected ? ' selected' : '') + '>' + optionList[optionItem] + '</option>';
+    }
+    htmlRow += '</td><td>';
+    htmlRow += '<button id="button-' + inputID + '-options"><span class="btn-icon fa fa-sliders"/> Options</button>';
+    htmlRow += '</td>';
+    htmlRow += '<td><span class="delete-row-icon action-icon fa fa-times" id="button-' + inputID + '-deleteRow"></span></td>';
 
-        var tdFinal = document.createElement("td");
-        tdFinal.setAttribute("style", "border-width: 0");
 
-        var imgElement = document.createElement("img");
-        imgElement.setAttribute("style", "width: 10px; height: 10px");
-        imgElement.setAttribute("src", PWM_GLOBAL['url-resources'] + "/redX.png");
-        imgElement.setAttribute("onclick", "ActionHandler.removeMultiSetting('" + settingKey + "','" + iteration + "')");
-        tdFinal.appendChild(imgElement);
-        newTableRow.appendChild(tdFinal);
-    }
+    newTableRow.innerHTML = htmlRow;
     var parentDivElement = PWM_MAIN.getObject(parentDiv);
     parentDivElement.appendChild(newTableRow);
+
+    PWM_MAIN.addEventHandler('button-' + inputID + '-options','click',function(){
+        ActionHandler.showOptionsDialog(settingKey, iteration);
+    });
+    PWM_MAIN.addEventHandler('input-' + inputID + '-name','input',function(){
+        PWM_VAR['clientSettingCache'][settingKey][iteration]['name'] = PWM_MAIN.getObject('input-' + inputID + '-name').value;
+        ActionHandler.writeFormSetting(settingKey);
+    });
+    PWM_MAIN.addEventHandler('input-' + inputID + '-description','input',function(){
+        PWM_VAR['clientSettingCache'][settingKey][iteration]['description'] = PWM_MAIN.getObject('input-' + inputID + '-description').value;
+        ActionHandler.writeFormSetting(settingKey);
+    });
+    PWM_MAIN.addEventHandler('select-' + inputID + '-type','input',function(){
+        PWM_VAR['clientSettingCache'][settingKey][iteration]['type'] = PWM_MAIN.getObject('select-' + inputID + '-type').value;
+        ActionHandler.writeFormSetting(settingKey);
+    });
+    PWM_MAIN.addEventHandler('button-' + inputID + '-deleteRow','click',function(){
+        ActionHandler.removeRow(settingKey, iteration);
+    });
 };
 
 ActionHandler.writeFormSetting = function(settingKey) {
@@ -1491,126 +1471,105 @@ ActionHandler.writeFormSetting = function(settingKey) {
 };
 
 ActionHandler.removeRow = function(keyName, iteration) {
-    delete PWM_VAR['clientSettingCache'][keyName][iteration];
-    console.log("removed iteration " + iteration + " from " + keyName + ", cached keyValue=" + PWM_VAR['clientSettingCache'][keyName]);
-    ActionHandler.writeFormSetting(keyName);
-    ActionHandler.redraw(keyName);
+    PWM_MAIN.showConfirmDialog({
+        text:'Are you sure you wish to delete this item?',
+        okAction:function(){
+            delete PWM_VAR['clientSettingCache'][keyName][iteration];
+            console.log("removed iteration " + iteration + " from " + keyName + ", cached keyValue=" + PWM_VAR['clientSettingCache'][keyName]);
+            ActionHandler.writeFormSetting(keyName);
+            ActionHandler.redraw(keyName);
+        }
+    })
 };
 
 ActionHandler.addRow = function(keyName) {
-    var currentSize = 0;
-    for (var loopVar in PWM_VAR['clientSettingCache'][keyName]) {
-        currentSize++;
-    }
-    PWM_VAR['clientSettingCache'][keyName][currentSize + 1] = {};
-    PWM_VAR['clientSettingCache'][keyName][currentSize + 1]['name'] = '';
-    PWM_VAR['clientSettingCache'][keyName][currentSize + 1]['description'] = '';
-    PWM_VAR['clientSettingCache'][keyName][currentSize + 1]['type'] = 'webservice';
-    PWM_VAR['clientSettingCache'][keyName][currentSize + 1]['method'] = 'get';
-    ActionHandler.writeFormSetting(keyName);
-    ActionHandler.redraw(keyName)
+    var body='Name <input class="configStringInput" id="newActionName" style="width:300px"/>';
+    PWM_MAIN.showConfirmDialog({title:'New Action',text:body,showClose:true,loadFunction:function(){
+        PWM_MAIN.getObject('dialog_ok_button').disabled = true;
+        PWM_MAIN.addEventHandler('newActionName','input',function(){
+            PWM_VAR['newActionName'] = PWM_MAIN.getObject('newActionName').value;
+            if (PWM_VAR['newActionName'] && PWM_VAR['newActionName'].length > 1) {
+                PWM_MAIN.getObject('dialog_ok_button').disabled = false;
+            }
+        });
+    },okAction:function(){
+        var currentSize = PWM_MAIN.itemCount(PWM_VAR['clientSettingCache'][keyName]);
+        PWM_VAR['clientSettingCache'][keyName][currentSize + 1] = ActionHandler.defaultValue;
+        PWM_VAR['clientSettingCache'][keyName][currentSize + 1].name = PWM_VAR['newActionName'];
+        ActionHandler.writeFormSetting(keyName);
+        ActionHandler.redraw(keyName)
+    }});
 };
 
+
 ActionHandler.showOptionsDialog = function(keyName, iteration) {
     require(["dojo/store/Memory","dijit/Dialog","dijit/form/Textarea","dijit/form/CheckBox","dijit/form/Select","dijit/form/ValidationTextBox"],function(Memory){
         var inputID = 'value_' + keyName + '_' + iteration + "_";
-        var bodyText = '<table style="border:0">';
+        var value = PWM_VAR['clientSettingCache'][keyName][iteration];
+        var titleText = 'title';
+        var bodyText = '<table class="noborder">';
         if (PWM_VAR['clientSettingCache'][keyName][iteration]['type'] == 'webservice') {
+            titleText = 'Web Service options for ' + PWM_VAR['clientSettingCache'][keyName][iteration]['name'];
             bodyText += '<tr>';
-            bodyText += '<td style="border:0; text-align: center" colspan="2">Web Service</td>';
-            bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">&nbsp;</td>';
-            bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">Method</td><td style="border:0;"><select id="' + inputID + 'method' + '"/></td>';
+            bodyText += '<td class="key">HTTP Method</td><td style="border:0;"><select id="select-' + inputID + '-method' + '">';
+
+            for (var optionItem in ActionHandler.httpMethodOptions) {
+                var label = ActionHandler.httpMethodOptions[optionItem]['label']
+                var optionValue = ActionHandler.httpMethodOptions[optionItem]['value'];
+                var selected = optionValue == PWM_VAR['clientSettingCache'][keyName][iteration]['method'];
+                bodyText += '<option value="' + optionValue + '"' + (selected ? ' selected' : '') + '>' + label + '</option>';
+            }
+            bodyText += '</td>';
             bodyText += '</tr><tr>';
-            //bodyText += '<td style="border:0; text-align: right">Client Side</td><td style="border:0;"><input type="checkbox" id="' + inputID + 'clientSide' + '"/></td>';
-            //bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">Headers</td><td style="border:0;"><button class="menubutton" onclick="ActionHandler.showHeadersDialog(\'' + keyName + '\',\'' + iteration + '\')">Edit</button></td>';
+            bodyText += '<td class="key">HTTP Headers</td><td><button id="button-' + inputID + '-headers"><span class="btn-icon fa fa-list-ul"/> Edit</button></td>';
             bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">URL</td><td style="border:0;"><input type="text" id="' + inputID + 'url' + '"/></td>';
+            bodyText += '<td class="key">URL</td><td><input type="text" placeholder="http://www.example.com/service"  id="input-' + inputID + '-url' + '" value="' + value['url'] + '"/></td>';
             bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">Body</td><td style="border:0;"><input type="text" id="' + inputID + 'body' + '"/></td>';
+            bodyText += '<td class="key">Body</td><td><textarea style="max-width:300px; height:100px; max-height:100px" class="configStringInput" id="input-' + inputID + '-body' + '"/>' + value['body'] + '</textarea></td>';
             bodyText += '</tr>';
         } else if (PWM_VAR['clientSettingCache'][keyName][iteration]['type'] == 'ldap') {
+            titleText = 'LDAP options for ' + PWM_VAR['clientSettingCache'][keyName][iteration]['name'];
             bodyText += '<tr>';
-            bodyText += '<td style="border:0; text-align: center" colspan="2">LDAP Value Write</td>';
+            bodyText += '<td class="key">Attribute Name</td><td><input style="width:300px" class="configStringInput" type="text" id="input-' + inputID + '-attributeName' + '" value="' + value['attributeName'] + '"/></td>';
             bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">&nbsp;</td>';
-            bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">Attribute Name</td><td style="border:0;"><input type="text" id="' + inputID + 'attributeName' + '"/></td>';
-            bodyText += '</tr><tr>';
-            bodyText += '<td style="border:0; text-align: right">Attribute Value</td><td style="border:0;"><input type="text" id="' + inputID + 'attributeValue' + '"/></td>';
+            bodyText += '<td class="key">Attribute Value</td><td><input style="width:300px" class="configStringInput" type="text" id="input-' + inputID + '-attributeValue' + '" value="' + value['attributeValue'] + '"/></td>';
             bodyText += '</tr>';
         }
-        bodyText += '<tr>';
-        bodyText += '<td style="border:0; text-align: right">&nbsp;</td>';
-        bodyText += '</tr><tr>';
-        bodyText += '</tr>';
         bodyText += '</table>';
-        bodyText += '<br/>';
-        bodyText += '<button class="btn" onclick="PWM_MAIN.clearDijitWidget(\'dialogPopup\');ActionHandler.redraw(\'' + keyName + '\')">OK</button>';
-
-        PWM_MAIN.clearDijitWidget('dialogPopup');
-        var theDialog = new dijit.Dialog({
-            id: 'dialogPopup',
-            title: 'Options for ' + PWM_VAR['clientSettingCache'][keyName][iteration]['name'],
-            style: "width: 650px",
-            content: bodyText,
-            hide: function(){
-                PWM_MAIN.clearDijitWidget('dialogPopup');
-                ActionHandler.redraw(keyName);
-            }
-        });
-        theDialog.show();
 
-        if (PWM_VAR['clientSettingCache'][keyName][iteration]['type'] == 'webservice') {
-            PWM_MAIN.clearDijitWidget(inputID + "method");
-            new dijit.form.Select({
-                value: PWM_VAR['clientSettingCache'][keyName][iteration]['method'],
-                options: [
-                    { label: "Delete", value: "delete" },
-                    { label: "Get", value: "get" },
-                    { label: "Post", value: "post" },
-                    { label: "Put", value: "put" }
-                ],
-                style: "width: 80px",
-                onChange: function(){PWM_VAR['clientSettingCache'][keyName][iteration]['method'] = this.value;ActionHandler.writeFormSetting(keyName)}
-            },inputID + "method");
-
-            //PWM_MAIN.clearDijitWidget(inputID + "clientSide");
-            //new dijit.form.CheckBox({
-            //    checked: PWM_VAR['clientSettingCache'][keyName][iteration]['clientSide'],
-            //    onChange: function(){PWM_VAR['clientSettingCache'][keyName][iteration]['clientSide'] = this.checked;ActionHandler.writeFormSetting(keyName)}
-            //},inputID + "clientSide");
-
-            PWM_MAIN.clearDijitWidget(inputID + "url");
-            new dijit.form.Textarea({
-                value: PWM_VAR['clientSettingCache'][keyName][iteration]['url'],
-                required: true,
-                onChange: function(){PWM_VAR['clientSettingCache'][keyName][iteration]['url'] = this.value;ActionHandler.writeFormSetting(keyName)}
-            },inputID + "url");
-
-            PWM_MAIN.clearDijitWidget(inputID + "body");
-            new dijit.form.Textarea({
-                value: PWM_VAR['clientSettingCache'][keyName][iteration]['body'],
-                onChange: function(){PWM_VAR['clientSettingCache'][keyName][iteration]['body'] = this.value;ActionHandler.writeFormSetting(keyName)}
-            },inputID + "body");
 
-        } else if (PWM_VAR['clientSettingCache'][keyName][iteration]['type'] == 'ldap') {
-            PWM_MAIN.clearDijitWidget(inputID + "attributeName");
-            new dijit.form.ValidationTextBox({
-                value: PWM_VAR['clientSettingCache'][keyName][iteration]['attributeName'],
-                required: true,
-                onChange: function(){PWM_VAR['clientSettingCache'][keyName][iteration]['attributeName'] = this.value;ActionHandler.writeFormSetting(keyName)}
-            },inputID + "attributeName");
-
-            PWM_MAIN.clearDijitWidget(inputID + "attributeValue");
-            new dijit.form.Textarea({
-                value: PWM_VAR['clientSettingCache'][keyName][iteration]['attributeValue'],
-                required: true,
-                onChange: function(){PWM_VAR['clientSettingCache'][keyName][iteration]['attributeValue'] = this.value;ActionHandler.writeFormSetting(keyName)}
-            },inputID + "attributeValue");
-        }
+        PWM_MAIN.showDialog({
+            title: titleText,
+            text: bodyText,
+            loadFunction: function(){
+                PWM_MAIN.addEventHandler('button-' + inputID + '-headers','click',function(){
+                    ActionHandler.showHeadersDialog(keyName,iteration);
+                });
+                if (PWM_VAR['clientSettingCache'][keyName][iteration]['type'] == 'webservice') {
+                    PWM_MAIN.addEventHandler('select-' + inputID + '-method','input',function(){
+                        PWM_VAR['clientSettingCache'][keyName][iteration]['method'] = PWM_MAIN.getObject('select-' + inputID + '-method').value;
+                        ActionHandler.writeFormSetting(keyName);
+                    });
+                    PWM_MAIN.addEventHandler('input-' + inputID + '-url','input',function(){
+                        PWM_VAR['clientSettingCache'][keyName][iteration]['url'] = PWM_MAIN.getObject('input-' + inputID + '-url').value;
+                        ActionHandler.writeFormSetting(keyName);
+                    });
+                    PWM_MAIN.addEventHandler('input-' + inputID + '-body','input',function(){
+                        PWM_VAR['clientSettingCache'][keyName][iteration]['body'] = PWM_MAIN.getObject('input-' + inputID + '-body').value;
+                        ActionHandler.writeFormSetting(keyName);
+                    });
+                } else if (PWM_VAR['clientSettingCache'][keyName][iteration]['type'] == 'ldap') {
+                    PWM_MAIN.addEventHandler('input-' + inputID + '-attributeName','input',function(){
+                        PWM_VAR['clientSettingCache'][keyName][iteration]['attributeName'] = PWM_MAIN.getObject('input-' + inputID + '-attributeName').value;
+                        ActionHandler.writeFormSetting(keyName);
+                    });
+                    PWM_MAIN.addEventHandler('input-' + inputID + '-attributeValue','input',function(){
+                        PWM_VAR['clientSettingCache'][keyName][iteration]['attributeValue'] = PWM_MAIN.getObject('input-' + inputID + '-attributeValue').value;
+                        ActionHandler.writeFormSetting(keyName);
+                    });
+                }
+            }
+        });
     });
 };
 
@@ -1619,104 +1578,80 @@ ActionHandler.showHeadersDialog = function(keyName, iteration) {
         var inputID = 'value_' + keyName + '_' + iteration + "_" + "headers_";
 
         var bodyText = '';
-        bodyText += '<table style="border:0" id="' + inputID + 'table">';
+        bodyText += '<table class="noborder">';
         bodyText += '<tr>';
-        bodyText += '<td style="border:0"><b>Name</b></td><td style="border:0"><b>Value</b></td>';
+        bodyText += '<td><b>Name</b></td><td><b>Value</b></td>';
         bodyText += '</tr><tr>';
         for (var headerName in PWM_VAR['clientSettingCache'][keyName][iteration]['headers']) {
             var value = PWM_VAR['clientSettingCache'][keyName][iteration]['headers'][headerName];
             var optionID = inputID + headerName;
-            bodyText += '<td style="border:1px">' + headerName + '</td><td style="border:1px">' + value + '</td>';
-            bodyText += '<td style="border:0">';
-            bodyText += '<img id="' + optionID + '-removeButton' + '" alt="crossMark" height="15" width="15" src="' + PWM_GLOBAL['url-resources'] + '/redX.png"';
-            bodyText += ' onclick="ActionHandler.removeHeader(\'' + keyName + '\',' + iteration + ',\'' + headerName + '\')" />';
-            bodyText += '</td>';
+            bodyText += '<td>' + headerName + '</td><td>' + value + '</td>';
+            bodyText += '<td><span class="delete-row-icon action-icon fa fa-times" id="button-' + optionID + '-deleteRow"></span></td>';
             bodyText += '</tr><tr>';
         }
         bodyText += '</tr></table>';
         bodyText += '<br/>';
-        bodyText += '<br/>';
-        bodyText += '<input type="text" id="addHeaderName"/>';
-        bodyText += '<input type="text" id="addHeaderValue"/>';
-        bodyText += '<input type="button" id="addHeaderButton" value="Add"/>';
-        bodyText += '<br/>';
-        bodyText += '<button class="btn" onclick="ActionHandler.showOptionsDialog(\'' + keyName + '\',\'' + iteration + '\')">OK</button>';
+        bodyText += '<button id="button-' + inputID + '-addHeader" class="btn"><span class="btn-icon fa fa-plus-square"></span>Add Header</button>';
 
-        PWM_MAIN.clearDijitWidget('dialogPopup');
-        var theDialog = new dijit.Dialog({
-            id: 'dialogPopup',
+        PWM_MAIN.showDialog({
             title: 'Http Headers for webservice ' + PWM_VAR['clientSettingCache'][keyName][iteration]['name'],
-            style: "width: 450px",
-            content: bodyText,
-            hide: function(){
-                PWM_MAIN.clearDijitWidget('dialogPopup');
+            text: bodyText,
+            okAction: function() {
                 ActionHandler.showOptionsDialog(keyName,iteration);
-            }
-        });
-        theDialog.show();
-
-        for (var headerName in PWM_VAR['clientSettingCache'][keyName][iteration]['headers']) {
-            var value = PWM_VAR['clientSettingCache'][keyName][iteration]['headers'][headerName];
-            var loopID = inputID + headerName;
-            PWM_MAIN.clearDijitWidget(loopID);
-            new TextBox({
-                onChange: function(){PWM_VAR['clientSettingCache'][keyName][iteration]['headers'][headerName] = this.value;ActionHandler.writeFormSetting(keyName)}
-            },loopID);
-        }
-
-        PWM_MAIN.clearDijitWidget("addHeaderName");
-        new ValidationTextBox({
-            placeholder: "Name",
-            id: "addHeaderName",
-            constraints: {min: 1}
-        },"addHeaderName");
-
-        PWM_MAIN.clearDijitWidget("addHeaderValue");
-        new ValidationTextBox({
-            placeholder: "Display Value",
-            id: "addHeaderValue",
-            constraints: {min: 1}
-        },"addHeaderValue");
-
-        PWM_MAIN.clearDijitWidget("addHeaderButton");
-        new Button({
-            label: "Add",
-            onClick: function() {
-                require(["dijit/registry"],function(registry){
-                    var name = registry.byId('addHeaderName').value;
-                    var value = registry.byId('addHeaderValue').value;
-                    ActionHandler.addHeader(keyName, iteration, name, value);
+            },
+            loadFunction: function() {
+                for (var headerName in PWM_VAR['clientSettingCache'][keyName][iteration]['headers']) {
+                    var headerID = inputID + headerName;
+                    PWM_MAIN.addEventHandler('button-' + headerID + '-deleteRow','click',function(){
+                        delete PWM_VAR['clientSettingCache'][keyName][iteration]['headers'][headerName];
+                        ActionHandler.writeFormSetting(keyName);
+                        ActionHandler.showHeadersDialog(keyName, iteration);
+                    });
+                }
+                PWM_MAIN.addEventHandler('button-' + inputID + '-addHeader','click',function(){
+                    ActionHandler.addHeader(keyName, iteration);
                 });
             }
-        },"addHeaderButton");
+        });
     });
 };
 
-ActionHandler.addHeader = function(keyName, iteration, headerName, headerValue) {
-    if (headerName == null || headerName.length < 1) {
-        alert('Name field is required');
-        return;
-    }
+ActionHandler.addHeader = function(keyName, iteration) {
+    var body = '<table class="noborder">';
+    body += '<tr><td>Name</td><td><input class="configStringInput" id="newHeaderName" style="width:300px"/></td></tr>';
+    body += '<tr><td>Value</td><td><input class="configStringInput" id="newHeaderValue" style="width:300px"/></td></tr>';
+    body += '</table>';
 
-    if (headerValue == null || headerValue.length < 1) {
-        alert('Value field is required');
-        return;
-    }
+    var updateFunction = function(){
+        PWM_MAIN.getObject('dialog_ok_button').disabled = true;
+        PWM_VAR['newHeaderName'] = PWM_MAIN.getObject('newHeaderName').value;
+        PWM_VAR['newHeaderValue'] = PWM_MAIN.getObject('newHeaderValue').value;
+        if (PWM_VAR['newHeaderName'].length > 1 && PWM_VAR['newHeaderValue'].length > 1) {
+            PWM_MAIN.getObject('dialog_ok_button').disabled = false;
+        }
+    };
 
-    if (!PWM_VAR['clientSettingCache'][keyName][iteration]['headers']) {
-        PWM_VAR['clientSettingCache'][keyName][iteration]['headers'] = {};
-    }
+    PWM_MAIN.showConfirmDialog({
+        title:'New Header',
+        text:body,
+        showClose:true,
+        loadFunction:function(){
+            PWM_MAIN.addEventHandler('newHeaderName','input',function(){
+                updateFunction();
+            });
+            PWM_MAIN.addEventHandler('newHeaderValue','input',function(){
+                updateFunction();
+            });
+        },okAction:function(){
+            var headers = PWM_VAR['clientSettingCache'][keyName][iteration]['headers'];
+            headers[PWM_VAR['newHeaderName']] = PWM_VAR['newHeaderValue'];
+            ActionHandler.writeFormSetting(keyName);
+            ActionHandler.showHeadersDialog(keyName, iteration);
+        }
+    });
 
-    PWM_VAR['clientSettingCache'][keyName][iteration]['headers'][headerName] = headerValue;
-    ActionHandler.writeFormSetting(keyName);
-    ActionHandler.showHeadersDialog(keyName, iteration);
 };
 
-ActionHandler.removeHeader = function(keyName, iteration, headerName) {
-    delete PWM_VAR['clientSettingCache'][keyName][iteration]['headers'][headerName];
-    ActionHandler.writeFormSetting(keyName);
-    ActionHandler.showHeadersDialog(keyName, iteration);
-};
 
 // -------------------------- email table handler ------------------------------------
 

+ 24 - 11
pwm/servlet/web/public/resources/js/main.js

@@ -121,7 +121,7 @@ PWM_MAIN.loadLocaleBundle = function(bundleName, completeFunction) {
 
 PWM_MAIN.initPage = function() {
     PWM_MAIN.applyFormAttributes();
-    
+
     try {
         PWM_MAIN.autofocusSupportExtension();
     } catch(e) {
@@ -147,7 +147,9 @@ PWM_MAIN.initPage = function() {
     if (PWM_MAIN.getObject('button_cancel')) {
         PWM_MAIN.getObject('button_cancel').style.visibility = 'visible';
         PWM_MAIN.addEventHandler('button_cancel', 'click', function () {
-            PWM_MAIN.handleFormCancel()
+            PWM_MAIN.showWaitDialog({loadFunction:function() {
+                PWM_MAIN.goto(PWM_GLOBAL['url-command'] + '?processAction=continue');
+            }});
         });
     }
 
@@ -156,6 +158,7 @@ PWM_MAIN.initPage = function() {
             PWM_MAIN.updateLoginContexts()
         });
     }
+
     PWM_MAIN.showTooltip({
         id: ['header-warning-message'],
         position: ['below', 'above'],
@@ -163,6 +166,10 @@ PWM_MAIN.initPage = function() {
         width: 500
     });
 
+    PWM_MAIN.addEventHandler('icon-configModeHelp','click',function(){
+        PWM_MAIN.showDialog({title:'Notice - Configuration Status: Open',text:PWM_CONFIG.showString('Display_ConfigOpenInfo')});
+    });
+
     if (PWM_GLOBAL['pageLeaveNotice'] > 0) {
         require(["dojo","dojo/on"], function(dojo,on){
             on(document, "beforeunload", function(){
@@ -373,13 +380,6 @@ PWM_MAIN.goto = function(url,options) {
 };
 
 
-PWM_MAIN.handleFormCancel = function() {
-    PWM_MAIN.showWaitDialog({loadFunction:function() {
-        var continueUrl = PWM_GLOBAL['url-command'] + '?processAction=continue&pwmFormID=' + PWM_GLOBAL['pwmFormID'];
-        window.location = continueUrl;
-    }});
-};
-
 PWM_MAIN.handleLoginFormSubmit = function(form, event) {
     console.log('entering handleLoginFormSubmit');
     PWM_MAIN.cancelEvent(event);
@@ -777,7 +777,7 @@ PWM_MAIN.showDialog = function(options) {
     var bodyText = '';
     bodyText += text;
     if (showOk || showCancel) {
-        bodyText += '<br/><div class="buttonbar">';
+        bodyText += '<div class="buttonbar">';
     }
     if (showOk) {
         bodyText += '<button class="btn" id="dialog_ok_button">'
@@ -1265,7 +1265,6 @@ PWM_MAIN.updateLoginContexts = function() {
             PWM_MAIN.getObject('contextSelectorWrapper').style.display = 'none';
         } else {
             PWM_MAIN.getObject('contextSelectorWrapper').style.display = 'inherit';
-            contextElement.options.length = 0;
             for (var key in contextList) {
                 (function (key) {
                     var display = contextList[key];
@@ -1845,5 +1844,19 @@ PWM_MAIN.cancelEvent = function(event) {
     }
 };
 
+PWM_MAIN.submitPostAction = function(buttonID,actionUrl,actionValue) {
+    PWM_MAIN.addEventHandler(buttonID,'click',function(){
+        var formElement = document.createElement('form');
+        formElement.setAttribute('id','form-sendReset');
+        formElement.setAttribute('action',actionUrl);
+        formElement.setAttribute('method','post');
+        formElement.innerHTML = '<input type="hidden" name="processAction" value="' + actionValue + '"> </input>'
+        + '<input type="hidden" name="pwmFormID" value="' + PWM_GLOBAL['pwmFormID'] + '"> </input>';
+
+        document.body.appendChild(formElement);
+        PWM_MAIN.handleFormSubmit(formElement);
+    });
+};
+
 PWM_MAIN.pageLoadHandler();
 

+ 1 - 1
pwm/servlet/web/public/resources/js/responses.js

@@ -182,4 +182,4 @@ PWM_RESPONSES.initSimpleRandomElements = function() {
             })(i);
         }
     });
-};
+};

+ 1 - 0
pwm/servlet/web/public/resources/style.css

@@ -637,6 +637,7 @@ img.qrcodeimage {
 
 .btn-icon {
     margin-right: 5px;
+    cursor: pointer;
 }
 
 .action-icon {