mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged V2.1 to HEAD
6833: Kerberos web filter for the web client. 6834: Kerberos web filter for WebDAV 6835: Updates to CIFS Kerberos logon support. 6836: Fix issue with editing properties of AVM nodes and changed clipboard to use lock aware AVM service 6837: Commented out the unknown opcode reporting as it can quickly fill the log files. AR-1742. 6839: Patch to allow * and ? wildcard characters within a term in any web-client search 6840: Fixed AR-1769: InvalidNameEndingPatch fails when running on 2.1 6841: AR-1761. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6873 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,908 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.app.servlet;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import javax.security.auth.callback.Callback;
|
||||||
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
import javax.security.auth.callback.NameCallback;
|
||||||
|
import javax.security.auth.callback.PasswordCallback;
|
||||||
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||||
|
import javax.security.auth.login.LoginContext;
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
import javax.security.sasl.RealmCallback;
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
|
import org.alfresco.config.ConfigService;
|
||||||
|
import org.alfresco.filesys.server.auth.kerberos.KerberosDetails;
|
||||||
|
import org.alfresco.filesys.server.auth.kerberos.SessionSetupPrivilegedAction;
|
||||||
|
import org.alfresco.filesys.server.auth.spnego.NegTokenInit;
|
||||||
|
import org.alfresco.filesys.server.auth.spnego.NegTokenTarg;
|
||||||
|
import org.alfresco.filesys.server.auth.spnego.OID;
|
||||||
|
import org.alfresco.filesys.server.auth.spnego.SPNEGO;
|
||||||
|
import org.alfresco.filesys.server.config.ServerConfiguration;
|
||||||
|
import org.alfresco.i18n.I18NUtil;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.authentication.NTLMMode;
|
||||||
|
import org.alfresco.service.ServiceRegistry;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.web.app.Application;
|
||||||
|
import org.alfresco.web.bean.LoginBean;
|
||||||
|
import org.alfresco.web.bean.repository.User;
|
||||||
|
import org.alfresco.web.config.LanguagesConfigElement;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.ietf.jgss.Oid;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kerberos Authentication Filter Class
|
||||||
|
*
|
||||||
|
* @author GKSpencer
|
||||||
|
*/
|
||||||
|
public class KerberosAuthenticationFilter extends AbstractAuthenticationFilter implements Filter, CallbackHandler
|
||||||
|
{
|
||||||
|
// Constants
|
||||||
|
//
|
||||||
|
// Default login configuration entry name
|
||||||
|
|
||||||
|
private static final String LoginConfigEntry = "AlfrescoHTTP";
|
||||||
|
|
||||||
|
// Locale object stored in the session
|
||||||
|
|
||||||
|
private static final String LOCALE = "locale";
|
||||||
|
public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";
|
||||||
|
|
||||||
|
// Debug logging
|
||||||
|
|
||||||
|
private static Log logger = LogFactory.getLog(KerberosAuthenticationFilter.class);
|
||||||
|
|
||||||
|
// Servlet context, required to get authentication service
|
||||||
|
|
||||||
|
private ServletContext m_context;
|
||||||
|
|
||||||
|
// File server configuration
|
||||||
|
|
||||||
|
private ServerConfiguration m_srvConfig;
|
||||||
|
|
||||||
|
// Various services required by the Kerberos authenticator
|
||||||
|
|
||||||
|
private AuthenticationService m_authService;
|
||||||
|
private AuthenticationComponent m_authComponent;
|
||||||
|
private PersonService m_personService;
|
||||||
|
private NodeService m_nodeService;
|
||||||
|
private TransactionService m_transactionService;
|
||||||
|
private ConfigService m_configService;
|
||||||
|
|
||||||
|
// Allow guest access
|
||||||
|
|
||||||
|
private boolean m_allowGuest;
|
||||||
|
|
||||||
|
// Login page address
|
||||||
|
|
||||||
|
private String m_loginPage;
|
||||||
|
|
||||||
|
// Random number generator used to generate challenge keys
|
||||||
|
|
||||||
|
private Random m_random = new Random(System.currentTimeMillis());
|
||||||
|
|
||||||
|
// Local server name, from either the file servers config or DNS host name
|
||||||
|
|
||||||
|
private String m_srvName;
|
||||||
|
|
||||||
|
// List of available locales (from the web-client configuration)
|
||||||
|
|
||||||
|
private List<String> m_languages;
|
||||||
|
|
||||||
|
// Kerberos settings
|
||||||
|
//
|
||||||
|
// Account name and password for server ticket
|
||||||
|
//
|
||||||
|
// The account name must be built from the HTTP server name, in the format :-
|
||||||
|
//
|
||||||
|
// HTTP/<server_name>@<realm>
|
||||||
|
|
||||||
|
private String m_accountName;
|
||||||
|
private String m_password;
|
||||||
|
|
||||||
|
// Kerberos realm and KDC address
|
||||||
|
|
||||||
|
private String m_krbRealm;
|
||||||
|
private String m_krbKDC;
|
||||||
|
|
||||||
|
// Login configuration entry name
|
||||||
|
|
||||||
|
private String m_loginEntryName = LoginConfigEntry;
|
||||||
|
|
||||||
|
// Server login context
|
||||||
|
|
||||||
|
private LoginContext m_loginContext;
|
||||||
|
|
||||||
|
// SPNEGO NegTokenInit blob, sent to the client in the SMB negotiate response
|
||||||
|
|
||||||
|
private byte[] m_negTokenInit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the filter
|
||||||
|
*
|
||||||
|
* @param args FilterConfig
|
||||||
|
* @exception ServletException
|
||||||
|
*/
|
||||||
|
public void init(FilterConfig args) throws ServletException
|
||||||
|
{
|
||||||
|
// Save the servlet context, needed to get hold of the authentication service
|
||||||
|
|
||||||
|
m_context = args.getServletContext();
|
||||||
|
|
||||||
|
// Setup the authentication context
|
||||||
|
|
||||||
|
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(m_context);
|
||||||
|
|
||||||
|
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||||
|
m_nodeService = serviceRegistry.getNodeService();
|
||||||
|
m_transactionService = serviceRegistry.getTransactionService();
|
||||||
|
|
||||||
|
m_authService = (AuthenticationService) ctx.getBean("AuthenticationService");
|
||||||
|
m_authComponent = (AuthenticationComponent) ctx.getBean("AuthenticationComponent");
|
||||||
|
m_personService = (PersonService) ctx.getBean("personService");
|
||||||
|
m_configService = (ConfigService) ctx.getBean("webClientConfigService");
|
||||||
|
|
||||||
|
m_srvConfig = (ServerConfiguration) ctx.getBean(ServerConfiguration.SERVER_CONFIGURATION);
|
||||||
|
|
||||||
|
// Check that the authentication component supports the required mode
|
||||||
|
|
||||||
|
if ( m_authComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
|
||||||
|
m_authComponent.getNTLMMode() != NTLMMode.PASS_THROUGH)
|
||||||
|
{
|
||||||
|
throw new ServletException("Required authentication mode not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the local server name, try the file server config first
|
||||||
|
|
||||||
|
if ( m_srvConfig != null)
|
||||||
|
{
|
||||||
|
m_srvName = m_srvConfig.getServerName();
|
||||||
|
|
||||||
|
if ( m_srvName == null)
|
||||||
|
{
|
||||||
|
// CIFS server may not be running so the local server name has not been set, generate
|
||||||
|
// a server name
|
||||||
|
|
||||||
|
m_srvName = m_srvConfig.getLocalServerName(true) + "_A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the host name
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Get the local host name
|
||||||
|
|
||||||
|
m_srvName = InetAddress.getLocalHost().getHostName();
|
||||||
|
|
||||||
|
// Strip any domain name
|
||||||
|
|
||||||
|
int pos = m_srvName.indexOf(".");
|
||||||
|
if ( pos != -1)
|
||||||
|
m_srvName = m_srvName.substring(0, pos - 1);
|
||||||
|
}
|
||||||
|
catch (UnknownHostException ex)
|
||||||
|
{
|
||||||
|
// Log the error
|
||||||
|
|
||||||
|
if ( logger.isErrorEnabled())
|
||||||
|
logger.error("Kerberos filter, error getting local host name", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the server name is valid
|
||||||
|
|
||||||
|
if ( m_srvName == null || m_srvName.length() == 0)
|
||||||
|
throw new ServletException("Failed to get local server name");
|
||||||
|
|
||||||
|
// Get a list of the available locales
|
||||||
|
|
||||||
|
LanguagesConfigElement config = (LanguagesConfigElement) m_configService.
|
||||||
|
getConfig("Languages").getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
|
||||||
|
|
||||||
|
m_languages = config.getLanguages();
|
||||||
|
|
||||||
|
// Check if Kerberos is enabled, get the Kerberos KDC address
|
||||||
|
|
||||||
|
String kdcAddress = args.getInitParameter("KDC");
|
||||||
|
|
||||||
|
if (kdcAddress != null && kdcAddress.length() > 0)
|
||||||
|
{
|
||||||
|
// Set the Kerberos KDC address
|
||||||
|
|
||||||
|
m_krbKDC = kdcAddress;
|
||||||
|
|
||||||
|
// Get the Kerberos realm
|
||||||
|
|
||||||
|
String krbRealm = args.getInitParameter("Realm");
|
||||||
|
if ( krbRealm != null && krbRealm.length() > 0)
|
||||||
|
{
|
||||||
|
// Set the Kerberos realm
|
||||||
|
|
||||||
|
m_krbRealm = krbRealm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new ServletException("Kerberos realm not specified");
|
||||||
|
|
||||||
|
// Get the CIFS service account password
|
||||||
|
|
||||||
|
String srvPassword = args.getInitParameter("Password");
|
||||||
|
if ( srvPassword != null && srvPassword.length() > 0)
|
||||||
|
{
|
||||||
|
// Set the CIFS service account password
|
||||||
|
|
||||||
|
m_password = srvPassword;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new ServletException("HTTP service account password not specified");
|
||||||
|
|
||||||
|
// Get the login configuration entry name
|
||||||
|
|
||||||
|
String loginEntry = args.getInitParameter("LoginEntry");
|
||||||
|
|
||||||
|
if ( loginEntry != null)
|
||||||
|
{
|
||||||
|
if ( loginEntry.length() > 0)
|
||||||
|
{
|
||||||
|
// Set the login configuration entry name to use
|
||||||
|
|
||||||
|
m_loginEntryName = loginEntry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new ServletException("Invalid login entry specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the local host name
|
||||||
|
|
||||||
|
String localName = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
localName = InetAddress.getLocalHost().getCanonicalHostName();
|
||||||
|
}
|
||||||
|
catch ( UnknownHostException ex)
|
||||||
|
{
|
||||||
|
throw new ServletException( "Failed to get local host name");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the server principal name
|
||||||
|
|
||||||
|
String principal = args.getInitParameter( "Principal");
|
||||||
|
|
||||||
|
if ( principal != null) {
|
||||||
|
|
||||||
|
// Use the supplied principal name to build the account name
|
||||||
|
|
||||||
|
StringBuffer httpAccount = new StringBuffer();
|
||||||
|
|
||||||
|
httpAccount.append( principal);
|
||||||
|
httpAccount.append("@");
|
||||||
|
httpAccount.append(m_krbRealm);
|
||||||
|
|
||||||
|
m_accountName = httpAccount.toString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// Build the HTTP service account name
|
||||||
|
|
||||||
|
StringBuilder httpAccount = new StringBuilder();
|
||||||
|
|
||||||
|
httpAccount.append("HTTP/");
|
||||||
|
httpAccount.append( localName);
|
||||||
|
httpAccount.append("@");
|
||||||
|
httpAccount.append(m_krbRealm);
|
||||||
|
|
||||||
|
m_accountName = httpAccount.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a login context for the CIFS server service
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug( "HTTP Kerberos login using account " + m_accountName);
|
||||||
|
|
||||||
|
// Login the CIFS server service
|
||||||
|
|
||||||
|
m_loginContext = new LoginContext( m_loginEntryName, this);
|
||||||
|
m_loginContext.login();
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug( "HTTP Kerberos login successful");
|
||||||
|
}
|
||||||
|
catch ( LoginException ex)
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isErrorEnabled())
|
||||||
|
logger.error("HTTP Kerberos web filter error", ex);
|
||||||
|
|
||||||
|
throw new ServletException("Failed to login HTTP server service");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the Oid list for the SPNEGO NegTokenInit, include NTLMSSP for fallback
|
||||||
|
|
||||||
|
Vector<Oid> mechTypes = new Vector<Oid>();
|
||||||
|
|
||||||
|
mechTypes.add(OID.KERBEROS5);
|
||||||
|
mechTypes.add(OID.MSKERBEROS5);
|
||||||
|
|
||||||
|
// Build the SPNEGO NegTokenInit blob
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Build the mechListMIC principle
|
||||||
|
//
|
||||||
|
// Note: This field is not as specified
|
||||||
|
|
||||||
|
String mecListMIC = null;
|
||||||
|
|
||||||
|
StringBuilder mic = new StringBuilder();
|
||||||
|
mic.append( localName);
|
||||||
|
mic.append("$@");
|
||||||
|
mic.append( m_krbRealm);
|
||||||
|
|
||||||
|
mecListMIC = mic.toString();
|
||||||
|
|
||||||
|
// Build the SPNEGO NegTokenInit that contains the authentication types that the HTTP server accepts
|
||||||
|
|
||||||
|
NegTokenInit negTokenInit = new NegTokenInit(mechTypes, mecListMIC);
|
||||||
|
|
||||||
|
// Encode the NegTokenInit blob
|
||||||
|
|
||||||
|
m_negTokenInit = negTokenInit.encode();
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isErrorEnabled())
|
||||||
|
logger.error("Error creating SPNEGO NegTokenInit blob", ex);
|
||||||
|
|
||||||
|
throw new ServletException("Failed to create SPNEGO NegTokenInit blob");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the filter
|
||||||
|
*
|
||||||
|
* @param sreq ServletRequest
|
||||||
|
* @param sresp ServletResponse
|
||||||
|
* @param chain FilterChain
|
||||||
|
* @exception IOException
|
||||||
|
* @exception ServletException
|
||||||
|
*/
|
||||||
|
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain) throws IOException,
|
||||||
|
ServletException
|
||||||
|
{
|
||||||
|
// Get the HTTP request/response/session
|
||||||
|
|
||||||
|
HttpServletRequest req = (HttpServletRequest) sreq;
|
||||||
|
HttpServletResponse resp = (HttpServletResponse) sresp;
|
||||||
|
|
||||||
|
HttpSession httpSess = req.getSession(true);
|
||||||
|
|
||||||
|
// Check if there is an authorization header with an SPNEGO security blob
|
||||||
|
|
||||||
|
String authHdr = req.getHeader("Authorization");
|
||||||
|
boolean reqAuth = false;
|
||||||
|
|
||||||
|
if ( authHdr != null && authHdr.startsWith("Negotiate"))
|
||||||
|
reqAuth = true;
|
||||||
|
|
||||||
|
// Check if the user is already authenticated
|
||||||
|
|
||||||
|
User user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
|
||||||
|
|
||||||
|
if ( user != null && reqAuth == false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("User " + user.getUserName() + " validate ticket");
|
||||||
|
|
||||||
|
// Validate the user ticket
|
||||||
|
|
||||||
|
m_authService.validate( user.getTicket());
|
||||||
|
reqAuth = false;
|
||||||
|
|
||||||
|
// Set the current locale
|
||||||
|
|
||||||
|
I18NUtil.setLocale(Application.getLanguage(httpSess));
|
||||||
|
}
|
||||||
|
catch (AuthenticationException ex)
|
||||||
|
{
|
||||||
|
if ( logger.isErrorEnabled())
|
||||||
|
logger.error("Failed to validate user " + user.getUserName(), ex);
|
||||||
|
|
||||||
|
reqAuth = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the user has been validated and we do not require re-authentication then continue to
|
||||||
|
// the next filter
|
||||||
|
|
||||||
|
if ( reqAuth == false && user != null)
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Authentication not required, chaining ...");
|
||||||
|
|
||||||
|
// Chain to the next filter
|
||||||
|
|
||||||
|
chain.doFilter(sreq, sresp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the login page is being accessed, do not intercept the login page
|
||||||
|
|
||||||
|
if ( req.getRequestURI().endsWith(getLoginPage()) == true)
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Login page requested, chaining ...");
|
||||||
|
|
||||||
|
// Chain to the next filter
|
||||||
|
|
||||||
|
chain.doFilter( sreq, sresp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the browser is Opera, if so then display the login page as Opera does not
|
||||||
|
// support SPNEGO
|
||||||
|
|
||||||
|
String userAgent = req.getHeader("user-agent");
|
||||||
|
|
||||||
|
if ( userAgent != null && userAgent.indexOf("Opera ") != -1)
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Opera detected, redirecting to login page");
|
||||||
|
|
||||||
|
// Redirect to the login page
|
||||||
|
|
||||||
|
resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the authorization header
|
||||||
|
|
||||||
|
if ( authHdr == null) {
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("New Kerberos auth request from " + req.getRemoteHost() + " (" +
|
||||||
|
req.getRemoteAddr() + ":" + req.getRemotePort() + ")");
|
||||||
|
|
||||||
|
// Send back a request for SPNEGO authentication
|
||||||
|
|
||||||
|
resp.setHeader("WWW-Authenticate", "Negotiate");
|
||||||
|
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
|
||||||
|
resp.flushBuffer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Decode the received SPNEGO blob and validate
|
||||||
|
|
||||||
|
final byte[] spnegoByts = Base64.decodeBase64( authHdr.substring(10).getBytes());
|
||||||
|
|
||||||
|
// Check the received SPNEGO token type
|
||||||
|
|
||||||
|
int tokType = -1;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tokType = SPNEGO.checkTokenType( spnegoByts, 0, spnegoByts.length);
|
||||||
|
}
|
||||||
|
catch ( IOException ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a NegTokenInit blob
|
||||||
|
|
||||||
|
if ( tokType == SPNEGO.NegTokenInit)
|
||||||
|
{
|
||||||
|
// Parse the SPNEGO security blob to get the Kerberos ticket
|
||||||
|
|
||||||
|
NegTokenInit negToken = new NegTokenInit();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Decode the security blob
|
||||||
|
|
||||||
|
negToken.decode( spnegoByts, 0, spnegoByts.length);
|
||||||
|
|
||||||
|
// Determine the authentication mechanism the client is using and logon
|
||||||
|
|
||||||
|
String oidStr = null;
|
||||||
|
if ( negToken.numberOfOids() > 0)
|
||||||
|
oidStr = negToken.getOidAt( 0).toString();
|
||||||
|
|
||||||
|
if ( oidStr != null && (oidStr.equals( OID.ID_MSKERBEROS5) || oidStr.equals(OID.ID_KERBEROS5)))
|
||||||
|
{
|
||||||
|
// Kerberos logon
|
||||||
|
|
||||||
|
if ( doKerberosLogon( negToken, req, resp, httpSess) != null)
|
||||||
|
{
|
||||||
|
// If the original URL requested was the login page then redirect to the browse view
|
||||||
|
|
||||||
|
if (req.getRequestURI().endsWith(getLoginPage()) == true)
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Login page requested, redirecting to browse page");
|
||||||
|
|
||||||
|
// Redirect to the browse view
|
||||||
|
|
||||||
|
resp.sendRedirect(req.getContextPath() + "/faces/jsp/browse/browse.jsp");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Allow the user to access the requested page
|
||||||
|
|
||||||
|
chain.doFilter( req, resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send back a request for SPNEGO authentication
|
||||||
|
|
||||||
|
resp.setHeader("WWW-Authenticate", "Negotiate");
|
||||||
|
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
|
||||||
|
resp.flushBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( IOException ex)
|
||||||
|
{
|
||||||
|
// Log the error
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown SPNEGO token type
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug( "Unknown SPNEGO token type");
|
||||||
|
|
||||||
|
// Redirect to the login page
|
||||||
|
|
||||||
|
resp.sendRedirect(req.getContextPath() + "/faces" + getLoginPage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the login page address
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
private String getLoginPage()
|
||||||
|
{
|
||||||
|
if (m_loginPage == null)
|
||||||
|
{
|
||||||
|
m_loginPage = Application.getLoginPage(m_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_loginPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the servlet filter
|
||||||
|
*/
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JAAS callback handler
|
||||||
|
*
|
||||||
|
* @param callbacks Callback[]
|
||||||
|
* @exception IOException
|
||||||
|
* @exception UnsupportedCallbackException
|
||||||
|
*/
|
||||||
|
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
|
||||||
|
{
|
||||||
|
// Process the callback list
|
||||||
|
|
||||||
|
for (int i = 0; i < callbacks.length; i++)
|
||||||
|
{
|
||||||
|
// Request for user name
|
||||||
|
|
||||||
|
if (callbacks[i] instanceof NameCallback)
|
||||||
|
{
|
||||||
|
NameCallback cb = (NameCallback) callbacks[i];
|
||||||
|
cb.setName(m_accountName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request for password
|
||||||
|
else if (callbacks[i] instanceof PasswordCallback)
|
||||||
|
{
|
||||||
|
PasswordCallback cb = (PasswordCallback) callbacks[i];
|
||||||
|
cb.setPassword(m_password.toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request for realm
|
||||||
|
|
||||||
|
else if (callbacks[i] instanceof RealmCallback)
|
||||||
|
{
|
||||||
|
RealmCallback cb = (RealmCallback) callbacks[i];
|
||||||
|
cb.setText(m_krbRealm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new UnsupportedCallbackException(callbacks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a Kerberos login and return an SPNEGO response
|
||||||
|
*
|
||||||
|
* @param negToken NegTokenInit
|
||||||
|
* @param req HttpServletRequest
|
||||||
|
* @param resp HttpServletResponse
|
||||||
|
* @param httpSess HttpSession
|
||||||
|
* @return NegTokenTarg
|
||||||
|
*/
|
||||||
|
private final NegTokenTarg doKerberosLogon( NegTokenInit negToken, HttpServletRequest req, HttpServletResponse resp, HttpSession httpSess)
|
||||||
|
{
|
||||||
|
// Authenticate the user
|
||||||
|
|
||||||
|
KerberosDetails krbDetails = null;
|
||||||
|
NegTokenTarg negTokenTarg = null;
|
||||||
|
|
||||||
|
UserTransaction tx = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Run the session setup as a privileged action
|
||||||
|
|
||||||
|
SessionSetupPrivilegedAction sessSetupAction = new SessionSetupPrivilegedAction( m_accountName, negToken.getMechtoken());
|
||||||
|
Object result = Subject.doAs( m_loginContext.getSubject(), sessSetupAction);
|
||||||
|
|
||||||
|
if ( result != null)
|
||||||
|
{
|
||||||
|
// Access the Kerberos response
|
||||||
|
|
||||||
|
krbDetails = (KerberosDetails) result;
|
||||||
|
|
||||||
|
// Create the NegTokenTarg response blob
|
||||||
|
|
||||||
|
negTokenTarg = new NegTokenTarg( SPNEGO.AcceptCompleted, OID.KERBEROS5, krbDetails.getResponseToken());
|
||||||
|
|
||||||
|
// Check if the user has been authenticated, if so then setup the user environment
|
||||||
|
|
||||||
|
if ( negTokenTarg != null)
|
||||||
|
{
|
||||||
|
// Create a read transaction
|
||||||
|
|
||||||
|
tx = m_transactionService.getUserTransaction();
|
||||||
|
|
||||||
|
NodeRef homeSpaceRef = null;
|
||||||
|
User user = null;
|
||||||
|
String userName = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Start the transaction
|
||||||
|
|
||||||
|
tx.begin();
|
||||||
|
|
||||||
|
// Setup User object and Home space ID etc.
|
||||||
|
|
||||||
|
NodeRef personNodeRef = m_personService.getPerson( krbDetails.getUserName());
|
||||||
|
|
||||||
|
// Use the system user to do the user name lookup
|
||||||
|
|
||||||
|
m_authComponent.setSystemUserAsCurrentUser();
|
||||||
|
|
||||||
|
// User name should match the uid in the person entry found
|
||||||
|
|
||||||
|
userName = (String) m_nodeService.getProperty(personNodeRef, ContentModel.PROP_USERNAME);
|
||||||
|
AuthenticationUtil.setCurrentUser( userName);
|
||||||
|
String currentTicket = m_authService.getCurrentTicket();
|
||||||
|
user = new User(userName, currentTicket, personNodeRef);
|
||||||
|
|
||||||
|
homeSpaceRef = (NodeRef) m_nodeService.getProperty( personNodeRef, ContentModel.PROP_HOMEFOLDER);
|
||||||
|
user.setHomeSpaceId(homeSpaceRef.getId());
|
||||||
|
|
||||||
|
// Commit
|
||||||
|
|
||||||
|
tx.commit();
|
||||||
|
}
|
||||||
|
catch (Throwable ex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tx.rollback();
|
||||||
|
}
|
||||||
|
catch (Exception ex2)
|
||||||
|
{
|
||||||
|
logger.error("Failed to rollback transaction", ex2);
|
||||||
|
}
|
||||||
|
if(ex instanceof RuntimeException)
|
||||||
|
{
|
||||||
|
throw (RuntimeException)ex;
|
||||||
|
}
|
||||||
|
else if(ex instanceof IOException)
|
||||||
|
{
|
||||||
|
throw (IOException)ex;
|
||||||
|
}
|
||||||
|
else if(ex instanceof ServletException)
|
||||||
|
{
|
||||||
|
throw (ServletException)ex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Authentication setup failed", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the user
|
||||||
|
|
||||||
|
httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
|
||||||
|
httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);
|
||||||
|
|
||||||
|
// Set the current locale from the Accept-Lanaguage header if available
|
||||||
|
|
||||||
|
Locale userLocale = parseAcceptLanguageHeader(req, m_languages);
|
||||||
|
|
||||||
|
if ( userLocale != null)
|
||||||
|
{
|
||||||
|
httpSess.setAttribute(LOCALE, userLocale);
|
||||||
|
httpSess.removeAttribute(MESSAGE_BUNDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the locale using the session
|
||||||
|
|
||||||
|
I18NUtil.setLocale(Application.getLanguage(httpSess));
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("User " + userName + " logged on via Kerberos");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Debug
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug( "No SPNEGO response, Kerberos logon failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log the error
|
||||||
|
|
||||||
|
if ( logger.isDebugEnabled())
|
||||||
|
logger.debug("Kerberos logon error", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the response SPNEGO blob
|
||||||
|
|
||||||
|
return negTokenTarg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the case insensitive logon name to the internal person object user name
|
||||||
|
*
|
||||||
|
* @param userName String
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
protected final String mapUserNameToPerson(String userName)
|
||||||
|
{
|
||||||
|
// Get the home folder for the user
|
||||||
|
|
||||||
|
UserTransaction tx = m_transactionService.getUserTransaction();
|
||||||
|
String personName = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tx.begin();
|
||||||
|
personName = m_personService.getUserIdentifier( userName);
|
||||||
|
tx.commit();
|
||||||
|
}
|
||||||
|
catch (Throwable ex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tx.rollback();
|
||||||
|
}
|
||||||
|
catch (Throwable ex2)
|
||||||
|
{
|
||||||
|
logger.error("Failed to rollback transaction", ex2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-throw the exception
|
||||||
|
|
||||||
|
if (ex instanceof RuntimeException)
|
||||||
|
{
|
||||||
|
throw (RuntimeException) ex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Error during execution of transaction.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the person name
|
||||||
|
|
||||||
|
return personName;
|
||||||
|
}
|
||||||
|
}
|
@@ -518,44 +518,9 @@ public final class SearchContext implements Serializable
|
|||||||
{
|
{
|
||||||
if (value.indexOf(' ') == -1)
|
if (value.indexOf(' ') == -1)
|
||||||
{
|
{
|
||||||
String safeValue;
|
|
||||||
String prefix = "";
|
|
||||||
String suffix = "";
|
|
||||||
|
|
||||||
// look for a wildcard suffix
|
|
||||||
if (value.charAt(value.length() - 1) != OP_WILDCARD)
|
|
||||||
{
|
|
||||||
// look for wildcard prefix
|
|
||||||
if (value.charAt(0) != OP_WILDCARD)
|
|
||||||
{
|
|
||||||
safeValue = QueryParser.escape(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
safeValue = QueryParser.escape(value.substring(1));
|
|
||||||
prefix = STR_OP_WILDCARD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// found a wildcard suffix - append it again after escaping the other characters
|
|
||||||
suffix = STR_OP_WILDCARD;
|
|
||||||
|
|
||||||
// look for wildcard prefix
|
|
||||||
if (value.charAt(0) != OP_WILDCARD)
|
|
||||||
{
|
|
||||||
safeValue = QueryParser.escape(value.substring(0, value.length() - 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
safeValue = QueryParser.escape(value.substring(1, value.length() - 1));
|
|
||||||
prefix = STR_OP_WILDCARD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (andOp) buf.append('+');
|
if (andOp) buf.append('+');
|
||||||
buf.append('@').append(Repository.escapeQName(qname)).append(":")
|
buf.append('@').append(Repository.escapeQName(qname)).append(":")
|
||||||
.append(prefix).append(safeValue).append(suffix).append(' ');
|
.append(SearchContext.escape(value)).append(' ');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -577,44 +542,30 @@ public final class SearchContext implements Serializable
|
|||||||
*/
|
*/
|
||||||
private static void processSearchTextAttribute(String qname, String value, StringBuilder attrBuf, StringBuilder textBuf)
|
private static void processSearchTextAttribute(String qname, String value, StringBuilder attrBuf, StringBuilder textBuf)
|
||||||
{
|
{
|
||||||
String safeValue;
|
textBuf.append("TEXT:").append(SearchContext.escape(value));
|
||||||
String suffix = "";
|
|
||||||
String prefix = "";
|
|
||||||
|
|
||||||
if (value.charAt(value.length() - 1) != OP_WILDCARD)
|
|
||||||
{
|
|
||||||
// look for wildcard prefix
|
|
||||||
if (value.charAt(0) != OP_WILDCARD)
|
|
||||||
{
|
|
||||||
safeValue = QueryParser.escape(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// found a leading wildcard - prepend it again after escaping the other characters
|
|
||||||
prefix = STR_OP_WILDCARD;
|
|
||||||
safeValue = QueryParser.escape(value.substring(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
suffix = STR_OP_WILDCARD;
|
|
||||||
|
|
||||||
// look for wildcard prefix
|
|
||||||
if (value.charAt(0) != OP_WILDCARD)
|
|
||||||
{
|
|
||||||
safeValue = QueryParser.escape(value.substring(0, value.length() - 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (value.length() == 1) return; // handle just opcode
|
|
||||||
prefix = STR_OP_WILDCARD;
|
|
||||||
safeValue = QueryParser.escape(value.substring(1, value.length() - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textBuf.append("TEXT:").append(prefix).append(safeValue).append(suffix);
|
|
||||||
attrBuf.append("@").append(qname).append(":")
|
attrBuf.append("@").append(qname).append(":")
|
||||||
.append(prefix).append(safeValue).append(suffix);
|
.append(SearchContext.escape(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a String where those characters that QueryParser
|
||||||
|
* expects to be escaped are escaped by a preceding <code>\</code>.
|
||||||
|
* '*' and '?' are not escaped.
|
||||||
|
*/
|
||||||
|
private static String escape(String s)
|
||||||
|
{
|
||||||
|
StringBuffer sb = new StringBuffer(s.length() + 4);
|
||||||
|
for (int i = 0; i < s.length(); i++)
|
||||||
|
{
|
||||||
|
char c = s.charAt(i);
|
||||||
|
if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' ||
|
||||||
|
c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~')
|
||||||
|
{
|
||||||
|
sb.append('\\');
|
||||||
|
}
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -97,7 +97,7 @@ public class AVMClipboardItem extends AbstractClipboardItem
|
|||||||
String sourcePath = AVMNodeConverter.ToAVMVersionPath(getNodeRef()).getSecond();
|
String sourcePath = AVMNodeConverter.ToAVMVersionPath(getNodeRef()).getSecond();
|
||||||
|
|
||||||
FileFolderService fileFolderService = getServiceRegistry().getFileFolderService();
|
FileFolderService fileFolderService = getServiceRegistry().getFileFolderService();
|
||||||
AVMService avmService = getServiceRegistry().getAVMService();
|
AVMService avmService = getServiceRegistry().getAVMLockingAwareService();
|
||||||
|
|
||||||
// initial name to attempt the copy of the item with
|
// initial name to attempt the copy of the item with
|
||||||
String name = getName();
|
String name = getName();
|
||||||
|
@@ -28,7 +28,6 @@ import java.io.Serializable;
|
|||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.faces.context.FacesContext;
|
import javax.faces.context.FacesContext;
|
||||||
@@ -50,7 +49,9 @@ import org.alfresco.web.app.Application;
|
|||||||
import org.alfresco.web.bean.content.EditContentPropertiesDialog;
|
import org.alfresco.web.bean.content.EditContentPropertiesDialog;
|
||||||
import org.alfresco.web.bean.repository.Node;
|
import org.alfresco.web.bean.repository.Node;
|
||||||
import org.alfresco.web.bean.repository.Repository;
|
import org.alfresco.web.bean.repository.Repository;
|
||||||
import org.alfresco.web.forms.*;
|
import org.alfresco.web.forms.FormInstanceData;
|
||||||
|
import org.alfresco.web.forms.FormsService;
|
||||||
|
import org.alfresco.web.forms.Rendition;
|
||||||
import org.alfresco.web.ui.common.Utils;
|
import org.alfresco.web.ui.common.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -186,8 +187,12 @@ public class EditFilePropertiesDialog extends EditContentPropertiesDialog
|
|||||||
// send the properties back to the repository
|
// send the properties back to the repository
|
||||||
this.avmService.setNodeProperties(AVMNodeConverter.ToAVMVersionPath(nodeRef).getSecond(), avmProps);
|
this.avmService.setNodeProperties(AVMNodeConverter.ToAVMVersionPath(nodeRef).getSecond(), avmProps);
|
||||||
|
|
||||||
// perform the rename last as for an AVM it changes the NodeRef
|
// perform the rename last as for an AVM it changes the NodeRef, but only if the name has changed!
|
||||||
if (name != null)
|
String path = AVMNodeConverter.ToAVMVersionPath(nodeRef).getSecond();
|
||||||
|
final String parentPath = AVMNodeConverter.SplitBase(path)[0];
|
||||||
|
final String oldName = AVMNodeConverter.SplitBase(path)[1];
|
||||||
|
|
||||||
|
if (name != null && name.equals(oldName) == false)
|
||||||
{
|
{
|
||||||
if (this.nodeService.hasAspect(nodeRef, WCMAppModel.ASPECT_RENDITION))
|
if (this.nodeService.hasAspect(nodeRef, WCMAppModel.ASPECT_RENDITION))
|
||||||
{
|
{
|
||||||
@@ -209,12 +214,8 @@ public class EditFilePropertiesDialog extends EditContentPropertiesDialog
|
|||||||
this.nodeService.removeProperty(nodeRef, WCMAppModel.PROP_RENDITIONS);
|
this.nodeService.removeProperty(nodeRef, WCMAppModel.PROP_RENDITIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
String path = AVMNodeConverter.ToAVMVersionPath(nodeRef).getSecond();
|
|
||||||
final String parentPath = AVMNodeConverter.SplitBase(path)[0];
|
|
||||||
final String oldName = AVMNodeConverter.SplitBase(path)[1];
|
|
||||||
this.avmService.rename(parentPath, oldName, parentPath, name);
|
this.avmService.rename(parentPath, oldName, parentPath, name);
|
||||||
nodeRef = AVMNodeConverter.ToNodeRef(-1, AVMNodeConverter.ExtendAVMPath(parentPath, name));
|
nodeRef = AVMNodeConverter.ToNodeRef(-1, AVMNodeConverter.ExtendAVMPath(parentPath, name));
|
||||||
editedProps.put(ContentModel.PROP_NAME.toString(), name);
|
|
||||||
|
|
||||||
if (this.nodeService.hasAspect(nodeRef, WCMAppModel.ASPECT_FORM_INSTANCE_DATA))
|
if (this.nodeService.hasAspect(nodeRef, WCMAppModel.ASPECT_FORM_INSTANCE_DATA))
|
||||||
{
|
{
|
||||||
@@ -232,6 +233,12 @@ public class EditFilePropertiesDialog extends EditContentPropertiesDialog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add the name property back to the properties map
|
||||||
|
if (name != null)
|
||||||
|
{
|
||||||
|
editedProps.put(ContentModel.PROP_NAME.toString(), name);
|
||||||
|
}
|
||||||
|
|
||||||
return outcome;
|
return outcome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user