mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
.externalToolBuilders
config
source
cpp
java
org
alfresco
email
filesys
alfresco
auth
avm
debug
repo
desk
CifsHelper.java
CifsIntegrationTest.java
ContentContext.java
ContentDiskDriver.java
ContentDiskInterface.java
ContentFileInfo.java
ContentIOControlHandler.java
ContentNetworkFile.java
ContentSearchContext.java
HomeShareMapper.java
LinkMemoryNetworkFile.java
NodeRefNetworkFile.java
state
util
AlfrescoConfigSection.java
CIFSServerBean.java
FTPServerBean.java
FileServerConfig.java
FileServerConfigMBean.java
NFSServerBean.java
ServerConfigurationBean.java
jcr
linkvalidation
model
repo
sandbox
service
tools
util
apache
queryRegister.dtd
meta-inf
test-resources
web
.classpath
.project
build.xml
Restructured the file server code packages. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7757 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
795 lines
26 KiB
Java
795 lines
26 KiB
Java
/*
|
|
* 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.filesys.repo;
|
|
|
|
import java.io.FileNotFoundException;
|
|
|
|
import org.alfresco.filesys.alfresco.AlfrescoClientInfo;
|
|
import org.alfresco.filesys.alfresco.AlfrescoContext;
|
|
import org.alfresco.filesys.alfresco.AlfrescoDiskDriver;
|
|
import org.alfresco.filesys.alfresco.DesktopAction;
|
|
import org.alfresco.filesys.alfresco.DesktopActionTable;
|
|
import org.alfresco.filesys.alfresco.DesktopParams;
|
|
import org.alfresco.filesys.alfresco.DesktopResponse;
|
|
import org.alfresco.filesys.alfresco.DesktopTarget;
|
|
import org.alfresco.filesys.alfresco.IOControl;
|
|
import org.alfresco.filesys.alfresco.IOControlHandler;
|
|
import org.alfresco.jlan.server.SrvSession;
|
|
import org.alfresco.jlan.server.auth.ClientInfo;
|
|
import org.alfresco.jlan.server.filesys.IOControlNotImplementedException;
|
|
import org.alfresco.jlan.server.filesys.NetworkFile;
|
|
import org.alfresco.jlan.server.filesys.TreeConnection;
|
|
import org.alfresco.jlan.smb.SMBException;
|
|
import org.alfresco.jlan.smb.SMBStatus;
|
|
import org.alfresco.jlan.smb.nt.NTIOCtl;
|
|
import org.alfresco.jlan.util.DataBuffer;
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.repo.security.authentication.AuthenticationException;
|
|
import org.alfresco.service.cmr.lock.LockType;
|
|
import org.alfresco.service.cmr.repository.ContentData;
|
|
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.transaction.TransactionService;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* Content Disk Driver I/O Control Handler Class
|
|
*
|
|
* <p>Provides the custom I/O control code handling used by the CIFS client interface application.
|
|
*
|
|
* @author gkspencer
|
|
*/
|
|
public class ContentIOControlHandler implements IOControlHandler
|
|
{
|
|
// Logging
|
|
|
|
private static final Log logger = LogFactory.getLog(ContentIOControlHandler.class);
|
|
|
|
// Filesystem driver and context
|
|
|
|
private ContentDiskDriver contentDriver;
|
|
private ContentContext contentContext;
|
|
|
|
/**
|
|
* Default constructor
|
|
*/
|
|
public ContentIOControlHandler()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Initalize the I/O control handler
|
|
*
|
|
* @param filesysDriver AlfrescoDiskDriver
|
|
* @param context AlfrescoContext
|
|
*/
|
|
public void initialize( AlfrescoDiskDriver filesysDriver, AlfrescoContext context)
|
|
{
|
|
this.contentDriver = (ContentDiskDriver) filesysDriver;
|
|
this.contentContext = (ContentContext) context;
|
|
}
|
|
|
|
/**
|
|
* Return the CIFS helper
|
|
*
|
|
* @return CifsHelper
|
|
*/
|
|
public final CifsHelper getCifsHelper()
|
|
{
|
|
return contentDriver.getCifsHelper();
|
|
}
|
|
|
|
/**
|
|
* Return the authentication service
|
|
*
|
|
* @return AuthenticationService
|
|
*/
|
|
public final AuthenticationService getAuthenticationService()
|
|
{
|
|
return contentDriver.getAuthenticationService();
|
|
}
|
|
|
|
/**
|
|
* Return the transaction service
|
|
*
|
|
* @return TransactionService
|
|
*/
|
|
public final TransactionService getTransactionService()
|
|
{
|
|
return contentDriver.getTransactionService();
|
|
}
|
|
|
|
/**
|
|
* Return the node service
|
|
*
|
|
* @return NodeService
|
|
*/
|
|
public final NodeService getNodeService()
|
|
{
|
|
return contentDriver.getNodeService();
|
|
}
|
|
|
|
/**
|
|
* Return the filesystem driver
|
|
*
|
|
* @return ContentDiskDriver
|
|
*/
|
|
public final ContentDiskDriver getContentDriver()
|
|
{
|
|
return contentDriver;
|
|
}
|
|
|
|
/**
|
|
* Return the filesystem context
|
|
*
|
|
* @return ContentContext
|
|
*/
|
|
public final ContentContext getContentContext()
|
|
{
|
|
return contentContext;
|
|
}
|
|
|
|
/**
|
|
* Process a filesystem I/O control request
|
|
*
|
|
* @param sess Server session
|
|
* @param tree Tree connection.
|
|
* @param ctrlCode I/O control code
|
|
* @param fid File id
|
|
* @param dataBuf I/O control specific input data
|
|
* @param isFSCtrl true if this is a filesystem control, or false for a device control
|
|
* @param filter if bit0 is set indicates that the control applies to the share root handle
|
|
* @return DataBuffer
|
|
* @exception IOControlNotImplementedException
|
|
* @exception SMBException
|
|
*/
|
|
public org.alfresco.jlan.util.DataBuffer processIOControl(SrvSession sess, TreeConnection tree, int ctrlCode, int fid, DataBuffer dataBuf,
|
|
boolean isFSCtrl, int filter)
|
|
throws IOControlNotImplementedException, SMBException
|
|
{
|
|
// Validate the file id
|
|
|
|
NetworkFile netFile = tree.findFile(fid);
|
|
if ( netFile == null || netFile.isDirectory() == false)
|
|
throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter);
|
|
|
|
// Split the control code
|
|
|
|
int devType = NTIOCtl.getDeviceType(ctrlCode);
|
|
int ioFunc = NTIOCtl.getFunctionCode(ctrlCode);
|
|
|
|
// Check for I/O controls that require a success status
|
|
|
|
if ( devType == NTIOCtl.DeviceFileSystem)
|
|
{
|
|
// I/O control requests that require a success status
|
|
//
|
|
// Create or get object id
|
|
|
|
if ( ioFunc == NTIOCtl.FsCtlCreateOrGetObjectId)
|
|
return null;
|
|
}
|
|
|
|
// Check if the I/O control looks like a custom I/O control request
|
|
|
|
if ( devType != NTIOCtl.DeviceFileSystem || dataBuf == null)
|
|
throw new IOControlNotImplementedException();
|
|
|
|
// Check if the request has a valid signature for an Alfresco CIFS server I/O control
|
|
|
|
if ( dataBuf.getLength() < IOControl.Signature.length())
|
|
throw new IOControlNotImplementedException("Bad request length");
|
|
|
|
String sig = dataBuf.getString(IOControl.Signature.length(), false);
|
|
|
|
if ( sig == null || sig.compareTo(IOControl.Signature) != 0)
|
|
throw new IOControlNotImplementedException("Bad request signature");
|
|
|
|
// Get the node for the parent folder, make sure it is a folder
|
|
|
|
NodeRef folderNode = null;
|
|
|
|
try
|
|
{
|
|
folderNode = contentDriver.getNodeForPath(tree, netFile.getFullName());
|
|
|
|
if ( getCifsHelper().isDirectory( folderNode) == false)
|
|
folderNode = null;
|
|
}
|
|
catch ( FileNotFoundException ex)
|
|
{
|
|
folderNode = null;
|
|
}
|
|
|
|
// If the folder node is not valid return an error
|
|
|
|
if ( folderNode == null)
|
|
throw new SMBException(SMBStatus.NTErr, SMBStatus.NTAccessDenied);
|
|
|
|
// Debug
|
|
|
|
if ( logger.isDebugEnabled()) {
|
|
logger.debug("IO control func=0x" + Integer.toHexString(ioFunc) + ", fid=" + fid + ", buffer=" + dataBuf);
|
|
logger.debug(" Folder nodeRef=" + folderNode);
|
|
}
|
|
|
|
// Check if the I/O control code is one of our custom codes
|
|
|
|
DataBuffer retBuffer = null;
|
|
|
|
switch ( ioFunc)
|
|
{
|
|
// Probe to check if this is an Alfresco CIFS server
|
|
|
|
case IOControl.CmdProbe:
|
|
|
|
// Return a buffer with the signature and protocol version
|
|
|
|
retBuffer = new DataBuffer(IOControl.Signature.length());
|
|
retBuffer.putFixedString(IOControl.Signature, IOControl.Signature.length());
|
|
retBuffer.putInt(DesktopAction.StsSuccess);
|
|
retBuffer.putInt(IOControl.Version);
|
|
break;
|
|
|
|
// Get file information for a file within the current folder
|
|
|
|
case IOControl.CmdFileStatus:
|
|
|
|
// Process the file status request
|
|
|
|
retBuffer = procIOFileStatus( sess, tree, dataBuf, folderNode);
|
|
break;
|
|
|
|
// Get action information for the specified executable path
|
|
|
|
case IOControl.CmdGetActionInfo:
|
|
|
|
// Process the get action information request
|
|
|
|
retBuffer = procGetActionInfo(sess, tree, dataBuf, folderNode, netFile);
|
|
break;
|
|
|
|
// Run the named action
|
|
|
|
case IOControl.CmdRunAction:
|
|
|
|
// Process the run action request
|
|
|
|
retBuffer = procRunAction(sess, tree, dataBuf, folderNode, netFile);
|
|
break;
|
|
|
|
// Return the authentication ticket
|
|
|
|
case IOControl.CmdGetAuthTicket:
|
|
|
|
// Process the get auth ticket request
|
|
|
|
retBuffer = procGetAuthTicket(sess, tree, dataBuf, folderNode, netFile);
|
|
break;
|
|
|
|
// Unknown I/O control code
|
|
|
|
default:
|
|
throw new IOControlNotImplementedException();
|
|
}
|
|
|
|
// Return the reply buffer, may be null
|
|
|
|
return retBuffer;
|
|
}
|
|
|
|
/**
|
|
* Process the file status I/O request
|
|
*
|
|
* @param sess Server session
|
|
* @param tree Tree connection
|
|
* @param reqBuf Request buffer
|
|
* @param folderNode NodeRef of parent folder
|
|
* @return DataBuffer
|
|
*/
|
|
private final DataBuffer procIOFileStatus( SrvSession sess, TreeConnection tree, DataBuffer reqBuf, NodeRef folderNode)
|
|
{
|
|
// Start a transaction
|
|
|
|
contentDriver.beginReadTransaction( sess);
|
|
|
|
// Get the file name from the request
|
|
|
|
String fName = reqBuf.getString( true);
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug(" File status, fname=" + fName);
|
|
|
|
// Create a response buffer
|
|
|
|
DataBuffer respBuf = new DataBuffer(256);
|
|
respBuf.putFixedString(IOControl.Signature, IOControl.Signature.length());
|
|
|
|
// Get the node for the file/folder
|
|
|
|
NodeRef childNode = null;
|
|
|
|
try
|
|
{
|
|
childNode = getCifsHelper().getNodeRef( folderNode, fName);
|
|
}
|
|
catch (FileNotFoundException ex)
|
|
{
|
|
}
|
|
|
|
// Check if the file/folder was found
|
|
|
|
if ( childNode == null)
|
|
{
|
|
// Return an error response
|
|
|
|
respBuf.putInt(DesktopAction.StsFileNotFound);
|
|
return respBuf;
|
|
}
|
|
|
|
// Check if this is a file or folder node
|
|
|
|
if ( getCifsHelper().isDirectory( childNode))
|
|
{
|
|
// Only return the status and node type for folders
|
|
|
|
respBuf.putInt(DesktopAction.StsSuccess);
|
|
respBuf.putInt(IOControl.TypeFolder);
|
|
}
|
|
else
|
|
{
|
|
// Indicate that this is a file node
|
|
|
|
respBuf.putInt(DesktopAction.StsSuccess);
|
|
respBuf.putInt(IOControl.TypeFile);
|
|
|
|
// Check if this file is a working copy
|
|
|
|
if ( getNodeService().hasAspect( childNode, ContentModel.ASPECT_WORKING_COPY))
|
|
{
|
|
// Indicate that this is a working copy
|
|
|
|
respBuf.putInt(IOControl.True);
|
|
|
|
// Get the owner username and file it was copied from
|
|
|
|
String owner = (String) getNodeService().getProperty( childNode, ContentModel.PROP_WORKING_COPY_OWNER);
|
|
String copiedFrom = null;
|
|
|
|
if ( getNodeService().hasAspect( childNode, ContentModel.ASPECT_COPIEDFROM))
|
|
{
|
|
// Get the path of the file the working copy was generated from
|
|
|
|
NodeRef fromNode = (NodeRef) getNodeService().getProperty( childNode, ContentModel.PROP_COPY_REFERENCE);
|
|
if ( fromNode != null)
|
|
copiedFrom = (String) getNodeService().getProperty( fromNode, ContentModel.PROP_NAME);
|
|
}
|
|
|
|
// Pack the owner and copied from values
|
|
|
|
respBuf.putString(owner != null ? owner : "", true, true);
|
|
respBuf.putString(copiedFrom != null ? copiedFrom : "", true, true);
|
|
}
|
|
else
|
|
{
|
|
// Not a working copy
|
|
|
|
respBuf.putInt(IOControl.False);
|
|
}
|
|
|
|
// Check the lock status of the file
|
|
|
|
if ( getNodeService().hasAspect( childNode, ContentModel.ASPECT_LOCKABLE))
|
|
{
|
|
// Get the lock type and owner
|
|
|
|
String lockTypeStr = (String) getNodeService().getProperty( childNode, ContentModel.PROP_LOCK_TYPE);
|
|
String lockOwner = null;
|
|
|
|
if ( lockTypeStr != null)
|
|
lockOwner = (String) getNodeService().getProperty( childNode, ContentModel.PROP_LOCK_OWNER);
|
|
|
|
// Pack the lock type, and owner if there is a lock on the file
|
|
|
|
if ( lockTypeStr == null)
|
|
respBuf.putInt(IOControl.LockNone);
|
|
else
|
|
{
|
|
LockType lockType = LockType.valueOf( lockTypeStr);
|
|
|
|
respBuf.putInt(lockType == LockType.READ_ONLY_LOCK ? IOControl.LockRead : IOControl.LockWrite);
|
|
respBuf.putString(lockOwner != null ? lockOwner : "", true, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// File is not lockable
|
|
|
|
respBuf.putInt(IOControl.LockNone);
|
|
}
|
|
|
|
// Get the content data details for the file
|
|
|
|
ContentData contentData = (ContentData) getNodeService().getProperty( childNode, ContentModel.PROP_CONTENT);
|
|
|
|
if ( contentData != null)
|
|
{
|
|
// Get the content mime-type
|
|
|
|
String mimeType = contentData.getMimetype();
|
|
|
|
// Pack the content length and mime-type
|
|
|
|
respBuf.putInt( IOControl.True);
|
|
respBuf.putLong( contentData.getSize());
|
|
respBuf.putString( mimeType != null ? mimeType : "", true, true);
|
|
}
|
|
else
|
|
{
|
|
// File does not have any content
|
|
|
|
respBuf.putInt( IOControl.False);
|
|
}
|
|
}
|
|
|
|
// Return the response
|
|
|
|
return respBuf;
|
|
}
|
|
|
|
/**
|
|
* Process the get action information request
|
|
*
|
|
* @param sess Server session
|
|
* @param tree Tree connection
|
|
* @param reqBuf Request buffer
|
|
* @param folderNode NodeRef of parent folder
|
|
* @param netFile NetworkFile for the folder
|
|
* @return DataBuffer
|
|
*/
|
|
private final DataBuffer procGetActionInfo( SrvSession sess, TreeConnection tree, DataBuffer reqBuf, NodeRef folderNode,
|
|
NetworkFile netFile)
|
|
{
|
|
// Get the executable file name from the request
|
|
|
|
String exeName = reqBuf.getString( true);
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug(" Get action info, exe=" + exeName);
|
|
|
|
// Create a response buffer
|
|
|
|
DataBuffer respBuf = new DataBuffer(256);
|
|
respBuf.putFixedString(IOControl.Signature, IOControl.Signature.length());
|
|
|
|
// Get the desktop actions list
|
|
|
|
DesktopActionTable deskActions = contentContext.getDesktopActions();
|
|
if ( deskActions == null)
|
|
{
|
|
respBuf.putInt(DesktopAction.StsNoSuchAction);
|
|
return respBuf;
|
|
}
|
|
|
|
// Convert the executable name to an action name
|
|
|
|
DesktopAction deskAction = deskActions.getActionViaPseudoName(exeName);
|
|
if ( deskAction == null)
|
|
{
|
|
respBuf.putInt(DesktopAction.StsNoSuchAction);
|
|
return respBuf;
|
|
}
|
|
|
|
// Return the desktop action details
|
|
|
|
respBuf.putInt(DesktopAction.StsSuccess);
|
|
respBuf.putString(deskAction.getName(), true);
|
|
respBuf.putInt(deskAction.getAttributes());
|
|
respBuf.putInt(deskAction.getPreProcessActions());
|
|
|
|
String confirmStr = deskAction.getConfirmationString();
|
|
respBuf.putString(confirmStr != null ? confirmStr : "", true);
|
|
|
|
// Return the response
|
|
|
|
return respBuf;
|
|
}
|
|
|
|
/**
|
|
* Process the run action request
|
|
*
|
|
* @param sess Server session
|
|
* @param tree Tree connection
|
|
* @param reqBuf Request buffer
|
|
* @param folderNode NodeRef of parent folder
|
|
* @param netFile NetworkFile for the folder
|
|
* @return DataBuffer
|
|
*/
|
|
private final DataBuffer procRunAction( SrvSession sess, TreeConnection tree, DataBuffer reqBuf, NodeRef folderNode,
|
|
NetworkFile netFile)
|
|
{
|
|
// Get the name of the action to run
|
|
|
|
String actionName = reqBuf.getString(true);
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug(" Run action, name=" + actionName);
|
|
|
|
// Create a response buffer
|
|
|
|
DataBuffer respBuf = new DataBuffer(256);
|
|
respBuf.putFixedString(IOControl.Signature, IOControl.Signature.length());
|
|
|
|
// Find the action handler
|
|
|
|
DesktopActionTable deskActions = contentContext.getDesktopActions();
|
|
DesktopAction action = null;
|
|
|
|
if ( deskActions != null)
|
|
action = deskActions.getAction(actionName);
|
|
|
|
if ( action == null)
|
|
{
|
|
respBuf.putInt(DesktopAction.StsNoSuchAction);
|
|
respBuf.putString("", true);
|
|
return respBuf;
|
|
}
|
|
|
|
// Start a transaction
|
|
|
|
contentDriver.beginReadTransaction( sess);
|
|
|
|
// Get an authentication ticket for the client, or validate the existing ticket. The ticket can be used when
|
|
// generating URLs for the client-side application so that the user does not have to re-authenticate
|
|
|
|
getTicketForClient( sess);
|
|
|
|
// Get the list of targets for the action
|
|
|
|
int targetCnt = reqBuf.getInt();
|
|
DesktopParams deskParams = new DesktopParams(sess, contentDriver, folderNode, netFile);
|
|
|
|
while ( reqBuf.getAvailableLength() > 4 && targetCnt > 0)
|
|
{
|
|
// Get the desktop target details
|
|
|
|
int typ = reqBuf.getInt();
|
|
String path = reqBuf.getString(true);
|
|
|
|
DesktopTarget target = new DesktopTarget(typ, path);
|
|
deskParams.addTarget(target);
|
|
|
|
// Find the node for the target path
|
|
|
|
NodeRef childNode = null;
|
|
|
|
try
|
|
{
|
|
// Check if the target path is relative to the folder we are working in or the root of the filesystem
|
|
|
|
if ( path.startsWith("\\"))
|
|
{
|
|
// Path is relative to the root of the filesystem
|
|
|
|
childNode = getCifsHelper().getNodeRef(contentContext.getRootNode(), path);
|
|
}
|
|
else
|
|
{
|
|
// Path is relative to the folder we are working in
|
|
|
|
childNode = getCifsHelper().getNodeRef( folderNode, path);
|
|
}
|
|
}
|
|
catch (FileNotFoundException ex)
|
|
{
|
|
}
|
|
|
|
// If the node is not valid then return an error status
|
|
|
|
if (childNode != null)
|
|
{
|
|
// Set the node ref for the target
|
|
|
|
target.setNode(childNode);
|
|
}
|
|
else
|
|
{
|
|
// Build an error response
|
|
|
|
respBuf.putInt(DesktopAction.StsFileNotFound);
|
|
respBuf.putString("Cannot find noderef for path " + path, true);
|
|
|
|
return respBuf;
|
|
}
|
|
|
|
// Update the target count
|
|
|
|
targetCnt--;
|
|
}
|
|
|
|
// DEBUG
|
|
|
|
if (logger.isDebugEnabled())
|
|
{
|
|
logger.debug(" Desktop params: " + deskParams.numberOfTargetNodes());
|
|
for ( int i = 0; i < deskParams.numberOfTargetNodes(); i++) {
|
|
DesktopTarget target = deskParams.getTarget(i);
|
|
logger.debug(" " + target);
|
|
}
|
|
}
|
|
|
|
// Run the desktop action
|
|
|
|
DesktopResponse deskResponse = null;
|
|
|
|
try
|
|
{
|
|
// Run the desktop action
|
|
|
|
deskResponse = action.runAction(deskParams);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Create an error response
|
|
|
|
deskResponse = new DesktopResponse(DesktopAction.StsError, ex.getMessage());
|
|
}
|
|
|
|
// Pack the action response
|
|
|
|
if ( deskResponse != null)
|
|
{
|
|
// Pack the status
|
|
|
|
respBuf.putInt(deskResponse.getStatus());
|
|
respBuf.putString(deskResponse.hasStatusMessage() ? deskResponse.getStatusMessage() : "", true);
|
|
}
|
|
else
|
|
{
|
|
// Pack an error response
|
|
|
|
respBuf.putInt(DesktopAction.StsError);
|
|
respBuf.putString("Action did not return response", true);
|
|
}
|
|
|
|
// Return the response
|
|
|
|
return respBuf;
|
|
}
|
|
|
|
/**
|
|
* Process the get authentication ticket request
|
|
*
|
|
* @param sess Server session
|
|
* @param tree Tree connection
|
|
* @param reqBuf Request buffer
|
|
* @param folderNode NodeRef of parent folder
|
|
* @param netFile NetworkFile for the folder
|
|
* @return DataBuffer
|
|
*/
|
|
private final DataBuffer procGetAuthTicket( SrvSession sess, TreeConnection tree, DataBuffer reqBuf, NodeRef folderNode,
|
|
NetworkFile netFile)
|
|
{
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug(" Get Auth Ticket");
|
|
|
|
// Create a response buffer
|
|
|
|
DataBuffer respBuf = new DataBuffer(256);
|
|
respBuf.putFixedString(IOControl.Signature, IOControl.Signature.length());
|
|
|
|
// Start a transaction
|
|
|
|
contentDriver.beginReadTransaction( sess);
|
|
|
|
// Get an authentication ticket for the client, or validate the existing ticket. The ticket can be used when
|
|
// generating URLs for the client-side application so that the user does not have to re-authenticate
|
|
|
|
getTicketForClient( sess);
|
|
|
|
// Pack the response
|
|
|
|
AlfrescoClientInfo cInfo = (AlfrescoClientInfo) sess.getClientInformation();
|
|
|
|
if ( cInfo != null && cInfo.getAuthenticationTicket() != null) {
|
|
respBuf.putInt(DesktopAction.StsAuthTicket);
|
|
respBuf.putString( cInfo.getAuthenticationTicket(), true);
|
|
}
|
|
else {
|
|
respBuf.putInt(DesktopAction.StsError);
|
|
respBuf.putString( "Client information invalid", true);
|
|
}
|
|
|
|
// Return the response
|
|
|
|
return respBuf;
|
|
}
|
|
|
|
/**
|
|
* Get, or validate, an authentication ticket for the client
|
|
*
|
|
* @param sess SrvSession
|
|
*/
|
|
private final void getTicketForClient(SrvSession sess)
|
|
{
|
|
// Get the client information and check if there is a ticket allocated
|
|
|
|
AlfrescoClientInfo cInfo = (AlfrescoClientInfo) sess.getClientInformation();
|
|
if ( cInfo == null)
|
|
return;
|
|
|
|
boolean needTicket = true;
|
|
|
|
if ( cInfo.hasAuthenticationTicket())
|
|
{
|
|
// Validate the existing ticket, it may have expired
|
|
|
|
try
|
|
{
|
|
// Validate the existing ticket
|
|
|
|
getAuthenticationService().validate( cInfo.getAuthenticationTicket());
|
|
needTicket = false;
|
|
}
|
|
catch ( AuthenticationException ex)
|
|
{
|
|
// Invalidate the current ticket
|
|
|
|
try
|
|
{
|
|
getAuthenticationService().invalidateTicket( cInfo.getAuthenticationTicket());
|
|
cInfo.setAuthenticationTicket( null);
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("Error during invalidate ticket", ex2);
|
|
}
|
|
|
|
// DEBUG
|
|
|
|
if ( logger.isDebugEnabled())
|
|
logger.debug("Auth ticket expired or invalid");
|
|
}
|
|
}
|
|
|
|
// Check if a ticket needs to be allocated
|
|
|
|
if ( needTicket == true)
|
|
{
|
|
// Allocate a new ticket and store in the client information for this session
|
|
|
|
String ticket = getAuthenticationService().getCurrentTicket();
|
|
cInfo.setAuthenticationTicket( ticket);
|
|
}
|
|
}
|
|
}
|