anchor.diff:      String subdomain = ParamUtils.getParameter( request, "subdomain" ); // shared with blacklist.
       if ( subdomain != null )
       {
  -        // Remove the hostname if the user is not sending just the subdomain.
  -        subdomain = subdomain.replace( "." + XMPPServer.getInstance().getServerInfo().getXMPPDomain(), "" );
  +        subdomain = subdomain.trim();
  +        try {
  +            subdomain = JID.domainprep(subdomain);
  +            // Remove the hostname if the user is not sending just the subdomain.
  +            subdomain = subdomain.replace( "." + XMPPServer.getInstance().getServerInfo().getXMPPDomain(), "" );
  +        } catch (Exception e) {
  +            errors.put("subdomain", e.getMessage());
  +        }
       }
       if ( componentAllowed && errors.isEmpty() )
       {
  
positive.code:                         <td><c:out value="${component.subdomain}"/></td>
                          <td><c:out value="${component.secret}"/></td>
                          <td align="center" style="border-right:1px #ccc solid;">
                              <a href="#" onclick="if (confirm('<fmt:message key="component.settings.confirm_delete" />')) { location.replace('connection-settings-external-components.jsp?deleteConf=${component.subdomain}'); } "
                                 title="<fmt:message key="global.click_delete" />"><img src="images/delete-16x16.gif" width="16" height="16" border="0" alt=""></a>
                          </td>
                      </tr>
  
negative.code: <%@ page import="org.jivesoftware.openfire.spi.ConnectionType" %>
  <%@ page import="org.jivesoftware.util.ModificationNotAllowedException" %>
  <%@ page import="org.jivesoftware.util.ParamUtils" %>
  <%@ page import="org.xmpp.packet.JID" %>
  <%@ page import="gnu.inet.encoding.StringprepException" %>
  <%@ page import="java.util.HashMap" %>
  <%@ page import="java.util.Map" %>
  <%@ page errorPage="error.jsp" %>
  